F-9991: size BlockCipher update output from length instead of input.length

pull/259/head
Chris Conlon 2026-08-17 14:04:48 -06:00
parent b8392ced50
commit 8b6d7ccb3c
4 changed files with 144 additions and 2 deletions

View File

@ -184,9 +184,22 @@ public abstract class BlockCipher extends NativeStruct {
checkStateAndInitialize();
throwIfKeyNotLoaded();
byte[] output = new byte[input.length];
if (input == null || offset < 0 || length < 0 ||
((long)offset + (long)length) > input.length) {
throw new WolfCryptException(WolfCryptError.BAD_FUNC_ARG.getCode());
}
native_update(opmode, input, offset, length, output, 0);
int outputLength;
byte[] output = new byte[length];
outputLength = native_update(opmode, input, offset, length, output, 0);
if (outputLength != length) {
/* resize array to match actual output length */
byte[] tmp = new byte[outputLength];
System.arraycopy(output, 0, tmp, 0, outputLength);
output = tmp;
}
return output;
}

View File

@ -126,6 +126,38 @@ public class AesEcbTest {
}
}
@Test
public void updateWithInvalidLengthShouldThrow() {
AesEcb enc = new AesEcb();
enc.setKey(KEY_128, AesEcb.ENCRYPT_MODE);
byte[] in = new byte[AesEcb.BLOCK_SIZE];
try {
enc.update(null, 0, AesEcb.BLOCK_SIZE);
fail("null input should throw");
} catch (WolfCryptException e) {
/* expected */
}
try {
enc.update(in, 0, -1);
fail("negative length should throw");
} catch (WolfCryptException e) {
/* expected */
}
try {
enc.update(in, AesEcb.BLOCK_SIZE, AesEcb.BLOCK_SIZE);
fail("offset plus length beyond input should throw");
} catch (WolfCryptException e) {
/* expected */
}
enc.releaseNativeStruct();
}
@Test
public void checkUpdateParams() throws ShortBufferException {
byte[] input = new byte[AesEcb.BLOCK_SIZE];

View File

@ -422,6 +422,32 @@ public class AesTest {
dec.releaseNativeStruct();
}
@Test
public void updateWithPartialLengthShouldSizeOutputToLength() {
byte[] key = Util.h2b("2b7e151628aed2a6abf7158809cf4f3c");
byte[] iv = Util.h2b("000102030405060708090A0B0C0D0E0F");
byte[] input = Util.h2b("6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51");
byte[] expected = Util.h2b("7649abac8119b246cee98e9b12e9197d");
/* process only the first block, output must be sized to length */
Aes enc = new Aes();
enc.setKey(key, iv, Aes.ENCRYPT_MODE);
byte[] cipher = enc.update(input, 0, Aes.BLOCK_SIZE);
assertEquals(Aes.BLOCK_SIZE, cipher.length);
assertArrayEquals(expected, cipher);
Aes dec = new Aes();
dec.setKey(key, iv, Aes.DECRYPT_MODE);
byte[] plain = dec.update(cipher, 0, Aes.BLOCK_SIZE);
assertEquals(Aes.BLOCK_SIZE, plain.length);
assertArrayEquals(Arrays.copyOf(input, Aes.BLOCK_SIZE), plain);
enc.releaseNativeStruct();
dec.releaseNativeStruct();
}
@Test
public void reuseObject() {
@ -457,6 +483,41 @@ public class AesTest {
dec.releaseNativeStruct();
}
@Test
public void updateWithInvalidLengthShouldThrow() {
byte[] key = Util.h2b("2b7e151628aed2a6abf7158809cf4f3c");
byte[] iv = Util.h2b("000102030405060708090A0B0C0D0E0F");
Aes enc = new Aes();
enc.setKey(key, iv, Aes.ENCRYPT_MODE);
byte[] in = new byte[Aes.BLOCK_SIZE];
try {
enc.update(null, 0, Aes.BLOCK_SIZE);
fail("null input should throw");
} catch (WolfCryptException e) {
/* expected */
}
try {
enc.update(in, 0, -1);
fail("negative length should throw");
} catch (WolfCryptException e) {
/* expected */
}
try {
enc.update(in, Aes.BLOCK_SIZE, Aes.BLOCK_SIZE);
fail("offset plus length beyond input should throw");
} catch (WolfCryptException e) {
/* expected */
}
enc.releaseNativeStruct();
}
@Test
public void testPadPKCS7() {

View File

@ -254,6 +254,42 @@ public class Des3Test {
dec.releaseNativeStruct();
}
@Test
public void updateWithInvalidLengthShouldThrow() {
byte[] key = Util.h2b("e61a38548694f1fd8cef251c518" +
"cc70bb613751c1ce52aa8");
byte[] iv = Util.h2b("48a8ceb8551fd4ad");
Des3 enc = new Des3();
enc.setKey(key, iv, Des3.ENCRYPT_MODE);
byte[] in = new byte[Des3.BLOCK_SIZE];
try {
enc.update(null, 0, Des3.BLOCK_SIZE);
fail("null input should throw");
} catch (WolfCryptException e) {
/* expected */
}
try {
enc.update(in, 0, -1);
fail("negative length should throw");
} catch (WolfCryptException e) {
/* expected */
}
try {
enc.update(in, Des3.BLOCK_SIZE, Des3.BLOCK_SIZE);
fail("offset plus length beyond input should throw");
} catch (WolfCryptException e) {
/* expected */
}
enc.releaseNativeStruct();
}
@Test
public void reuseObject() {