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