1 /* $OpenBSD: exdata_test.c,v 1.3 2024/10/02 14:12:21 jsing Exp $ */ 2 /* 3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdio.h> 19 #include <string.h> 20 21 #include <openssl/crypto.h> 22 23 static int ex_new_calls; 24 static int ex_free_calls; 25 static int ex_dup_calls; 26 27 static int 28 ex_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, 29 void *argp) 30 { 31 long *arg = argp; 32 33 if (ptr != NULL) { 34 fprintf(stderr, "FAIL: ex_new() called with ptr != NULL\n"); 35 return 0; 36 } 37 if (argl != 1234 || *arg != 1234) { 38 fprintf(stderr, "FAIL: ex_new() with bad arguments\n"); 39 return 0; 40 } 41 42 ex_new_calls++; 43 44 return 1; 45 } 46 47 static int 48 ex_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, 49 int idx, long argl, void *argp) 50 { 51 long *arg = argp; 52 53 if (argl != 1234 || *arg != 1234) { 54 fprintf(stderr, "FAIL: ex_dup() with bad arguments\n"); 55 return 0; 56 } 57 58 ex_dup_calls++; 59 60 return 1; 61 } 62 63 static void 64 ex_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, 65 long argl, void *argp) 66 { 67 long *arg = argp; 68 69 if (argl != 1234 || *arg != 1234) { 70 fprintf(stderr, "FAIL: ex_free() with bad arguments\n"); 71 return; 72 } 73 74 ex_free_calls++; 75 } 76 77 struct exdata { 78 CRYPTO_EX_DATA exdata; 79 int val; 80 }; 81 82 static int 83 ex_data_test(void) 84 { 85 struct exdata exdata1, exdata2, exdata3, exdata4; 86 void *argp; 87 long argl; 88 int idx1, idx2; 89 int failed = 1; 90 91 memset(&exdata1, 0, sizeof(exdata1)); 92 memset(&exdata2, 0, sizeof(exdata2)); 93 memset(&exdata3, 0, sizeof(exdata3)); 94 memset(&exdata4, 0, sizeof(exdata4)); 95 96 argl = 1234; 97 argp = &argl; 98 99 if ((idx1 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp, 100 ex_new, ex_dup, ex_free)) < 0) { 101 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index failed\n"); 102 goto failure; 103 } 104 if (idx1 == 0) { 105 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned 0 " 106 "(reserved for internal use)\n"); 107 goto failure; 108 } 109 110 if ((idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, 0, NULL, 111 NULL, NULL, NULL)) < 0) { 112 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index failed\n"); 113 goto failure; 114 } 115 if (idx1 == idx2) { 116 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned the " 117 "same value\n"); 118 goto failure; 119 } 120 if (idx2 < idx1) { 121 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned " 122 "idx2 < idx1\n"); 123 goto failure; 124 } 125 126 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata)) { 127 fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed\n"); 128 goto failure; 129 } 130 131 if (!CRYPTO_set_ex_data(&exdata1.exdata, idx2, &idx2)) { 132 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index 2\n"); 133 goto failure; 134 } 135 if (!CRYPTO_set_ex_data(&exdata1.exdata, idx1, &idx1)) { 136 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index 1\n"); 137 goto failure; 138 } 139 if (CRYPTO_get_ex_data(&exdata1.exdata, idx1) != &idx1) { 140 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index 1\n"); 141 goto failure; 142 } 143 if (CRYPTO_get_ex_data(&exdata1.exdata, idx2) != &idx2) { 144 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index 2\n"); 145 goto failure; 146 } 147 148 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2.exdata, 149 &exdata1.exdata)) { 150 fprintf(stderr, "FAIL: CRYPTO_dup_ex_data() failed\n"); 151 goto failure; 152 } 153 if (CRYPTO_get_ex_data(&exdata2.exdata, idx1) != &idx1) { 154 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed after dup\n"); 155 goto failure; 156 } 157 if (CRYPTO_get_ex_data(&exdata2.exdata, idx2) != &idx2) { 158 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed after dup\n"); 159 goto failure; 160 } 161 162 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata); 163 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2, &exdata2.exdata); 164 165 if (ex_new_calls != 1) { 166 fprintf(stderr, "FAIL: got %d ex_new calls, want %d\n", 167 ex_new_calls, 1); 168 goto failure; 169 } 170 if (ex_dup_calls != 1) { 171 fprintf(stderr, "FAIL: got %d ex_dup calls, want %d\n", 172 ex_dup_calls, 1); 173 goto failure; 174 } 175 if (ex_free_calls != 2) { 176 fprintf(stderr, "FAIL: got %d ex_free calls, want %d\n", 177 ex_free_calls, 2); 178 goto failure; 179 } 180 181 /* The current implementation allows for data to be set without new. */ 182 if (!CRYPTO_set_ex_data(&exdata3.exdata, idx1, &idx1)) { 183 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index " 184 "1 (without new)\n"); 185 goto failure; 186 } 187 if (CRYPTO_get_ex_data(&exdata3.exdata, idx1) != &idx1) { 188 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index " 189 "1 (without new)\n"); 190 goto failure; 191 } 192 193 /* And indexes can be used without allocation. */ 194 if (!CRYPTO_set_ex_data(&exdata3.exdata, idx2 + 1, &idx2)) { 195 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index " 196 "%d (unallocated)\n", idx2 + 1); 197 goto failure; 198 } 199 if (CRYPTO_get_ex_data(&exdata3.exdata, idx2 + 1) != &idx2) { 200 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index " 201 "%d\n", idx2 + 1); 202 goto failure; 203 } 204 205 /* And new can be called without getting any index first. */ 206 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, &exdata4, &exdata4.exdata)) { 207 fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed with " 208 "uninitialised index\n"); 209 goto failure; 210 } 211 212 /* And dup can be called after new or without new... */ 213 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata)) { 214 fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed\n"); 215 goto failure; 216 } 217 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2.exdata, 218 &exdata1.exdata)) { 219 fprintf(stderr, "FAIL: CRYPTO_dup_ex_data() after new failed\n"); 220 goto failure; 221 } 222 223 failed = 0; 224 225 failure: 226 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata); 227 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2, &exdata2.exdata); 228 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata3, &exdata3.exdata); 229 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, &exdata4, &exdata4.exdata); 230 231 return failed; 232 } 233 234 static int 235 ex_new_index_test(void) 236 { 237 int failed = 1; 238 int idx; 239 240 if ((idx = CRYPTO_get_ex_new_index(-1, 0, NULL, NULL, NULL, 241 NULL)) > 0) { 242 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() succeeded with " 243 "negative class\n"); 244 goto failure; 245 } 246 if ((idx = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX__COUNT, 0, 247 NULL, NULL, NULL, NULL)) > 0) { 248 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() succeeded with " 249 "class exceeding maximum\n"); 250 goto failure; 251 } 252 253 failed = 0; 254 255 failure: 256 return failed; 257 } 258 259 int 260 main(int argc, char **argv) 261 { 262 int failed = 0; 263 264 failed |= ex_data_test(); 265 failed |= ex_new_index_test(); 266 267 /* Force a clean up. */ 268 CRYPTO_cleanup_all_ex_data(); 269 270 return failed; 271 } 272