Skip to content

Commit b90c599

Browse files
committed
F-5637: validate RSA JNI buffer sizes against DirectByteBuffer capacity
1 parent ac41d9a commit b90c599

2 files changed

Lines changed: 192 additions & 9 deletions

File tree

native/com_wolfssl_WolfCryptRSA.c

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doSign
4242
int keyInit = 0;
4343
unsigned int idx;
4444
unsigned int tmpOut;
45+
jint outSzVal = 0;
4546
unsigned char* inBuf = NULL;
4647
unsigned char* outBuf = NULL;
4748
unsigned char* keyBuf = NULL;
@@ -72,7 +73,19 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doSign
7273
}
7374

7475
/* get output buffer size */
75-
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
76+
if ((*jenv)->GetArrayLength(jenv, outSz) < 1) {
77+
return -1;
78+
}
79+
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, &outSzVal);
80+
81+
/* Reject negative output size or size larger than backing buffer */
82+
if ((outSzVal < 0) ||
83+
(inSz > (*jenv)->GetDirectBufferCapacity(jenv, in)) ||
84+
(keySz > (*jenv)->GetDirectBufferCapacity(jenv, keyDer)) ||
85+
((jlong)outSzVal > (*jenv)->GetDirectBufferCapacity(jenv, out))) {
86+
return -1;
87+
}
88+
tmpOut = (unsigned int)outSzVal;
7689

7790
ret = wc_InitRng(&rng);
7891
if (ret != 0) {
@@ -97,8 +110,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doSign
97110
&myKey, &rng);
98111
if (ret > 0) {
99112
/* save and convert to 0 for success */
100-
tmpOut = ret;
101-
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
113+
outSzVal = ret;
114+
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, &outSzVal);
102115
ret = 0;
103116
}
104117
} else {
@@ -151,6 +164,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doVerify
151164
return -1;
152165
}
153166

167+
/* Reject sizes larger than their backing direct buffers */
168+
if ((sigSz > (*jenv)->GetDirectBufferCapacity(jenv, sig)) ||
169+
(keySz > (*jenv)->GetDirectBufferCapacity(jenv, keyDer)) ||
170+
(outSz > (*jenv)->GetDirectBufferCapacity(jenv, out))) {
171+
return -1;
172+
}
173+
154174
wc_InitRsaKey(&myKey, NULL);
155175
idx = 0;
156176

@@ -181,6 +201,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doEnc
181201
int keyInit = 0;
182202
unsigned int idx;
183203
unsigned int tmpOut;
204+
jint outSzVal = 0;
184205
unsigned char* inBuf = NULL;
185206
unsigned char* outBuf = NULL;
186207
unsigned char* keyBuf = NULL;
@@ -211,7 +232,19 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doEnc
211232
}
212233

213234
/* get output buffer size */
214-
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
235+
if ((*jenv)->GetArrayLength(jenv, outSz) < 1) {
236+
return -1;
237+
}
238+
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, &outSzVal);
239+
240+
/* Reject negative output size or size larger than backing buffer */
241+
if ((outSzVal < 0) ||
242+
(inSz > (*jenv)->GetDirectBufferCapacity(jenv, in)) ||
243+
(keySz > (*jenv)->GetDirectBufferCapacity(jenv, keyDer)) ||
244+
((jlong)outSzVal > (*jenv)->GetDirectBufferCapacity(jenv, out))) {
245+
return -1;
246+
}
247+
tmpOut = (unsigned int)outSzVal;
215248

216249
ret = wc_InitRng(&rng);
217250
if (ret != 0) {
@@ -236,7 +269,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doEnc
236269
&myKey, &rng);
237270
if (ret > 0) {
238271
/* save and convert to 0 for success */
239-
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&ret);
272+
outSzVal = ret;
273+
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, &outSzVal);
240274
ret = 0;
241275
}
242276
} else {
@@ -264,6 +298,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssSign
264298
int keyInit = 0;
265299
unsigned int idx = 0;
266300
unsigned int tmpOut;
301+
jint outSzVal = 0;
267302
unsigned char* inBuf = NULL;
268303
unsigned char* outBuf = NULL;
269304
unsigned char* keyBuf = NULL;
@@ -299,7 +334,19 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssSign
299334
}
300335

301336
/* get output buffer size */
302-
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
337+
if ((*jenv)->GetArrayLength(jenv, outSz) < 1) {
338+
return -1;
339+
}
340+
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, &outSzVal);
341+
342+
/* Reject negative output size or size larger than backing buffer */
343+
if ((outSzVal < 0) ||
344+
(inSz > (*jenv)->GetDirectBufferCapacity(jenv, in)) ||
345+
(keySz > (*jenv)->GetDirectBufferCapacity(jenv, keyDer)) ||
346+
((jlong)outSzVal > (*jenv)->GetDirectBufferCapacity(jenv, out))) {
347+
return -1;
348+
}
349+
tmpOut = (unsigned int)outSzVal;
303350

304351
ret = wc_InitRng(&rng);
305352
if (ret != 0) {
@@ -322,8 +369,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssSign
322369
ret = wc_RsaPSS_Sign(inBuf, (unsigned int)inSz, outBuf, tmpOut,
323370
hashType, mgf, &myKey, &rng);
324371
if (ret > 0) {
325-
tmpOut = ret;
326-
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
372+
outSzVal = ret;
373+
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, &outSzVal);
327374
ret = 0;
328375
}
329376
} else {
@@ -394,6 +441,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssVerify
394441
return -1;
395442
}
396443

444+
/* Reject sizes larger than their backing direct buffers */
445+
if ((sigSz > (*jenv)->GetDirectBufferCapacity(jenv, sig)) ||
446+
(keySz > (*jenv)->GetDirectBufferCapacity(jenv, keyDer)) ||
447+
(outSz > (*jenv)->GetDirectBufferCapacity(jenv, out))) {
448+
return -1;
449+
}
450+
397451
ret = wc_InitRsaKey(&myKey, NULL);
398452
if (ret != 0) {
399453
printf("wc_InitRsaKey failed, ret = %d\n", ret);
@@ -472,6 +526,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doDec
472526
return -1;
473527
}
474528

529+
/* Reject sizes larger than their backing direct buffers */
530+
if ((inSz > (*jenv)->GetDirectBufferCapacity(jenv, in)) ||
531+
(keySz > (*jenv)->GetDirectBufferCapacity(jenv, keyDer)) ||
532+
(outSz > (*jenv)->GetDirectBufferCapacity(jenv, out))) {
533+
return -1;
534+
}
535+
475536
wc_InitRsaKey(&myKey, NULL);
476537
idx = 0;
477538

src/test/com/wolfssl/test/WolfCryptRSATest.java

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,17 @@
2121

2222
package com.wolfssl.test;
2323

24+
import org.junit.Assume;
2425
import org.junit.BeforeClass;
2526
import org.junit.Rule;
2627
import org.junit.Test;
2728
import org.junit.rules.TestRule;
2829
import static org.junit.Assert.assertNotNull;
30+
import static org.junit.Assert.assertEquals;
2931

32+
import java.nio.ByteBuffer;
33+
34+
import com.wolfssl.WolfSSL;
3035
import com.wolfssl.WolfSSLException;
3136
import com.wolfssl.WolfCryptRSA;
3237

@@ -36,12 +41,129 @@ public class WolfCryptRSATest {
3641
public TestRule testWatcher = TimedTestWatcher.create();
3742

3843
@BeforeClass
39-
public static void beforeClass() {
44+
public static void beforeClass() throws WolfSSLException {
4045
System.out.println("WolfCryptRSA Class");
46+
WolfSSL.loadLibrary();
4147
}
4248

4349
@Test
4450
public void testRSANew() throws WolfSSLException {
4551
assertNotNull(new WolfCryptRSA());
4652
}
53+
54+
/* A size larger than its backing direct buffer must be rejected */
55+
@Test
56+
public void testDoSignRejectsOversizedSz() {
57+
Assume.assumeTrue(WolfSSL.RsaEnabled());
58+
WolfCryptRSA rsa = new WolfCryptRSA();
59+
ByteBuffer in = ByteBuffer.allocateDirect(64);
60+
ByteBuffer out = ByteBuffer.allocateDirect(256);
61+
ByteBuffer key = ByteBuffer.allocateDirect(128);
62+
63+
assertEquals(-1, rsa.doSign(in, 65, out, new int[]{256}, key, 128));
64+
assertEquals(-1, rsa.doSign(in, 64, out, new int[]{257}, key, 128));
65+
assertEquals(-1,
66+
rsa.doSign(in, 64, out, new int[]{256}, key, 0x100000000L + 16));
67+
}
68+
69+
@Test
70+
public void testDoEncRejectsOversizedSz() {
71+
Assume.assumeTrue(WolfSSL.RsaEnabled());
72+
WolfCryptRSA rsa = new WolfCryptRSA();
73+
ByteBuffer in = ByteBuffer.allocateDirect(64);
74+
ByteBuffer out = ByteBuffer.allocateDirect(256);
75+
ByteBuffer key = ByteBuffer.allocateDirect(128);
76+
77+
assertEquals(-1, rsa.doEnc(in, 65, out, new int[]{256}, key, 128));
78+
assertEquals(-1, rsa.doEnc(in, 64, out, new int[]{257}, key, 128));
79+
assertEquals(-1,
80+
rsa.doEnc(in, 64, out, new int[]{256}, key, 0x100000000L + 16));
81+
}
82+
83+
@Test
84+
public void testDoVerifyRejectsOversizedSz() {
85+
Assume.assumeTrue(WolfSSL.RsaEnabled());
86+
WolfCryptRSA rsa = new WolfCryptRSA();
87+
ByteBuffer sig = ByteBuffer.allocateDirect(64);
88+
ByteBuffer out = ByteBuffer.allocateDirect(256);
89+
ByteBuffer key = ByteBuffer.allocateDirect(128);
90+
91+
assertEquals(-1, rsa.doVerify(sig, 65, out, 256, key, 128));
92+
assertEquals(-1, rsa.doVerify(sig, 64, out, 257, key, 128));
93+
assertEquals(-1,
94+
rsa.doVerify(sig, 64, out, 256, key, 0x100000000L + 16));
95+
}
96+
97+
@Test
98+
public void testDoDecRejectsOversizedSz() {
99+
Assume.assumeTrue(WolfSSL.RsaEnabled());
100+
WolfCryptRSA rsa = new WolfCryptRSA();
101+
ByteBuffer in = ByteBuffer.allocateDirect(64);
102+
ByteBuffer out = ByteBuffer.allocateDirect(256);
103+
ByteBuffer key = ByteBuffer.allocateDirect(128);
104+
105+
assertEquals(-1, rsa.doDec(in, 65, out, 256, key, 128));
106+
assertEquals(-1, rsa.doDec(in, 64, out, 257, key, 128));
107+
assertEquals(-1,
108+
rsa.doDec(in, 64, out, 256, key, 0x100000000L + 16));
109+
}
110+
111+
/* SHA-256 hash OID sum, which wolfSSL encodes two ways depending on the
112+
* build: current default, or the legacy WOLFSSL_OLD_OID_SUM value
113+
* (see wolfSSL oid_sum.h). */
114+
private static final int SHA256_OID = 0x7cb37afb;
115+
private static final int SHA256_OID_OLD = 414;
116+
117+
/* Return a SHA-256 hash OID wc_OidGetHash accepts, or -1 if none
118+
* (PSS not compiled, or an OID-sum scheme we do not know). */
119+
private static int findPssHashOid(WolfCryptRSA rsa) {
120+
ByteBuffer b = ByteBuffer.allocateDirect(64);
121+
int[] candidates = { SHA256_OID, SHA256_OID_OLD };
122+
for (int oid : candidates) {
123+
int ret = rsa.doPssVerify(b, 64, b, 64, oid, 0, b, 64);
124+
if (ret != -1 && ret != WolfSSL.NOT_COMPILED_IN) {
125+
return oid;
126+
}
127+
}
128+
return -1;
129+
}
130+
131+
@Test
132+
public void testDoPssSignRejectsOversizedSz() {
133+
Assume.assumeTrue(WolfSSL.RsaEnabled());
134+
WolfCryptRSA rsa = new WolfCryptRSA();
135+
int oid = findPssHashOid(rsa);
136+
Assume.assumeTrue("PSS unavailable or unknown hash OID scheme",
137+
oid != -1);
138+
139+
ByteBuffer in = ByteBuffer.allocateDirect(64);
140+
ByteBuffer out = ByteBuffer.allocateDirect(256);
141+
ByteBuffer key = ByteBuffer.allocateDirect(128);
142+
143+
assertEquals(-1,
144+
rsa.doPssSign(in, 65, out, new int[]{256}, oid, 0, key, 128));
145+
assertEquals(-1,
146+
rsa.doPssSign(in, 64, out, new int[]{257}, oid, 0, key, 128));
147+
assertEquals(-1,
148+
rsa.doPssSign(in, 64, out, new int[]{256}, oid, 0, key,
149+
0x100000000L + 16));
150+
}
151+
152+
@Test
153+
public void testDoPssVerifyRejectsOversizedSz() {
154+
Assume.assumeTrue(WolfSSL.RsaEnabled());
155+
WolfCryptRSA rsa = new WolfCryptRSA();
156+
int oid = findPssHashOid(rsa);
157+
Assume.assumeTrue("PSS unavailable or unknown hash OID scheme",
158+
oid != -1);
159+
160+
ByteBuffer sig = ByteBuffer.allocateDirect(64);
161+
ByteBuffer out = ByteBuffer.allocateDirect(256);
162+
ByteBuffer key = ByteBuffer.allocateDirect(128);
163+
164+
assertEquals(-1, rsa.doPssVerify(sig, 65, out, 256, oid, 0, key, 128));
165+
assertEquals(-1, rsa.doPssVerify(sig, 64, out, 257, oid, 0, key, 128));
166+
assertEquals(-1,
167+
rsa.doPssVerify(sig, 64, out, 256, oid, 0, key, 0x100000000L + 16));
168+
}
47169
}

0 commit comments

Comments
 (0)