1/*
2 * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 8072452
27 * @summary Support DHE sizes up to 8192-bits and DSA sizes up to 3072-bits
28 * @library ..
29 * @modules jdk.crypto.cryptoki
30 * @run main/othervm SupportedDHKeys
31 * @run main/othervm SupportedDHKeys sm
32 */
33
34import java.math.BigInteger;
35import java.security.KeyPair;
36import java.security.KeyPairGenerator;
37import java.security.Provider;
38import javax.crypto.interfaces.DHPrivateKey;
39import javax.crypto.interfaces.DHPublicKey;
40import javax.crypto.spec.DHParameterSpec;
41
42public class SupportedDHKeys extends PKCS11Test {
43
44    /*
45     * Sizes and values for various lengths.
46     */
47    private enum SupportedKeySize {
48        dhp512(512),   dhp768(768),    dhp832(832),
49        dhp1024(1024), dhp1536(1536),  dhp2048(2048);
50
51        // the underlying pkcs11 may not support the following sizes yet
52        //
53        // dhp3072(3072), dhp4096(4096),  dhp6144(6144),
54        // dhp8192(8192);
55
56        final int primeSize;
57
58        SupportedKeySize(int primeSize) {
59            this.primeSize = primeSize;
60        }
61    }
62
63    @Override
64    public void main(Provider provider) throws Exception {
65        if (provider.getService("KeyPairGenerator", "DiffieHellman") == null) {
66            System.out.println("No support of DH KeyPairGenerator, skipping");
67            return;
68        }
69
70        for (SupportedKeySize keySize : SupportedKeySize.values()) {
71            System.out.println("Checking " + keySize.primeSize + " ...");
72            KeyPairGenerator kpg =
73                    KeyPairGenerator.getInstance("DiffieHellman", provider);
74            kpg.initialize(keySize.primeSize);
75            KeyPair kp = kpg.generateKeyPair();
76            checkKeyPair(kp, keySize.primeSize, provider);
77
78            DHPublicKey publicKey = (DHPublicKey)kp.getPublic();
79            BigInteger p = publicKey.getParams().getP();
80            BigInteger g = publicKey.getParams().getG();
81            kpg.initialize(new DHParameterSpec(p, g));
82            kp = kpg.generateKeyPair();
83            checkKeyPair(kp, keySize.primeSize, provider);
84        }
85    }
86
87    private static void checkKeyPair(KeyPair kp, int pSize,
88                Provider provider) throws Exception {
89
90        DHPrivateKey privateKey = (DHPrivateKey)kp.getPrivate();
91        BigInteger p = privateKey.getParams().getP();
92        if (p.bitLength() != pSize) {
93            throw new Exception(
94                "Invalid modulus size: " + p.bitLength() + "/" + pSize);
95        }
96
97        // System.out.println("P(" + pSize + "): " + p.toString());
98        if (!p.isProbablePrime(128)) {
99            throw new Exception("Good luck, the modulus is composite!");
100        }
101
102        DHPublicKey publicKey = (DHPublicKey)kp.getPublic();
103        p = publicKey.getParams().getP();
104        if (p.bitLength() != pSize) {
105            throw new Exception(
106                "Invalid modulus size: " + p.bitLength() + "/" + pSize);
107        }
108
109        BigInteger leftOpen = BigInteger.ONE;
110        BigInteger rightOpen = p.subtract(BigInteger.ONE);
111
112        // ignore the private key range checking on Solaris at present
113        if (!provider.getName().equals("SunPKCS11-Solaris")) {
114            BigInteger x = privateKey.getX();
115            if ((x.compareTo(leftOpen) <= 0) ||
116                    (x.compareTo(rightOpen) >= 0)) {
117                throw new Exception(
118                    "X outside range [2, p - 2]:  x: " + x + " p: " + p);
119            }
120        }
121
122        BigInteger y = publicKey.getY();
123        if ((y.compareTo(leftOpen) <= 0) ||
124                (y.compareTo(rightOpen) >= 0)) {
125            throw new Exception(
126                "Y outside range [2, p - 2]:  y: " + y + " p: " + p);
127        }
128    }
129
130    public static void main(String[] args) throws Exception {
131        main(new SupportedDHKeys(), args);
132    }
133}
134