blob: 4d9ec321af8df54a4875fecea878d3eae2b4ab17 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.pkcs11;
27
28import java.util.*;
29
30import java.security.*;
31import java.security.spec.AlgorithmParameterSpec;
32
33import javax.crypto.*;
34import javax.crypto.spec.*;
35
36import sun.security.internal.spec.*;
37import sun.security.internal.interfaces.TlsMasterSecret;
38
39import static sun.security.pkcs11.TemplateManager.*;
40import sun.security.pkcs11.wrapper.*;
41import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
42
43/**
44 * KeyGenerator to calculate the SSL/TLS key material (cipher keys and ivs,
45 * mac keys) from the master secret.
46 *
47 * @author Andreas Sterbenz
48 * @since 1.6
49 */
50public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
51
52 private final static String MSG = "TlsKeyMaterialGenerator must be "
53 + "initialized using a TlsKeyMaterialParameterSpec";
54
55 // token instance
56 private final Token token;
57
58 // algorithm name
59 private final String algorithm;
60
61 // mechanism id
62 private long mechanism;
63
64 // parameter spec
65 private TlsKeyMaterialParameterSpec spec;
66
67 // master secret as a P11Key
68 private P11Key p11Key;
69
70 // version, e.g. 0x0301
71 private int version;
72
73 P11TlsKeyMaterialGenerator(Token token, String algorithm, long mechanism)
74 throws PKCS11Exception {
75 super();
76 this.token = token;
77 this.algorithm = algorithm;
78 this.mechanism = mechanism;
79 }
80
81 protected void engineInit(SecureRandom random) {
82 throw new InvalidParameterException(MSG);
83 }
84
85 protected void engineInit(AlgorithmParameterSpec params,
86 SecureRandom random) throws InvalidAlgorithmParameterException {
87 if (params instanceof TlsKeyMaterialParameterSpec == false) {
88 throw new InvalidAlgorithmParameterException(MSG);
89 }
90 this.spec = (TlsKeyMaterialParameterSpec)params;
91 try {
92 p11Key = P11SecretKeyFactory.convertKey
93 (token, spec.getMasterSecret(), "TlsMasterSecret");
94 } catch (InvalidKeyException e) {
95 throw new InvalidAlgorithmParameterException("init() failed", e);
96 }
97 version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
98 if ((version < 0x0300) && (version > 0x0302)) {
99 throw new InvalidAlgorithmParameterException
100 ("Only SSL 3.0, TLS 1.0, and TLS 1.1 are supported");
101 }
102 // we assume the token supports both the CKM_SSL3_* and the CKM_TLS_*
103 // mechanisms
104 }
105
106 protected void engineInit(int keysize, SecureRandom random) {
107 throw new InvalidParameterException(MSG);
108 }
109
110 protected SecretKey engineGenerateKey() {
111 if (spec == null) {
112 throw new IllegalStateException
113 ("TlsKeyMaterialGenerator must be initialized");
114 }
115 mechanism = (version == 0x0300) ? CKM_SSL3_KEY_AND_MAC_DERIVE
116 : CKM_TLS_KEY_AND_MAC_DERIVE;
117 int macBits = spec.getMacKeyLength() << 3;
118 int ivBits = spec.getIvLength() << 3;
119
120 int expandedKeyBits = spec.getExpandedCipherKeyLength() << 3;
121 int keyBits = spec.getCipherKeyLength() << 3;
122 boolean isExportable;
123 if (expandedKeyBits != 0) {
124 isExportable = true;
125 } else {
126 isExportable = false;
127 expandedKeyBits = keyBits;
128 }
129
130 CK_SSL3_RANDOM_DATA random = new CK_SSL3_RANDOM_DATA
131 (spec.getClientRandom(), spec.getServerRandom());
132 CK_SSL3_KEY_MAT_PARAMS params = new CK_SSL3_KEY_MAT_PARAMS
133 (macBits, keyBits, ivBits, isExportable, random);
134
135 String cipherAlgorithm = spec.getCipherAlgorithm();
136 long keyType = P11SecretKeyFactory.getKeyType(cipherAlgorithm);
137 if (keyType < 0) {
138 if (keyBits != 0) {
139 throw new ProviderException
140 ("Unknown algorithm: " + spec.getCipherAlgorithm());
141 } else {
142 // NULL encryption ciphersuites
143 keyType = CKK_GENERIC_SECRET;
144 }
145 }
146
147 Session session = null;
148 try {
149 session = token.getObjSession();
150 CK_ATTRIBUTE[] attributes;
151 if (keyBits != 0) {
152 attributes = new CK_ATTRIBUTE[] {
153 new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
154 new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
155 new CK_ATTRIBUTE(CKA_VALUE_LEN, expandedKeyBits >> 3),
156 };
157 } else {
158 // ciphersuites with NULL ciphers
159 attributes = new CK_ATTRIBUTE[0];
160 }
161 attributes = token.getAttributes
162 (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
163 // the returned keyID is a dummy, ignore
164 long keyID = token.p11.C_DeriveKey(session.id(),
165 new CK_MECHANISM(mechanism, params), p11Key.keyID, attributes);
166
167 CK_SSL3_KEY_MAT_OUT out = params.pReturnedKeyMaterial;
168 // Note that the MAC keys do not inherit all attributes from the
169 // template, but they do inherit the sensitive/extractable/token
170 // flags, which is all P11Key cares about.
171 SecretKey clientMacKey = P11Key.secretKey
172 (session, out.hClientMacSecret, "MAC", macBits, attributes);
173 SecretKey serverMacKey = P11Key.secretKey
174 (session, out.hServerMacSecret, "MAC", macBits, attributes);
175 SecretKey clientCipherKey, serverCipherKey;
176 if (keyBits != 0) {
177 clientCipherKey = P11Key.secretKey(session, out.hClientKey,
178 cipherAlgorithm, expandedKeyBits, attributes);
179 serverCipherKey = P11Key.secretKey(session, out.hServerKey,
180 cipherAlgorithm, expandedKeyBits, attributes);
181 } else {
182 clientCipherKey = null;
183 serverCipherKey = null;
184 }
185 IvParameterSpec clientIv = (out.pIVClient == null)
186 ? null : new IvParameterSpec(out.pIVClient);
187 IvParameterSpec serverIv = (out.pIVServer == null)
188 ? null : new IvParameterSpec(out.pIVServer);
189
190 return new TlsKeyMaterialSpec(clientMacKey, serverMacKey,
191 clientCipherKey, clientIv, serverCipherKey, serverIv);
192
193 } catch (Exception e) {
194 throw new ProviderException("Could not generate key", e);
195 } finally {
196 token.releaseSession(session);
197 }
198 }
199
200}