195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved. 395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written 595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com). 695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL. 795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as 995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to. The following conditions 1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA, 1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms 1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in 1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed. 1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution 1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used. 1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or 2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package. 2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without 2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions 2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met: 2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright 2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer. 2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright 2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer in the 2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * documentation and/or other materials provided with the distribution. 3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software 3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * must display the following acknowledgement: 3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes cryptographic software written by 3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Eric Young (eay@cryptsoft.com)" 3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The word 'cryptographic' can be left out if the rouines from the library 3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * being used are not cryptographic related :-). 3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from 3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the apps directory (application code) you must include an acknowledgement: 3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE. 5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or 5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed. i.e. this code cannot simply be 5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence 5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.] 5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* ==================================================================== 5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without 6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions 6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met: 6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright 6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer. 6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright 6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer in 6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the documentation and/or other materials provided with the 7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * distribution. 7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this 7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * software must display the following acknowledgment: 7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software developed by the OpenSSL Project 7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * endorse or promote products derived from this software without 7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * prior written permission. For written permission, please contact 8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * openssl-core@openssl.org. 8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5. Products derived from this software may not be called "OpenSSL" 8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * nor may "OpenSSL" appear in their names without prior written 8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * permission of the OpenSSL Project. 8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6. Redistributions of any form whatsoever must retain the following 8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * acknowledgment: 8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software developed by the OpenSSL Project 8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ==================================================================== 10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This product includes cryptographic software written by Eric Young 10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (eay@cryptsoft.com). This product includes software written by Tim 10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Hudson (tjh@cryptsoft.com). */ 10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/ex_data.h> 11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <assert.h> 11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h> 11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/lhash.h> 11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h> 11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/stack.h> 11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/thread.h> 11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "crypto_error.h" 12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "internal.h" 12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleytypedef struct crypto_ex_data_func_st { 12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley long argl; /* Arbitary long */ 12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley void *argp; /* Arbitary void pointer */ 12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_new *new_func; 12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_free *free_func; 12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_dup *dup_func; 12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} CRYPTO_EX_DATA_FUNCS; 12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleytypedef struct st_ex_class_item { 13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; 13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int class_value; 13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* TODO(fork): isn't |meth_num| just the length of |meth|? */ 13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int meth_num; 13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} EX_CLASS_ITEM; 13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic LHASH_OF(EX_CLASS_ITEM) *global_classes = NULL; 13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int global_next_class = 100; 14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int new_class(void) { 14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret; 14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); 14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = global_next_class++; 14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); 14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* class_hash is a hash function used by an LHASH of |EX_CLASS_ITEM| 15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * structures. */ 15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic uint32_t class_hash(const EX_CLASS_ITEM *a) { 15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return a->class_value; 15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* class_cmp is a comparision function for an LHASH of |EX_CLASS_ITEM| 15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * structures. */ 15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int class_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) { 15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return a->class_value - b->class_value; 16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* data_funcs_free is a callback function from |sk_pop_free| that frees a 16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * |CRYPTO_EX_DATA_FUNCS|. */ 16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void data_funcs_free(CRYPTO_EX_DATA_FUNCS *funcs) { 16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(funcs); 16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* class_free is a callback function from lh_doall to free the EX_CLASS_ITEM 16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * structures. */ 17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void class_free(EX_CLASS_ITEM *item) { 17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, data_funcs_free); 17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 174c44d2f4cb8a892a603edbbe710fa82bcd30f9cb5David Benjaminstatic LHASH_OF(EX_CLASS_ITEM) *get_classes(void) { 17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley LHASH_OF(EX_CLASS_ITEM) *ret; 17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); 17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = global_classes; 17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); 18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ret != NULL) { 18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); 18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (global_classes == NULL) { 18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp); 18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = global_classes; 19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); 19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void cleanup(void) { 19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley LHASH_OF(EX_CLASS_ITEM) *classes = get_classes(); 19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley lh_EX_CLASS_ITEM_doall(classes, class_free); 19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley lh_EX_CLASS_ITEM_free(classes); 20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley global_classes = NULL; 20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic EX_CLASS_ITEM *get_class(int class_value) { 20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley LHASH_OF(EX_CLASS_ITEM) *const classes = get_classes(); 20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EX_CLASS_ITEM template, *class_item; 20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ok = 0; 20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); 21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley template.class_value = class_value; 21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley class_item = lh_EX_CLASS_ITEM_retrieve(classes, &template); 21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (class_item != NULL) { 21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ok = 1; 21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley class_item = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); 21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (class_item) { 21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley class_item->class_value = class_value; 21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley class_item->meth_num = 0; 21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley class_item->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); 22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (class_item->meth != NULL) { 22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EX_CLASS_ITEM *old_data; 22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ok = lh_EX_CLASS_ITEM_insert(classes, &old_data, class_item); 22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley assert(old_data == NULL); 22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); 22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ok) { 23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (class_item) { 23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (class_item->meth) { 23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_free(class_item->meth); 23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(class_item); 23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley class_item = NULL; 23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(CRYPTO, get_class, ERR_R_MALLOC_FAILURE); 23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return class_item; 24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int get_new_index(int class_value, long argl, void *argp, 24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, 24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_free *free_func) { 24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EX_CLASS_ITEM *const item = get_class(class_value); 24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_DATA_FUNCS *funcs; 24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret = -1; 25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!item) { 25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); 25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (funcs == NULL) { 25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE); 25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley funcs->argl = argl; 26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley funcs->argp = argp; 26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley funcs->new_func = new_func; 26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley funcs->dup_func = dup_func; 26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley funcs->free_func = free_func; 26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); 26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* TODO(fork): this loop appears to only ever run once. */ 26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley while (sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) <= item->meth_num) { 27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, NULL)) { 27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE); 27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(funcs); 27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = item->meth_num++; 27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley (void)sk_CRYPTO_EX_DATA_FUNCS_set(item->meth, ret, funcs); 27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr: 28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); 28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any, 28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for the given class. If there are some pointers, it sets |*out| to point to 28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on 28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * success or zero on error. */ 28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out, 29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int class_value) { 29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EX_CLASS_ITEM *const item = get_class(class_value); 29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t n; 29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!item) { 29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out = NULL; 29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a 30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * shallow copy of the list under lock and then use the structures without 30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the lock held. */ 30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); 30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley n = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); 30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (n > 0) { 30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth); 30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); 30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (n > 0 && *out == NULL) { 31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE); 31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { 31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; 32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t i; 32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ad->sk = NULL; 32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!get_func_pointers(&func_pointers, class_value)) { 32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { 32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_DATA_FUNCS *func_pointer = 33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); 33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (func_pointer->new_func) { 33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl, 33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley func_pointer->argp); 33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); 33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int dup_ex_data(int class_value, CRYPTO_EX_DATA *to, 34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const CRYPTO_EX_DATA *from) { 34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; 34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t i; 34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!from->sk) { 34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* In this case, |from| is blank, which is also the initial state of |to|, 34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * so there's nothing to do. */ 35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!get_func_pointers(&func_pointers, class_value)) { 35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { 35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_DATA_FUNCS *func_pointer = 35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); 36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley void *ptr = CRYPTO_get_ex_data(from, i); 36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (func_pointer->dup_func) { 36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl, 36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley func_pointer->argp); 36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_set_ex_data(to, i, ptr); 36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); 36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { 37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; 37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t i; 37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!get_func_pointers(&func_pointers, class_value)) { 37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return; 37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { 38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley CRYPTO_EX_DATA_FUNCS *func_pointer = 38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); 38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (func_pointer->free_func) { 38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley void *ptr = CRYPTO_get_ex_data(ad, i); 38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl, 38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley func_pointer->argp); 38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); 39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ad->sk) { 39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sk_void_free(ad->sk); 39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ad->sk = NULL; 39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst CRYPTO_EX_DATA_IMPL ex_data_default_impl = { 40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley new_class, cleanup, get_new_index, new_ex_data, dup_ex_data, free_ex_data}; 401