xref: /openbsd-src/regress/lib/libcrypto/exdata/exdata_test.c (revision eff6c37d8c4461f70ca2041c37e60ec6f0e0bbd4)
1*eff6c37dSjsing /* $OpenBSD: exdata_test.c,v 1.3 2024/10/02 14:12:21 jsing Exp $ */
24736a7f3Sjsing /*
34736a7f3Sjsing  * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
44736a7f3Sjsing  *
54736a7f3Sjsing  * Permission to use, copy, modify, and distribute this software for any
64736a7f3Sjsing  * purpose with or without fee is hereby granted, provided that the above
74736a7f3Sjsing  * copyright notice and this permission notice appear in all copies.
84736a7f3Sjsing  *
94736a7f3Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104736a7f3Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114736a7f3Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124736a7f3Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134736a7f3Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144736a7f3Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154736a7f3Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164736a7f3Sjsing  */
174736a7f3Sjsing 
184736a7f3Sjsing #include <stdio.h>
194736a7f3Sjsing #include <string.h>
204736a7f3Sjsing 
214736a7f3Sjsing #include <openssl/crypto.h>
224736a7f3Sjsing 
234736a7f3Sjsing static int ex_new_calls;
244736a7f3Sjsing static int ex_free_calls;
254736a7f3Sjsing static int ex_dup_calls;
264736a7f3Sjsing 
274736a7f3Sjsing static int
284736a7f3Sjsing ex_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl,
294736a7f3Sjsing     void *argp)
304736a7f3Sjsing {
314736a7f3Sjsing 	long *arg = argp;
324736a7f3Sjsing 
335352dbd8Sjsing 	if (ptr != NULL) {
345352dbd8Sjsing 		fprintf(stderr, "FAIL: ex_new() called with ptr != NULL\n");
355352dbd8Sjsing 		return 0;
365352dbd8Sjsing 	}
374736a7f3Sjsing 	if (argl != 1234 || *arg != 1234) {
384736a7f3Sjsing 		fprintf(stderr, "FAIL: ex_new() with bad arguments\n");
394736a7f3Sjsing 		return 0;
404736a7f3Sjsing 	}
414736a7f3Sjsing 
424736a7f3Sjsing 	ex_new_calls++;
434736a7f3Sjsing 
444736a7f3Sjsing 	return 1;
454736a7f3Sjsing }
464736a7f3Sjsing 
474736a7f3Sjsing static int
484736a7f3Sjsing ex_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d,
494736a7f3Sjsing     int idx, long argl, void *argp)
504736a7f3Sjsing {
514736a7f3Sjsing 	long *arg = argp;
524736a7f3Sjsing 
534736a7f3Sjsing 	if (argl != 1234 || *arg != 1234) {
544736a7f3Sjsing 		fprintf(stderr, "FAIL: ex_dup() with bad arguments\n");
554736a7f3Sjsing 		return 0;
564736a7f3Sjsing 	}
574736a7f3Sjsing 
584736a7f3Sjsing 	ex_dup_calls++;
594736a7f3Sjsing 
604736a7f3Sjsing 	return 1;
614736a7f3Sjsing }
624736a7f3Sjsing 
634736a7f3Sjsing static void
644736a7f3Sjsing ex_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
654736a7f3Sjsing     long argl, void *argp)
664736a7f3Sjsing {
674736a7f3Sjsing 	long *arg = argp;
684736a7f3Sjsing 
694736a7f3Sjsing 	if (argl != 1234 || *arg != 1234) {
704736a7f3Sjsing 		fprintf(stderr, "FAIL: ex_free() with bad arguments\n");
714736a7f3Sjsing 		return;
724736a7f3Sjsing 	}
734736a7f3Sjsing 
744736a7f3Sjsing 	ex_free_calls++;
754736a7f3Sjsing }
764736a7f3Sjsing 
774736a7f3Sjsing struct exdata {
784736a7f3Sjsing 	CRYPTO_EX_DATA exdata;
794736a7f3Sjsing 	int val;
804736a7f3Sjsing };
814736a7f3Sjsing 
824736a7f3Sjsing static int
834736a7f3Sjsing ex_data_test(void)
844736a7f3Sjsing {
855352dbd8Sjsing 	struct exdata exdata1, exdata2, exdata3, exdata4;
864736a7f3Sjsing 	void *argp;
874736a7f3Sjsing 	long argl;
884736a7f3Sjsing 	int idx1, idx2;
894736a7f3Sjsing 	int failed = 1;
904736a7f3Sjsing 
914736a7f3Sjsing 	memset(&exdata1, 0, sizeof(exdata1));
924736a7f3Sjsing 	memset(&exdata2, 0, sizeof(exdata2));
935352dbd8Sjsing 	memset(&exdata3, 0, sizeof(exdata3));
945352dbd8Sjsing 	memset(&exdata4, 0, sizeof(exdata4));
954736a7f3Sjsing 
964736a7f3Sjsing 	argl = 1234;
974736a7f3Sjsing 	argp = &argl;
984736a7f3Sjsing 
994736a7f3Sjsing 	if ((idx1 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
1004736a7f3Sjsing 	    ex_new, ex_dup, ex_free)) < 0) {
1014736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index failed\n");
1024736a7f3Sjsing 		goto failure;
1034736a7f3Sjsing 	}
1044736a7f3Sjsing 	if (idx1 == 0) {
1054736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned 0 "
1064736a7f3Sjsing 		    "(reserved for internal use)\n");
1074736a7f3Sjsing 		goto failure;
1084736a7f3Sjsing 	}
1094736a7f3Sjsing 
1104736a7f3Sjsing 	if ((idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, 0, NULL,
1114736a7f3Sjsing 	    NULL, NULL, NULL)) < 0) {
1124736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index failed\n");
1134736a7f3Sjsing 		goto failure;
1144736a7f3Sjsing 	}
1154736a7f3Sjsing 	if (idx1 == idx2) {
1164736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned the "
1174736a7f3Sjsing 		    "same value\n");
1184736a7f3Sjsing 		goto failure;
1194736a7f3Sjsing 	}
1204736a7f3Sjsing 	if (idx2 < idx1) {
1214736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned "
1224736a7f3Sjsing 		    "idx2 < idx1\n");
1234736a7f3Sjsing 		goto failure;
1244736a7f3Sjsing 	}
1254736a7f3Sjsing 
1264736a7f3Sjsing 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata)) {
1274736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed\n");
1284736a7f3Sjsing 		goto failure;
1294736a7f3Sjsing 	}
1304736a7f3Sjsing 
1314736a7f3Sjsing 	if (!CRYPTO_set_ex_data(&exdata1.exdata, idx2, &idx2)) {
1325352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index 2\n");
1334736a7f3Sjsing 		goto failure;
1344736a7f3Sjsing 	}
1354736a7f3Sjsing 	if (!CRYPTO_set_ex_data(&exdata1.exdata, idx1, &idx1)) {
1365352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index 1\n");
1374736a7f3Sjsing 		goto failure;
1384736a7f3Sjsing 	}
1394736a7f3Sjsing 	if (CRYPTO_get_ex_data(&exdata1.exdata, idx1) != &idx1) {
1405352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index 1\n");
1414736a7f3Sjsing 		goto failure;
1424736a7f3Sjsing 	}
1434736a7f3Sjsing 	if (CRYPTO_get_ex_data(&exdata1.exdata, idx2) != &idx2) {
1445352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index 2\n");
1454736a7f3Sjsing 		goto failure;
1464736a7f3Sjsing 	}
1474736a7f3Sjsing 
1484736a7f3Sjsing 	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2.exdata,
1494736a7f3Sjsing 	    &exdata1.exdata)) {
1505352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_dup_ex_data() failed\n");
1514736a7f3Sjsing 		goto failure;
1524736a7f3Sjsing 	}
1534736a7f3Sjsing 	if (CRYPTO_get_ex_data(&exdata2.exdata, idx1) != &idx1) {
1545352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed after dup\n");
1554736a7f3Sjsing 		goto failure;
1564736a7f3Sjsing 	}
1574736a7f3Sjsing 	if (CRYPTO_get_ex_data(&exdata2.exdata, idx2) != &idx2) {
1585352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed after dup\n");
1594736a7f3Sjsing 		goto failure;
1604736a7f3Sjsing 	}
1614736a7f3Sjsing 
1624736a7f3Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata);
1634736a7f3Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2, &exdata2.exdata);
1644736a7f3Sjsing 
1654736a7f3Sjsing 	if (ex_new_calls != 1) {
1664736a7f3Sjsing 		fprintf(stderr, "FAIL: got %d ex_new calls, want %d\n",
1674736a7f3Sjsing 		    ex_new_calls, 1);
1684736a7f3Sjsing 		goto failure;
1694736a7f3Sjsing 	}
1704736a7f3Sjsing 	if (ex_dup_calls != 1) {
1714736a7f3Sjsing 		fprintf(stderr, "FAIL: got %d ex_dup calls, want %d\n",
1724736a7f3Sjsing 		    ex_dup_calls, 1);
1734736a7f3Sjsing 		goto failure;
1744736a7f3Sjsing 	}
1754736a7f3Sjsing 	if (ex_free_calls != 2) {
1764736a7f3Sjsing 		fprintf(stderr, "FAIL: got %d ex_free calls, want %d\n",
1774736a7f3Sjsing 		    ex_free_calls, 2);
1784736a7f3Sjsing 		goto failure;
1794736a7f3Sjsing 	}
1804736a7f3Sjsing 
1815352dbd8Sjsing 	/* The current implementation allows for data to be set without new. */
1825352dbd8Sjsing 	if (!CRYPTO_set_ex_data(&exdata3.exdata, idx1, &idx1)) {
1835352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index "
1845352dbd8Sjsing 		    "1 (without new)\n");
1855352dbd8Sjsing 		goto failure;
1865352dbd8Sjsing 	}
1875352dbd8Sjsing 	if (CRYPTO_get_ex_data(&exdata3.exdata, idx1) != &idx1) {
1885352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index "
1895352dbd8Sjsing 		    "1 (without new)\n");
1905352dbd8Sjsing 		goto failure;
1915352dbd8Sjsing 	}
1925352dbd8Sjsing 
1935352dbd8Sjsing 	/* And indexes can be used without allocation. */
1945352dbd8Sjsing 	if (!CRYPTO_set_ex_data(&exdata3.exdata, idx2 + 1, &idx2)) {
1955352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index "
1965352dbd8Sjsing 		    "%d (unallocated)\n", idx2 + 1);
1975352dbd8Sjsing 		goto failure;
1985352dbd8Sjsing 	}
1995352dbd8Sjsing 	if (CRYPTO_get_ex_data(&exdata3.exdata, idx2 + 1) != &idx2) {
2005352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index "
2015352dbd8Sjsing 		    "%d\n", idx2 + 1);
2025352dbd8Sjsing 		goto failure;
2035352dbd8Sjsing 	}
2045352dbd8Sjsing 
2055352dbd8Sjsing 	/* And new can be called without getting any index first. */
2065352dbd8Sjsing 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, &exdata4, &exdata4.exdata)) {
2075352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed with "
2085352dbd8Sjsing 		    "uninitialised index\n");
2095352dbd8Sjsing 		goto failure;
2105352dbd8Sjsing 	}
2115352dbd8Sjsing 
2125352dbd8Sjsing 	/* And dup can be called after new or without new... */
2135352dbd8Sjsing 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata)) {
2145352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed\n");
2155352dbd8Sjsing 		goto failure;
2165352dbd8Sjsing 	}
2175352dbd8Sjsing 	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2.exdata,
2185352dbd8Sjsing 	    &exdata1.exdata)) {
2195352dbd8Sjsing 		fprintf(stderr, "FAIL: CRYPTO_dup_ex_data() after new failed\n");
2205352dbd8Sjsing 		goto failure;
2215352dbd8Sjsing 	}
2225352dbd8Sjsing 
2234736a7f3Sjsing 	failed = 0;
2244736a7f3Sjsing 
2254736a7f3Sjsing  failure:
2264736a7f3Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata);
2274736a7f3Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2, &exdata2.exdata);
2285352dbd8Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata3, &exdata3.exdata);
2295352dbd8Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, &exdata4, &exdata4.exdata);
2304736a7f3Sjsing 
2314736a7f3Sjsing 	return failed;
2324736a7f3Sjsing }
2334736a7f3Sjsing 
2344736a7f3Sjsing static int
2354736a7f3Sjsing ex_new_index_test(void)
2364736a7f3Sjsing {
2374736a7f3Sjsing 	int failed = 1;
2384736a7f3Sjsing 	int idx;
2394736a7f3Sjsing 
2404736a7f3Sjsing 	if ((idx = CRYPTO_get_ex_new_index(-1, 0, NULL, NULL, NULL,
2414736a7f3Sjsing 	    NULL)) > 0) {
2424736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() succeeded with "
2434736a7f3Sjsing 		    "negative class\n");
2444736a7f3Sjsing 		goto failure;
2454736a7f3Sjsing 	}
2464736a7f3Sjsing 	if ((idx = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX__COUNT, 0,
2474736a7f3Sjsing 	    NULL, NULL, NULL, NULL)) > 0) {
2484736a7f3Sjsing 		fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() succeeded with "
2494736a7f3Sjsing 		    "class exceeding maximum\n");
2504736a7f3Sjsing 		goto failure;
2514736a7f3Sjsing 	}
2524736a7f3Sjsing 
2534736a7f3Sjsing 	failed = 0;
2544736a7f3Sjsing 
2554736a7f3Sjsing  failure:
2564736a7f3Sjsing 	return failed;
2574736a7f3Sjsing }
2584736a7f3Sjsing 
2594736a7f3Sjsing int
2604736a7f3Sjsing main(int argc, char **argv)
2614736a7f3Sjsing {
2624736a7f3Sjsing 	int failed = 0;
2634736a7f3Sjsing 
2644736a7f3Sjsing 	failed |= ex_data_test();
2654736a7f3Sjsing 	failed |= ex_new_index_test();
2664736a7f3Sjsing 
2674736a7f3Sjsing 	/* Force a clean up. */
2684736a7f3Sjsing 	CRYPTO_cleanup_all_ex_data();
2694736a7f3Sjsing 
2704736a7f3Sjsing 	return failed;
2714736a7f3Sjsing }
272