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