xref: /openbsd-src/regress/lib/libcrypto/rsa/rsa_padding_test.c (revision e10c7425818047f2f5dbec51b5086d21c1b11636)
1*e10c7425Sjsing /*	$OpenBSD: rsa_padding_test.c,v 1.2 2024/03/30 02:20:39 jsing Exp $	*/
26e3e576cSjsing /*
36e3e576cSjsing  * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
46e3e576cSjsing  *
56e3e576cSjsing  * Permission to use, copy, modify, and distribute this software for any
66e3e576cSjsing  * purpose with or without fee is hereby granted, provided that the above
76e3e576cSjsing  * copyright notice and this permission notice appear in all copies.
86e3e576cSjsing  *
96e3e576cSjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
106e3e576cSjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
116e3e576cSjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
126e3e576cSjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
136e3e576cSjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
146e3e576cSjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
156e3e576cSjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
166e3e576cSjsing  */
176e3e576cSjsing 
186e3e576cSjsing #include <stdint.h>
196e3e576cSjsing #include <string.h>
206e3e576cSjsing 
216e3e576cSjsing #include <openssl/err.h>
226e3e576cSjsing #include <openssl/rsa.h>
236e3e576cSjsing 
246e3e576cSjsing #if 0
256e3e576cSjsing static void
266e3e576cSjsing hexdump(const unsigned char *buf, size_t len)
276e3e576cSjsing {
286e3e576cSjsing 	size_t i;
296e3e576cSjsing 
306e3e576cSjsing 	for (i = 1; i <= len; i++)
316e3e576cSjsing 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
326e3e576cSjsing 
336e3e576cSjsing 	fprintf(stderr, "\n");
346e3e576cSjsing }
356e3e576cSjsing #endif
366e3e576cSjsing 
376e3e576cSjsing struct pkcs1_test {
386e3e576cSjsing 	uint8_t in[128];
396e3e576cSjsing 	size_t in_len;
406e3e576cSjsing 	int want;
416e3e576cSjsing 	int want_error;
426e3e576cSjsing };
436e3e576cSjsing 
446e3e576cSjsing static const struct pkcs1_test pkcs1_type1_tests[] = {
456e3e576cSjsing 	{
466e3e576cSjsing 		.in = {
476e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
486e3e576cSjsing 			0xff, 0xff, 0xff, 0xff, 0x00, 0x6f, 0x6f, 0x6f,
496e3e576cSjsing 			0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
506e3e576cSjsing 			0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
516e3e576cSjsing 		},
526e3e576cSjsing 		.in_len = 32,
536e3e576cSjsing 		.want = 19,
546e3e576cSjsing 	},
556e3e576cSjsing 	{
566e3e576cSjsing 		.in = {
576e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
586e3e576cSjsing 			0xff, 0xff, 0x00,
596e3e576cSjsing 		},
606e3e576cSjsing 		.in_len = 11,
616e3e576cSjsing 		.want = 0,
626e3e576cSjsing 	},
636e3e576cSjsing 	{
646e3e576cSjsing 		.in = {
656e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
666e3e576cSjsing 			0xff, 0xff, 0x00, 0xff,
676e3e576cSjsing 		},
686e3e576cSjsing 		.in_len = 12,
696e3e576cSjsing 		.want = 1,
706e3e576cSjsing 	},
716e3e576cSjsing 	{
726e3e576cSjsing 		/* Insufficient padding bytes (< 8). */
736e3e576cSjsing 		.in = {
746e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
756e3e576cSjsing 			0xff, 0x00, 0xff, 0xff,
766e3e576cSjsing 		},
776e3e576cSjsing 		.in_len = 12,
786e3e576cSjsing 		.want = -1,
796e3e576cSjsing 		.want_error = RSA_R_BAD_PAD_BYTE_COUNT,
806e3e576cSjsing 	},
816e3e576cSjsing 	{
826e3e576cSjsing 		/* Incorrect padding type (0x00). */
836e3e576cSjsing 		.in = {
846e3e576cSjsing 			0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
856e3e576cSjsing 			0xff, 0xff, 0x00, 0xff,
866e3e576cSjsing 		},
876e3e576cSjsing 		.in_len = 12,
886e3e576cSjsing 		.want = -1,
896e3e576cSjsing 		.want_error = RSA_R_BLOCK_TYPE_IS_NOT_01,
906e3e576cSjsing 	},
916e3e576cSjsing 	{
926e3e576cSjsing 		/* Incorrect padding type (0x02). */
936e3e576cSjsing 		.in = {
946e3e576cSjsing 			0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
956e3e576cSjsing 			0xff, 0xff, 0x00, 0xff,
966e3e576cSjsing 		},
976e3e576cSjsing 		.in_len = 12,
986e3e576cSjsing 		.want = -1,
996e3e576cSjsing 		.want_error = RSA_R_BLOCK_TYPE_IS_NOT_01,
1006e3e576cSjsing 	},
1016e3e576cSjsing 	{
1026e3e576cSjsing 		/* Non-padding byte before end of padding marker. */
1036e3e576cSjsing 		.in = {
1046e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1056e3e576cSjsing 			0xff, 0xfe, 0x00, 0xff,
1066e3e576cSjsing 		},
1076e3e576cSjsing 		.in_len = 12,
1086e3e576cSjsing 		.want = -1,
1096e3e576cSjsing 		.want_error = RSA_R_BAD_FIXED_HEADER_DECRYPT,
1106e3e576cSjsing 	},
1116e3e576cSjsing 	{
1126e3e576cSjsing 		/* No end of padding marker. */
1136e3e576cSjsing 		.in = {
1146e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1156e3e576cSjsing 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1166e3e576cSjsing 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1176e3e576cSjsing 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1186e3e576cSjsing 		},
1196e3e576cSjsing 		.in_len = 32,
1206e3e576cSjsing 		.want = -1,
1216e3e576cSjsing 		.want_error = RSA_R_NULL_BEFORE_BLOCK_MISSING,
1226e3e576cSjsing 	},
1236e3e576cSjsing };
1246e3e576cSjsing 
1256e3e576cSjsing #define N_PKCS1_TYPE1_TESTS \
1266e3e576cSjsing 	(sizeof(pkcs1_type1_tests) / sizeof(pkcs1_type1_tests[0]))
1276e3e576cSjsing 
1286e3e576cSjsing static int
test_pkcs1_type1(void)1296e3e576cSjsing test_pkcs1_type1(void)
1306e3e576cSjsing {
1316e3e576cSjsing 	const struct pkcs1_test *pt;
1326e3e576cSjsing 	uint8_t buf[32], in[19], out[512];
1336e3e576cSjsing 	int pad_len;
1346e3e576cSjsing 	long err;
1356e3e576cSjsing 	size_t i;
1366e3e576cSjsing 	int failed = 1;
1376e3e576cSjsing 
138*e10c7425Sjsing 	for (i = 0; i < 1000; i++) {
139*e10c7425Sjsing 		arc4random_buf(in, sizeof(in));
1406e3e576cSjsing 
141*e10c7425Sjsing 		if (!RSA_padding_add_PKCS1_type_1(buf, sizeof(buf), in,
142*e10c7425Sjsing 		    sizeof(in))) {
143*e10c7425Sjsing 			fprintf(stderr, "FAIL: failed to add PKCS1 type 1 "
144*e10c7425Sjsing 			    "padding\n");
1456e3e576cSjsing 			goto failed;
1466e3e576cSjsing 		}
1476e3e576cSjsing 
1486e3e576cSjsing 		pad_len = RSA_padding_check_PKCS1_type_1(out, sizeof(out) - 1,
1496e3e576cSjsing 		    buf + 1, sizeof(buf) - 1, sizeof(buf));
1506e3e576cSjsing 		if (pad_len != sizeof(in)) {
151*e10c7425Sjsing 			fprintf(stderr, "FAIL: failed to check PKCS1 type 1 "
152*e10c7425Sjsing 			    "padding\n");
1536e3e576cSjsing 			ERR_print_errors_fp(stderr);
1546e3e576cSjsing 			goto failed;
1556e3e576cSjsing 		}
156*e10c7425Sjsing 	}
1576e3e576cSjsing 
1586e3e576cSjsing 	for (i = 0; i < N_PKCS1_TYPE1_TESTS; i++) {
1596e3e576cSjsing 		pt = &pkcs1_type1_tests[i];
1606e3e576cSjsing 
1616e3e576cSjsing 		ERR_clear_error();
1626e3e576cSjsing 
1636e3e576cSjsing 		pad_len = RSA_padding_check_PKCS1_type_1(out, sizeof(out) - 1,
1646e3e576cSjsing 		    pt->in + 1, pt->in_len - 1, pt->in_len);
1656e3e576cSjsing 
1666e3e576cSjsing 		if (pad_len != pt->want) {
1676e3e576cSjsing 			fprintf(stderr, "FAIL: test %zu - failed to check "
1686e3e576cSjsing 			    "PKCS1 type 1 padding (%d != %d)\n", i, pad_len,
1696e3e576cSjsing 			    pt->want);
1706e3e576cSjsing 			ERR_print_errors_fp(stderr);
1716e3e576cSjsing 			goto failed;
1726e3e576cSjsing 		}
1736e3e576cSjsing 
1746e3e576cSjsing 		err = ERR_peek_error();
1756e3e576cSjsing 		if (pt->want == -1 && ERR_GET_REASON(err) != pt->want_error) {
1766e3e576cSjsing 			fprintf(stderr, "FAIL: test %zu - PKCS1 type 1 padding "
1776e3e576cSjsing 			    "check failed with error reason %i, want %i\n",
1786e3e576cSjsing 			    i, ERR_GET_REASON(err), pt->want_error);
1796e3e576cSjsing 			ERR_print_errors_fp(stderr);
1806e3e576cSjsing 			goto failed;
1816e3e576cSjsing 		}
1826e3e576cSjsing 	}
1836e3e576cSjsing 
1846e3e576cSjsing 	failed = 0;
1856e3e576cSjsing 
1866e3e576cSjsing  failed:
1876e3e576cSjsing 	return failed;
1886e3e576cSjsing }
1896e3e576cSjsing 
1906e3e576cSjsing static const struct pkcs1_test pkcs1_type2_tests[] = {
1916e3e576cSjsing 	{
1926e3e576cSjsing 		.in = {
1936e3e576cSjsing 			0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1946e3e576cSjsing 			0xff, 0xff, 0xff, 0xff, 0x00, 0x6f, 0x6f, 0x6f,
1956e3e576cSjsing 			0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
1966e3e576cSjsing 			0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
1976e3e576cSjsing 		},
1986e3e576cSjsing 		.in_len = 32,
1996e3e576cSjsing 		.want = 19,
2006e3e576cSjsing 	},
2016e3e576cSjsing 	{
2026e3e576cSjsing 		.in = {
2036e3e576cSjsing 			0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2046e3e576cSjsing 			0xff, 0xff, 0x00,
2056e3e576cSjsing 		},
2066e3e576cSjsing 		.in_len = 11,
2076e3e576cSjsing 		.want = 0,
2086e3e576cSjsing 	},
2096e3e576cSjsing 	{
2106e3e576cSjsing 		.in = {
2116e3e576cSjsing 			0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2126e3e576cSjsing 			0xff, 0xff, 0x00, 0xff,
2136e3e576cSjsing 		},
2146e3e576cSjsing 		.in_len = 12,
2156e3e576cSjsing 		.want = 1,
2166e3e576cSjsing 	},
2176e3e576cSjsing 	{
2186e3e576cSjsing 		/* Insufficient padding bytes (< 8). */
2196e3e576cSjsing 		.in = {
2206e3e576cSjsing 			0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2216e3e576cSjsing 			0xff, 0x00, 0xff, 0xff,
2226e3e576cSjsing 		},
2236e3e576cSjsing 		.in_len = 12,
2246e3e576cSjsing 		.want = -1,
2256e3e576cSjsing 		.want_error = RSA_R_BAD_PAD_BYTE_COUNT,
2266e3e576cSjsing 	},
2276e3e576cSjsing 	{
2286e3e576cSjsing 		/* Incorrect padding type (0x00). */
2296e3e576cSjsing 		.in = {
2306e3e576cSjsing 			0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2316e3e576cSjsing 			0xff, 0xff, 0x00, 0xff,
2326e3e576cSjsing 		},
2336e3e576cSjsing 		.in_len = 12,
2346e3e576cSjsing 		.want = -1,
2356e3e576cSjsing 		.want_error = RSA_R_BLOCK_TYPE_IS_NOT_02,
2366e3e576cSjsing 	},
2376e3e576cSjsing 	{
2386e3e576cSjsing 		/* Incorrect padding type (0x01). */
2396e3e576cSjsing 		.in = {
2406e3e576cSjsing 			0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2416e3e576cSjsing 			0xff, 0xff, 0x00, 0xff,
2426e3e576cSjsing 		},
2436e3e576cSjsing 		.in_len = 12,
2446e3e576cSjsing 		.want = -1,
2456e3e576cSjsing 		.want_error = RSA_R_BLOCK_TYPE_IS_NOT_02,
2466e3e576cSjsing 	},
2476e3e576cSjsing 	{
2486e3e576cSjsing 		/* No end of padding marker. */
2496e3e576cSjsing 		.in = {
2506e3e576cSjsing 			0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2516e3e576cSjsing 			0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x6f, 0x6f,
2526e3e576cSjsing 			0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
2536e3e576cSjsing 			0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
2546e3e576cSjsing 		},
2556e3e576cSjsing 		.in_len = 32,
2566e3e576cSjsing 		.want = -1,
2576e3e576cSjsing 		.want_error = RSA_R_NULL_BEFORE_BLOCK_MISSING,
2586e3e576cSjsing 	},
2596e3e576cSjsing };
2606e3e576cSjsing 
2616e3e576cSjsing #define N_PKCS1_TYPE2_TESTS \
2626e3e576cSjsing 	(sizeof(pkcs1_type2_tests) / sizeof(pkcs1_type2_tests[0]))
2636e3e576cSjsing 
2646e3e576cSjsing static int
test_pkcs1_type2(void)2656e3e576cSjsing test_pkcs1_type2(void)
2666e3e576cSjsing {
2676e3e576cSjsing 	const struct pkcs1_test *pt;
268*e10c7425Sjsing 	uint8_t buf[32], in[19], out[512];
2696e3e576cSjsing 	int pad_len;
2706e3e576cSjsing 	long err;
2716e3e576cSjsing 	size_t i;
2726e3e576cSjsing 	int failed = 1;
2736e3e576cSjsing 
274*e10c7425Sjsing 	for (i = 0; i < 1000; i++) {
275*e10c7425Sjsing 		arc4random_buf(in, sizeof(in));
2766e3e576cSjsing 
277*e10c7425Sjsing 		if (!RSA_padding_add_PKCS1_type_2(buf, sizeof(buf), in,
278*e10c7425Sjsing 		    sizeof(in))) {
279*e10c7425Sjsing 			fprintf(stderr, "FAIL: failed to add PKCS1 type 2 "
280*e10c7425Sjsing 			    "padding\n");
2816e3e576cSjsing 			goto failed;
2826e3e576cSjsing 		}
2836e3e576cSjsing 
2846e3e576cSjsing 		pad_len = RSA_padding_check_PKCS1_type_2(out, sizeof(out) - 1,
285*e10c7425Sjsing 		    buf + 1, sizeof(buf) - 1, sizeof(buf));
2866e3e576cSjsing 		if (pad_len != sizeof(in)) {
287*e10c7425Sjsing 			fprintf(stderr, "FAIL: failed to check PKCS1 type 2 "
288*e10c7425Sjsing 			    "padding\n");
2896e3e576cSjsing 			ERR_print_errors_fp(stderr);
2906e3e576cSjsing 			goto failed;
2916e3e576cSjsing 		}
292*e10c7425Sjsing 	}
2936e3e576cSjsing 
2946e3e576cSjsing 	for (i = 0; i < N_PKCS1_TYPE2_TESTS; i++) {
2956e3e576cSjsing 		pt = &pkcs1_type2_tests[i];
2966e3e576cSjsing 
2976e3e576cSjsing 		ERR_clear_error();
2986e3e576cSjsing 
2996e3e576cSjsing 		pad_len = RSA_padding_check_PKCS1_type_2(out, sizeof(out) - 1,
3006e3e576cSjsing 		    pt->in + 1, pt->in_len - 1, pt->in_len);
3016e3e576cSjsing 
3026e3e576cSjsing 		if (pad_len != pt->want) {
3036e3e576cSjsing 			fprintf(stderr, "FAIL: test %zu - failed to check "
3046e3e576cSjsing 			    "PKCS1 type 2 padding (%d != %d)\n", i, pad_len,
3056e3e576cSjsing 			    pt->want);
3066e3e576cSjsing 			ERR_print_errors_fp(stderr);
3076e3e576cSjsing 			goto failed;
3086e3e576cSjsing 		}
3096e3e576cSjsing 
3106e3e576cSjsing 		err = ERR_peek_error();
3116e3e576cSjsing 		if (pt->want == -1 && ERR_GET_REASON(err) != pt->want_error) {
3126e3e576cSjsing 			fprintf(stderr, "FAIL: test %zu - PKCS1 type 2 padding "
3136e3e576cSjsing 			    "check failed with error reason %i, want %i\n",
3146e3e576cSjsing 			    i, ERR_GET_REASON(err), pt->want_error);
3156e3e576cSjsing 			ERR_print_errors_fp(stderr);
3166e3e576cSjsing 			goto failed;
3176e3e576cSjsing 		}
3186e3e576cSjsing 	}
3196e3e576cSjsing 
3206e3e576cSjsing 	failed = 0;
3216e3e576cSjsing 
3226e3e576cSjsing  failed:
3236e3e576cSjsing 	return failed;
3246e3e576cSjsing }
3256e3e576cSjsing 
3266e3e576cSjsing int
main(int argc,char ** argv)3276e3e576cSjsing main(int argc, char **argv)
3286e3e576cSjsing {
3296e3e576cSjsing 	int failed = 0;
3306e3e576cSjsing 
3316e3e576cSjsing 	failed |= test_pkcs1_type1();
3326e3e576cSjsing 	failed |= test_pkcs1_type2();
3336e3e576cSjsing 
3346e3e576cSjsing 	return failed;
3356e3e576cSjsing }
336