blob: b49cbeac050015468b8d15403bc5740db34997f1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-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.*;
32
33import static sun.security.pkcs11.TemplateManager.*;
34import sun.security.pkcs11.wrapper.*;
35import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
36
37/**
38 * KeyGenerator implementation class. This class currently supports
39 * DES, DESede, AES, ARCFOUR, and Blowfish.
40 *
41 * @author Andreas Sterbenz
42 * @since 1.5
43 */
44final class P11KeyGenerator extends KeyGeneratorSpi {
45
46 // token instance
47 private final Token token;
48
49 // algorithm name
50 private final String algorithm;
51
52 // mechanism id
53 private long mechanism;
54
55 // raw key size in bits, e.g. 64 for DES. Always valid.
56 private int keySize;
57
58 // bits of entropy in the key, e.g. 56 for DES. Always valid.
59 private int significantKeySize;
60
61 // keyType (CKK_*), needed for TemplateManager call only.
62 private long keyType;
63
64 // for determining if both 112 and 168 bits of DESede key lengths
65 // are supported.
66 private boolean supportBothKeySizes;
67
68 // min and max key sizes (in bits) for variable-key-length
69 // algorithms, e.g. RC4 and Blowfish
70 private int minKeySize;
71 private int maxKeySize;
72
73 P11KeyGenerator(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 if (this.mechanism == CKM_DES3_KEY_GEN) {
81 /* Given the current lookup order specified in SunPKCS11.java,
82 if CKM_DES2_KEY_GEN is used to construct this object, it
83 means that CKM_DES3_KEY_GEN is disabled or unsupported.
84 */
85 supportBothKeySizes =
86 (token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
87 (token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
88 } else if (this.mechanism == CKM_RC4_KEY_GEN) {
89 CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism);
90 // Although PKCS#11 spec documented that these are in bits,
91 // NSS, for one, uses bytes. Multiple by 8 if the number seems
92 // unreasonably small.
93 if (info.ulMinKeySize < 8) {
94 minKeySize = (int)info.ulMinKeySize << 3;
95 maxKeySize = (int)info.ulMaxKeySize << 3;
96 } else {
97 minKeySize = (int)info.ulMinKeySize;
98 maxKeySize = (int)info.ulMaxKeySize;
99 }
100 // Explicitly disallow keys shorter than 40-bits for security
101 if (minKeySize < 40) minKeySize = 40;
102 } else if (this.mechanism == CKM_BLOWFISH_KEY_GEN) {
103 CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism);
104 maxKeySize = (int)info.ulMaxKeySize << 3;
105 minKeySize = (int)info.ulMinKeySize << 3;
106 // Explicitly disallow keys shorter than 40-bits for security
107 if (minKeySize < 40) minKeySize = 40;
108 }
109
110 setDefaultKeySize();
111 }
112
113 // set default keysize and also initialize keyType
114 private void setDefaultKeySize() {
115 // whether to check default key size against the min and max value
116 boolean validateKeySize = false;
117 switch ((int)mechanism) {
118 case (int)CKM_DES_KEY_GEN:
119 keySize = 64;
120 significantKeySize = 56;
121 keyType = CKK_DES;
122 break;
123 case (int)CKM_DES2_KEY_GEN:
124 keySize = 128;
125 significantKeySize = 112;
126 keyType = CKK_DES2;
127 break;
128 case (int)CKM_DES3_KEY_GEN:
129 keySize = 192;
130 significantKeySize = 168;
131 keyType = CKK_DES3;
132 break;
133 case (int)CKM_AES_KEY_GEN:
134 keyType = CKK_AES;
135 keySize = 128;
136 significantKeySize = 128;
137 break;
138 case (int)CKM_RC4_KEY_GEN:
139 keyType = CKK_RC4;
140 keySize = 128;
141 validateKeySize = true;
142 break;
143 case (int)CKM_BLOWFISH_KEY_GEN:
144 keyType = CKK_BLOWFISH;
145 keySize = 128;
146 validateKeySize = true;
147 break;
148 default:
149 throw new ProviderException("Unknown mechanism " + mechanism);
150 }
151 if (validateKeySize &&
152 ((keySize > maxKeySize) || (keySize < minKeySize))) {
153 throw new ProviderException("Unsupported key size");
154 }
155 }
156
157 // see JCE spec
158 protected void engineInit(SecureRandom random) {
159 token.ensureValid();
160 setDefaultKeySize();
161 }
162
163 // see JCE spec
164 protected void engineInit(AlgorithmParameterSpec params,
165 SecureRandom random) throws InvalidAlgorithmParameterException {
166 throw new InvalidAlgorithmParameterException
167 ("AlgorithmParameterSpec not supported");
168 }
169
170 // see JCE spec
171 protected void engineInit(int keySize, SecureRandom random) {
172 token.ensureValid();
173 switch ((int)mechanism) {
174 case (int)CKM_DES_KEY_GEN:
175 if ((keySize != this.keySize) &&
176 (keySize != this.significantKeySize)) {
177 throw new InvalidParameterException
178 ("DES key length must be 56 bits");
179 }
180 break;
181 case (int)CKM_DES2_KEY_GEN:
182 case (int)CKM_DES3_KEY_GEN:
183 long newMechanism;
184 if ((keySize == 112) || (keySize == 128)) {
185 newMechanism = CKM_DES2_KEY_GEN;
186 } else if ((keySize == 168) || (keySize == 192)) {
187 newMechanism = CKM_DES3_KEY_GEN;
188 } else {
189 throw new InvalidParameterException
190 ("DESede key length must be 112, or 168 bits");
191 }
192 if (mechanism != newMechanism) {
193 if (supportBothKeySizes) {
194 mechanism = newMechanism;
195 setDefaultKeySize();
196 } else {
197 throw new InvalidParameterException
198 ("Only " + significantKeySize +
199 "-bit DESede key length is supported");
200 }
201 }
202 break;
203 case (int)CKM_AES_KEY_GEN:
204 if ((keySize != 128) && (keySize != 192) && (keySize != 256)) {
205 throw new InvalidParameterException
206 ("AES key length must be 128, 192, or 256 bits");
207 }
208 this.keySize = keySize;
209 significantKeySize = keySize;
210 break;
211 case (int)CKM_RC4_KEY_GEN:
212 case (int)CKM_BLOWFISH_KEY_GEN:
213 if ((keySize < minKeySize) || (keySize > maxKeySize)) {
214 throw new InvalidParameterException
215 (algorithm + " key length must be between " +
216 minKeySize + " and " + maxKeySize + " bits");
217 }
218 this.keySize = keySize;
219 this.significantKeySize = keySize;
220 break;
221 default:
222 throw new ProviderException("Unknown mechanism " + mechanism);
223 }
224 }
225
226 // see JCE spec
227 protected SecretKey engineGenerateKey() {
228 Session session = null;
229 try {
230 session = token.getObjSession();
231 CK_ATTRIBUTE[] attributes;
232 switch ((int)keyType) {
233 case (int)CKK_DES:
234 case (int)CKK_DES2:
235 case (int)CKK_DES3:
236 // fixed length, do not specify CKA_VALUE_LEN
237 attributes = new CK_ATTRIBUTE[] {
238 new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
239 };
240 break;
241 default:
242 attributes = new CK_ATTRIBUTE[] {
243 new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
244 new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),
245 };
246 break;
247 }
248 attributes = token.getAttributes
249 (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
250 long keyID = token.p11.C_GenerateKey
251 (session.id(), new CK_MECHANISM(mechanism), attributes);
252 return P11Key.secretKey
253 (session, keyID, algorithm, significantKeySize, attributes);
254 } catch (PKCS11Exception e) {
255 throw new ProviderException("Could not generate key", e);
256 } finally {
257 token.releaseSession(session);
258 }
259 }
260
261}