1 /* 2 * Copyright (c) 2005, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.pkcs11; 27 28 import java.security.*; 29 import java.security.spec.AlgorithmParameterSpec; 30 31 import javax.crypto.*; 32 import sun.security.internal.spec.TlsMasterSecretParameterSpec; 33 34 import static sun.security.pkcs11.TemplateManager.*; 35 import sun.security.pkcs11.wrapper.*; 36 import sun.security.ssl.ProtocolVersion; 37 38 import static sun.security.pkcs11.wrapper.PKCS11Constants.*; 39 40 /** 41 * KeyGenerator for the SSL/TLS master secret. 42 * 43 * @author Andreas Sterbenz 44 * @since 1.6 45 */ 46 public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi { 47 48 private final static String MSG = "TlsMasterSecretGenerator must be " 49 + "initialized using a TlsMasterSecretParameterSpec"; 50 51 // token instance 52 private final Token token; 53 54 // algorithm name 55 private final String algorithm; 56 57 // mechanism id 58 private long mechanism; 59 60 private ProtocolVersion tlsVersion; 61 62 @SuppressWarnings("deprecation") 63 private TlsMasterSecretParameterSpec spec; 64 private P11Key p11Key; 65 66 CK_VERSION ckVersion; 67 68 // whether SSLv3 is supported 69 private final boolean supportSSLv3; 70 71 P11TlsMasterSecretGenerator(Token token, String algorithm, long mechanism) 72 throws PKCS11Exception { 73 super(); 74 this.token = token; 75 this.algorithm = algorithm; 76 this.mechanism = mechanism; 77 78 // Given the current lookup order specified in SunPKCS11.java, if 79 // CKM_SSL3_MASTER_KEY_DERIVE is not used to construct this object, 80 // it means that this mech is disabled or unsupported. 81 supportSSLv3 = (mechanism == CKM_SSL3_MASTER_KEY_DERIVE); 82 } 83 84 protected void engineInit(SecureRandom random) { 85 throw new InvalidParameterException(MSG); 86 } 87 88 @SuppressWarnings("deprecation") 89 protected void engineInit(AlgorithmParameterSpec params, 90 SecureRandom random) throws InvalidAlgorithmParameterException { 91 if (params instanceof TlsMasterSecretParameterSpec == false) { 92 throw new InvalidAlgorithmParameterException(MSG); 93 } 94 95 TlsMasterSecretParameterSpec spec = (TlsMasterSecretParameterSpec)params; 96 tlsVersion = ProtocolVersion.valueOf(spec.getMajorVersion(), spec.getMinorVersion()); 97 if ((tlsVersion.compareTo(ProtocolVersion.SSL30) == 0 && !supportSSLv3) || 98 (tlsVersion.compareTo(ProtocolVersion.SSL30) < 0) || 99 (tlsVersion.compareTo(ProtocolVersion.TLS12) > 0)) { 100 throw new InvalidAlgorithmParameterException 101 ("Only" + (supportSSLv3? " SSL 3.0,": "") + 102 " TLS 1.0, TLS 1.1 and TLS 1.2 are supported (" + 103 tlsVersion + ")"); 104 } 105 106 SecretKey key = spec.getPremasterSecret(); 107 // algorithm should be either TlsRsaPremasterSecret or TlsPremasterSecret, 108 // but we omit the check 109 try { 110 p11Key = P11SecretKeyFactory.convertKey(token, key, null); 111 } catch (InvalidKeyException e) { 112 throw new InvalidAlgorithmParameterException("init() failed", e); 113 } 114 this.spec = spec; 115 final boolean isTlsRsaPremasterSecret = p11Key.getAlgorithm().equals("TlsRsaPremasterSecret"); 116 if (tlsVersion.compareTo(ProtocolVersion.SSL30) == 0) { 117 mechanism = isTlsRsaPremasterSecret ? 118 CKM_SSL3_MASTER_KEY_DERIVE : CKM_SSL3_MASTER_KEY_DERIVE_DH; 119 } else if (tlsVersion.compareTo(ProtocolVersion.TLS10) == 0 || 120 tlsVersion.compareTo(ProtocolVersion.TLS11) == 0) { 121 mechanism = isTlsRsaPremasterSecret ? 122 CKM_TLS_MASTER_KEY_DERIVE : CKM_TLS_MASTER_KEY_DERIVE_DH; 123 } else if (tlsVersion.compareTo(ProtocolVersion.TLS12) == 0) { 124 mechanism = isTlsRsaPremasterSecret ? 125 CKM_TLS12_MASTER_KEY_DERIVE : CKM_TLS12_MASTER_KEY_DERIVE_DH; 126 } 127 if (isTlsRsaPremasterSecret) { 128 ckVersion = new CK_VERSION(0, 0); 129 } else { 130 // Note: we use DH for all non-RSA premaster secrets. That includes 131 // Kerberos. That should not be a problem because master secret 132 // calculation is always a straightforward application of the 133 // TLS PRF (or the SSL equivalent). 134 // The only thing special about RSA master secret calculation is 135 // that it extracts the version numbers from the premaster secret. 136 ckVersion = null; 137 } 138 } 139 140 protected void engineInit(int keysize, SecureRandom random) { 141 throw new InvalidParameterException(MSG); 142 } 143 144 protected SecretKey engineGenerateKey() { 145 if (spec == null) { 146 throw new IllegalStateException 147 ("TlsMasterSecretGenerator must be initialized"); 148 } 149 byte[] clientRandom = spec.getClientRandom(); 150 byte[] serverRandom = spec.getServerRandom(); 151 CK_SSL3_RANDOM_DATA random = 152 new CK_SSL3_RANDOM_DATA(clientRandom, serverRandom); 153 CK_MECHANISM ckMechanism = null; 154 if (tlsVersion.compareTo(ProtocolVersion.TLS12) < 0) { 155 CK_SSL3_MASTER_KEY_DERIVE_PARAMS params = 156 new CK_SSL3_MASTER_KEY_DERIVE_PARAMS(random, ckVersion); 157 ckMechanism = new CK_MECHANISM(mechanism, params); 158 } else if (tlsVersion.compareTo(ProtocolVersion.TLS12) == 0) { 159 CK_TLS12_MASTER_KEY_DERIVE_PARAMS params = 160 new CK_TLS12_MASTER_KEY_DERIVE_PARAMS(random, ckVersion, 161 SunPKCS11.hashAlgorithmToHashMechanismMap.get(spec.getPRFHashAlg())); 162 ckMechanism = new CK_MECHANISM(mechanism, params); 163 } 164 Session session = null; 165 try { 166 session = token.getObjSession(); 167 CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE, 168 CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); 169 long keyID = token.p11.C_DeriveKey(session.id(), 170 ckMechanism, p11Key.keyID, attributes); 171 int major, minor; 172 if (ckVersion == null) { 173 major = -1; 174 minor = -1; 175 } else { 176 major = ckVersion.major; 177 minor = ckVersion.minor; 178 } 179 SecretKey key = P11Key.masterSecretKey(session, keyID, 180 "TlsMasterSecret", 48 << 3, attributes, major, minor); 181 return key; 182 } catch (Exception e) { 183 throw new ProviderException("Could not generate key", e); 184 } finally { 185 token.releaseSession(session); 186 } 187 } 188 }