1 /* 2 * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <string.h> 12 #include <stdlib.h> 13 #include <openssl/crypto.h> 14 15 #include "testutil.h" 16 17 static long saved_argl; 18 static void *saved_argp; 19 static int saved_idx; 20 static int saved_idx2; 21 static int saved_idx3; 22 static int gbl_result; 23 24 /* 25 * SIMPLE EX_DATA IMPLEMENTATION 26 * Apps explicitly set/get ex_data as needed 27 */ 28 29 static void exnew(void *parent, void *ptr, CRYPTO_EX_DATA *ad, 30 int idx, long argl, void *argp) 31 { 32 if (!TEST_int_eq(idx, saved_idx) 33 || !TEST_long_eq(argl, saved_argl) 34 || !TEST_ptr_eq(argp, saved_argp) 35 || !TEST_ptr_null(ptr)) 36 gbl_result = 0; 37 } 38 39 static int exdup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, 40 void **from_d, int idx, long argl, void *argp) 41 { 42 if (!TEST_int_eq(idx, saved_idx) 43 || !TEST_long_eq(argl, saved_argl) 44 || !TEST_ptr_eq(argp, saved_argp) 45 || !TEST_ptr(from_d)) 46 gbl_result = 0; 47 return 1; 48 } 49 50 static void exfree(void *parent, void *ptr, CRYPTO_EX_DATA *ad, 51 int idx, long argl, void *argp) 52 { 53 if (!TEST_int_eq(idx, saved_idx) 54 || !TEST_long_eq(argl, saved_argl) 55 || !TEST_ptr_eq(argp, saved_argp)) 56 gbl_result = 0; 57 } 58 59 /* 60 * PRE-ALLOCATED EX_DATA IMPLEMENTATION 61 * Extended data structure is allocated in exnew2/freed in exfree2 62 * Data is stored inside extended data structure 63 */ 64 65 typedef struct myobj_ex_data_st { 66 char *hello; 67 int new; 68 int dup; 69 } MYOBJ_EX_DATA; 70 71 static void exnew2(void *parent, void *ptr, CRYPTO_EX_DATA *ad, 72 int idx, long argl, void *argp) 73 { 74 MYOBJ_EX_DATA *ex_data = OPENSSL_zalloc(sizeof(*ex_data)); 75 76 if (!TEST_true(idx == saved_idx2 || idx == saved_idx3) 77 || !TEST_long_eq(argl, saved_argl) 78 || !TEST_ptr_eq(argp, saved_argp) 79 || !TEST_ptr_null(ptr) 80 || !TEST_ptr(ex_data) 81 || !TEST_true(CRYPTO_set_ex_data(ad, idx, ex_data))) { 82 gbl_result = 0; 83 OPENSSL_free(ex_data); 84 } else { 85 ex_data->new = 1; 86 } 87 } 88 89 static int exdup2(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, 90 void **from_d, int idx, long argl, void *argp) 91 { 92 MYOBJ_EX_DATA **update_ex_data = (MYOBJ_EX_DATA**)from_d; 93 MYOBJ_EX_DATA *ex_data = NULL; 94 95 if (!TEST_true(idx == saved_idx2 || idx == saved_idx3) 96 || !TEST_long_eq(argl, saved_argl) 97 || !TEST_ptr_eq(argp, saved_argp) 98 || !TEST_ptr(from_d) 99 || !TEST_ptr(*update_ex_data) 100 || !TEST_ptr(ex_data = CRYPTO_get_ex_data(to, idx)) 101 || !TEST_true(ex_data->new)) { 102 gbl_result = 0; 103 } else { 104 /* Copy hello over */ 105 ex_data->hello = (*update_ex_data)->hello; 106 /* indicate this is a dup */ 107 ex_data->dup = 1; 108 /* Keep my original ex_data */ 109 *update_ex_data = ex_data; 110 } 111 return 1; 112 } 113 114 static void exfree2(void *parent, void *ptr, CRYPTO_EX_DATA *ad, 115 int idx, long argl, void *argp) 116 { 117 MYOBJ_EX_DATA *ex_data = CRYPTO_get_ex_data(ad, idx); 118 119 if (!TEST_true(idx == saved_idx2 || idx == saved_idx3) 120 || !TEST_long_eq(argl, saved_argl) 121 || !TEST_ptr_eq(argp, saved_argp) 122 || !TEST_true(CRYPTO_set_ex_data(ad, idx, NULL))) 123 gbl_result = 0; 124 OPENSSL_free(ex_data); 125 } 126 127 typedef struct myobj_st { 128 CRYPTO_EX_DATA ex_data; 129 int id; 130 int st; 131 } MYOBJ; 132 133 static MYOBJ *MYOBJ_new(void) 134 { 135 static int count = 0; 136 MYOBJ *obj = OPENSSL_malloc(sizeof(*obj)); 137 138 if (obj != NULL) { 139 obj->id = ++count; 140 obj->st = CRYPTO_new_ex_data(CRYPTO_EX_INDEX_APP, obj, &obj->ex_data); 141 } 142 return obj; 143 } 144 145 static void MYOBJ_sethello(MYOBJ *obj, char *cp) 146 { 147 obj->st = CRYPTO_set_ex_data(&obj->ex_data, saved_idx, cp); 148 if (!TEST_int_eq(obj->st, 1)) 149 gbl_result = 0; 150 } 151 152 static char *MYOBJ_gethello(MYOBJ *obj) 153 { 154 return CRYPTO_get_ex_data(&obj->ex_data, saved_idx); 155 } 156 157 static void MYOBJ_sethello2(MYOBJ *obj, char *cp) 158 { 159 MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx2); 160 161 if (TEST_ptr(ex_data)) 162 ex_data->hello = cp; 163 else 164 obj->st = gbl_result = 0; 165 } 166 167 static char *MYOBJ_gethello2(MYOBJ *obj) 168 { 169 MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx2); 170 171 if (TEST_ptr(ex_data)) 172 return ex_data->hello; 173 174 obj->st = gbl_result = 0; 175 return NULL; 176 } 177 178 static void MYOBJ_allochello3(MYOBJ *obj, char *cp) 179 { 180 MYOBJ_EX_DATA* ex_data = NULL; 181 182 if (TEST_ptr_null(ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx3)) 183 && TEST_true(CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_APP, obj, 184 &obj->ex_data, saved_idx3)) 185 && TEST_ptr(ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx3))) 186 ex_data->hello = cp; 187 else 188 obj->st = gbl_result = 0; 189 } 190 191 static char *MYOBJ_gethello3(MYOBJ *obj) 192 { 193 MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx3); 194 195 if (TEST_ptr(ex_data)) 196 return ex_data->hello; 197 198 obj->st = gbl_result = 0; 199 return NULL; 200 } 201 202 static void MYOBJ_free(MYOBJ *obj) 203 { 204 if (obj != NULL) { 205 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_APP, obj, &obj->ex_data); 206 OPENSSL_free(obj); 207 } 208 } 209 210 static MYOBJ *MYOBJ_dup(MYOBJ *in) 211 { 212 MYOBJ *obj = MYOBJ_new(); 213 214 if (obj != NULL) 215 obj->st |= CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_APP, &obj->ex_data, 216 &in->ex_data); 217 return obj; 218 } 219 220 static int test_exdata(void) 221 { 222 MYOBJ *t1 = NULL, *t2 = NULL, *t3 = NULL; 223 MYOBJ_EX_DATA *ex_data = NULL; 224 const char *cp; 225 char *p; 226 int res = 0; 227 228 gbl_result = 1; 229 230 if (!TEST_ptr(p = OPENSSL_strdup("hello world"))) 231 return 0; 232 saved_argl = 21; 233 if (!TEST_ptr(saved_argp = OPENSSL_malloc(1))) 234 goto err; 235 saved_idx = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_APP, 236 saved_argl, saved_argp, 237 exnew, exdup, exfree); 238 saved_idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_APP, 239 saved_argl, saved_argp, 240 exnew2, exdup2, exfree2); 241 t1 = MYOBJ_new(); 242 t2 = MYOBJ_new(); 243 if (!TEST_int_eq(t1->st, 1) || !TEST_int_eq(t2->st, 1)) 244 goto err; 245 if (!TEST_ptr(CRYPTO_get_ex_data(&t1->ex_data, saved_idx2))) 246 goto err; 247 248 /* 249 * saved_idx3 differs from other indexes by being created after the exdata 250 * was initialized. 251 */ 252 saved_idx3 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_APP, 253 saved_argl, saved_argp, 254 exnew2, exdup2, exfree2); 255 if (!TEST_ptr_null(CRYPTO_get_ex_data(&t1->ex_data, saved_idx3))) 256 goto err; 257 258 MYOBJ_sethello(t1, p); 259 cp = MYOBJ_gethello(t1); 260 if (!TEST_ptr_eq(cp, p)) 261 goto err; 262 263 MYOBJ_sethello2(t1, p); 264 cp = MYOBJ_gethello2(t1); 265 if (!TEST_ptr_eq(cp, p)) 266 goto err; 267 268 MYOBJ_allochello3(t1, p); 269 cp = MYOBJ_gethello3(t1); 270 if (!TEST_ptr_eq(cp, p)) 271 goto err; 272 273 cp = MYOBJ_gethello(t2); 274 if (!TEST_ptr_null(cp)) 275 goto err; 276 277 cp = MYOBJ_gethello2(t2); 278 if (!TEST_ptr_null(cp)) 279 goto err; 280 281 t3 = MYOBJ_dup(t1); 282 if (!TEST_int_eq(t3->st, 1)) 283 goto err; 284 285 ex_data = CRYPTO_get_ex_data(&t3->ex_data, saved_idx2); 286 if (!TEST_ptr(ex_data)) 287 goto err; 288 if (!TEST_int_eq(ex_data->dup, 1)) 289 goto err; 290 291 cp = MYOBJ_gethello(t3); 292 if (!TEST_ptr_eq(cp, p)) 293 goto err; 294 295 cp = MYOBJ_gethello2(t3); 296 if (!TEST_ptr_eq(cp, p)) 297 goto err; 298 299 cp = MYOBJ_gethello3(t3); 300 if (!TEST_ptr_eq(cp, p)) 301 goto err; 302 303 if (gbl_result) 304 res = 1; 305 err: 306 MYOBJ_free(t1); 307 MYOBJ_free(t2); 308 MYOBJ_free(t3); 309 OPENSSL_free(saved_argp); 310 saved_argp = NULL; 311 OPENSSL_free(p); 312 return res; 313 } 314 315 int setup_tests(void) 316 { 317 ADD_TEST(test_exdata); 318 return 1; 319 } 320