xref: /openbsd/lib/libcrypto/err/err.c (revision bda79ee4)
1 /* $OpenBSD: err.c,v 1.75 2024/11/02 12:46:36 tb Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 /* ====================================================================
59  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60  *
61  * Redistribution and use in source and binary forms, with or without
62  * modification, are permitted provided that the following conditions
63  * are met:
64  *
65  * 1. Redistributions of source code must retain the above copyright
66  *    notice, this list of conditions and the following disclaimer.
67  *
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in
70  *    the documentation and/or other materials provided with the
71  *    distribution.
72  *
73  * 3. All advertising materials mentioning features or use of this
74  *    software must display the following acknowledgment:
75  *    "This product includes software developed by the OpenSSL Project
76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77  *
78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79  *    endorse or promote products derived from this software without
80  *    prior written permission. For written permission, please contact
81  *    openssl-core@openssl.org.
82  *
83  * 5. Products derived from this software may not be called "OpenSSL"
84  *    nor may "OpenSSL" appear in their names without prior written
85  *    permission of the OpenSSL Project.
86  *
87  * 6. Redistributions of any form whatsoever must retain the following
88  *    acknowledgment:
89  *    "This product includes software developed by the OpenSSL Project
90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103  * OF THE POSSIBILITY OF SUCH DAMAGE.
104  * ====================================================================
105  *
106  * This product includes cryptographic software written by Eric Young
107  * (eay@cryptsoft.com).  This product includes software written by Tim
108  * Hudson (tjh@cryptsoft.com).
109  *
110  */
111 
112 #include <pthread.h>
113 #include <stdarg.h>
114 #include <stdio.h>
115 #include <string.h>
116 
117 #include <openssl/opensslconf.h>
118 
119 #include <openssl/bio.h>
120 #include <openssl/buffer.h>
121 #include <openssl/crypto.h>
122 #include <openssl/err.h>
123 #include <openssl/lhash.h>
124 
125 DECLARE_LHASH_OF(ERR_STRING_DATA);
126 DECLARE_LHASH_OF(ERR_STATE);
127 
128 typedef struct err_state_st {
129 	pthread_t tid;
130 	int err_flags[ERR_NUM_ERRORS];
131 	unsigned long err_buffer[ERR_NUM_ERRORS];
132 	char *err_data[ERR_NUM_ERRORS];
133 	int err_data_flags[ERR_NUM_ERRORS];
134 	const char *err_file[ERR_NUM_ERRORS];
135 	int err_line[ERR_NUM_ERRORS];
136 	int top, bottom;
137 } ERR_STATE;
138 
139 #ifndef OPENSSL_NO_ERR
140 static const ERR_STRING_DATA ERR_str_libraries[] = {
141 	{ERR_PACK(ERR_LIB_NONE, 0, 0),		"unknown library"},
142 	{ERR_PACK(ERR_LIB_SYS, 0, 0),		"system library"},
143 	{ERR_PACK(ERR_LIB_BN, 0, 0),		"bignum routines"},
144 	{ERR_PACK(ERR_LIB_RSA, 0, 0),		"rsa routines"},
145 	{ERR_PACK(ERR_LIB_DH, 0, 0),		"Diffie-Hellman routines"},
146 	{ERR_PACK(ERR_LIB_EVP, 0, 0),		"digital envelope routines"},
147 	{ERR_PACK(ERR_LIB_BUF, 0, 0),		"memory buffer routines"},
148 	{ERR_PACK(ERR_LIB_OBJ, 0, 0),		"object identifier routines"},
149 	{ERR_PACK(ERR_LIB_PEM, 0, 0),		"PEM routines"},
150 	{ERR_PACK(ERR_LIB_DSA, 0, 0),		"dsa routines"},
151 	{ERR_PACK(ERR_LIB_X509, 0, 0),		"x509 certificate routines"},
152 	{ERR_PACK(ERR_LIB_ASN1, 0, 0),		"asn1 encoding routines"},
153 	{ERR_PACK(ERR_LIB_CONF, 0, 0),		"configuration file routines"},
154 	{ERR_PACK(ERR_LIB_CRYPTO, 0, 0),	"common libcrypto routines"},
155 	{ERR_PACK(ERR_LIB_EC, 0, 0),		"elliptic curve routines"},
156 	{ERR_PACK(ERR_LIB_SSL, 0, 0),		"SSL routines"},
157 	{ERR_PACK(ERR_LIB_BIO, 0, 0),		"BIO routines"},
158 	{ERR_PACK(ERR_LIB_PKCS7, 0, 0),		"PKCS7 routines"},
159 	{ERR_PACK(ERR_LIB_X509V3, 0, 0),	"X509 V3 routines"},
160 	{ERR_PACK(ERR_LIB_PKCS12, 0, 0),	"PKCS12 routines"},
161 	{ERR_PACK(ERR_LIB_RAND, 0, 0),		"random number generator"},
162 	{ERR_PACK(ERR_LIB_DSO, 0, 0),		"DSO support routines"},
163 	{ERR_PACK(ERR_LIB_TS, 0, 0),		"time stamp routines"},
164 	{ERR_PACK(ERR_LIB_ENGINE, 0, 0),	"engine routines"},
165 	{ERR_PACK(ERR_LIB_OCSP, 0, 0),		"OCSP routines"},
166 	{ERR_PACK(ERR_LIB_FIPS, 0, 0),		"FIPS routines"},
167 	{ERR_PACK(ERR_LIB_CMS, 0, 0),		"CMS routines"},
168 	{ERR_PACK(ERR_LIB_HMAC, 0, 0),		"HMAC routines"},
169 	{ERR_PACK(ERR_LIB_GOST, 0, 0),		"GOST routines"},
170 	{0, NULL},
171 };
172 
173 static const ERR_STRING_DATA ERR_str_functs[] = {
174 	{ERR_PACK(ERR_LIB_SYS, SYS_F_FOPEN, 0),		"fopen"},
175 	{ERR_PACK(ERR_LIB_SYS, SYS_F_CONNECT, 0),	"connect"},
176 	{ERR_PACK(ERR_LIB_SYS, SYS_F_GETSERVBYNAME, 0),	"getservbyname"},
177 	{ERR_PACK(ERR_LIB_SYS, SYS_F_SOCKET, 0),	"socket"},
178 	{ERR_PACK(ERR_LIB_SYS, SYS_F_IOCTLSOCKET, 0),	"ioctl"},
179 	{ERR_PACK(ERR_LIB_SYS, SYS_F_BIND, 0),		"bind"},
180 	{ERR_PACK(ERR_LIB_SYS, SYS_F_LISTEN, 0),	"listen"},
181 	{ERR_PACK(ERR_LIB_SYS, SYS_F_ACCEPT, 0),	"accept"},
182 	{ERR_PACK(ERR_LIB_SYS, SYS_F_OPENDIR, 0),	"opendir"},
183 	{ERR_PACK(ERR_LIB_SYS, SYS_F_FREAD, 0),		"fread"},
184 	{0, NULL},
185 };
186 
187 static const ERR_STRING_DATA ERR_str_reasons[] = {
188 	{ERR_R_SYS_LIB,				"system lib"},
189 	{ERR_R_BN_LIB,				"BN lib"},
190 	{ERR_R_RSA_LIB,				"RSA lib"},
191 	{ERR_R_DH_LIB,				"DH lib"},
192 	{ERR_R_EVP_LIB,				"EVP lib"},
193 	{ERR_R_BUF_LIB,				"BUF lib"},
194 	{ERR_R_OBJ_LIB,				"OBJ lib"},
195 	{ERR_R_PEM_LIB,				"PEM lib"},
196 	{ERR_R_DSA_LIB,				"DSA lib"},
197 	{ERR_R_X509_LIB,			"X509 lib"},
198 	{ERR_R_ASN1_LIB,			"ASN1 lib"},
199 	{ERR_R_CONF_LIB,			"CONF lib"},
200 	{ERR_R_CRYPTO_LIB,			"CRYPTO lib"},
201 	{ERR_R_EC_LIB,				"EC lib"},
202 	{ERR_R_SSL_LIB,				"SSL lib"},
203 	{ERR_R_BIO_LIB,				"BIO lib"},
204 	{ERR_R_PKCS7_LIB,			"PKCS7 lib"},
205 	{ERR_R_X509V3_LIB,			"X509V3 lib"},
206 	{ERR_R_PKCS12_LIB,			"PKCS12 lib"},
207 	{ERR_R_RAND_LIB,			"RAND lib"},
208 	{ERR_R_DSO_LIB,				"DSO lib"},
209 	{ERR_R_ENGINE_LIB,			"ENGINE lib"},
210 	{ERR_R_OCSP_LIB,			"OCSP lib"},
211 	{ERR_R_TS_LIB,				"TS lib"},
212 
213 	{ERR_R_NESTED_ASN1_ERROR,		"nested asn1 error"},
214 	{ERR_R_BAD_ASN1_OBJECT_HEADER,		"bad asn1 object header"},
215 	{ERR_R_BAD_GET_ASN1_OBJECT_CALL,	"bad get asn1 object call"},
216 	{ERR_R_EXPECTING_AN_ASN1_SEQUENCE,	"expecting an asn1 sequence"},
217 	{ERR_R_ASN1_LENGTH_MISMATCH,		"asn1 length mismatch"},
218 	{ERR_R_MISSING_ASN1_EOS,		"missing asn1 eos"},
219 
220 	{ERR_R_FATAL,				"fatal"},
221 	{ERR_R_MALLOC_FAILURE,			"malloc failure"},
222 	{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,	"called a function you should not call"},
223 	{ERR_R_PASSED_NULL_PARAMETER,		"passed a null parameter"},
224 	{ERR_R_INTERNAL_ERROR,			"internal error"},
225 	{ERR_R_DISABLED,			"called a function that was disabled at compile-time"},
226 	{ERR_R_INIT_FAIL,			"initialization failure"},
227 
228 	{0, NULL},
229 };
230 #endif
231 
232 static void ERR_STATE_free(ERR_STATE *s);
233 
234 /*
235  * The internal state used by "err_defaults" - as such, the setting, reading,
236  * creating, and deleting of this data should only be permitted via the
237  * "err_defaults" functions. This way, a linked module can completely defer all
238  * ERR state operation (together with requisite locking) to the implementations
239  * and state in the loading application.
240  */
241 static LHASH_OF(ERR_STRING_DATA) *err_error_hash = NULL;
242 static LHASH_OF(ERR_STATE) *err_thread_hash = NULL;
243 static int err_thread_hash_references = 0;
244 static int err_library_number = ERR_LIB_USER;
245 
246 static pthread_t err_init_thread;
247 
248 /*
249  * These are the callbacks provided to "lh_new()" when creating the LHASH tables
250  * internal to the "err_defaults" implementation.
251  */
252 
253 static unsigned long
err_string_data_hash(const ERR_STRING_DATA * a)254 err_string_data_hash(const ERR_STRING_DATA *a)
255 {
256 	unsigned long ret, l;
257 
258 	l = a->error;
259 	ret = l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
260 	return (ret^ret % 19*13);
261 }
IMPLEMENT_LHASH_HASH_FN(err_string_data,ERR_STRING_DATA)262 static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA)
263 
264 static int
265 err_string_data_cmp(const ERR_STRING_DATA *a, const ERR_STRING_DATA *b)
266 {
267 	return (int)(a->error - b->error);
268 }
IMPLEMENT_LHASH_COMP_FN(err_string_data,ERR_STRING_DATA)269 static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA)
270 
271 static LHASH_OF(ERR_STRING_DATA) *
272 err_get(int create)
273 {
274 	LHASH_OF(ERR_STRING_DATA) *ret = NULL;
275 
276 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
277 	if (!err_error_hash && create)
278 		err_error_hash = lh_ERR_STRING_DATA_new();
279 	if (err_error_hash)
280 		ret = err_error_hash;
281 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
282 
283 	return ret;
284 }
285 
286 static void
err_del(void)287 err_del(void)
288 {
289 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
290 	if (err_error_hash) {
291 		lh_ERR_STRING_DATA_free(err_error_hash);
292 		err_error_hash = NULL;
293 	}
294 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
295 }
296 
297 static const ERR_STRING_DATA *
err_get_item(const ERR_STRING_DATA * d)298 err_get_item(const ERR_STRING_DATA *d)
299 {
300 	ERR_STRING_DATA *p;
301 	LHASH_OF(ERR_STRING_DATA) *hash;
302 
303 	hash = err_get(0);
304 	if (!hash)
305 		return NULL;
306 
307 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
308 	p = lh_ERR_STRING_DATA_retrieve(hash, d);
309 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
310 
311 	return p;
312 }
313 
314 static const ERR_STRING_DATA *
err_set_item(const ERR_STRING_DATA * d)315 err_set_item(const ERR_STRING_DATA *d)
316 {
317 	const ERR_STRING_DATA *p;
318 	LHASH_OF(ERR_STRING_DATA) *hash;
319 
320 	hash = err_get(1);
321 	if (!hash)
322 		return NULL;
323 
324 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
325 	p = lh_ERR_STRING_DATA_insert(hash, (void *)d);
326 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
327 
328 	return p;
329 }
330 
331 static const ERR_STRING_DATA *
err_del_item(const ERR_STRING_DATA * d)332 err_del_item(const ERR_STRING_DATA *d)
333 {
334 	ERR_STRING_DATA *p;
335 	LHASH_OF(ERR_STRING_DATA) *hash;
336 
337 	hash = err_get(0);
338 	if (!hash)
339 		return NULL;
340 
341 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
342 	p = lh_ERR_STRING_DATA_delete(hash, d);
343 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
344 
345 	return p;
346 }
347 
348 static unsigned long
err_state_hash(const ERR_STATE * a)349 err_state_hash(const ERR_STATE *a)
350 {
351 	return 13 * (unsigned long)a->tid;
352 }
IMPLEMENT_LHASH_HASH_FN(err_state,ERR_STATE)353 static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
354 
355 static int
356 err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
357 {
358 	return pthread_equal(a->tid, b->tid) == 0;
359 }
IMPLEMENT_LHASH_COMP_FN(err_state,ERR_STATE)360 static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
361 
362 static LHASH_OF(ERR_STATE) *
363 err_thread_get(int create)
364 {
365 	LHASH_OF(ERR_STATE) *ret = NULL;
366 
367 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
368 	if (!err_thread_hash && create)
369 		err_thread_hash = lh_ERR_STATE_new();
370 	if (err_thread_hash) {
371 		err_thread_hash_references++;
372 		ret = err_thread_hash;
373 	}
374 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
375 	return ret;
376 }
377 
378 static void
err_thread_release(LHASH_OF (ERR_STATE)** hash)379 err_thread_release(LHASH_OF(ERR_STATE) **hash)
380 {
381 	int i;
382 
383 	if (hash == NULL || *hash == NULL)
384 		return;
385 
386 	i = CRYPTO_add(&err_thread_hash_references, -1, CRYPTO_LOCK_ERR);
387 	if (i > 0)
388 		return;
389 
390 	*hash = NULL;
391 }
392 
393 static ERR_STATE *
err_thread_get_item(const ERR_STATE * d)394 err_thread_get_item(const ERR_STATE *d)
395 {
396 	ERR_STATE *p;
397 	LHASH_OF(ERR_STATE) *hash;
398 
399 	hash = err_thread_get(0);
400 	if (!hash)
401 		return NULL;
402 
403 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
404 	p = lh_ERR_STATE_retrieve(hash, d);
405 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
406 
407 	err_thread_release(&hash);
408 	return p;
409 }
410 
411 static ERR_STATE *
err_thread_set_item(ERR_STATE * d)412 err_thread_set_item(ERR_STATE *d)
413 {
414 	ERR_STATE *p;
415 	LHASH_OF(ERR_STATE) *hash;
416 
417 	hash = err_thread_get(1);
418 	if (!hash)
419 		return NULL;
420 
421 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
422 	p = lh_ERR_STATE_insert(hash, d);
423 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
424 
425 	err_thread_release(&hash);
426 	return p;
427 }
428 
429 static void
err_thread_del_item(const ERR_STATE * d)430 err_thread_del_item(const ERR_STATE *d)
431 {
432 	ERR_STATE *p;
433 	LHASH_OF(ERR_STATE) *hash;
434 
435 	hash = err_thread_get(0);
436 	if (!hash)
437 		return;
438 
439 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
440 	p = lh_ERR_STATE_delete(hash, d);
441 	/* make sure we don't leak memory */
442 	if (err_thread_hash_references == 1 &&
443 	    err_thread_hash && lh_ERR_STATE_num_items(err_thread_hash) == 0) {
444 		lh_ERR_STATE_free(err_thread_hash);
445 		err_thread_hash = NULL;
446 	}
447 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
448 
449 	err_thread_release(&hash);
450 	if (p)
451 		ERR_STATE_free(p);
452 }
453 
454 static int
err_get_next_lib(void)455 err_get_next_lib(void)
456 {
457 	int ret;
458 
459 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
460 	ret = err_library_number++;
461 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
462 
463 	return ret;
464 }
465 
466 
467 #ifndef OPENSSL_NO_ERR
468 #define NUM_SYS_STR_REASONS 127
469 #define LEN_SYS_STR_REASON 32
470 
471 static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
472 
473 /*
474  * SYS_str_reasons is filled with copies of strerror() results at
475  * initialization. 'errno' values up to 127 should cover all usual errors,
476  * others will be displayed numerically by ERR_error_string. It is crucial that
477  * we have something for each reason code that occurs in ERR_str_reasons, or
478  * bogus reason strings will be returned for SYSerror(), which always gets an
479  * errno value and never one of those 'standard' reason codes.
480  */
481 
482 static void
err_build_SYS_str_reasons(void)483 err_build_SYS_str_reasons(void)
484 {
485 	/* malloc cannot be used here, use static storage instead */
486 	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
487 	int save_errno;
488 	int i;
489 
490 	/* strerror(3) will set errno to EINVAL when i is an unknown errno. */
491 	save_errno = errno;
492 	for (i = 1; i <= NUM_SYS_STR_REASONS; i++) {
493 		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
494 
495 		str->error = (unsigned long)i;
496 		if (str->string == NULL) {
497 			char (*dest)[LEN_SYS_STR_REASON] =
498 			    &(strerror_tab[i - 1]);
499 			const char *src = strerror(i);
500 			if (src != NULL) {
501 				strlcpy(*dest, src, sizeof *dest);
502 				str->string = *dest;
503 			}
504 		}
505 		if (str->string == NULL)
506 			str->string = "unknown";
507 	}
508 	errno = save_errno;
509 
510 	/*
511 	 * Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
512 	 * as required by ERR_load_strings.
513 	 */
514 }
515 #endif
516 
517 static void
err_clear_data(ERR_STATE * s,int i)518 err_clear_data(ERR_STATE *s, int i)
519 {
520 	if ((s->err_data_flags[i] & ERR_TXT_MALLOCED) != 0)
521 		free(s->err_data[i]);
522 
523 	s->err_data[i] = NULL;
524 	s->err_data_flags[i] = 0;
525 }
526 
527 static void
err_clear(ERR_STATE * s,int i)528 err_clear(ERR_STATE *s, int i)
529 {
530 	s->err_flags[i] = 0;
531 	s->err_buffer[i] = 0;
532 	s->err_file[i] = NULL;
533 	s->err_line[i] = -1;
534 
535 	err_clear_data(s, i);
536 }
537 
538 static void
ERR_STATE_free(ERR_STATE * s)539 ERR_STATE_free(ERR_STATE *s)
540 {
541 	int i;
542 
543 	if (s == NULL)
544 		return;
545 
546 	for (i = 0; i < ERR_NUM_ERRORS; i++)
547 		err_clear_data(s, i);
548 
549 	free(s);
550 }
551 
552 static ERR_STATE *
ERR_get_state(void)553 ERR_get_state(void)
554 {
555 	static ERR_STATE fallback;
556 	ERR_STATE *ret, tmp, *tmpp = NULL;
557 	int i;
558 
559 	tmp.tid = pthread_self();
560 	ret = err_thread_get_item(&tmp);
561 
562 	/* ret == the error state, if NULL, make a new one */
563 	if (ret == NULL) {
564 		ret = malloc(sizeof(ERR_STATE));
565 		if (ret == NULL)
566 			return (&fallback);
567 		ret->tid = pthread_self();
568 		ret->top = 0;
569 		ret->bottom = 0;
570 		for (i = 0; i < ERR_NUM_ERRORS; i++) {
571 			ret->err_data[i] = NULL;
572 			ret->err_data_flags[i] = 0;
573 		}
574 		tmpp = err_thread_set_item(ret);
575 		/* To check if insertion failed, do a get. */
576 		if (err_thread_get_item(ret) != ret) {
577 			ERR_STATE_free(ret); /* could not insert it */
578 			return (&fallback);
579 		}
580 		/*
581 		 * If a race occurred in this function and we came second,
582 		 * tmpp is the first one that we just replaced.
583 		 */
584 		if (tmpp)
585 			ERR_STATE_free(tmpp);
586 	}
587 	return ret;
588 }
589 
590 static void
err_load_strings(int lib,ERR_STRING_DATA * str)591 err_load_strings(int lib, ERR_STRING_DATA *str)
592 {
593 	while (str->error != 0) {
594 		if (lib)
595 			str->error |= ERR_PACK(lib, 0, 0);
596 		err_set_item(str);
597 		str++;
598 	}
599 }
600 
601 static void
err_load_const_strings(const ERR_STRING_DATA * str)602 err_load_const_strings(const ERR_STRING_DATA *str)
603 {
604 	while (str->error != 0) {
605 		err_set_item(str);
606 		str++;
607 	}
608 }
609 
610 static unsigned long
get_error_values(int inc,int top,const char ** file,int * line,const char ** data,int * flags)611 get_error_values(int inc, int top, const char **file, int *line,
612     const char **data, int *flags)
613 {
614 	int i = 0;
615 	ERR_STATE *es;
616 	unsigned long ret;
617 
618 	es = ERR_get_state();
619 
620 	if (inc && top) {
621 		if (file)
622 			*file = "";
623 		if (line)
624 			*line = 0;
625 		if (data)
626 			*data = "";
627 		if (flags)
628 			*flags = 0;
629 
630 		return ERR_R_INTERNAL_ERROR;
631 	}
632 
633 	if (es->bottom == es->top)
634 		return 0;
635 	if (top)
636 		i = es->top;			 /* last error */
637 	else
638 		i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
639 
640 	ret = es->err_buffer[i];
641 	if (inc) {
642 		es->bottom = i;
643 		es->err_buffer[i] = 0;
644 	}
645 
646 	if ((file != NULL) && (line != NULL)) {
647 		if (es->err_file[i] == NULL) {
648 			*file = "NA";
649 			if (line != NULL)
650 				*line = 0;
651 		} else {
652 			*file = es->err_file[i];
653 			if (line != NULL)
654 				*line = es->err_line[i];
655 		}
656 	}
657 
658 	if (data == NULL) {
659 		if (inc) {
660 			err_clear_data(es, i);
661 		}
662 	} else {
663 		if (es->err_data[i] == NULL) {
664 			*data = "";
665 			if (flags != NULL)
666 				*flags = 0;
667 		} else {
668 			*data = es->err_data[i];
669 			if (flags != NULL)
670 				*flags = es->err_data_flags[i];
671 		}
672 	}
673 	return ret;
674 }
675 
676 void
ERR_load_ERR_strings_internal(void)677 ERR_load_ERR_strings_internal(void)
678 {
679 	err_init_thread = pthread_self();
680 #ifndef OPENSSL_NO_ERR
681 	err_load_const_strings(ERR_str_libraries);
682 	err_load_const_strings(ERR_str_reasons);
683 	err_load_const_strings(ERR_str_functs);
684 	err_build_SYS_str_reasons();
685 	err_load_strings(ERR_LIB_SYS, SYS_str_reasons);
686 #endif
687 }
688 
689 void
ERR_load_ERR_strings(void)690 ERR_load_ERR_strings(void)
691 {
692 	static pthread_once_t once = PTHREAD_ONCE_INIT;
693 
694 	if (pthread_equal(pthread_self(), err_init_thread))
695 		return; /* don't recurse */
696 
697 	/* Prayer and clean living lets you ignore errors, OpenSSL style */
698 	(void) OPENSSL_init_crypto(0, NULL);
699 
700 	(void) pthread_once(&once, ERR_load_ERR_strings_internal);
701 }
702 LCRYPTO_ALIAS(ERR_load_ERR_strings);
703 
704 void
ERR_load_strings(int lib,ERR_STRING_DATA * str)705 ERR_load_strings(int lib, ERR_STRING_DATA *str)
706 {
707 	ERR_load_ERR_strings();
708 	err_load_strings(lib, str);
709 }
710 LCRYPTO_ALIAS(ERR_load_strings);
711 
712 void
ERR_load_const_strings(const ERR_STRING_DATA * str)713 ERR_load_const_strings(const ERR_STRING_DATA *str)
714 {
715 	ERR_load_ERR_strings();
716 	err_load_const_strings(str);
717 }
718 
719 void
ERR_unload_strings(int lib,ERR_STRING_DATA * str)720 ERR_unload_strings(int lib, ERR_STRING_DATA *str)
721 {
722 	/* Prayer and clean living lets you ignore errors, OpenSSL style */
723 	(void) OPENSSL_init_crypto(0, NULL);
724 
725 	while (str->error) {
726 		if (lib)
727 			str->error |= ERR_PACK(lib, 0, 0);
728 		err_del_item(str);
729 		str++;
730 	}
731 }
732 LCRYPTO_ALIAS(ERR_unload_strings);
733 
734 void
ERR_free_strings(void)735 ERR_free_strings(void)
736 {
737 	/* Prayer and clean living lets you ignore errors, OpenSSL style */
738 	(void) OPENSSL_init_crypto(0, NULL);
739 
740 	err_del();
741 }
742 LCRYPTO_ALIAS(ERR_free_strings);
743 
744 int
ERR_get_next_error_library(void)745 ERR_get_next_error_library(void)
746 {
747 	return err_get_next_lib();
748 }
749 LCRYPTO_ALIAS(ERR_get_next_error_library);
750 
751 void
ERR_remove_thread_state(const CRYPTO_THREADID * id)752 ERR_remove_thread_state(const CRYPTO_THREADID *id)
753 {
754 	ERR_STATE tmp;
755 
756 	OPENSSL_assert(id == NULL);
757 	tmp.tid = pthread_self();
758 
759 	/*
760 	 * err_thread_del_item automatically destroys the LHASH if the number of
761 	 * items reaches zero.
762 	 */
763 	err_thread_del_item(&tmp);
764 }
765 LCRYPTO_ALIAS(ERR_remove_thread_state);
766 
767 void
ERR_remove_state(unsigned long pid)768 ERR_remove_state(unsigned long pid)
769 {
770 	ERR_remove_thread_state(NULL);
771 }
772 LCRYPTO_ALIAS(ERR_remove_state);
773 
774 int
ERR_set_mark(void)775 ERR_set_mark(void)
776 {
777 	ERR_STATE *es;
778 
779 	es = ERR_get_state();
780 
781 	if (es->bottom == es->top)
782 		return 0;
783 	es->err_flags[es->top] |= ERR_FLAG_MARK;
784 	return 1;
785 }
786 LCRYPTO_ALIAS(ERR_set_mark);
787 
788 int
ERR_pop_to_mark(void)789 ERR_pop_to_mark(void)
790 {
791 	ERR_STATE *es;
792 
793 	es = ERR_get_state();
794 
795 	while (es->bottom != es->top &&
796 	    (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
797 		err_clear(es, es->top);
798 		es->top -= 1;
799 		if (es->top == -1)
800 			es->top = ERR_NUM_ERRORS - 1;
801 	}
802 
803 	if (es->bottom == es->top)
804 		return 0;
805 	es->err_flags[es->top]&=~ERR_FLAG_MARK;
806 	return 1;
807 }
808 LCRYPTO_ALIAS(ERR_pop_to_mark);
809 
810 void
ERR_clear_error(void)811 ERR_clear_error(void)
812 {
813 	int i;
814 	ERR_STATE *es;
815 
816 	es = ERR_get_state();
817 
818 	for (i = 0; i < ERR_NUM_ERRORS; i++)
819 		err_clear(es, i);
820 
821 	es->top = es->bottom = 0;
822 }
823 LCRYPTO_ALIAS(ERR_clear_error);
824 
825 void
err_clear_last_constant_time(int clear)826 err_clear_last_constant_time(int clear)
827 {
828 	ERR_STATE *es;
829 	int top;
830 
831 	es = ERR_get_state();
832 	if (es == NULL)
833         return;
834 
835 	top = es->top;
836 
837 	es->err_flags[top] &= ~(0 - clear);
838 	es->err_buffer[top] &= ~(0UL - clear);
839 	es->err_file[top] = (const char *)((uintptr_t)es->err_file[top] &
840 	    ~((uintptr_t)0 - clear));
841 	es->err_line[top] |= 0 - clear;
842 
843 	es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
844 }
845 
846 void
ERR_put_error(int lib,int func,int reason,const char * file,int line)847 ERR_put_error(int lib, int func, int reason, const char *file, int line)
848 {
849 	ERR_STATE *es;
850 	int save_errno = errno;
851 
852 	es = ERR_get_state();
853 
854 	es->top = (es->top + 1) % ERR_NUM_ERRORS;
855 	if (es->top == es->bottom)
856 		es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
857 	es->err_flags[es->top] = 0;
858 	es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
859 	es->err_file[es->top] = file;
860 	es->err_line[es->top] = line;
861 	err_clear_data(es, es->top);
862 	errno = save_errno;
863 }
864 LCRYPTO_ALIAS(ERR_put_error);
865 
866 void
ERR_asprintf_error_data(char * format,...)867 ERR_asprintf_error_data(char * format, ...)
868 {
869 	char *errbuf = NULL;
870 	va_list ap;
871 	int r;
872 
873 	va_start(ap, format);
874 	r = vasprintf(&errbuf, format, ap);
875 	va_end(ap);
876 	if (r == -1)
877 		ERR_set_error_data("malloc failed", ERR_TXT_STRING);
878 	else
879 		ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING);
880 }
881 LCRYPTO_ALIAS(ERR_asprintf_error_data);
882 
883 void
ERR_set_error_data(char * data,int flags)884 ERR_set_error_data(char *data, int flags)
885 {
886 	ERR_STATE *es;
887 	int i;
888 
889 	es = ERR_get_state();
890 
891 	i = es->top;
892 	if (i == 0)
893 		i = ERR_NUM_ERRORS - 1;
894 
895 	err_clear_data(es, i);
896 	es->err_data[i] = data;
897 	es->err_data_flags[i] = flags;
898 }
899 LCRYPTO_ALIAS(ERR_set_error_data);
900 
901 unsigned long
ERR_get_error(void)902 ERR_get_error(void)
903 {
904 	return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
905 }
906 LCRYPTO_ALIAS(ERR_get_error);
907 
908 unsigned long
ERR_get_error_line(const char ** file,int * line)909 ERR_get_error_line(const char **file, int *line)
910 {
911 	return (get_error_values(1, 0, file, line, NULL, NULL));
912 }
913 LCRYPTO_ALIAS(ERR_get_error_line);
914 
915 unsigned long
ERR_get_error_line_data(const char ** file,int * line,const char ** data,int * flags)916 ERR_get_error_line_data(const char **file, int *line,
917     const char **data, int *flags)
918 {
919 	return (get_error_values(1, 0, file, line, data, flags));
920 }
921 LCRYPTO_ALIAS(ERR_get_error_line_data);
922 
923 unsigned long
ERR_peek_error(void)924 ERR_peek_error(void)
925 {
926 	return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
927 }
928 LCRYPTO_ALIAS(ERR_peek_error);
929 
930 unsigned long
ERR_peek_error_line(const char ** file,int * line)931 ERR_peek_error_line(const char **file, int *line)
932 {
933 	return (get_error_values(0, 0, file, line, NULL, NULL));
934 }
935 LCRYPTO_ALIAS(ERR_peek_error_line);
936 
937 unsigned long
ERR_peek_error_line_data(const char ** file,int * line,const char ** data,int * flags)938 ERR_peek_error_line_data(const char **file, int *line,
939     const char **data, int *flags)
940 {
941 	return (get_error_values(0, 0, file, line, data, flags));
942 }
943 LCRYPTO_ALIAS(ERR_peek_error_line_data);
944 
945 unsigned long
ERR_peek_last_error(void)946 ERR_peek_last_error(void)
947 {
948 	return (get_error_values(0, 1, NULL, NULL, NULL, NULL));
949 }
950 LCRYPTO_ALIAS(ERR_peek_last_error);
951 
952 unsigned long
ERR_peek_last_error_line(const char ** file,int * line)953 ERR_peek_last_error_line(const char **file, int *line)
954 {
955 	return (get_error_values(0, 1, file, line, NULL, NULL));
956 }
957 LCRYPTO_ALIAS(ERR_peek_last_error_line);
958 
959 unsigned long
ERR_peek_last_error_line_data(const char ** file,int * line,const char ** data,int * flags)960 ERR_peek_last_error_line_data(const char **file, int *line,
961     const char **data, int *flags)
962 {
963 	return (get_error_values(0, 1, file, line, data, flags));
964 }
965 LCRYPTO_ALIAS(ERR_peek_last_error_line_data);
966 
967 const char *
ERR_lib_error_string(unsigned long e)968 ERR_lib_error_string(unsigned long e)
969 {
970 	const ERR_STRING_DATA *p;
971 	ERR_STRING_DATA d;
972 	unsigned long l;
973 
974 	if (!OPENSSL_init_crypto(0, NULL))
975 		return NULL;
976 
977 	l = ERR_GET_LIB(e);
978 	d.error = ERR_PACK(l, 0, 0);
979 	p = err_get_item(&d);
980 	return ((p == NULL) ? NULL : p->string);
981 }
982 LCRYPTO_ALIAS(ERR_lib_error_string);
983 
984 const char *
ERR_func_error_string(unsigned long e)985 ERR_func_error_string(unsigned long e)
986 {
987 	const ERR_STRING_DATA *p;
988 	ERR_STRING_DATA d;
989 	unsigned long l, f;
990 
991 	l = ERR_GET_LIB(e);
992 	f = ERR_GET_FUNC(e);
993 	d.error = ERR_PACK(l, f, 0);
994 	p = err_get_item(&d);
995 	return ((p == NULL) ? NULL : p->string);
996 }
997 LCRYPTO_ALIAS(ERR_func_error_string);
998 
999 const char *
ERR_reason_error_string(unsigned long e)1000 ERR_reason_error_string(unsigned long e)
1001 {
1002 	const ERR_STRING_DATA *p = NULL;
1003 	ERR_STRING_DATA d;
1004 	unsigned long l, r;
1005 
1006 	l = ERR_GET_LIB(e);
1007 	r = ERR_GET_REASON(e);
1008 	d.error = ERR_PACK(l, 0, r);
1009 	p = err_get_item(&d);
1010 	if (!p) {
1011 		d.error = ERR_PACK(0, 0, r);
1012 		p = err_get_item(&d);
1013 	}
1014 	return ((p == NULL) ? NULL : p->string);
1015 }
1016 LCRYPTO_ALIAS(ERR_reason_error_string);
1017 
1018 void
ERR_error_string_n(unsigned long e,char * buf,size_t len)1019 ERR_error_string_n(unsigned long e, char *buf, size_t len)
1020 {
1021 	char lsbuf[30], fsbuf[30], rsbuf[30];
1022 	const char *ls, *fs, *rs;
1023 	int l, f, r, ret;
1024 
1025 	l = ERR_GET_LIB(e);
1026 	f = ERR_GET_FUNC(e);
1027 	r = ERR_GET_REASON(e);
1028 
1029 	ls = ERR_lib_error_string(e);
1030 	fs = ERR_func_error_string(e);
1031 	rs = ERR_reason_error_string(e);
1032 
1033 	if (ls == NULL) {
1034 		(void) snprintf(lsbuf, sizeof(lsbuf), "lib(%d)", l);
1035 		ls = lsbuf;
1036 	}
1037 	if (fs == NULL) {
1038 		(void) snprintf(fsbuf, sizeof(fsbuf), "func(%d)", f);
1039 		fs = fsbuf;
1040 	}
1041 	if (rs == NULL) {
1042 		(void) snprintf(rsbuf, sizeof(rsbuf), "reason(%d)", r);
1043 		rs = rsbuf;
1044 	}
1045 
1046 	ret = snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, fs, rs);
1047 	if (ret == -1)
1048 		return;	/* can't happen, and can't do better if it does */
1049 	if (ret >= len) {
1050 		/*
1051 		 * output may be truncated; make sure we always have 5
1052 		 * colon-separated fields, i.e. 4 colons ...
1053 		 */
1054 #define NUM_COLONS 4
1055 		if (len > NUM_COLONS) /* ... if possible */
1056 		{
1057 			int i;
1058 			char *s = buf;
1059 
1060 			for (i = 0; i < NUM_COLONS; i++) {
1061 				char *colon = strchr(s, ':');
1062 				if (colon == NULL ||
1063 				    colon > &buf[len - 1] - NUM_COLONS + i) {
1064 					/* set colon no. i at last possible position
1065 					 * (buf[len-1] is the terminating 0)*/
1066 					colon = &buf[len - 1] - NUM_COLONS + i;
1067 					*colon = ':';
1068 				}
1069 				s = colon + 1;
1070 			}
1071 		}
1072 	}
1073 }
1074 LCRYPTO_ALIAS(ERR_error_string_n);
1075 
1076 /*
1077  * ERR_error_string_n should be used instead for ret != NULL
1078  * as ERR_error_string cannot know how large the buffer is.
1079  *
1080  * BAD for multi-threading: uses a local buffer if ret == NULL.
1081  */
1082 char *
ERR_error_string(unsigned long e,char * ret)1083 ERR_error_string(unsigned long e, char *ret)
1084 {
1085 	static char buf[256];
1086 
1087 	if (ret == NULL)
1088 		ret = buf;
1089 	ERR_error_string_n(e, ret, 256);
1090 
1091 	return ret;
1092 }
1093 LCRYPTO_ALIAS(ERR_error_string);
1094