blob: 8bdd9cf3d1d5e4757986694c66f3b3b0e5975ee4 [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.security.*;
29import java.security.spec.AlgorithmParameterSpec;
30
31import javax.crypto.*;
32import javax.crypto.spec.*;
33
34import sun.security.internal.spec.TlsMasterSecretParameterSpec;
35
36import static sun.security.pkcs11.TemplateManager.*;
37import sun.security.pkcs11.wrapper.*;
38import 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 */
46public 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}