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