F-8212: bound bufSz to buffer capacity in FIPS RNG GenerateBlock wrappers

Chris Conlon 2026-08-28 16:13:11 -06:00
parent b8392ced50
commit e1e97fe400
2 changed files with 76 additions and 5 deletions

View File

@ -1928,6 +1928,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
RNG* rng = NULL;
byte* buf = NULL;
jlong bufCap = 0;
rng = (RNG*) getNativeStruct(env, rng_object);
if ((*env)->ExceptionOccurred(env)) {
@ -1936,9 +1937,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
}
buf = getDirectBufferAddress(env, buf_buffer);
bufCap = (*env)->GetDirectBufferCapacity(env, buf_buffer);
if (!rng || !buf)
/* reject NULL, negative, or bufSz beyond the buffer capacity, the
* capacity ceiling also keeps the word32 cast from wrapping */
if (rng == NULL || buf == NULL || bufSz < 0 || bufSz > bufCap) {
return BAD_FUNC_ARG;
}
#if FIPS_VERSION_GT(5,0)
ret = wc_RNG_GenerateBlock_fips(rng, buf, (word32)bufSz);
@ -1948,7 +1953,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
LogStr("RNG_GenerateBlock_fips(rng=%p, buf, bufSz) = %d\n", rng, ret);
LogStr("output[%u]: [%p]\n", (word32)bufSz, buf);
LogHex(buf, 0, bufSz);
LogHex(buf, 0, (word32)bufSz);
#endif
@ -1965,6 +1970,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
RNG* rng = NULL;
byte* buf = NULL;
word32 bufLen = 0;
rng = (RNG*) getNativeStruct(env, rng_object);
if ((*env)->ExceptionOccurred(env)) {
@ -1973,8 +1979,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
}
buf = getByteArray(env, buf_buffer);
bufLen = getByteArrayLength(env, buf_buffer);
if (rng == NULL || buf == NULL) {
/* reject NULL, negative, or bufSz beyond the backing array */
if (rng == NULL || buf == NULL || bufSz < 0 || bufSz > (jlong)bufLen) {
ret = BAD_FUNC_ARG;
}
else {
@ -1986,8 +1994,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
}
LogStr("RNG_GenerateBlock_fips(rng=%p, buf, bufSz) = %d\n", rng, ret);
LogStr("output[%u]: [%p]\n", (word32)bufSz, buf);
LogHex(buf, 0, bufSz);
if (buf != NULL && ret == 0) {
LogStr("output[%u]: [%p]\n", (word32)bufSz, buf);
LogHex(buf, 0, (word32)bufSz);
}
releaseByteArray(env, buf_buffer, buf, ret);

View File

@ -24,6 +24,7 @@ package com.wolfssl.wolfcrypt.test.fips;
import static org.junit.Assert.*;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.junit.BeforeClass;
import org.junit.Test;
@ -34,6 +35,7 @@ import org.junit.runner.Description;
import com.wolfssl.wolfcrypt.Rng;
import com.wolfssl.wolfcrypt.WolfCrypt;
import com.wolfssl.wolfcrypt.WolfCryptError;
import com.wolfssl.wolfcrypt.Fips;
import com.wolfssl.wolfcrypt.test.Util;
@ -60,6 +62,65 @@ public class RngFipsTest extends FipsTest {
assertEquals(WolfCrypt.SUCCESS, Fips.FreeRng_fips(rng));
}
@Test
public void GenerateBlockShouldRejectBadBufSzUsingByteBuffer() {
Rng rng = new Rng();
ByteBuffer buf = ByteBuffer.allocateDirect(32);
assertEquals(WolfCrypt.SUCCESS, Fips.InitRng_fips(rng));
/* valid request within capacity fills the buffer */
assertEquals(WolfCrypt.SUCCESS,
Fips.RNG_GenerateBlock_fips(rng, buf, 32));
byte[] filled = new byte[32];
buf.duplicate().get(filled);
assertFalse("buffer should not be all zeros after generate",
Arrays.equals(filled, new byte[32]));
/* zero length is admitted by the guard and handled by the RNG */
assertEquals(WolfCrypt.SUCCESS,
Fips.RNG_GenerateBlock_fips(rng, buf, 0));
/* negative bufSz is rejected before the RNG call */
assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_GenerateBlock_fips(rng, buf, -1));
/* bufSz larger than capacity is rejected before the RNG call */
assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_GenerateBlock_fips(rng, buf, 33));
assertEquals(WolfCrypt.SUCCESS, Fips.FreeRng_fips(rng));
}
@Test
public void GenerateBlockShouldRejectBadBufSzUsingByteArray() {
Rng rng = new Rng();
byte[] buf = new byte[32];
assertEquals(WolfCrypt.SUCCESS, Fips.InitRng_fips(rng));
/* valid request within length fills the buffer */
assertEquals(WolfCrypt.SUCCESS,
Fips.RNG_GenerateBlock_fips(rng, buf, 32));
assertFalse("buffer should not be all zeros after generate",
Arrays.equals(buf, new byte[32]));
/* zero length is admitted by the guard and handled by the RNG */
assertEquals(WolfCrypt.SUCCESS,
Fips.RNG_GenerateBlock_fips(rng, buf, 0));
/* negative bufSz is rejected before the RNG call */
assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_GenerateBlock_fips(rng, buf, -1));
/* bufSz larger than the array is rejected before the RNG call */
assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_GenerateBlock_fips(rng, buf, 33));
assertEquals(WolfCrypt.SUCCESS, Fips.FreeRng_fips(rng));
}
@Test
public void HeathTestShouldReturnZeroUsingByteBuffer() {
String[] inputA = new String[] {