327 byte[] ivValue;
328 if (params != null) {
329 try {
330 IvParameterSpec ivSpec =
331 params.getParameterSpec(IvParameterSpec.class);
332 ivValue = ivSpec.getIV();
333 } catch (InvalidParameterSpecException e) {
334 throw new InvalidAlgorithmParameterException
335 ("Could not decode IV", e);
336 }
337 } else {
338 ivValue = null;
339 }
340 implInit(opmode, key, ivValue, random);
341 }
342
343 // actual init() implementation
344 private void implInit(int opmode, Key key, byte[] iv,
345 SecureRandom random)
346 throws InvalidKeyException, InvalidAlgorithmParameterException {
347 cancelOperation();
348 if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
349 throw new InvalidKeyException("Key size is invalid");
350 }
351 switch (opmode) {
352 case Cipher.ENCRYPT_MODE:
353 encrypt = true;
354 break;
355 case Cipher.DECRYPT_MODE:
356 encrypt = false;
357 break;
358 default:
359 throw new InvalidAlgorithmParameterException
360 ("Unsupported mode: " + opmode);
361 }
362 if (blockMode == MODE_ECB) { // ECB or stream cipher
363 if (iv != null) {
364 if (blockSize == 0) {
365 throw new InvalidAlgorithmParameterException
366 ("IV not used with stream ciphers");
367 } else {
387 } else {
388 if (iv.length != blockSize) {
389 throw new InvalidAlgorithmParameterException
390 ("IV length must match block size");
391 }
392 }
393 }
394 this.iv = iv;
395 p11Key = P11SecretKeyFactory.convertKey(token, key, keyAlgorithm);
396 try {
397 initialize();
398 } catch (PKCS11Exception e) {
399 throw new InvalidKeyException("Could not initialize cipher", e);
400 }
401 }
402
403 private void cancelOperation() {
404 if (initialized == false) {
405 return;
406 }
407 initialized = false;
408 if ((session == null) || (token.explicitCancel == false)) {
409 return;
410 }
411 // cancel operation by finishing it
412 int bufLen = doFinalLength(0);
413 byte[] buffer = new byte[bufLen];
414 try {
415 if (encrypt) {
416 token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
417 } else {
418 token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
419 }
420 } catch (PKCS11Exception e) {
421 throw new ProviderException("Cancel failed", e);
422 } finally {
423 reset();
424 }
425 }
426
427 private void ensureInitialized() throws PKCS11Exception {
428 if (initialized == false) {
429 initialize();
430 }
431 }
432
433 private void initialize() throws PKCS11Exception {
434 if (session == null) {
435 session = token.getOpSession();
436 }
437 CK_MECHANISM mechParams = (blockMode == MODE_CTR?
438 new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
439 new CK_MECHANISM(mechanism, iv));
440
441 try {
442 if (encrypt) {
443 token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
466 result -= (result & (blockSize - 1));
467 }
468 return result;
469 }
470
471 // if doFinal(inLen) is called, how big does the output buffer have to be?
472 private int doFinalLength(int inLen) {
473 if (inLen < 0) {
474 return 0;
475 }
476
477 int result = inLen + bytesBuffered;
478 if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
479 // add the number of bytes to make the last block complete.
480 result += (blockSize - (result & (blockSize - 1)));
481 }
482 return result;
483 }
484
485 // reset the states to the pre-initialized values
486 private void reset() {
487 initialized = false;
488 bytesBuffered = 0;
489 padBufferLen = 0;
490 if (session != null) {
491 session = token.releaseSession(session);
492 }
493 }
494
495 // see JCE spec
496 protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
497 try {
498 byte[] out = new byte[updateLength(inLen)];
499 int n = engineUpdate(in, inOfs, inLen, out, 0);
500 return P11Util.convert(out, 0, n);
501 } catch (ShortBufferException e) {
502 // convert since the output length is calculated by updateLength()
503 throw new ProviderException(e);
504 }
505 }
506
593 newPadBufferLen = padBuffer.length;
594 }
595 inLen -= newPadBufferLen;
596 }
597 if (inLen > 0) {
598 k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
599 inLen, 0, out, (outOfs + k), (outLen - k));
600 }
601 // update 'padBuffer' if using our own padding impl.
602 if (paddingObj != null) {
603 bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
604 }
605 }
606 bytesBuffered += (inLen - k);
607 return k;
608 } catch (PKCS11Exception e) {
609 if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
610 throw (ShortBufferException)
611 (new ShortBufferException().initCause(e));
612 }
613 reset();
614 throw new ProviderException("update() failed", e);
615 }
616 }
617
618 private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
619 throws ShortBufferException {
620 int inLen = inBuffer.remaining();
621 if (inLen <= 0) {
622 return 0;
623 }
624
625 int outLen = outBuffer.remaining();
626 if (outLen < updateLength(inLen)) {
627 throw new ShortBufferException();
628 }
629 int origPos = inBuffer.position();
630 try {
631 ensureInitialized();
632
633 long inAddr = 0;
711 // update 'padBuffer' if using our own padding impl.
712 if (paddingObj != null && newPadBufferLen != 0) {
713 bufferInputBytes(inBuffer, newPadBufferLen);
714 }
715 }
716 bytesBuffered += (inLen - k);
717 if (!(outBuffer instanceof DirectBuffer) &&
718 !outBuffer.hasArray()) {
719 outBuffer.put(outArray, outOfs, k);
720 } else {
721 outBuffer.position(outBuffer.position() + k);
722 }
723 return k;
724 } catch (PKCS11Exception e) {
725 // Reset input buffer to its original position for
726 inBuffer.position(origPos);
727 if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
728 throw (ShortBufferException)
729 (new ShortBufferException().initCause(e));
730 }
731 reset();
732 throw new ProviderException("update() failed", e);
733 }
734 }
735
736 private int implDoFinal(byte[] out, int outOfs, int outLen)
737 throws ShortBufferException, IllegalBlockSizeException,
738 BadPaddingException {
739 int requiredOutLen = doFinalLength(0);
740 if (outLen < requiredOutLen) {
741 throw new ShortBufferException();
742 }
743 try {
744 ensureInitialized();
745 int k = 0;
746 if (encrypt) {
747 if (paddingObj != null) {
748 int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
749 requiredOutLen - bytesBuffered);
750 k = token.p11.C_EncryptUpdate(session.id(),
751 0, padBuffer, 0, actualPadLen,
752 0, out, outOfs, outLen);
753 }
754 k += token.p11.C_EncryptFinal(session.id(),
755 0, out, (outOfs + k), (outLen - k));
756 } else {
757 if (paddingObj != null) {
758 if (padBufferLen != 0) {
759 k = token.p11.C_DecryptUpdate(session.id(), 0,
760 padBuffer, 0, padBufferLen, 0, padBuffer, 0,
761 padBuffer.length);
762 }
763 k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
764 padBuffer.length - k);
765 int actualPadLen = paddingObj.unpad(padBuffer, k);
766 k -= actualPadLen;
767 System.arraycopy(padBuffer, 0, out, outOfs, k);
768 } else {
769 k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
770 outLen);
771 }
772 }
773 return k;
774 } catch (PKCS11Exception e) {
775 handleException(e);
776 throw new ProviderException("doFinal() failed", e);
777 } finally {
778 reset();
779 }
780 }
781
782 private int implDoFinal(ByteBuffer outBuffer)
783 throws ShortBufferException, IllegalBlockSizeException,
784 BadPaddingException {
785 int outLen = outBuffer.remaining();
786 int requiredOutLen = doFinalLength(0);
787 if (outLen < requiredOutLen) {
788 throw new ShortBufferException();
789 }
790
791 try {
792 ensureInitialized();
793
794 long outAddr = 0;
795 byte[] outArray = null;
796 int outOfs = 0;
797 if (outBuffer instanceof DirectBuffer) {
798 outAddr = ((DirectBuffer) outBuffer).address();
799 outOfs = outBuffer.position();
800 } else {
801 if (outBuffer.hasArray()) {
802 outArray = outBuffer.array();
803 outOfs = outBuffer.position() + outBuffer.arrayOffset();
804 } else {
805 outArray = new byte[outLen];
806 }
807 }
808
809 int k = 0;
810
811 if (encrypt) {
812 if (paddingObj != null) {
813 int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
814 requiredOutLen - bytesBuffered);
815 k = token.p11.C_EncryptUpdate(session.id(),
816 0, padBuffer, 0, actualPadLen,
817 outAddr, outArray, outOfs, outLen);
818 }
819 k += token.p11.C_EncryptFinal(session.id(),
820 outAddr, outArray, (outOfs + k), (outLen - k));
821 } else {
822 if (paddingObj != null) {
823 if (padBufferLen != 0) {
824 k = token.p11.C_DecryptUpdate(session.id(),
825 0, padBuffer, 0, padBufferLen,
826 0, padBuffer, 0, padBuffer.length);
827 padBufferLen = 0;
828 }
829 k += token.p11.C_DecryptFinal(session.id(),
830 0, padBuffer, k, padBuffer.length - k);
831 int actualPadLen = paddingObj.unpad(padBuffer, k);
832 k -= actualPadLen;
833 outArray = padBuffer;
834 outOfs = 0;
835 } else {
836 k = token.p11.C_DecryptFinal(session.id(),
837 outAddr, outArray, outOfs, outLen);
838 }
839 }
840 if ((!encrypt && paddingObj != null) ||
841 (!(outBuffer instanceof DirectBuffer) &&
842 !outBuffer.hasArray())) {
843 outBuffer.put(outArray, outOfs, k);
844 } else {
845 outBuffer.position(outBuffer.position() + k);
846 }
847 return k;
848 } catch (PKCS11Exception e) {
849 handleException(e);
850 throw new ProviderException("doFinal() failed", e);
851 } finally {
852 reset();
853 }
854 }
855
856 private void handleException(PKCS11Exception e)
857 throws ShortBufferException, IllegalBlockSizeException {
858 long errorCode = e.getErrorCode();
859 if (errorCode == CKR_BUFFER_TOO_SMALL) {
860 throw (ShortBufferException)
861 (new ShortBufferException().initCause(e));
862 } else if (errorCode == CKR_DATA_LEN_RANGE ||
863 errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
864 throw (IllegalBlockSizeException)
865 (new IllegalBlockSizeException(e.toString()).initCause(e));
866 }
867 }
868
869 // see JCE spec
870 protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
871 InvalidKeyException {
872 // XXX key wrapping
|
327 byte[] ivValue;
328 if (params != null) {
329 try {
330 IvParameterSpec ivSpec =
331 params.getParameterSpec(IvParameterSpec.class);
332 ivValue = ivSpec.getIV();
333 } catch (InvalidParameterSpecException e) {
334 throw new InvalidAlgorithmParameterException
335 ("Could not decode IV", e);
336 }
337 } else {
338 ivValue = null;
339 }
340 implInit(opmode, key, ivValue, random);
341 }
342
343 // actual init() implementation
344 private void implInit(int opmode, Key key, byte[] iv,
345 SecureRandom random)
346 throws InvalidKeyException, InvalidAlgorithmParameterException {
347 reset(true);
348 if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
349 throw new InvalidKeyException("Key size is invalid");
350 }
351 switch (opmode) {
352 case Cipher.ENCRYPT_MODE:
353 encrypt = true;
354 break;
355 case Cipher.DECRYPT_MODE:
356 encrypt = false;
357 break;
358 default:
359 throw new InvalidAlgorithmParameterException
360 ("Unsupported mode: " + opmode);
361 }
362 if (blockMode == MODE_ECB) { // ECB or stream cipher
363 if (iv != null) {
364 if (blockSize == 0) {
365 throw new InvalidAlgorithmParameterException
366 ("IV not used with stream ciphers");
367 } else {
387 } else {
388 if (iv.length != blockSize) {
389 throw new InvalidAlgorithmParameterException
390 ("IV length must match block size");
391 }
392 }
393 }
394 this.iv = iv;
395 p11Key = P11SecretKeyFactory.convertKey(token, key, keyAlgorithm);
396 try {
397 initialize();
398 } catch (PKCS11Exception e) {
399 throw new InvalidKeyException("Could not initialize cipher", e);
400 }
401 }
402
403 private void cancelOperation() {
404 if (initialized == false) {
405 return;
406 }
407
408 if ((session == null) || (token.explicitCancel == false)) {
409 return;
410 }
411 try {
412 if (session.hasObjects() == false) {
413 session = token.killSession(session);
414 return;
415 } else {
416 // cancel operation by finishing it
417 int bufLen = doFinalLength(0);
418 byte[] buffer = new byte[bufLen];
419 if (encrypt) {
420 token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
421 } else {
422 token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
423 }
424 }
425 } catch (PKCS11Exception e) {
426 throw new ProviderException("Cancel failed", e);
427 }
428 }
429
430 private void ensureInitialized() throws PKCS11Exception {
431 if (initialized == false) {
432 initialize();
433 }
434 }
435
436 private void initialize() throws PKCS11Exception {
437 if (session == null) {
438 session = token.getOpSession();
439 }
440 CK_MECHANISM mechParams = (blockMode == MODE_CTR?
441 new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
442 new CK_MECHANISM(mechanism, iv));
443
444 try {
445 if (encrypt) {
446 token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
469 result -= (result & (blockSize - 1));
470 }
471 return result;
472 }
473
474 // if doFinal(inLen) is called, how big does the output buffer have to be?
475 private int doFinalLength(int inLen) {
476 if (inLen < 0) {
477 return 0;
478 }
479
480 int result = inLen + bytesBuffered;
481 if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
482 // add the number of bytes to make the last block complete.
483 result += (blockSize - (result & (blockSize - 1)));
484 }
485 return result;
486 }
487
488 // reset the states to the pre-initialized values
489 private void reset(boolean doCancel) {
490 if (doCancel) cancelOperation();
491
492 initialized = false;
493 bytesBuffered = 0;
494 padBufferLen = 0;
495 if (session != null) {
496 session = token.releaseSession(session);
497 }
498 }
499
500 // see JCE spec
501 protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
502 try {
503 byte[] out = new byte[updateLength(inLen)];
504 int n = engineUpdate(in, inOfs, inLen, out, 0);
505 return P11Util.convert(out, 0, n);
506 } catch (ShortBufferException e) {
507 // convert since the output length is calculated by updateLength()
508 throw new ProviderException(e);
509 }
510 }
511
598 newPadBufferLen = padBuffer.length;
599 }
600 inLen -= newPadBufferLen;
601 }
602 if (inLen > 0) {
603 k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
604 inLen, 0, out, (outOfs + k), (outLen - k));
605 }
606 // update 'padBuffer' if using our own padding impl.
607 if (paddingObj != null) {
608 bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
609 }
610 }
611 bytesBuffered += (inLen - k);
612 return k;
613 } catch (PKCS11Exception e) {
614 if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
615 throw (ShortBufferException)
616 (new ShortBufferException().initCause(e));
617 }
618 reset(false);
619 throw new ProviderException("update() failed", e);
620 }
621 }
622
623 private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
624 throws ShortBufferException {
625 int inLen = inBuffer.remaining();
626 if (inLen <= 0) {
627 return 0;
628 }
629
630 int outLen = outBuffer.remaining();
631 if (outLen < updateLength(inLen)) {
632 throw new ShortBufferException();
633 }
634 int origPos = inBuffer.position();
635 try {
636 ensureInitialized();
637
638 long inAddr = 0;
716 // update 'padBuffer' if using our own padding impl.
717 if (paddingObj != null && newPadBufferLen != 0) {
718 bufferInputBytes(inBuffer, newPadBufferLen);
719 }
720 }
721 bytesBuffered += (inLen - k);
722 if (!(outBuffer instanceof DirectBuffer) &&
723 !outBuffer.hasArray()) {
724 outBuffer.put(outArray, outOfs, k);
725 } else {
726 outBuffer.position(outBuffer.position() + k);
727 }
728 return k;
729 } catch (PKCS11Exception e) {
730 // Reset input buffer to its original position for
731 inBuffer.position(origPos);
732 if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
733 throw (ShortBufferException)
734 (new ShortBufferException().initCause(e));
735 }
736 reset(false);
737 throw new ProviderException("update() failed", e);
738 }
739 }
740
741 private int implDoFinal(byte[] out, int outOfs, int outLen)
742 throws ShortBufferException, IllegalBlockSizeException,
743 BadPaddingException {
744 int requiredOutLen = doFinalLength(0);
745 if (outLen < requiredOutLen) {
746 throw new ShortBufferException();
747 }
748 boolean doCancel = true;
749 try {
750 ensureInitialized();
751 int k = 0;
752 if (encrypt) {
753 if (paddingObj != null) {
754 int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
755 requiredOutLen - bytesBuffered);
756 k = token.p11.C_EncryptUpdate(session.id(),
757 0, padBuffer, 0, actualPadLen,
758 0, out, outOfs, outLen);
759 }
760 k += token.p11.C_EncryptFinal(session.id(),
761 0, out, (outOfs + k), (outLen - k));
762 doCancel = false;
763 } else {
764 // Special handling to match SunJCE provider behavior
765 if (bytesBuffered == 0 && padBufferLen == 0) {
766 return 0;
767 }
768 if (paddingObj != null) {
769 if (padBufferLen != 0) {
770 k = token.p11.C_DecryptUpdate(session.id(), 0,
771 padBuffer, 0, padBufferLen, 0, padBuffer, 0,
772 padBuffer.length);
773 }
774 k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
775 padBuffer.length - k);
776 doCancel = false;
777
778 int actualPadLen = paddingObj.unpad(padBuffer, k);
779 k -= actualPadLen;
780 System.arraycopy(padBuffer, 0, out, outOfs, k);
781 } else {
782 k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
783 outLen);
784 doCancel = false;
785 }
786 }
787 return k;
788 } catch (PKCS11Exception e) {
789 doCancel = false;
790 handleException(e);
791 throw new ProviderException("doFinal() failed", e);
792 } finally {
793 reset(doCancel);
794 }
795 }
796
797 private int implDoFinal(ByteBuffer outBuffer)
798 throws ShortBufferException, IllegalBlockSizeException,
799 BadPaddingException {
800 int outLen = outBuffer.remaining();
801 int requiredOutLen = doFinalLength(0);
802 if (outLen < requiredOutLen) {
803 throw new ShortBufferException();
804 }
805
806 boolean doCancel = true;
807 try {
808 ensureInitialized();
809
810 long outAddr = 0;
811 byte[] outArray = null;
812 int outOfs = 0;
813 if (outBuffer instanceof DirectBuffer) {
814 outAddr = ((DirectBuffer) outBuffer).address();
815 outOfs = outBuffer.position();
816 } else {
817 if (outBuffer.hasArray()) {
818 outArray = outBuffer.array();
819 outOfs = outBuffer.position() + outBuffer.arrayOffset();
820 } else {
821 outArray = new byte[outLen];
822 }
823 }
824
825 int k = 0;
826
827 if (encrypt) {
828 if (paddingObj != null) {
829 int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
830 requiredOutLen - bytesBuffered);
831 k = token.p11.C_EncryptUpdate(session.id(),
832 0, padBuffer, 0, actualPadLen,
833 outAddr, outArray, outOfs, outLen);
834 }
835 k += token.p11.C_EncryptFinal(session.id(),
836 outAddr, outArray, (outOfs + k), (outLen - k));
837 doCancel = false;
838 } else {
839 // Special handling to match SunJCE provider behavior
840 if (bytesBuffered == 0 && padBufferLen == 0) {
841 return 0;
842 }
843
844 if (paddingObj != null) {
845 if (padBufferLen != 0) {
846 k = token.p11.C_DecryptUpdate(session.id(),
847 0, padBuffer, 0, padBufferLen,
848 0, padBuffer, 0, padBuffer.length);
849 padBufferLen = 0;
850 }
851 k += token.p11.C_DecryptFinal(session.id(),
852 0, padBuffer, k, padBuffer.length - k);
853 doCancel = false;
854
855 int actualPadLen = paddingObj.unpad(padBuffer, k);
856 k -= actualPadLen;
857 outArray = padBuffer;
858 outOfs = 0;
859 } else {
860 k = token.p11.C_DecryptFinal(session.id(),
861 outAddr, outArray, outOfs, outLen);
862 doCancel = false;
863 }
864 }
865 if ((!encrypt && paddingObj != null) ||
866 (!(outBuffer instanceof DirectBuffer) &&
867 !outBuffer.hasArray())) {
868 outBuffer.put(outArray, outOfs, k);
869 } else {
870 outBuffer.position(outBuffer.position() + k);
871 }
872 return k;
873 } catch (PKCS11Exception e) {
874 doCancel = false;
875 handleException(e);
876 throw new ProviderException("doFinal() failed", e);
877 } finally {
878 reset(doCancel);
879 }
880 }
881
882 private void handleException(PKCS11Exception e)
883 throws ShortBufferException, IllegalBlockSizeException {
884 long errorCode = e.getErrorCode();
885 if (errorCode == CKR_BUFFER_TOO_SMALL) {
886 throw (ShortBufferException)
887 (new ShortBufferException().initCause(e));
888 } else if (errorCode == CKR_DATA_LEN_RANGE ||
889 errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
890 throw (IllegalBlockSizeException)
891 (new IllegalBlockSizeException(e.toString()).initCause(e));
892 }
893 }
894
895 // see JCE spec
896 protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
897 InvalidKeyException {
898 // XXX key wrapping
|