1 /* 2 * Copyright (c) 2018, 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 4936763 8184359 27 * @summary KeyAgreement Test with all supported algorithms from JCE. 28 * Arguments order <KeyExchangeAlgorithm> <KeyGenAlgorithm> <Provider> 29 * It removes com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java 30 * as the same functionality for DiffieHellman is covered along with 31 * this test file was covered before with JDK-4936763. 32 * @run main/othervm -Djdk.crypto.KeyAgreement.legacyKDF=true KeyAgreementTest 33 * DiffieHellman DH SunJCE 34 * @run main KeyAgreementTest ECDH EC SunEC 35 * @run main KeyAgreementTest XDH XDH SunEC 36 */ 37 import java.security.KeyPair; 38 import java.security.KeyPairGenerator; 39 import java.security.spec.NamedParameterSpec; 40 import java.security.spec.AlgorithmParameterSpec; 41 import java.security.spec.ECGenParameterSpec; 42 import java.util.ArrayList; 43 import java.util.Arrays; 44 import java.util.List; 45 import javax.crypto.KeyAgreement; 46 import javax.crypto.spec.DHGenParameterSpec; 47 48 public class KeyAgreementTest { 49 main(String[] args)50 public static void main(String[] args) throws Exception { 51 52 String kaAlgo = args[0]; 53 String kpgAlgo = args[1]; 54 String provider = args[2]; 55 AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo); 56 List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs(); 57 for (AlgorithmParameterSpec spec : specs) { 58 testKeyAgreement(provider, kaAlgo, kpgAlgo, spec); 59 } 60 } 61 62 /** 63 * Generate AlgorithmParameterSpec using all possible supported curve for 64 * KeyExchangeAlgorithm. 65 */ 66 private enum AlgoSpec { 67 // EC curve supported for KeyGeneration can found between intersection 68 // of curves define in 69 // "java.base/share/classes/sun/security/util/CurveDB.java" 70 // and 71 // "jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c" 72 ECDH( 73 // SEC2 prime curves 74 "secp112r1", "secp112r2", "secp128r1", "secp128r2", "secp160k1", 75 "secp160r1", "secp192k1", "secp192r1", "secp224k1", "secp224r1", 76 "secp256k1", "secp256r1", "secp384r1", "secp521r1", 77 // ANSI X9.62 prime curves 78 "X9.62 prime192v2", "X9.62 prime192v3", "X9.62 prime239v1", 79 "X9.62 prime239v2", "X9.62 prime239v3", 80 // SEC2 binary curves 81 "sect113r1", "sect113r2", "sect131r1", "sect131r2", "sect163k1", 82 "sect163r1", "sect163r2", "sect193r1", "sect193r2", "sect233k1", 83 "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", 84 "sect409r1", "sect571k1", "sect571r1", 85 // ANSI X9.62 binary curves 86 "X9.62 c2tnb191v1", "X9.62 c2tnb191v2", "X9.62 c2tnb191v3", 87 "X9.62 c2tnb239v1", "X9.62 c2tnb239v2", "X9.62 c2tnb239v3", 88 "X9.62 c2tnb359v1", "X9.62 c2tnb431r1" 89 ), 90 XDH("X25519", "X448"), 91 // There is no curve for DiffieHellman 92 DiffieHellman(new String[]{}); 93 94 private final List<AlgorithmParameterSpec> specs = new ArrayList<>(); 95 AlgoSpec(String... curves)96 private AlgoSpec(String... curves) { 97 // Generate AlgorithmParameterSpec for each KeyExchangeAlgorithm 98 for (String crv : curves) { 99 switch (this.name()) { 100 case "ECDH": 101 specs.add(new ECGenParameterSpec(crv)); 102 break; 103 case "XDH": 104 specs.add(new NamedParameterSpec(crv)); 105 break; 106 case "DiffieHellman": 107 specs.add(new DHGenParameterSpec(512, 64)); 108 break; 109 default: 110 throw new RuntimeException("Invalid Algo name " 111 + this.name()); 112 } 113 } 114 } 115 getAlgorithmParameterSpecs()116 public List<AlgorithmParameterSpec> getAlgorithmParameterSpecs() { 117 return this.specs; 118 } 119 } 120 121 /** 122 * Perform KeyAgreement operation using native as well as JCE provider. 123 */ testKeyAgreement(String provider, String kaAlgo, String kpgAlgo, AlgorithmParameterSpec spec)124 private static void testKeyAgreement(String provider, String kaAlgo, 125 String kpgAlgo, AlgorithmParameterSpec spec) throws Exception { 126 127 KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider); 128 kpg.initialize(spec); 129 KeyPair kp1 = kpg.generateKeyPair(); 130 KeyPair kp2 = kpg.generateKeyPair(); 131 132 // Uses KeyAgreement based on Provider search order. 133 KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo); 134 ka1.init(kp1.getPrivate()); 135 ka1.doPhase(kp2.getPublic(), true); 136 byte[] secret1 = ka1.generateSecret(); 137 138 // Uses SunJCE provider 139 KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider); 140 ka2.init(kp2.getPrivate()); 141 ka2.doPhase(kp1.getPublic(), true); 142 // Keeping the legacy generateSecret method for DiffieHellman as it was 143 // defined in removed Test file from JDK-4936763, 144 // com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java. 145 byte[] secret2 = "DiffieHellman".equals(kaAlgo) 146 ? ka2.generateSecret("AES").getEncoded() : ka2.generateSecret(); 147 148 // With related keypairs, each provider should generate same 149 // KeyAgreement secret. 150 if (!Arrays.equals(secret1, secret2)) { 151 throw new Exception("KeyAgreement secret mismatch."); 152 } 153 } 154 } 155