1193645Ssimon/* crypto/err/err_def.c */ 2193645Ssimon/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3193645Ssimon * All rights reserved. 4193645Ssimon * 5193645Ssimon * This package is an SSL implementation written 6193645Ssimon * by Eric Young (eay@cryptsoft.com). 7193645Ssimon * The implementation was written so as to conform with Netscapes SSL. 8296465Sdelphij * 9193645Ssimon * This library is free for commercial and non-commercial use as long as 10193645Ssimon * the following conditions are aheared to. The following conditions 11193645Ssimon * apply to all code found in this distribution, be it the RC4, RSA, 12193645Ssimon * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13193645Ssimon * included with this distribution is covered by the same copyright terms 14193645Ssimon * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296465Sdelphij * 16193645Ssimon * Copyright remains Eric Young's, and as such any Copyright notices in 17193645Ssimon * the code are not to be removed. 18193645Ssimon * If this package is used in a product, Eric Young should be given attribution 19193645Ssimon * as the author of the parts of the library used. 20193645Ssimon * This can be in the form of a textual message at program startup or 21193645Ssimon * in documentation (online or textual) provided with the package. 22296465Sdelphij * 23193645Ssimon * Redistribution and use in source and binary forms, with or without 24193645Ssimon * modification, are permitted provided that the following conditions 25193645Ssimon * are met: 26193645Ssimon * 1. Redistributions of source code must retain the copyright 27193645Ssimon * notice, this list of conditions and the following disclaimer. 28193645Ssimon * 2. Redistributions in binary form must reproduce the above copyright 29193645Ssimon * notice, this list of conditions and the following disclaimer in the 30193645Ssimon * documentation and/or other materials provided with the distribution. 31193645Ssimon * 3. All advertising materials mentioning features or use of this software 32193645Ssimon * must display the following acknowledgement: 33193645Ssimon * "This product includes cryptographic software written by 34193645Ssimon * Eric Young (eay@cryptsoft.com)" 35193645Ssimon * The word 'cryptographic' can be left out if the rouines from the library 36193645Ssimon * being used are not cryptographic related :-). 37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 38193645Ssimon * the apps directory (application code) you must include an acknowledgement: 39193645Ssimon * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296465Sdelphij * 41193645Ssimon * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42193645Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43193645Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44193645Ssimon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45193645Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46193645Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47193645Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48193645Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49193645Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50193645Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51193645Ssimon * SUCH DAMAGE. 52296465Sdelphij * 53193645Ssimon * The licence and distribution terms for any publically available version or 54193645Ssimon * derivative of this code cannot be changed. i.e. this code cannot simply be 55193645Ssimon * copied and put under another distribution licence 56193645Ssimon * [including the GNU Public Licence.] 57193645Ssimon */ 58193645Ssimon/* ==================================================================== 59193645Ssimon * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 60193645Ssimon * 61193645Ssimon * Redistribution and use in source and binary forms, with or without 62193645Ssimon * modification, are permitted provided that the following conditions 63193645Ssimon * are met: 64193645Ssimon * 65193645Ssimon * 1. Redistributions of source code must retain the above copyright 66296465Sdelphij * notice, this list of conditions and the following disclaimer. 67193645Ssimon * 68193645Ssimon * 2. Redistributions in binary form must reproduce the above copyright 69193645Ssimon * notice, this list of conditions and the following disclaimer in 70193645Ssimon * the documentation and/or other materials provided with the 71193645Ssimon * distribution. 72193645Ssimon * 73193645Ssimon * 3. All advertising materials mentioning features or use of this 74193645Ssimon * software must display the following acknowledgment: 75193645Ssimon * "This product includes software developed by the OpenSSL Project 76193645Ssimon * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77193645Ssimon * 78193645Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79193645Ssimon * endorse or promote products derived from this software without 80193645Ssimon * prior written permission. For written permission, please contact 81193645Ssimon * openssl-core@openssl.org. 82193645Ssimon * 83193645Ssimon * 5. Products derived from this software may not be called "OpenSSL" 84193645Ssimon * nor may "OpenSSL" appear in their names without prior written 85193645Ssimon * permission of the OpenSSL Project. 86193645Ssimon * 87193645Ssimon * 6. Redistributions of any form whatsoever must retain the following 88193645Ssimon * acknowledgment: 89193645Ssimon * "This product includes software developed by the OpenSSL Project 90193645Ssimon * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91193645Ssimon * 92193645Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93193645Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94193645Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95193645Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96193645Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97193645Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98193645Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99193645Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100193645Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101193645Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102193645Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103193645Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 104193645Ssimon * ==================================================================== 105193645Ssimon * 106193645Ssimon * This product includes cryptographic software written by Eric Young 107193645Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 108193645Ssimon * Hudson (tjh@cryptsoft.com). 109193645Ssimon * 110193645Ssimon */ 111193645Ssimon 112193645Ssimon#include <stdio.h> 113193645Ssimon#include <stdarg.h> 114193645Ssimon#include <string.h> 115193645Ssimon#include "cryptlib.h" 116193645Ssimon#include <openssl/lhash.h> 117193645Ssimon#include <openssl/crypto.h> 118193645Ssimon#include <openssl/buffer.h> 119193645Ssimon#include <openssl/bio.h> 120193645Ssimon#include <openssl/err.h> 121193645Ssimon 122193645Ssimon#define err_clear_data(p,i) \ 123296465Sdelphij do { \ 124296465Sdelphij if (((p)->err_data[i] != NULL) && \ 125296465Sdelphij (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \ 126296465Sdelphij { \ 127296465Sdelphij OPENSSL_free((p)->err_data[i]); \ 128296465Sdelphij (p)->err_data[i]=NULL; \ 129296465Sdelphij } \ 130296465Sdelphij (p)->err_data_flags[i]=0; \ 131296465Sdelphij } while(0) 132193645Ssimon 133193645Ssimon#define err_clear(p,i) \ 134296465Sdelphij do { \ 135296465Sdelphij (p)->err_flags[i]=0; \ 136296465Sdelphij (p)->err_buffer[i]=0; \ 137296465Sdelphij err_clear_data(p,i); \ 138296465Sdelphij (p)->err_file[i]=NULL; \ 139296465Sdelphij (p)->err_line[i]= -1; \ 140296465Sdelphij } while(0) 141193645Ssimon 142193645Ssimonstatic void err_load_strings(int lib, ERR_STRING_DATA *str); 143193645Ssimon 144193645Ssimonstatic void ERR_STATE_free(ERR_STATE *s); 145193645Ssimon 146193645Ssimon/* Define the predeclared (but externally opaque) "ERR_FNS" type */ 147296465Sdelphijstruct st_ERR_FNS { 148296465Sdelphij /* Works on the "error_hash" string table */ 149296465Sdelphij LHASH *(*cb_err_get) (int create); 150296465Sdelphij void (*cb_err_del) (void); 151296465Sdelphij ERR_STRING_DATA *(*cb_err_get_item) (const ERR_STRING_DATA *); 152296465Sdelphij ERR_STRING_DATA *(*cb_err_set_item) (ERR_STRING_DATA *); 153296465Sdelphij ERR_STRING_DATA *(*cb_err_del_item) (ERR_STRING_DATA *); 154296465Sdelphij /* Works on the "thread_hash" error-state table */ 155296465Sdelphij LHASH *(*cb_thread_get) (int create); 156296465Sdelphij void (*cb_thread_release) (LHASH **hash); 157296465Sdelphij ERR_STATE *(*cb_thread_get_item) (const ERR_STATE *); 158296465Sdelphij ERR_STATE *(*cb_thread_set_item) (ERR_STATE *); 159296465Sdelphij void (*cb_thread_del_item) (const ERR_STATE *); 160296465Sdelphij /* Returns the next available error "library" numbers */ 161296465Sdelphij int (*cb_get_next_lib) (void); 162296465Sdelphij}; 163193645Ssimon 164193645Ssimon/* Predeclarations of the "err_defaults" functions */ 165193645Ssimonstatic LHASH *int_err_get(int create); 166193645Ssimonstatic void int_err_del(void); 167193645Ssimonstatic ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); 168193645Ssimonstatic ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *); 169193645Ssimonstatic ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *); 170193645Ssimonstatic LHASH *int_thread_get(int create); 171193645Ssimonstatic void int_thread_release(LHASH **hash); 172193645Ssimonstatic ERR_STATE *int_thread_get_item(const ERR_STATE *); 173193645Ssimonstatic ERR_STATE *int_thread_set_item(ERR_STATE *); 174193645Ssimonstatic void int_thread_del_item(const ERR_STATE *); 175193645Ssimonstatic int int_err_get_next_lib(void); 176193645Ssimon/* The static ERR_FNS table using these defaults functions */ 177296465Sdelphijstatic const ERR_FNS err_defaults = { 178296465Sdelphij int_err_get, 179296465Sdelphij int_err_del, 180296465Sdelphij int_err_get_item, 181296465Sdelphij int_err_set_item, 182296465Sdelphij int_err_del_item, 183296465Sdelphij int_thread_get, 184296465Sdelphij int_thread_release, 185296465Sdelphij int_thread_get_item, 186296465Sdelphij int_thread_set_item, 187296465Sdelphij int_thread_del_item, 188296465Sdelphij int_err_get_next_lib 189296465Sdelphij}; 190193645Ssimon 191193645Ssimon/* The replacable table of ERR_FNS functions we use at run-time */ 192193645Ssimonstatic const ERR_FNS *err_fns = NULL; 193193645Ssimon 194193645Ssimon/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */ 195193645Ssimon#define ERRFN(a) err_fns->cb_##a 196193645Ssimon 197296465Sdelphij/* 198296465Sdelphij * The internal state used by "err_defaults" - as such, the setting, reading, 199193645Ssimon * creating, and deleting of this data should only be permitted via the 200296465Sdelphij * "err_defaults" functions. This way, a linked module can completely defer 201296465Sdelphij * all ERR state operation (together with requisite locking) to the 202296465Sdelphij * implementations and state in the loading application. 203296465Sdelphij */ 204193645Ssimonstatic LHASH *int_error_hash = NULL; 205193645Ssimonstatic LHASH *int_thread_hash = NULL; 206193645Ssimonstatic int int_thread_hash_references = 0; 207296465Sdelphijstatic int int_err_library_number = ERR_LIB_USER; 208193645Ssimon 209296465Sdelphij/* 210296465Sdelphij * Internal function that checks whether "err_fns" is set and if not, sets it 211296465Sdelphij * to the defaults. 212296465Sdelphij */ 213193645Ssimonstatic void err_fns_check(void) 214296465Sdelphij{ 215296465Sdelphij if (err_fns) 216296465Sdelphij return; 217193645Ssimon 218296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 219296465Sdelphij if (!err_fns) 220296465Sdelphij err_fns = &err_defaults; 221296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 222296465Sdelphij} 223296465Sdelphij 224193645Ssimon/* API functions to get or set the underlying ERR functions. */ 225193645Ssimon 226193645Ssimonconst ERR_FNS *ERR_get_implementation(void) 227296465Sdelphij{ 228296465Sdelphij err_fns_check(); 229296465Sdelphij return err_fns; 230296465Sdelphij} 231193645Ssimon 232193645Ssimonint ERR_set_implementation(const ERR_FNS *fns) 233296465Sdelphij{ 234296465Sdelphij int ret = 0; 235193645Ssimon 236296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 237296465Sdelphij /* 238296465Sdelphij * It's too late if 'err_fns' is non-NULL. BTW: not much point setting an 239296465Sdelphij * error is there?! 240296465Sdelphij */ 241296465Sdelphij if (!err_fns) { 242296465Sdelphij err_fns = fns; 243296465Sdelphij ret = 1; 244296465Sdelphij } 245296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 246296465Sdelphij return ret; 247296465Sdelphij} 248193645Ssimon 249296465Sdelphij/* 250296465Sdelphij * These are the callbacks provided to "lh_new()" when creating the LHASH 251296465Sdelphij * tables internal to the "err_defaults" implementation. 252296465Sdelphij */ 253193645Ssimon 254193645Ssimon/* static unsigned long err_hash(ERR_STRING_DATA *a); */ 255193645Ssimonstatic unsigned long err_hash(const void *a_void); 256193645Ssimon/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */ 257193645Ssimonstatic int err_cmp(const void *a_void, const void *b_void); 258193645Ssimon/* static unsigned long pid_hash(ERR_STATE *pid); */ 259193645Ssimonstatic unsigned long pid_hash(const void *pid_void); 260193645Ssimon/* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */ 261296465Sdelphijstatic int pid_cmp(const void *a_void, const void *pid_void); 262193645Ssimon 263193645Ssimon/* The internal functions used in the "err_defaults" implementation */ 264193645Ssimon 265193645Ssimonstatic LHASH *int_err_get(int create) 266296465Sdelphij{ 267296465Sdelphij LHASH *ret = NULL; 268193645Ssimon 269296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 270296465Sdelphij if (!int_error_hash && create) { 271296465Sdelphij CRYPTO_push_info("int_err_get (err.c)"); 272296465Sdelphij int_error_hash = lh_new(err_hash, err_cmp); 273296465Sdelphij CRYPTO_pop_info(); 274296465Sdelphij } 275296465Sdelphij if (int_error_hash) 276296465Sdelphij ret = int_error_hash; 277296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 278193645Ssimon 279296465Sdelphij return ret; 280296465Sdelphij} 281193645Ssimon 282193645Ssimonstatic void int_err_del(void) 283296465Sdelphij{ 284296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 285296465Sdelphij if (int_error_hash) { 286296465Sdelphij lh_free(int_error_hash); 287296465Sdelphij int_error_hash = NULL; 288296465Sdelphij } 289296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 290296465Sdelphij} 291193645Ssimon 292193645Ssimonstatic ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) 293296465Sdelphij{ 294296465Sdelphij ERR_STRING_DATA *p; 295296465Sdelphij LHASH *hash; 296193645Ssimon 297296465Sdelphij err_fns_check(); 298296465Sdelphij hash = ERRFN(err_get) (0); 299296465Sdelphij if (!hash) 300296465Sdelphij return NULL; 301193645Ssimon 302296465Sdelphij CRYPTO_r_lock(CRYPTO_LOCK_ERR); 303296465Sdelphij p = (ERR_STRING_DATA *)lh_retrieve(hash, d); 304296465Sdelphij CRYPTO_r_unlock(CRYPTO_LOCK_ERR); 305193645Ssimon 306296465Sdelphij return p; 307296465Sdelphij} 308193645Ssimon 309193645Ssimonstatic ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d) 310296465Sdelphij{ 311296465Sdelphij ERR_STRING_DATA *p; 312296465Sdelphij LHASH *hash; 313193645Ssimon 314296465Sdelphij err_fns_check(); 315296465Sdelphij hash = ERRFN(err_get) (1); 316296465Sdelphij if (!hash) 317296465Sdelphij return NULL; 318193645Ssimon 319296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 320296465Sdelphij p = (ERR_STRING_DATA *)lh_insert(hash, d); 321296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 322193645Ssimon 323296465Sdelphij return p; 324296465Sdelphij} 325193645Ssimon 326193645Ssimonstatic ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d) 327296465Sdelphij{ 328296465Sdelphij ERR_STRING_DATA *p; 329296465Sdelphij LHASH *hash; 330193645Ssimon 331296465Sdelphij err_fns_check(); 332296465Sdelphij hash = ERRFN(err_get) (0); 333296465Sdelphij if (!hash) 334296465Sdelphij return NULL; 335193645Ssimon 336296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 337296465Sdelphij p = (ERR_STRING_DATA *)lh_delete(hash, d); 338296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 339193645Ssimon 340296465Sdelphij return p; 341296465Sdelphij} 342193645Ssimon 343193645Ssimonstatic LHASH *int_thread_get(int create) 344296465Sdelphij{ 345296465Sdelphij LHASH *ret = NULL; 346193645Ssimon 347296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 348296465Sdelphij if (!int_thread_hash && create) { 349296465Sdelphij CRYPTO_push_info("int_thread_get (err.c)"); 350296465Sdelphij int_thread_hash = lh_new(pid_hash, pid_cmp); 351296465Sdelphij CRYPTO_pop_info(); 352296465Sdelphij } 353296465Sdelphij if (int_thread_hash) { 354296465Sdelphij int_thread_hash_references++; 355296465Sdelphij ret = int_thread_hash; 356296465Sdelphij } 357296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 358296465Sdelphij return ret; 359296465Sdelphij} 360193645Ssimon 361193645Ssimonstatic void int_thread_release(LHASH **hash) 362296465Sdelphij{ 363296465Sdelphij int i; 364193645Ssimon 365296465Sdelphij if (hash == NULL || *hash == NULL) 366296465Sdelphij return; 367193645Ssimon 368296465Sdelphij i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR); 369193645Ssimon 370193645Ssimon#ifdef REF_PRINT 371296465Sdelphij fprintf(stderr, "%4d:%s\n", int_thread_hash_references, "ERR"); 372193645Ssimon#endif 373296465Sdelphij if (i > 0) 374296465Sdelphij return; 375193645Ssimon#ifdef REF_CHECK 376296465Sdelphij if (i < 0) { 377296465Sdelphij fprintf(stderr, "int_thread_release, bad reference count\n"); 378296465Sdelphij abort(); /* ok */ 379296465Sdelphij } 380193645Ssimon#endif 381296465Sdelphij *hash = NULL; 382296465Sdelphij} 383193645Ssimon 384193645Ssimonstatic ERR_STATE *int_thread_get_item(const ERR_STATE *d) 385296465Sdelphij{ 386296465Sdelphij ERR_STATE *p; 387296465Sdelphij LHASH *hash; 388193645Ssimon 389296465Sdelphij err_fns_check(); 390296465Sdelphij hash = ERRFN(thread_get) (0); 391296465Sdelphij if (!hash) 392296465Sdelphij return NULL; 393193645Ssimon 394296465Sdelphij CRYPTO_r_lock(CRYPTO_LOCK_ERR); 395296465Sdelphij p = (ERR_STATE *)lh_retrieve(hash, d); 396296465Sdelphij CRYPTO_r_unlock(CRYPTO_LOCK_ERR); 397193645Ssimon 398296465Sdelphij ERRFN(thread_release) (&hash); 399296465Sdelphij return p; 400296465Sdelphij} 401193645Ssimon 402193645Ssimonstatic ERR_STATE *int_thread_set_item(ERR_STATE *d) 403296465Sdelphij{ 404296465Sdelphij ERR_STATE *p; 405296465Sdelphij LHASH *hash; 406193645Ssimon 407296465Sdelphij err_fns_check(); 408296465Sdelphij hash = ERRFN(thread_get) (1); 409296465Sdelphij if (!hash) 410296465Sdelphij return NULL; 411193645Ssimon 412296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 413296465Sdelphij p = (ERR_STATE *)lh_insert(hash, d); 414296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 415193645Ssimon 416296465Sdelphij ERRFN(thread_release) (&hash); 417296465Sdelphij return p; 418296465Sdelphij} 419193645Ssimon 420193645Ssimonstatic void int_thread_del_item(const ERR_STATE *d) 421296465Sdelphij{ 422296465Sdelphij ERR_STATE *p; 423296465Sdelphij LHASH *hash; 424193645Ssimon 425296465Sdelphij err_fns_check(); 426296465Sdelphij hash = ERRFN(thread_get) (0); 427296465Sdelphij if (!hash) 428296465Sdelphij return; 429193645Ssimon 430296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 431296465Sdelphij p = (ERR_STATE *)lh_delete(hash, d); 432296465Sdelphij /* make sure we don't leak memory */ 433296465Sdelphij if (int_thread_hash_references == 1 434296465Sdelphij && int_thread_hash && (lh_num_items(int_thread_hash) == 0)) { 435296465Sdelphij lh_free(int_thread_hash); 436296465Sdelphij int_thread_hash = NULL; 437296465Sdelphij } 438296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 439193645Ssimon 440296465Sdelphij ERRFN(thread_release) (&hash); 441296465Sdelphij if (p) 442296465Sdelphij ERR_STATE_free(p); 443296465Sdelphij} 444193645Ssimon 445193645Ssimonstatic int int_err_get_next_lib(void) 446296465Sdelphij{ 447296465Sdelphij int ret; 448193645Ssimon 449296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ERR); 450296465Sdelphij ret = int_err_library_number++; 451296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 452193645Ssimon 453296465Sdelphij return ret; 454296465Sdelphij} 455193645Ssimon 456193645Ssimonstatic void ERR_STATE_free(ERR_STATE *s) 457296465Sdelphij{ 458296465Sdelphij int i; 459193645Ssimon 460296465Sdelphij if (s == NULL) 461296465Sdelphij return; 462193645Ssimon 463296465Sdelphij for (i = 0; i < ERR_NUM_ERRORS; i++) { 464296465Sdelphij err_clear_data(s, i); 465296465Sdelphij } 466296465Sdelphij OPENSSL_free(s); 467296465Sdelphij} 468193645Ssimon 469193645Ssimonstatic void err_load_strings(int lib, ERR_STRING_DATA *str) 470296465Sdelphij{ 471296465Sdelphij while (str->error) { 472296465Sdelphij if (lib) 473296465Sdelphij str->error |= ERR_PACK(lib, 0, 0); 474296465Sdelphij ERRFN(err_set_item) (str); 475296465Sdelphij str++; 476296465Sdelphij } 477296465Sdelphij} 478193645Ssimon 479193645Ssimonvoid ERR_load_strings(int lib, ERR_STRING_DATA *str) 480296465Sdelphij{ 481296465Sdelphij err_fns_check(); 482296465Sdelphij err_load_strings(lib, str); 483296465Sdelphij} 484193645Ssimon 485193645Ssimonvoid ERR_unload_strings(int lib, ERR_STRING_DATA *str) 486296465Sdelphij{ 487296465Sdelphij while (str->error) { 488296465Sdelphij if (lib) 489296465Sdelphij str->error |= ERR_PACK(lib, 0, 0); 490296465Sdelphij ERRFN(err_del_item) (str); 491296465Sdelphij str++; 492296465Sdelphij } 493296465Sdelphij} 494193645Ssimon 495193645Ssimonvoid ERR_free_strings(void) 496296465Sdelphij{ 497296465Sdelphij err_fns_check(); 498296465Sdelphij ERRFN(err_del) (); 499296465Sdelphij} 500193645Ssimon 501193645SsimonLHASH *ERR_get_string_table(void) 502296465Sdelphij{ 503296465Sdelphij err_fns_check(); 504296465Sdelphij return ERRFN(err_get) (0); 505296465Sdelphij} 506193645Ssimon 507193645SsimonLHASH *ERR_get_err_state_table(void) 508296465Sdelphij{ 509296465Sdelphij err_fns_check(); 510296465Sdelphij return ERRFN(thread_get) (0); 511296465Sdelphij} 512193645Ssimon 513193645Ssimonvoid ERR_release_err_state_table(LHASH **hash) 514296465Sdelphij{ 515296465Sdelphij err_fns_check(); 516296465Sdelphij ERRFN(thread_release) (hash); 517296465Sdelphij} 518193645Ssimon 519193645Ssimonconst char *ERR_lib_error_string(unsigned long e) 520296465Sdelphij{ 521296465Sdelphij ERR_STRING_DATA d, *p; 522296465Sdelphij unsigned long l; 523193645Ssimon 524296465Sdelphij err_fns_check(); 525296465Sdelphij l = ERR_GET_LIB(e); 526296465Sdelphij d.error = ERR_PACK(l, 0, 0); 527296465Sdelphij p = ERRFN(err_get_item) (&d); 528296465Sdelphij return ((p == NULL) ? NULL : p->string); 529296465Sdelphij} 530193645Ssimon 531193645Ssimonconst char *ERR_func_error_string(unsigned long e) 532296465Sdelphij{ 533296465Sdelphij ERR_STRING_DATA d, *p; 534296465Sdelphij unsigned long l, f; 535193645Ssimon 536296465Sdelphij err_fns_check(); 537296465Sdelphij l = ERR_GET_LIB(e); 538296465Sdelphij f = ERR_GET_FUNC(e); 539296465Sdelphij d.error = ERR_PACK(l, f, 0); 540296465Sdelphij p = ERRFN(err_get_item) (&d); 541296465Sdelphij return ((p == NULL) ? NULL : p->string); 542296465Sdelphij} 543193645Ssimon 544193645Ssimonconst char *ERR_reason_error_string(unsigned long e) 545296465Sdelphij{ 546296465Sdelphij ERR_STRING_DATA d, *p = NULL; 547296465Sdelphij unsigned long l, r; 548193645Ssimon 549296465Sdelphij err_fns_check(); 550296465Sdelphij l = ERR_GET_LIB(e); 551296465Sdelphij r = ERR_GET_REASON(e); 552296465Sdelphij d.error = ERR_PACK(l, 0, r); 553296465Sdelphij p = ERRFN(err_get_item) (&d); 554296465Sdelphij if (!p) { 555296465Sdelphij d.error = ERR_PACK(0, 0, r); 556296465Sdelphij p = ERRFN(err_get_item) (&d); 557296465Sdelphij } 558296465Sdelphij return ((p == NULL) ? NULL : p->string); 559296465Sdelphij} 560193645Ssimon 561193645Ssimon/* static unsigned long err_hash(ERR_STRING_DATA *a) */ 562193645Ssimonstatic unsigned long err_hash(const void *a_void) 563296465Sdelphij{ 564296465Sdelphij unsigned long ret, l; 565193645Ssimon 566296465Sdelphij l = ((const ERR_STRING_DATA *)a_void)->error; 567296465Sdelphij ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l); 568296465Sdelphij return (ret ^ ret % 19 * 13); 569296465Sdelphij} 570193645Ssimon 571193645Ssimon/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */ 572193645Ssimonstatic int err_cmp(const void *a_void, const void *b_void) 573296465Sdelphij{ 574296465Sdelphij return ((int)(((const ERR_STRING_DATA *)a_void)->error - 575296465Sdelphij ((const ERR_STRING_DATA *)b_void)->error)); 576296465Sdelphij} 577193645Ssimon 578193645Ssimon/* static unsigned long pid_hash(ERR_STATE *a) */ 579193645Ssimonstatic unsigned long pid_hash(const void *a_void) 580296465Sdelphij{ 581296465Sdelphij return (((const ERR_STATE *)a_void)->pid * 13); 582296465Sdelphij} 583193645Ssimon 584193645Ssimon/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */ 585193645Ssimonstatic int pid_cmp(const void *a_void, const void *b_void) 586296465Sdelphij{ 587296465Sdelphij return ((int)((long)((const ERR_STATE *)a_void)->pid - 588296465Sdelphij (long)((const ERR_STATE *)b_void)->pid)); 589296465Sdelphij} 590296465Sdelphij 591193645Ssimon#ifdef OPENSSL_FIPS 592193645Ssimonstatic void int_err_remove_state(unsigned long pid) 593193645Ssimon#else 594193645Ssimonvoid ERR_remove_state(unsigned long pid) 595193645Ssimon#endif 596296465Sdelphij{ 597296465Sdelphij ERR_STATE tmp; 598193645Ssimon 599296465Sdelphij err_fns_check(); 600296465Sdelphij if (pid == 0) 601296465Sdelphij pid = (unsigned long)CRYPTO_thread_id(); 602296465Sdelphij tmp.pid = pid; 603296465Sdelphij /* 604296465Sdelphij * thread_del_item automatically destroys the LHASH if the number of 605296465Sdelphij * items reaches zero. 606296465Sdelphij */ 607296465Sdelphij ERRFN(thread_del_item) (&tmp); 608296465Sdelphij} 609193645Ssimon 610193645Ssimon#ifdef OPENSSL_FIPS 611296465Sdelphijstatic ERR_STATE *int_err_get_state(void) 612193645Ssimon#else 613193645SsimonERR_STATE *ERR_get_state(void) 614193645Ssimon#endif 615296465Sdelphij{ 616296465Sdelphij static ERR_STATE fallback; 617296465Sdelphij ERR_STATE *ret, tmp, *tmpp = NULL; 618296465Sdelphij int i; 619296465Sdelphij unsigned long pid; 620193645Ssimon 621296465Sdelphij err_fns_check(); 622296465Sdelphij pid = (unsigned long)CRYPTO_thread_id(); 623296465Sdelphij tmp.pid = pid; 624296465Sdelphij ret = ERRFN(thread_get_item) (&tmp); 625193645Ssimon 626296465Sdelphij /* ret == the error state, if NULL, make a new one */ 627296465Sdelphij if (ret == NULL) { 628296465Sdelphij ret = (ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE)); 629296465Sdelphij if (ret == NULL) 630296465Sdelphij return (&fallback); 631296465Sdelphij ret->pid = pid; 632296465Sdelphij ret->top = 0; 633296465Sdelphij ret->bottom = 0; 634296465Sdelphij for (i = 0; i < ERR_NUM_ERRORS; i++) { 635296465Sdelphij ret->err_data[i] = NULL; 636296465Sdelphij ret->err_data_flags[i] = 0; 637296465Sdelphij } 638296465Sdelphij tmpp = ERRFN(thread_set_item) (ret); 639296465Sdelphij /* To check if insertion failed, do a get. */ 640296465Sdelphij if (ERRFN(thread_get_item) (ret) != ret) { 641296465Sdelphij ERR_STATE_free(ret); /* could not insert it */ 642296465Sdelphij return (&fallback); 643296465Sdelphij } 644296465Sdelphij /* 645296465Sdelphij * If a race occured in this function and we came second, tmpp is the 646296465Sdelphij * first one that we just replaced. 647296465Sdelphij */ 648296465Sdelphij if (tmpp) 649296465Sdelphij ERR_STATE_free(tmpp); 650296465Sdelphij } 651296465Sdelphij return ret; 652296465Sdelphij} 653193645Ssimon 654193645Ssimon#ifdef OPENSSL_FIPS 655193645Ssimonvoid int_ERR_lib_init(void) 656296465Sdelphij{ 657296465Sdelphij int_ERR_set_state_func(int_err_get_state, int_err_remove_state); 658296465Sdelphij} 659193645Ssimon#endif 660193645Ssimon 661193645Ssimonint ERR_get_next_error_library(void) 662296465Sdelphij{ 663296465Sdelphij err_fns_check(); 664296465Sdelphij return ERRFN(get_next_lib) (); 665296465Sdelphij} 666