1 /*
2 * Copyright (c) 2003, 2015, 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 import java.security.spec.*;
31
32 import java.util.Locale;
33
34 import javax.crypto.*;
35 import javax.crypto.spec.*;
36
37 import static sun.security.pkcs11.TemplateManager.*;
38 import sun.security.pkcs11.wrapper.*;
39 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
40 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
41 import sun.security.util.KeyUtil;
42
43 /**
44 * RSA Cipher implementation class. We currently only support
45 * PKCS#1 v1.5 padding on top of CKM_RSA_PKCS.
46 *
47 * @author Andreas Sterbenz
48 * @since 1.5
49 */
50 final class P11RSACipher extends CipherSpi {
51
52 // minimum length of PKCS#1 v1.5 padding
53 private final static int PKCS1_MIN_PADDING_LENGTH = 11;
54
55 // constant byte[] of length 0
56 private final static byte[] B0 = new byte[0];
57
58 // mode constant for public key encryption
59 private final static int MODE_ENCRYPT = 1;
60 // mode constant for private key decryption
61 private final static int MODE_DECRYPT = 2;
62 // mode constant for private key encryption (signing)
63 private final static int MODE_SIGN = 3;
64 // mode constant for public key decryption (verifying)
65 private final static int MODE_VERIFY = 4;
66
67 // padding type constant for NoPadding
68 private final static int PAD_NONE = 1;
69 // padding type constant for PKCS1Padding
70 private final static int PAD_PKCS1 = 2;
71
72 // token instance
73 private final Token token;
74
75 // algorithm name (always "RSA")
76 private final String algorithm;
77
78 // mechanism id
79 private final long mechanism;
80
81 // associated session, if any
82 private Session session;
83
84 // mode, one of MODE_* above
85 private int mode;
86
87 // padding, one of PAD_* above
88 private int padType;
89
90 private byte[] buffer;
91 private int bufOfs;
92
93 // key, if init() was called
94 private P11Key p11Key;
95
96 // flag indicating whether an operation is initialized
97 private boolean initialized;
98
99 // maximum input data size allowed
100 // for decryption, this is the length of the key
101 // for encryption, length of the key minus minimum padding length
102 private int maxInputSize;
103
104 // maximum output size. this is the length of the key
105 private int outputSize;
106
107 // cipher parameter for TLS RSA premaster secret
108 private AlgorithmParameterSpec spec = null;
109
110 // the source of randomness
111 private SecureRandom random;
112
113 P11RSACipher(Token token, String algorithm, long mechanism)
114 throws PKCS11Exception {
115 super();
116 this.token = token;
117 this.algorithm = "RSA";
118 this.mechanism = mechanism;
119 }
120
121 // modes do not make sense for RSA, but allow ECB
122 // see JCE spec
123 protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
124 if (mode.equalsIgnoreCase("ECB") == false) {
125 throw new NoSuchAlgorithmException("Unsupported mode " + mode);
126 }
127 }
128
129 protected void engineSetPadding(String padding)
130 throws NoSuchPaddingException {
131 String lowerPadding = padding.toLowerCase(Locale.ENGLISH);
132 if (lowerPadding.equals("pkcs1padding")) {
133 padType = PAD_PKCS1;
134 } else if (lowerPadding.equals("nopadding")) {
135 padType = PAD_NONE;
136 } else {
137 throw new NoSuchPaddingException("Unsupported padding " + padding);
138 }
139 }
140
141 // return 0 as block size, we are not a block cipher
142 // see JCE spec
143 protected int engineGetBlockSize() {
144 return 0;
145 }
146
147 // return the output size
148 // see JCE spec
149 protected int engineGetOutputSize(int inputLen) {
150 return outputSize;
151 }
152
153 // no IV, return null
154 // see JCE spec
155 protected byte[] engineGetIV() {
156 return null;
157 }
158
159 // no parameters, return null
160 // see JCE spec
161 protected AlgorithmParameters engineGetParameters() {
162 return null;
163 }
164
165 // see JCE spec
166 protected void engineInit(int opmode, Key key, SecureRandom random)
167 throws InvalidKeyException {
168 implInit(opmode, key);
169 }
170
171 // see JCE spec
172 @SuppressWarnings("deprecation")
173 protected void engineInit(int opmode, Key key,
174 AlgorithmParameterSpec params, SecureRandom random)
175 throws InvalidKeyException, InvalidAlgorithmParameterException {
176 if (params != null) {
177 if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
178 throw new InvalidAlgorithmParameterException(
179 "Parameters not supported");
180 }
181 spec = params;
182 this.random = random; // for TLS RSA premaster secret
183 }
184 implInit(opmode, key);
185 }
186
187 // see JCE spec
188 protected void engineInit(int opmode, Key key, AlgorithmParameters params,
189 SecureRandom random)
190 throws InvalidKeyException, InvalidAlgorithmParameterException {
191 if (params != null) {
192 throw new InvalidAlgorithmParameterException(
193 "Parameters not supported");
194 }
195 implInit(opmode, key);
196 }
197
198 private void implInit(int opmode, Key key) throws InvalidKeyException {
199 cancelOperation();
200 p11Key = P11KeyFactory.convertKey(token, key, algorithm);
201 boolean encrypt;
202 if (opmode == Cipher.ENCRYPT_MODE) {
203 encrypt = true;
204 } else if (opmode == Cipher.DECRYPT_MODE) {
205 encrypt = false;
206 } else if (opmode == Cipher.WRAP_MODE) {
207 if (p11Key.isPublic() == false) {
208 throw new InvalidKeyException
209 ("Wrap has to be used with public keys");
210 }
211 // No further setup needed for C_Wrap(). We'll initialize later if
212 // we can't use C_Wrap().
213 return;
214 } else if (opmode == Cipher.UNWRAP_MODE) {
215 if (p11Key.isPrivate() == false) {
216 throw new InvalidKeyException
217 ("Unwrap has to be used with private keys");
218 }
219 // No further setup needed for C_Unwrap(). We'll initialize later
220 // if we can't use C_Unwrap().
221 return;
222 } else {
223 throw new InvalidKeyException("Unsupported mode: " + opmode);
224 }
225 if (p11Key.isPublic()) {
226 mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
227 } else if (p11Key.isPrivate()) {
228 mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
229 } else {
230 throw new InvalidKeyException("Unknown key type: " + p11Key);
231 }
232 int n = (p11Key.length() + 7) >> 3;
233 outputSize = n;
234 buffer = new byte[n];
235 maxInputSize = ((padType == PAD_PKCS1 && encrypt) ?
236 (n - PKCS1_MIN_PADDING_LENGTH) : n);
237 try {
238 initialize();
239 } catch (PKCS11Exception e) {
240 throw new InvalidKeyException("init() failed", e);
241 }
242 }
243
244 private void cancelOperation() {
245 token.ensureValid();
246 if (initialized == false) {
247 return;
248 }
249 initialized = false;
250 if ((session == null) || (token.explicitCancel == false)) {
251 return;
252 }
253 if (session.hasObjects() == false) {
254 session = token.killSession(session);
255 return;
256 }
257 try {
258 PKCS11 p11 = token.p11;
259 int inLen = maxInputSize;
260 int outLen = buffer.length;
261 switch (mode) {
262 case MODE_ENCRYPT:
263 p11.C_Encrypt
264 (session.id(), buffer, 0, inLen, buffer, 0, outLen);
265 break;
266 case MODE_DECRYPT:
267 p11.C_Decrypt
268 (session.id(), buffer, 0, inLen, buffer, 0, outLen);
269 break;
270 case MODE_SIGN:
271 byte[] tmpBuffer = new byte[maxInputSize];
272 p11.C_Sign
273 (session.id(), tmpBuffer);
274 break;
275 case MODE_VERIFY:
276 p11.C_VerifyRecover
277 (session.id(), buffer, 0, inLen, buffer, 0, outLen);
278 break;
279 default:
280 throw new ProviderException("internal error");
281 }
282 } catch (PKCS11Exception e) {
283 // XXX ensure this always works, ignore error
284 }
285 }
286
287 private void ensureInitialized() throws PKCS11Exception {
288 token.ensureValid();
289 if (initialized == false) {
290 initialize();
291 }
292 }
293
294 private void initialize() throws PKCS11Exception {
295 if (session == null) {
296 session = token.getOpSession();
297 }
298 PKCS11 p11 = token.p11;
299 CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
300 switch (mode) {
301 case MODE_ENCRYPT:
302 p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID);
303 break;
304 case MODE_DECRYPT:
305 p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID);
306 break;
307 case MODE_SIGN:
308 p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID);
309 break;
310 case MODE_VERIFY:
311 p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID);
312 break;
313 default:
314 throw new AssertionError("internal error");
315 }
316 bufOfs = 0;
317 initialized = true;
318 }
319
320 private void implUpdate(byte[] in, int inOfs, int inLen) {
321 try {
322 ensureInitialized();
323 } catch (PKCS11Exception e) {
324 throw new ProviderException("update() failed", e);
325 }
326 if ((inLen == 0) || (in == null)) {
327 return;
328 }
329 if (bufOfs + inLen > maxInputSize) {
330 bufOfs = maxInputSize + 1;
331 return;
332 }
333 System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
334 bufOfs += inLen;
335 }
336
337 private int implDoFinal(byte[] out, int outOfs, int outLen)
338 throws BadPaddingException, IllegalBlockSizeException {
339 if (bufOfs > maxInputSize) {
340 throw new IllegalBlockSizeException("Data must not be longer "
341 + "than " + maxInputSize + " bytes");
342 }
343 try {
344 ensureInitialized();
345 PKCS11 p11 = token.p11;
346 int n;
347 switch (mode) {
348 case MODE_ENCRYPT:
349 n = p11.C_Encrypt
350 (session.id(), buffer, 0, bufOfs, out, outOfs, outLen);
351 break;
352 case MODE_DECRYPT:
353 n = p11.C_Decrypt
354 (session.id(), buffer, 0, bufOfs, out, outOfs, outLen);
355 break;
356 case MODE_SIGN:
357 byte[] tmpBuffer = new byte[bufOfs];
358 System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs);
359 tmpBuffer = p11.C_Sign(session.id(), tmpBuffer);
360 if (tmpBuffer.length > outLen) {
361 throw new BadPaddingException(
362 "Output buffer (" + outLen + ") is too small to " +
363 "hold the produced data (" + tmpBuffer.length + ")");
364 }
365 System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length);
366 n = tmpBuffer.length;
367 break;
368 case MODE_VERIFY:
369 n = p11.C_VerifyRecover
370 (session.id(), buffer, 0, bufOfs, out, outOfs, outLen);
371 break;
372 default:
373 throw new ProviderException("internal error");
374 }
375 return n;
376 } catch (PKCS11Exception e) {
377 throw (BadPaddingException)new BadPaddingException
378 ("doFinal() failed").initCause(e);
379 } finally {
380 initialized = false;
381 session = token.releaseSession(session);
382 }
383 }
384
385 // see JCE spec
386 protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
387 implUpdate(in, inOfs, inLen);
388 return B0;
389 }
390
391 // see JCE spec
392 protected int engineUpdate(byte[] in, int inOfs, int inLen,
393 byte[] out, int outOfs) throws ShortBufferException {
394 implUpdate(in, inOfs, inLen);
395 return 0;
396 }
397
398 // see JCE spec
399 protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
400 throws IllegalBlockSizeException, BadPaddingException {
401 implUpdate(in, inOfs, inLen);
402 int n = implDoFinal(buffer, 0, buffer.length);
403 byte[] out = new byte[n];
404 System.arraycopy(buffer, 0, out, 0, n);
405 return out;
406 }
407
408 // see JCE spec
409 protected int engineDoFinal(byte[] in, int inOfs, int inLen,
410 byte[] out, int outOfs) throws ShortBufferException,
411 IllegalBlockSizeException, BadPaddingException {
412 implUpdate(in, inOfs, inLen);
413 return implDoFinal(out, outOfs, out.length - outOfs);
414 }
415
416 private byte[] doFinal() throws BadPaddingException,
417 IllegalBlockSizeException {
418 byte[] t = new byte[2048];
419 int n = implDoFinal(t, 0, t.length);
420 byte[] out = new byte[n];
421 System.arraycopy(t, 0, out, 0, n);
422 return out;
423 }
424
425 // see JCE spec
426 protected byte[] engineWrap(Key key) throws InvalidKeyException,
427 IllegalBlockSizeException {
428 String keyAlg = key.getAlgorithm();
429 P11Key sKey = null;
430 try {
431 // The conversion may fail, e.g. trying to wrap an AES key on
432 // a token that does not support AES, or when the key size is
433 // not within the range supported by the token.
434 sKey = P11SecretKeyFactory.convertKey(token, key, keyAlg);
435 } catch (InvalidKeyException ike) {
436 byte[] toBeWrappedKey = key.getEncoded();
437 if (toBeWrappedKey == null) {
438 throw new InvalidKeyException
439 ("wrap() failed, no encoding available", ike);
440 }
441 // Directly encrypt the key encoding when key conversion failed
442 implInit(Cipher.ENCRYPT_MODE, p11Key);
443 implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length);
444 try {
445 return doFinal();
446 } catch (BadPaddingException bpe) {
447 // should not occur
448 throw new InvalidKeyException("wrap() failed", bpe);
449 } finally {
450 // Restore original mode
451 implInit(Cipher.WRAP_MODE, p11Key);
452 }
453 }
454 Session s = null;
455 try {
456 s = token.getOpSession();
457 return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
458 p11Key.keyID, sKey.keyID);
459 } catch (PKCS11Exception e) {
460 throw new InvalidKeyException("wrap() failed", e);
461 } finally {
462 token.releaseSession(s);
463 }
464 }
465
466 // see JCE spec
467 @SuppressWarnings("deprecation")
468 protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
469 int type) throws InvalidKeyException, NoSuchAlgorithmException {
470
471 boolean isTlsRsaPremasterSecret =
472 algorithm.equals("TlsRsaPremasterSecret");
473 Exception failover = null;
474
475 // Should C_Unwrap be preferred for non-TLS RSA premaster secret?
476 if (token.supportsRawSecretKeyImport()) {
477 // XXX implement unwrap using C_Unwrap() for all keys
478 implInit(Cipher.DECRYPT_MODE, p11Key);
479 try {
480 if (wrappedKey.length > maxInputSize) {
481 throw new InvalidKeyException("Key is too long for unwrapping");
482 }
483
484 byte[] encoded = null;
485 implUpdate(wrappedKey, 0, wrappedKey.length);
486 try {
487 encoded = doFinal();
488 } catch (BadPaddingException e) {
489 if (isTlsRsaPremasterSecret) {
490 failover = e;
491 } else {
492 throw new InvalidKeyException("Unwrapping failed", e);
493 }
494 } catch (IllegalBlockSizeException e) {
495 // should not occur, handled with length check above
496 throw new InvalidKeyException("Unwrapping failed", e);
497 }
498
499 if (isTlsRsaPremasterSecret) {
500 if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
501 throw new IllegalStateException(
502 "No TlsRsaPremasterSecretParameterSpec specified");
503 }
504
505 // polish the TLS premaster secret
506 TlsRsaPremasterSecretParameterSpec psps =
507 (TlsRsaPremasterSecretParameterSpec)spec;
508 encoded = KeyUtil.checkTlsPreMasterSecretKey(
509 psps.getClientVersion(), psps.getServerVersion(),
510 random, encoded, (failover != null));
511 }
512
513 return ConstructKeys.constructKey(encoded, algorithm, type);
514 } finally {
515 // Restore original mode
516 implInit(Cipher.UNWRAP_MODE, p11Key);
517 }
518 } else {
519 Session s = null;
520 SecretKey secretKey = null;
521 try {
522 try {
523 s = token.getObjSession();
524 long keyType = CKK_GENERIC_SECRET;
525 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
526 new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
527 new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
528 };
529 attributes = token.getAttributes(
530 O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
531 long keyID = token.p11.C_UnwrapKey(s.id(),
532 new CK_MECHANISM(mechanism), p11Key.keyID,
533 wrappedKey, attributes);
534 secretKey = P11Key.secretKey(s, keyID,
535 algorithm, 48 << 3, attributes);
536 } catch (PKCS11Exception e) {
537 if (isTlsRsaPremasterSecret) {
538 failover = e;
539 } else {
540 throw new InvalidKeyException("unwrap() failed", e);
541 }
542 }
543
544 if (isTlsRsaPremasterSecret) {
545 TlsRsaPremasterSecretParameterSpec psps =
546 (TlsRsaPremasterSecretParameterSpec)spec;
547
548 // Please use the tricky failover as the parameter so that
549 // smart compiler won't dispose the unused variable.
550 secretKey = polishPreMasterSecretKey(token, s,
551 failover, secretKey,
552 psps.getClientVersion(), psps.getServerVersion());
553 }
554
555 return secretKey;
556 } finally {
557 token.releaseSession(s);
558 }
559 }
560 }
561
562 // see JCE spec
563 protected int engineGetKeySize(Key key) throws InvalidKeyException {
564 int n = P11KeyFactory.convertKey(token, key, algorithm).length();
565 return n;
566 }
567
568 private static SecretKey polishPreMasterSecretKey(
569 Token token, Session session,
570 Exception failover, SecretKey unwrappedKey,
571 int clientVersion, int serverVersion) {
572
573 SecretKey newKey;
574 CK_VERSION version = new CK_VERSION(
575 (clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
576 try {
577 CK_ATTRIBUTE[] attributes = token.getAttributes(
578 O_GENERATE, CKO_SECRET_KEY,
579 CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
580 long keyID = token.p11.C_GenerateKey(session.id(),
581 new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
582 attributes);
583 newKey = P11Key.secretKey(session,
584 keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
585 } catch (PKCS11Exception e) {
586 throw new ProviderException(
587 "Could not generate premaster secret", e);
588 }
589
590 return (failover == null) ? unwrappedKey : newKey;
591 }
592
593 }
594
595 final class ConstructKeys {
596 /**
597 * Construct a public key from its encoding.
598 *
599 * @param encodedKey the encoding of a public key.
600 *
601 * @param encodedKeyAlgorithm the algorithm the encodedKey is for.
602 *
603 * @return a public key constructed from the encodedKey.
604 */
605 private static final PublicKey constructPublicKey(byte[] encodedKey,
606 String encodedKeyAlgorithm)
607 throws InvalidKeyException, NoSuchAlgorithmException {
608 try {
609 KeyFactory keyFactory =
610 KeyFactory.getInstance(encodedKeyAlgorithm);
611 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
612 return keyFactory.generatePublic(keySpec);
613 } catch (NoSuchAlgorithmException nsae) {
614 throw new NoSuchAlgorithmException("No installed providers " +
615 "can create keys for the " +
616 encodedKeyAlgorithm +
617 "algorithm", nsae);
618 } catch (InvalidKeySpecException ike) {
619 throw new InvalidKeyException("Cannot construct public key", ike);
620 }
621 }
622
623 /**
624 * Construct a private key from its encoding.
625 *
626 * @param encodedKey the encoding of a private key.
627 *
628 * @param encodedKeyAlgorithm the algorithm the wrapped key is for.
629 *
630 * @return a private key constructed from the encodedKey.
631 */
632 private static final PrivateKey constructPrivateKey(byte[] encodedKey,
633 String encodedKeyAlgorithm) throws InvalidKeyException,
634 NoSuchAlgorithmException {
635 try {
636 KeyFactory keyFactory =
637 KeyFactory.getInstance(encodedKeyAlgorithm);
638 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
639 return keyFactory.generatePrivate(keySpec);
640 } catch (NoSuchAlgorithmException nsae) {
641 throw new NoSuchAlgorithmException("No installed providers " +
642 "can create keys for the " +
643 encodedKeyAlgorithm +
644 "algorithm", nsae);
645 } catch (InvalidKeySpecException ike) {
646 throw new InvalidKeyException("Cannot construct private key", ike);
647 }
648 }
649
650 /**
651 * Construct a secret key from its encoding.
652 *
653 * @param encodedKey the encoding of a secret key.
654 *
655 * @param encodedKeyAlgorithm the algorithm the secret key is for.
656 *
657 * @return a secret key constructed from the encodedKey.
658 */
659 private static final SecretKey constructSecretKey(byte[] encodedKey,
660 String encodedKeyAlgorithm) {
661 return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
662 }
663
664 static final Key constructKey(byte[] encoding, String keyAlgorithm,
665 int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
666 switch (keyType) {
667 case Cipher.SECRET_KEY:
668 return constructSecretKey(encoding, keyAlgorithm);
669 case Cipher.PRIVATE_KEY:
670 return constructPrivateKey(encoding, keyAlgorithm);
671 case Cipher.PUBLIC_KEY:
672 return constructPublicKey(encoding, keyAlgorithm);
673 default:
674 throw new InvalidKeyException("Unknown keytype " + keyType);
675 }
676 }
677 }