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)
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);
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");
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;
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 */
|
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 reset(true);
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 ensureInitialized();
239 } catch (PKCS11Exception e) {
240 throw new InvalidKeyException("init() failed", e);
241 }
242 }
243
244 // reset the states to the pre-initialized values
245 private void reset(boolean doCancel) {
246 if (!initialized) {
247 return;
248 }
249 initialized = false;
250 try {
251 if (session == null) {
252 return;
253 }
254 if (doCancel && token.explicitCancel) {
255 cancelOperation();
256 }
257 } finally {
258 p11Key.decNativeKeyRef();
259 session = token.releaseSession(session);
260 }
261 }
262
263 private void cancelOperation() {
264 token.ensureValid();
265 if (session.hasObjects() == false) {
266 session = token.killSession(session);
267 return;
268 } else {
269 try {
270 PKCS11 p11 = token.p11;
271 int inLen = maxInputSize;
272 int outLen = buffer.length;
273 switch (mode) {
274 case MODE_ENCRYPT:
275 p11.C_Encrypt(session.id(), buffer, 0, inLen, buffer, 0,
276 outLen);
277 break;
278 case MODE_DECRYPT:
279 p11.C_Decrypt(session.id(), buffer, 0, inLen, buffer, 0,
280 outLen);
281 break;
282 case MODE_SIGN:
283 byte[] tmpBuffer = new byte[maxInputSize];
284 p11.C_Sign
285 (session.id(), tmpBuffer);
286 break;
287 case MODE_VERIFY:
288 p11.C_VerifyRecover(session.id(), buffer, 0, inLen, buffer,
289 0, outLen);
290 break;
291 default:
292 throw new ProviderException("internal error");
293 }
294 } catch (PKCS11Exception e) {
295 // XXX ensure this always works, ignore error
296 }
297 }
298 }
299
300 private void ensureInitialized() throws PKCS11Exception {
301 if (initialized) {
302 return;
303 }
304 if (p11Key == null) {
305 throw new ProviderException(
306 "Operation cannot be performed without " +
307 "calling engineInit first");
308 }
309 token.ensureValid();
310 p11Key.incNativeKeyRef();
311 try {
312 if (session == null) {
313 session = token.getOpSession();
314 }
315 PKCS11 p11 = token.p11;
316 CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
317 switch (mode) {
318 case MODE_ENCRYPT:
319 p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID);
320 break;
321 case MODE_DECRYPT:
322 p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID);
323 break;
324 case MODE_SIGN:
325 p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID);
326 break;
327 case MODE_VERIFY:
328 p11.C_VerifyRecoverInit(session.id(), ckMechanism,
329 p11Key.keyID);
330 break;
331 default:
332 throw new AssertionError("internal error");
333 }
334 } catch (Throwable t) {
335 p11Key.decNativeKeyRef();
336 session = token.releaseSession(session);
337 throw t;
338 }
339 initialized = true;
340 bufOfs = 0;
341 }
342
343 private void implUpdate(byte[] in, int inOfs, int inLen) {
344 try {
345 ensureInitialized();
346 } catch (PKCS11Exception e) {
347 throw new ProviderException("update() failed", e);
348 }
349 if ((inLen == 0) || (in == null)) {
350 return;
351 }
352 if (bufOfs + inLen > maxInputSize) {
353 bufOfs = maxInputSize + 1;
354 return;
355 }
356 System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
357 bufOfs += inLen;
358 }
359
360 private int implDoFinal(byte[] out, int outOfs, int outLen)
383 if (tmpBuffer.length > outLen) {
384 throw new BadPaddingException(
385 "Output buffer (" + outLen + ") is too small to " +
386 "hold the produced data (" + tmpBuffer.length + ")");
387 }
388 System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length);
389 n = tmpBuffer.length;
390 break;
391 case MODE_VERIFY:
392 n = p11.C_VerifyRecover
393 (session.id(), buffer, 0, bufOfs, out, outOfs, outLen);
394 break;
395 default:
396 throw new ProviderException("internal error");
397 }
398 return n;
399 } catch (PKCS11Exception e) {
400 throw (BadPaddingException)new BadPaddingException
401 ("doFinal() failed").initCause(e);
402 } finally {
403 reset(false);
404 }
405 }
406
407 // see JCE spec
408 protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
409 implUpdate(in, inOfs, inLen);
410 return B0;
411 }
412
413 // see JCE spec
414 protected int engineUpdate(byte[] in, int inOfs, int inLen,
415 byte[] out, int outOfs) throws ShortBufferException {
416 implUpdate(in, inOfs, inLen);
417 return 0;
418 }
419
420 // see JCE spec
421 protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
422 throws IllegalBlockSizeException, BadPaddingException {
423 implUpdate(in, inOfs, inLen);
459 if (toBeWrappedKey == null) {
460 throw new InvalidKeyException
461 ("wrap() failed, no encoding available", ike);
462 }
463 // Directly encrypt the key encoding when key conversion failed
464 implInit(Cipher.ENCRYPT_MODE, p11Key);
465 implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length);
466 try {
467 return doFinal();
468 } catch (BadPaddingException bpe) {
469 // should not occur
470 throw new InvalidKeyException("wrap() failed", bpe);
471 } finally {
472 // Restore original mode
473 implInit(Cipher.WRAP_MODE, p11Key);
474 }
475 }
476 Session s = null;
477 try {
478 s = token.getOpSession();
479 p11Key.incNativeKeyRef();
480 sKey.incNativeKeyRef();
481 return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
482 p11Key.keyID, sKey.keyID);
483 } catch (PKCS11Exception e) {
484 throw new InvalidKeyException("wrap() failed", e);
485 } finally {
486 p11Key.decNativeKeyRef();
487 sKey.decNativeKeyRef();
488 token.releaseSession(s);
489 }
490 }
491
492 // see JCE spec
493 @SuppressWarnings("deprecation")
494 protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
495 int type) throws InvalidKeyException, NoSuchAlgorithmException {
496
497 boolean isTlsRsaPremasterSecret =
498 algorithm.equals("TlsRsaPremasterSecret");
499 Exception failover = null;
500
501 // Should C_Unwrap be preferred for non-TLS RSA premaster secret?
502 if (token.supportsRawSecretKeyImport()) {
503 // XXX implement unwrap using C_Unwrap() for all keys
504 implInit(Cipher.DECRYPT_MODE, p11Key);
505 try {
506 if (wrappedKey.length > maxInputSize) {
507 throw new InvalidKeyException("Key is too long for unwrapping");
537 }
538
539 return ConstructKeys.constructKey(encoded, algorithm, type);
540 } finally {
541 // Restore original mode
542 implInit(Cipher.UNWRAP_MODE, p11Key);
543 }
544 } else {
545 Session s = null;
546 SecretKey secretKey = null;
547 try {
548 try {
549 s = token.getObjSession();
550 long keyType = CKK_GENERIC_SECRET;
551 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
552 new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
553 new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
554 };
555 attributes = token.getAttributes(
556 O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
557 p11Key.incNativeKeyRef();
558 long keyID;
559 try {
560 keyID = token.p11.C_UnwrapKey(s.id(),
561 new CK_MECHANISM(mechanism), p11Key.keyID,
562 wrappedKey, attributes);
563 } finally {
564 p11Key.decNativeKeyRef();
565 }
566 secretKey = P11Key.secretKey(s, keyID,
567 algorithm, 48 << 3, attributes, true);
568 } catch (PKCS11Exception e) {
569 if (isTlsRsaPremasterSecret) {
570 failover = e;
571 } else {
572 throw new InvalidKeyException("unwrap() failed", e);
573 }
574 }
575
576 if (isTlsRsaPremasterSecret) {
577 TlsRsaPremasterSecretParameterSpec psps =
578 (TlsRsaPremasterSecretParameterSpec)spec;
579
580 // Please use the tricky failover as the parameter so that
581 // smart compiler won't dispose the unused variable.
582 secretKey = polishPreMasterSecretKey(token, s,
583 failover, secretKey,
584 psps.getClientVersion(), psps.getServerVersion());
585 }
586
587 return secretKey;
595 protected int engineGetKeySize(Key key) throws InvalidKeyException {
596 int n = P11KeyFactory.convertKey(token, key, algorithm).length();
597 return n;
598 }
599
600 private static SecretKey polishPreMasterSecretKey(
601 Token token, Session session,
602 Exception failover, SecretKey unwrappedKey,
603 int clientVersion, int serverVersion) {
604
605 SecretKey newKey;
606 CK_VERSION version = new CK_VERSION(
607 (clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
608 try {
609 CK_ATTRIBUTE[] attributes = token.getAttributes(
610 O_GENERATE, CKO_SECRET_KEY,
611 CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
612 long keyID = token.p11.C_GenerateKey(session.id(),
613 new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
614 attributes);
615 newKey = P11Key.secretKey(session, keyID,
616 "TlsRsaPremasterSecret", 48 << 3, attributes, true);
617 } catch (PKCS11Exception e) {
618 throw new ProviderException(
619 "Could not generate premaster secret", e);
620 }
621
622 return (failover == null) ? unwrappedKey : newKey;
623 }
624
625 }
626
627 final class ConstructKeys {
628 /**
629 * Construct a public key from its encoding.
630 *
631 * @param encodedKey the encoding of a public key.
632 *
633 * @param encodedKeyAlgorithm the algorithm the encodedKey is for.
634 *
635 * @return a public key constructed from the encodedKey.
636 */
|