diff -up openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java.sav openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java --- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java.sav 2012-02-14 16:12:51.000000000 -0500 +++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java 2012-05-02 14:07:20.642722122 -0400 @@ -160,10 +160,16 @@ final class P11Cipher extends CipherSpi // original IV, if in MODE_CBC or MODE_CTR private byte[] iv; - // number of bytes buffered internally by the native mechanism and padBuffer - // if we do the padding + // number of bytes buffered by the blockBuffer private int bytesBuffered; + // number of bytes buffered internally + private int bytesBufferedInt; + + // bytes buffered from an incomplete block + private byte[] blockBuffer; + private int blockBufferLen; + P11Cipher(Token token, String algorithm, long mechanism) throws PKCS11Exception, NoSuchAlgorithmException { super(); @@ -194,6 +200,9 @@ final class P11Cipher extends CipherSpi // should not happen throw new ProviderException(nspe); } + + if (blockSize > 0) + blockBuffer = new byte[blockSize]; } protected void engineSetMode(String mode) throws NoSuchAlgorithmException { @@ -435,7 +444,9 @@ final class P11Cipher extends CipherSpi throw ex; } bytesBuffered = 0; + bytesBufferedInt = 0; padBufferLen = 0; + blockBufferLen = 0; initialized = true; } @@ -445,7 +456,7 @@ final class P11Cipher extends CipherSpi return 0; } - int result = inLen + bytesBuffered; + int result = inLen + bytesBuffered + bytesBufferedInt; if (blockSize != 0) { // minus the number of bytes in the last incomplete block. result -= (result & (blockSize - 1)); @@ -459,7 +470,7 @@ final class P11Cipher extends CipherSpi return 0; } - int result = inLen + bytesBuffered; + int result = inLen + bytesBuffered + bytesBufferedInt; if (blockSize != 0 && encrypt && paddingType != PAD_NONE) { // add the number of bytes to make the last block complete. result += (blockSize - (result & (blockSize - 1))); @@ -471,7 +482,9 @@ final class P11Cipher extends CipherSpi private void reset() { initialized = false; bytesBuffered = 0; + bytesBufferedInt = 0; padBufferLen = 0; + blockBufferLen = 0; if (session != null) { session = token.releaseSession(session); } @@ -547,48 +560,57 @@ final class P11Cipher extends CipherSpi 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, + int newBlockBufferLen = 0; + + // NSS throws up when called with data not in multiple + // of blocks. Try to work around this by holding the + // extra data in blockBuffer. + if (blockBufferLen != 0) { + if (blockBufferLen != blockBuffer.length) { + int bufCapacity = blockBuffer.length - blockBufferLen; + if (inLen >= bufCapacity) { + bufferInputBytes(in, inOfs, bufCapacity); + inOfs += bufCapacity; + inLen -= bufCapacity; + } else { + bufferInputBytes(in, inOfs, inLen); + return 0; + } + } + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), 0, blockBuffer, 0, + blockBufferLen, 0, out, outOfs, + outLen); + } else { + k = token.p11.C_DecryptUpdate(session.id(), 0, blockBuffer, 0, + blockBufferLen, 0, out, outOfs, + outLen); + } + blockBufferLen = 0; + bytesBuffered = 0; + } + + if (inLen == 0) + return k; + + newBlockBufferLen = inLen & (blockSize - 1); + if (!encrypt && paddingObj != null && newBlockBufferLen == 0) + // Hold the last block in the buffer if we need to unpad + newBlockBufferLen = blockBuffer.length; + inLen -= newBlockBufferLen; + + if (inLen > 0) { + if (encrypt) { + k = token.p11.C_EncryptUpdate(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); + } else { + k = token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs, + inLen, 0, out, (outOfs + k), (outLen - k)); + } + } + + bufferInputBytes(in, inOfs + inLen, newBlockBufferLen); + bytesBufferedInt += (inLen - k); return k; } catch (PKCS11Exception e) { if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) { @@ -643,62 +665,65 @@ final class P11Cipher extends CipherSpi } 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); + int newBlockBufferLen = 0; + + // NSS throws up when called with data not in multiple + // of blocks. Try to work around this by holding the + // extra data in blockBuffer. + if (blockBufferLen != 0) { + if (blockBufferLen != blockBuffer.length) { + int bufCapacity = blockBuffer.length - blockBufferLen; + if (inLen >= bufCapacity) { + bufferInputBytes(inBuffer, bufCapacity); + inOfs += bufCapacity; + inLen -= bufCapacity; + } else { + bufferInputBytes(inBuffer, inLen); + return 0; + } + } + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), 0, blockBuffer, 0, + blockBufferLen, outAddr, outArray, outOfs, + outLen); + } else { + k = token.p11.C_DecryptUpdate(session.id(), 0, blockBuffer, 0, + blockBufferLen, outAddr, outArray, outOfs, + outLen); + } + blockBufferLen = 0; + bytesBuffered = 0; + } + + if (inLen == 0) + return k; + + newBlockBufferLen = inLen & (blockSize - 1); + if (!encrypt && paddingObj != null && newBlockBufferLen == 0) + // Hold the last block in the buffer if we need to unpad + newBlockBufferLen = blockBuffer.length; + inLen -= newBlockBufferLen; + + if (inAddr == 0 && inArray == null) { + inArray = new byte[inLen]; + inBuffer.get(inArray); + } else { + inBuffer.position(inBuffer.position() + inLen); + } + + if (inLen > 0) { + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), inAddr, inArray, inOfs, + inLen, outAddr, outArray, (outOfs + k), (outLen - k)); + } else { + k = token.p11.C_DecryptUpdate(session.id(), inAddr, inArray, inOfs, + inLen, outAddr, outArray, (outOfs + k), (outLen - k)); + } + } + + bufferInputBytes(inBuffer, newBlockBufferLen); + bytesBufferedInt += (inLen - k); + if (!(outBuffer instanceof DirectBuffer) && !outBuffer.hasArray()) { outBuffer.put(outArray, outOfs, k); @@ -728,31 +753,42 @@ final class P11Cipher extends CipherSpi try { ensureInitialized(); int k = 0; + if (blockBufferLen != 0) { + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), + 0, blockBuffer, 0, blockBufferLen, + 0, out, outOfs, outLen); + } else { + if (paddingObj == null) + k = token.p11.C_DecryptUpdate(session.id(), 0, + blockBuffer, 0, blockBufferLen, 0, + out, outOfs, outLen); + else + k = token.p11.C_DecryptUpdate(session.id(), 0, + blockBuffer, 0, blockBufferLen, 0, + padBuffer, 0, padBuffer.length); + } + } 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); + requiredOutLen - bytesBufferedInt); + k += token.p11.C_EncryptUpdate(session.id(), + 0, padBuffer, 0, actualPadLen, + 0, out, (outOfs + k), (outLen - k)); } 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); + k += token.p11.C_DecryptFinal(session.id(), 0, out, (outOfs + k), + (outLen - k)); } } return k; @@ -793,6 +829,23 @@ final class P11Cipher extends CipherSpi int k = 0; + if (blockBufferLen != 0) { + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), + 0, blockBuffer, 0, blockBufferLen, + outAddr, outArray, outOfs, outLen); + } else { + if (paddingObj == null) + k = token.p11.C_DecryptUpdate(session.id(), 0, + blockBuffer, 0, blockBufferLen, outAddr, + outArray, outOfs, outLen); + else + k = token.p11.C_DecryptUpdate(session.id(), 0, + blockBuffer, 0, blockBufferLen, 0, + padBuffer, 0, padBuffer.length); + } + } + if (encrypt) { if (paddingObj != null) { int actualPadLen = paddingObj.setPaddingBytes(padBuffer, @@ -805,12 +858,6 @@ final class P11Cipher extends CipherSpi 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); @@ -819,7 +866,8 @@ final class P11Cipher extends CipherSpi outOfs = 0; } else { k = token.p11.C_DecryptFinal(session.id(), - outAddr, outArray, outOfs, outLen); + outAddr, outArray, + (outOfs + k), (outLen - k)); } } if ((!encrypt && paddingObj != null) || @@ -875,14 +923,14 @@ final class P11Cipher extends CipherSpi } private final void bufferInputBytes(byte[] in, int inOfs, int len) { - System.arraycopy(in, inOfs, padBuffer, padBufferLen, len); - padBufferLen += len; + System.arraycopy(in, inOfs, blockBuffer, blockBufferLen, len); + blockBufferLen += len; bytesBuffered += len; } private final void bufferInputBytes(ByteBuffer inBuffer, int len) { - inBuffer.get(padBuffer, padBufferLen, len); - padBufferLen += len; + inBuffer.get(blockBuffer, blockBufferLen, len); + blockBufferLen += len; bytesBuffered += len; } }