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