F-3572: add offset and len sanity checks to Md5 byte array update

pull/255/head
Chris Conlon 2026-08-11 16:11:27 -06:00
parent 9e4efe06b1
commit 620e63e5ed
10 changed files with 129 additions and 11 deletions

View File

@ -190,8 +190,8 @@ Java_com_wolfssl_wolfcrypt_Md5_native_1update_1internal___3BII(
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (md5 == NULL || data == NULL ||
((word32)(offset + len) > dataSz)) {
if (md5 == NULL || data == NULL || offset < 0 || len < 0 ||
(((jlong)offset + (jlong)len) > (jlong)dataSz)) {
ret = BAD_FUNC_ARG;
} else {
ret = wc_Md5Update(md5, data + offset, len);

View File

@ -319,7 +319,7 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1update_1internal___3BII(
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
((jlong)offset + (jlong)len) > (jlong)dataSz) {
ret = BAD_FUNC_ARG;
}
else {
@ -536,7 +536,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1interna
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
((jlong)offset + (jlong)len) > (jlong)dataSz) {
ret = BAD_FUNC_ARG;
}
else {
@ -763,7 +763,7 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1update_1internal___3BII(
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
((jlong)offset + (jlong)len) > (jlong)dataSz) {
ret = BAD_FUNC_ARG;
}
else {
@ -969,7 +969,7 @@ Java_com_wolfssl_wolfcrypt_Sha384_native_1update_1internal___3BII(
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
((jlong)offset + (jlong)len) > (jlong)dataSz) {
ret = BAD_FUNC_ARG;
}
else {
@ -1176,7 +1176,7 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1update_1internal___3BII(
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
((jlong)offset + (jlong)len) > (jlong)dataSz) {
ret = BAD_FUNC_ARG;
}
else {
@ -1471,7 +1471,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal_
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
((jlong)offset + (jlong)len) > (jlong)dataSz) {
ret = BAD_FUNC_ARG;
}

View File

@ -169,9 +169,8 @@ public abstract class MessageDigest extends NativeStruct {
checkStateAndInitialize();
if (((offset + len) > data.length) || offset < 0 || len < 0) {
throw new RuntimeException(
"Invalid offset or length");
if (offset < 0 || len < 0 || len > (data.length - offset)) {
throw new RuntimeException("Invalid offset or length");
}
native_update(data, offset, len);

View File

@ -75,6 +75,23 @@ public class Md5Test {
assertEquals(NativeStruct.NULL, new Md5().getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Md5 md5 = new Md5();
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
md5.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void hashShouldMatchUsingByteBuffer() throws ShortBufferException {
String[] dataVector = new String[] {

View File

@ -85,6 +85,23 @@ public class Sha224Test {
assertEquals(NativeStruct.NULL, new Sha224().getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Sha224 sha = new Sha224();
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
sha.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void hashShouldMatchUsingByteBuffer() throws ShortBufferException {

View File

@ -75,6 +75,23 @@ public class Sha256Test {
assertEquals(NativeStruct.NULL, new Sha256().getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Sha256 sha = new Sha256();
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
sha.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void hashShouldMatchUsingByteBuffer() throws ShortBufferException {
String[] dataVector = new String[] {

View File

@ -75,6 +75,23 @@ public class Sha384Test {
assertEquals(NativeStruct.NULL, new Sha384().getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Sha384 sha = new Sha384();
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
sha.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void hashShouldMatchUsingByteBuffer() throws ShortBufferException {
String[] dataVector = new String[] { "", "c2edba56a6b82cc3",

View File

@ -75,6 +75,23 @@ public class Sha3Test {
new Sha3(Sha3.TYPE_SHA3_256).getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
sha.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void sha3_256HashShouldMatchUsingByteArray() {
/* Test vectors from NIST FIPS 202 - SHA-3 Standard */

View File

@ -75,6 +75,23 @@ public class Sha512Test {
assertEquals(NativeStruct.NULL, new Sha512().getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Sha512 sha = new Sha512();
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
sha.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void hashShouldMatchUsingByteBuffer() throws ShortBufferException {
String[] dataVector = new String[] { "", "20580a530f01e771",

View File

@ -75,6 +75,23 @@ public class ShaTest {
assertEquals(NativeStruct.NULL, new Sha().getNativeStruct());
}
@Test
public void updateWithWrappedOffsetAndLenShouldThrow() {
Sha sha = new Sha();
byte[] data = new byte[8];
/* offset + len wraps int arithmetic, update must reject it */
try {
sha.update(data, 1, Integer.MAX_VALUE);
fail("update() should have thrown for wrapped offset + len");
} catch (IllegalStateException e) {
/* init failure is not the bounds rejection */
throw e;
} catch (RuntimeException e) {
/* expected */
}
}
@Test
public void hashShouldMatchUsingByteBuffer() throws ShortBufferException {
String[] dataVector = new String[] {