diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dca93d9..0854c309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ method. * Add version gating to some tests introduced in 1.5.0 [PR #128](https://github.com/corretto/amazon-corretto-crypto-provider/pull/128) * More accurate output size estimates from `Cipher.getOutputSize()` [PR #138](https://github.com/corretto/amazon-corretto-crypto-provider/pull/138) * Validate that `AesGcmSpi` receives a non-null key on init to prevent unncessarily late NPE [PR #146](https://github.com/corretto/amazon-corretto-crypto-provider/pull/146) +* Gracefully handle calling `Cipher.doFinal()` without any input bytes in `RsaCipher` [PR #147](https://github.com/corretto/amazon-corretto-crypto-provider/pull/147) ## 1.5.0 ### Breaking Change Warning diff --git a/src/com/amazon/corretto/crypto/provider/RsaCipher.java b/src/com/amazon/corretto/crypto/provider/RsaCipher.java index 774990c5..dbff75bb 100644 --- a/src/com/amazon/corretto/crypto/provider/RsaCipher.java +++ b/src/com/amazon/corretto/crypto/provider/RsaCipher.java @@ -177,6 +177,14 @@ protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, final b inputOffset = 0; inputLen = buffer_.size(); } + // One-shot, no input. Cipher only calls engineDoFinal with null input in doFinal overloads + // that don't take an input buffer, and in those cases, inputOffset and inputLen are 0. + // We set them here anyways to be safe, because the API makes no such guarantee. + else if (input == null) { + input = Utils.EMPTY_ARRAY; + inputOffset = 0; + inputLen = 0; + } if (output.length - outputOffset < engineGetOutputSize(inputLen)) { throw new ShortBufferException(); diff --git a/tst/com/amazon/corretto/crypto/provider/test/RsaCipherTest.java b/tst/com/amazon/corretto/crypto/provider/test/RsaCipherTest.java index e1039ce6..97a751b7 100644 --- a/tst/com/amazon/corretto/crypto/provider/test/RsaCipherTest.java +++ b/tst/com/amazon/corretto/crypto/provider/test/RsaCipherTest.java @@ -867,6 +867,17 @@ public void threadStorm() throws Throwable { } } + @Test + public void noInputDoFinal() throws Exception { + assumeMinimumVersion("1.6.0", AmazonCorrettoCryptoProvider.INSTANCE); + final Cipher enc = Cipher.getInstance(NO_PADDING, NATIVE_PROVIDER); + enc.init(Cipher.ENCRYPT_MODE, PAIR_1024.getPublic()); + final byte[] result = enc.doFinal(); + for (final byte b : result) { + assertEquals(b, 0); + } + } + private void testNative2Jce(final String padding, final int keySize) throws GeneralSecurityException { final Cipher jceC = Cipher.getInstance(padding); final Cipher nativeC = Cipher.getInstance(padding, NATIVE_PROVIDER);