@@ -1160,17 +1160,15 @@ int test_wc_RsaKeyToDer_SizeOverflow(void)
11601160 EXPECT_DECLS ;
11611161#if !defined(NO_RSA ) && defined(USE_INTEGER_HEAP_MATH ) && \
11621162 defined(WOLFSSL_ASN_TEMPLATE ) && \
1163- (defined(WOLFSSL_KEY_GEN ) || defined(WOLFSSL_KEY_TO_DER )) && \
1164- !defined(_WIN32 )
1165- #include <sys/mman.h>
1163+ (defined(WOLFSSL_KEY_GEN ) || defined(WOLFSSL_KEY_TO_DER ))
11661164 RsaKey key ;
11671165 int i ;
11681166 int derRet ;
11691167 int crafted_used ;
11701168 int top_bits ;
11711169 mp_digit top_digit ;
1172- mp_digit * crafted_dp = MAP_FAILED ;
1173- size_t dp_bytes = 0 ;
1170+ mp_digit storage = 0 ; /* the only digit mp_count_bits ever reads */
1171+ mp_digit * fake_dp = NULL ;
11741172
11751173 int orig_used = 0 ;
11761174 int orig_alloc = 0 ;
@@ -1181,6 +1179,11 @@ int test_wc_RsaKeyToDer_SizeOverflow(void)
11811179
11821180 XMEMSET (& key , 0 , sizeof (key ));
11831181
1182+ /* Skip on 32-bit: biasing dp by ~half the address space is unsafe. */
1183+ if (sizeof (void * ) < 8 ) {
1184+ return TEST_SKIPPED ;
1185+ }
1186+
11841187 /* Find 'used' count that makes (used-1)*DIGIT_BIT + top_bits = -48
11851188 * as signed int, causing mp_unsigned_bin_size to return -6. */
11861189 {
@@ -1205,8 +1208,6 @@ int test_wc_RsaKeyToDer_SizeOverflow(void)
12051208 }
12061209 }
12071210
1208- dp_bytes = (size_t )crafted_used * sizeof (mp_digit );
1209-
12101211 ExpectIntEQ (wc_InitRsaKey (& key , HEAP_HINT ), 0 );
12111212
12121213 /* Set up dummy RSA private key fields. */
@@ -1234,31 +1235,20 @@ int test_wc_RsaKeyToDer_SizeOverflow(void)
12341235 orig_dp = key .p .dp ;
12351236 }
12361237
1237- /* Sparse mmap — only the page at dp[used-1] is faulted in. */
1238+ /* The vulnerable path (mp_unsigned_bin_size -> mp_count_bits, and
1239+ * mp_leading_bit) only reads dp[used-1]. Bias dp so that index
1240+ * (used-1) lands on our single real digit -- no giant allocation
1241+ * (and no mmap/VirtualAlloc) needed. */
12381242 if (EXPECT_SUCCESS ()) {
1239- crafted_dp = (mp_digit * )mmap (NULL , dp_bytes ,
1240- PROT_READ | PROT_WRITE ,
1241- MAP_PRIVATE | MAP_ANONYMOUS
1242- #ifdef MAP_NORESERVE
1243- | MAP_NORESERVE
1244- #endif
1245- , -1 , 0 );
1243+ storage = top_digit ;
1244+ fake_dp = (mp_digit * )((wc_ptr_t )& storage
1245+ - (wc_ptr_t )(crafted_used - 1 ) * sizeof (mp_digit ));
1246+
1247+ key .p .dp = fake_dp ;
1248+ key .p .used = crafted_used ;
1249+ key .p .alloc = crafted_used ;
1250+ key .p .sign = 0 ; /* MP_ZPOS */
12461251 }
1247- if (crafted_dp == MAP_FAILED ) {
1248- key .p .dp = orig_dp ;
1249- key .p .used = orig_used ;
1250- key .p .alloc = orig_alloc ;
1251- key .p .sign = orig_sign ;
1252- DoExpectIntEQ (wc_FreeRsaKey (& key ), 0 );
1253- return TEST_SKIPPED ;
1254- }
1255-
1256- crafted_dp [crafted_used - 1 ] = top_digit ;
1257-
1258- key .p .dp = crafted_dp ;
1259- key .p .used = crafted_used ;
1260- key .p .alloc = crafted_used ;
1261- key .p .sign = 0 ; /* MP_ZPOS */
12621252
12631253 /* Should return an error, not a bogus small size. */
12641254 derRet = wc_RsaKeyToDer (& key , NULL , 0 );
@@ -1270,10 +1260,6 @@ int test_wc_RsaKeyToDer_SizeOverflow(void)
12701260 key .p .alloc = orig_alloc ;
12711261 key .p .sign = orig_sign ;
12721262
1273- if (crafted_dp != MAP_FAILED ) {
1274- munmap (crafted_dp , dp_bytes );
1275- }
1276-
12771263 DoExpectIntEQ (wc_FreeRsaKey (& key ), 0 );
12781264#endif
12791265 return EXPECT_RESULT ();
0 commit comments