1 /* 2 * Copyright (c) 2005, 2007, 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 javax.crypto.spec.*; 33 34 import sun.security.internal.spec.TlsMasterSecretParameterSpec; 35 36 import static sun.security.pkcs11.TemplateManager.*; 37 import sun.security.pkcs11.wrapper.*; 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 TlsMasterSecretParameterSpec spec; 61 private P11Key p11Key; 62 63 int version; 64 65 P11TlsMasterSecretGenerator(Token token, String algorithm, long mechanism) 66 throws PKCS11Exception { 67 super(); 68 this.token = token; 69 this.algorithm = algorithm; 70 this.mechanism = mechanism; 71 } 72 73 protected void engineInit(SecureRandom random) { 74 throw new InvalidParameterException(MSG); 75 } 76 77 protected void engineInit(AlgorithmParameterSpec params, 78 SecureRandom random) throws InvalidAlgorithmParameterException { 79 if (params instanceof TlsMasterSecretParameterSpec == false) { 80 throw new InvalidAlgorithmParameterException(MSG); 81 } 82 this.spec = (TlsMasterSecretParameterSpec)params; 83 SecretKey key = spec.getPremasterSecret(); 84 // algorithm should be either TlsRsaPremasterSecret or TlsPremasterSecret, 85 // but we omit the check 86 try { 87 p11Key = P11SecretKeyFactory.convertKey(token, key, null); 88 } catch (InvalidKeyException e) { 89 throw new InvalidAlgorithmParameterException("init() failed", e); 90 } 91 version = (spec.getMajorVersion() << 8) | spec.getMinorVersion(); 92 if ((version < 0x0300) || (version > 0x0302)) { 93 throw new InvalidAlgorithmParameterException 94 ("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported"); 95 } 96 // We assume the token supports the required mechanism. If it does not, 97 // generateKey() will fail and the failover should take care of us. 98 } 99 100 protected void engineInit(int keysize, SecureRandom random) { 101 throw new InvalidParameterException(MSG); 102 } 103 104 protected SecretKey engineGenerateKey() { 105 if (spec == null) { 106 throw new IllegalStateException 107 ("TlsMasterSecretGenerator must be initialized"); 108 } 109 CK_VERSION ckVersion; 110 if (p11Key.getAlgorithm().equals("TlsRsaPremasterSecret")) { 111 mechanism = (version == 0x0300) ? CKM_SSL3_MASTER_KEY_DERIVE 112 : CKM_TLS_MASTER_KEY_DERIVE; 113 ckVersion = new CK_VERSION(0, 0); 114 } else { 115 // Note: we use DH for all non-RSA premaster secrets. That includes 116 // Kerberos. That should not be a problem because master secret 117 // calculation is always a straightforward application of the 118 // TLS PRF (or the SSL equivalent). 119 // The only thing special about RSA master secret calculation is 120 // that it extracts the version numbers from the premaster secret. 121 mechanism = (version == 0x0300) ? CKM_SSL3_MASTER_KEY_DERIVE_DH 122 : CKM_TLS_MASTER_KEY_DERIVE_DH; 123 ckVersion = null; 124 } 125 byte[] clientRandom = spec.getClientRandom(); 126 byte[] serverRandom = spec.getServerRandom(); 127 CK_SSL3_RANDOM_DATA random = 128 new CK_SSL3_RANDOM_DATA(clientRandom, serverRandom); 129 CK_SSL3_MASTER_KEY_DERIVE_PARAMS params = 130 new CK_SSL3_MASTER_KEY_DERIVE_PARAMS(random, ckVersion); 131 132 Session session = null; 133 try { 134 session = token.getObjSession(); 135 CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE, 136 CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); 137 long keyID = token.p11.C_DeriveKey(session.id(), 138 new CK_MECHANISM(mechanism, params), p11Key.keyID, attributes); 139 int major, minor; 140 ckVersion = params.pVersion; 141 if (ckVersion == null) { 142 major = -1; 143 minor = -1; 144 } else { 145 major = ckVersion.major; 146 minor = ckVersion.minor; 147 } 148 SecretKey key = P11Key.masterSecretKey(session, keyID, 149 "TlsMasterSecret", 48 << 3, attributes, major, minor); 150 return key; 151 } catch (Exception e) { 152 throw new ProviderException("Could not generate key", e); 153 } finally { 154 token.releaseSession(session); 155 } 156 } 157 158 }