private void initialize() throws PKCS11Exception { if (session == null) { session = token.getOpSession(); } PKCS11 p11 = token.p11; CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism); switch (mode) { case MODE_ENCRYPT: p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID); break; case MODE_DECRYPT: p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID); break; case MODE_SIGN: p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID); break; case MODE_VERIFY: p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID); break; default: throw new AssertionError("internal error"); } bufOfs = 0; initialized = true; }
private int implUpdate(byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws ShortBufferException { if (outLen < updateLength(inLen)) { throw new ShortBufferException(); } try { ensureInitialized(); int k = 0; if (encrypt) { k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen, 0, out, outOfs, outLen); } else { int newPadBufferLen = 0; if (paddingObj != null) { if (padBufferLen != 0) { // NSS throws up when called with data not in multiple // of blocks. Try to work around this by holding the // extra data in padBuffer. if (padBufferLen != padBuffer.length) { int bufCapacity = padBuffer.length - padBufferLen; if (inLen > bufCapacity) { bufferInputBytes(in, inOfs, bufCapacity); inOfs += bufCapacity; inLen -= bufCapacity; } else { bufferInputBytes(in, inOfs, inLen); return 0; } } k = token.p11.C_DecryptUpdate( session.id(), 0, padBuffer, 0, padBufferLen, 0, out, outOfs, outLen); padBufferLen = 0; } newPadBufferLen = inLen & (blockSize - 1); if (newPadBufferLen == 0) { newPadBufferLen = padBuffer.length; } inLen -= newPadBufferLen; } if (inLen > 0) { k += token.p11.C_DecryptUpdate( session.id(), 0, in, inOfs, inLen, 0, out, (outOfs + k), (outLen - k)); } // update 'padBuffer' if using our own padding impl. if (paddingObj != null) { bufferInputBytes(in, inOfs + inLen, newPadBufferLen); } } bytesBuffered += (inLen - k); return k; } catch (PKCS11Exception e) { if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) { throw (ShortBufferException) (new ShortBufferException().initCause(e)); } reset(); throw new ProviderException("update() failed", e); } }
private int implDoFinal(byte[] out, int outOfs, int outLen) throws BadPaddingException, IllegalBlockSizeException { if (bufOfs > maxInputSize) { throw new IllegalBlockSizeException( "Data must not be longer " + "than " + maxInputSize + " bytes"); } try { ensureInitialized(); PKCS11 p11 = token.p11; int n; switch (mode) { case MODE_ENCRYPT: n = p11.C_Encrypt(session.id(), buffer, 0, bufOfs, out, outOfs, outLen); break; case MODE_DECRYPT: n = p11.C_Decrypt(session.id(), buffer, 0, bufOfs, out, outOfs, outLen); break; case MODE_SIGN: byte[] tmpBuffer = new byte[bufOfs]; System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs); tmpBuffer = p11.C_Sign(session.id(), tmpBuffer); if (tmpBuffer.length > outLen) { throw new BadPaddingException("Output buffer too small"); } System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length); n = tmpBuffer.length; break; case MODE_VERIFY: n = p11.C_VerifyRecover(session.id(), buffer, 0, bufOfs, out, outOfs, outLen); break; default: throw new ProviderException("internal error"); } return n; } catch (PKCS11Exception e) { throw (BadPaddingException) new BadPaddingException("doFinal() failed").initCause(e); } finally { initialized = false; session = token.releaseSession(session); } }
private int implDoFinal(byte[] out, int outOfs, int outLen) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { int requiredOutLen = doFinalLength(0); if (outLen < requiredOutLen) { throw new ShortBufferException(); } try { ensureInitialized(); int k = 0; if (encrypt) { if (paddingObj != null) { int actualPadLen = paddingObj.setPaddingBytes(padBuffer, requiredOutLen - bytesBuffered); k = token.p11.C_EncryptUpdate( session.id(), 0, padBuffer, 0, actualPadLen, 0, out, outOfs, outLen); } k += token.p11.C_EncryptFinal(session.id(), 0, out, (outOfs + k), (outLen - k)); } else { if (paddingObj != null) { if (padBufferLen != 0) { k = token.p11.C_DecryptUpdate( session.id(), 0, padBuffer, 0, padBufferLen, 0, padBuffer, 0, padBuffer.length); } k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k, padBuffer.length - k); int actualPadLen = paddingObj.unpad(padBuffer, k); k -= actualPadLen; System.arraycopy(padBuffer, 0, out, outOfs, k); } else { k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs, outLen); } } return k; } catch (PKCS11Exception e) { handleException(e); throw new ProviderException("doFinal() failed", e); } finally { reset(); } }
private void cancelOperation() { token.ensureValid(); if (initialized == false) { return; } initialized = false; if ((session == null) || (token.explicitCancel == false)) { return; } if (session.hasObjects() == false) { session = token.killSession(session); return; } try { PKCS11 p11 = token.p11; int inLen = maxInputSize; int outLen = buffer.length; switch (mode) { case MODE_ENCRYPT: p11.C_Encrypt(session.id(), buffer, 0, inLen, buffer, 0, outLen); break; case MODE_DECRYPT: p11.C_Decrypt(session.id(), buffer, 0, inLen, buffer, 0, outLen); break; case MODE_SIGN: byte[] tmpBuffer = new byte[maxInputSize]; p11.C_Sign(session.id(), tmpBuffer); break; case MODE_VERIFY: p11.C_VerifyRecover(session.id(), buffer, 0, inLen, buffer, 0, outLen); break; default: throw new ProviderException("internal error"); } } catch (PKCS11Exception e) { // XXX ensure this always works, ignore error } }
private void cancelOperation() { if (initialized == false) { return; } initialized = false; if ((session == null) || (token.explicitCancel == false)) { return; } // cancel operation by finishing it int bufLen = doFinalLength(0); byte[] buffer = new byte[bufLen]; try { if (encrypt) { token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen); } else { token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen); } } catch (PKCS11Exception e) { throw new ProviderException("Cancel failed", e); } finally { reset(); } }
private void initialize() throws PKCS11Exception { if (session == null) { session = token.getOpSession(); } CK_MECHANISM mechParams = (blockMode == MODE_CTR ? new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) : new CK_MECHANISM(mechanism, iv)); try { if (encrypt) { token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID); } else { token.p11.C_DecryptInit(session.id(), mechParams, p11Key.keyID); } } catch (PKCS11Exception ex) { // release session when initialization failed session = token.releaseSession(session); throw ex; } bytesBuffered = 0; padBufferLen = 0; initialized = true; }
// see JCE spec protected byte[] engineWrap(Key key) throws InvalidKeyException, IllegalBlockSizeException { String keyAlg = key.getAlgorithm(); P11Key sKey = null; try { // The conversion may fail, e.g. trying to wrap an AES key on // a token that does not support AES, or when the key size is // not within the range supported by the token. sKey = P11SecretKeyFactory.convertKey(token, key, keyAlg); } catch (InvalidKeyException ike) { byte[] toBeWrappedKey = key.getEncoded(); if (toBeWrappedKey == null) { throw new InvalidKeyException("wrap() failed, no encoding available", ike); } // Directly encrypt the key encoding when key conversion failed implInit(Cipher.ENCRYPT_MODE, p11Key); implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length); try { return doFinal(); } catch (BadPaddingException bpe) { // should not occur throw new InvalidKeyException("wrap() failed", bpe); } finally { // Restore original mode implInit(Cipher.WRAP_MODE, p11Key); } } Session s = null; try { s = token.getOpSession(); return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism), p11Key.keyID, sKey.keyID); } catch (PKCS11Exception e) { throw new InvalidKeyException("wrap() failed", e); } finally { token.releaseSession(s); } }
private int implDoFinal(ByteBuffer outBuffer) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { int outLen = outBuffer.remaining(); int requiredOutLen = doFinalLength(0); if (outLen < requiredOutLen) { throw new ShortBufferException(); } try { ensureInitialized(); long outAddr = 0; byte[] outArray = null; int outOfs = 0; if (outBuffer instanceof DirectBuffer) { outAddr = ((DirectBuffer) outBuffer).address(); outOfs = outBuffer.position(); } else { if (outBuffer.hasArray()) { outArray = outBuffer.array(); outOfs = outBuffer.position() + outBuffer.arrayOffset(); } else { outArray = new byte[outLen]; } } int k = 0; if (encrypt) { if (paddingObj != null) { int actualPadLen = paddingObj.setPaddingBytes(padBuffer, requiredOutLen - bytesBuffered); k = token.p11.C_EncryptUpdate( session.id(), 0, padBuffer, 0, actualPadLen, outAddr, outArray, outOfs, outLen); } k += token.p11.C_EncryptFinal(session.id(), outAddr, outArray, (outOfs + k), (outLen - k)); } else { if (paddingObj != null) { if (padBufferLen != 0) { k = token.p11.C_DecryptUpdate( session.id(), 0, padBuffer, 0, padBufferLen, 0, padBuffer, 0, padBuffer.length); padBufferLen = 0; } k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k, padBuffer.length - k); int actualPadLen = paddingObj.unpad(padBuffer, k); k -= actualPadLen; outArray = padBuffer; outOfs = 0; } else { k = token.p11.C_DecryptFinal(session.id(), outAddr, outArray, outOfs, outLen); } } if ((!encrypt && paddingObj != null) || (!(outBuffer instanceof DirectBuffer) && !outBuffer.hasArray())) { outBuffer.put(outArray, outOfs, k); } else { outBuffer.position(outBuffer.position() + k); } return k; } catch (PKCS11Exception e) { handleException(e); throw new ProviderException("doFinal() failed", e); } finally { reset(); } }
private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer) throws ShortBufferException { int inLen = inBuffer.remaining(); if (inLen <= 0) { return 0; } int outLen = outBuffer.remaining(); if (outLen < updateLength(inLen)) { throw new ShortBufferException(); } int origPos = inBuffer.position(); try { ensureInitialized(); long inAddr = 0; int inOfs = 0; byte[] inArray = null; if (inBuffer instanceof DirectBuffer) { inAddr = ((DirectBuffer) inBuffer).address(); inOfs = origPos; } else if (inBuffer.hasArray()) { inArray = inBuffer.array(); inOfs = (origPos + inBuffer.arrayOffset()); } long outAddr = 0; int outOfs = 0; byte[] outArray = null; if (outBuffer instanceof DirectBuffer) { outAddr = ((DirectBuffer) outBuffer).address(); outOfs = outBuffer.position(); } else { if (outBuffer.hasArray()) { outArray = outBuffer.array(); outOfs = (outBuffer.position() + outBuffer.arrayOffset()); } else { outArray = new byte[outLen]; } } int k = 0; if (encrypt) { if (inAddr == 0 && inArray == null) { inArray = new byte[inLen]; inBuffer.get(inArray); } else { inBuffer.position(origPos + inLen); } k = token.p11.C_EncryptUpdate( session.id(), inAddr, inArray, inOfs, inLen, outAddr, outArray, outOfs, outLen); } else { int newPadBufferLen = 0; if (paddingObj != null) { if (padBufferLen != 0) { // NSS throws up when called with data not in multiple // of blocks. Try to work around this by holding the // extra data in padBuffer. if (padBufferLen != padBuffer.length) { int bufCapacity = padBuffer.length - padBufferLen; if (inLen > bufCapacity) { bufferInputBytes(inBuffer, bufCapacity); inOfs += bufCapacity; inLen -= bufCapacity; } else { bufferInputBytes(inBuffer, inLen); return 0; } } k = token.p11.C_DecryptUpdate( session.id(), 0, padBuffer, 0, padBufferLen, outAddr, outArray, outOfs, outLen); padBufferLen = 0; } newPadBufferLen = inLen & (blockSize - 1); if (newPadBufferLen == 0) { newPadBufferLen = padBuffer.length; } inLen -= newPadBufferLen; } if (inLen > 0) { if (inAddr == 0 && inArray == null) { inArray = new byte[inLen]; inBuffer.get(inArray); } else { inBuffer.position(inBuffer.position() + inLen); } k += token.p11.C_DecryptUpdate( session.id(), inAddr, inArray, inOfs, inLen, outAddr, outArray, (outOfs + k), (outLen - k)); } // update 'padBuffer' if using our own padding impl. if (paddingObj != null && newPadBufferLen != 0) { bufferInputBytes(inBuffer, newPadBufferLen); } } bytesBuffered += (inLen - k); if (!(outBuffer instanceof DirectBuffer) && !outBuffer.hasArray()) { outBuffer.put(outArray, outOfs, k); } else { outBuffer.position(outBuffer.position() + k); } return k; } catch (PKCS11Exception e) { // Reset input buffer to its original position for inBuffer.position(origPos); if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) { throw (ShortBufferException) (new ShortBufferException().initCause(e)); } reset(); throw new ProviderException("update() failed", e); } }