blob: 89832fce5055a2838b576267212edad607e97164 [file] [log] [blame]
David Benjamin820731a2015-07-23 20:01:51 -04001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
Adam Langley95c29f32014-06-20 12:00:00 -07003 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
Adam Langley95c29f32014-06-20 12:00:00 -070057#include <openssl/mem.h>
58
59#include <assert.h>
Bob Beck350f8542023-02-07 16:11:58 -070060#include <errno.h>
61#include <limits.h>
Adam Langley95c29f32014-06-20 12:00:00 -070062#include <stdarg.h>
63#include <stdio.h>
Bob Beck350f8542023-02-07 16:11:58 -070064#include <stdlib.h>
Adam Langley95c29f32014-06-20 12:00:00 -070065
David Benjamin3ba95862019-10-21 16:14:33 -040066#include <openssl/err.h>
67
Adam Langleyded93582014-07-31 15:23:51 -070068#if defined(OPENSSL_WINDOWS)
David Benjamina353cdb2016-06-09 16:48:33 -040069OPENSSL_MSVC_PRAGMA(warning(push, 3))
Adam Langley3e719312015-03-20 16:32:23 -070070#include <windows.h>
David Benjamin054e5972016-06-16 12:08:26 -040071OPENSSL_MSVC_PRAGMA(warning(pop))
Adam Langleyded93582014-07-31 15:23:51 -070072#endif
73
David Benjamin582904f2023-02-04 18:30:36 -050074#if defined(BORINGSSL_MALLOC_FAILURE_TESTING)
75#include <errno.h>
76#include <signal.h>
77#include <unistd.h>
78#endif
79
David Benjamin17cf2cb2016-12-13 01:07:13 -050080#include "internal.h"
81
Adam Langley95c29f32014-06-20 12:00:00 -070082
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -070083#define OPENSSL_MALLOC_PREFIX 8
David Benjaminb7d63202022-07-26 13:25:02 -070084static_assert(OPENSSL_MALLOC_PREFIX >= sizeof(size_t), "size_t too large");
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -070085
David Benjaminda8bb842019-02-26 22:13:28 -060086#if defined(OPENSSL_ASAN)
87void __asan_poison_memory_region(const volatile void *addr, size_t size);
88void __asan_unpoison_memory_region(const volatile void *addr, size_t size);
89#else
90static void __asan_poison_memory_region(const void *addr, size_t size) {}
91static void __asan_unpoison_memory_region(const void *addr, size_t size) {}
92#endif
93
John Sheu787b26c2019-05-03 12:08:12 -070094// Windows doesn't really support weak symbols as of May 2019, and Clang on
95// Windows will emit strong symbols instead. See
96// https://bugs.llvm.org/show_bug.cgi?id=37598
Adam Langley0cf14d32020-03-30 09:24:45 -070097#if defined(__ELF__) && defined(__GNUC__)
98#define WEAK_SYMBOL_FUNC(rettype, name, args) \
99 rettype name args __attribute__((weak));
Wiktor Garbacz9ae40ce2020-02-05 18:14:20 +0100100#else
Adam Langley0cf14d32020-03-30 09:24:45 -0700101#define WEAK_SYMBOL_FUNC(rettype, name, args) static rettype(*name) args = NULL;
Wiktor Garbacz9ae40ce2020-02-05 18:14:20 +0100102#endif
103
Chris Kennellyb5e4a222018-09-10 11:47:15 -0400104// sdallocx is a sized |free| function. By passing the size (which we happen to
Adam Langleyb49b78e2021-09-02 14:57:02 -0700105// always know in BoringSSL), the malloc implementation can save work. We cannot
106// depend on |sdallocx| being available, however, so it's a weak symbol.
Chris Kennellyb5e4a222018-09-10 11:47:15 -0400107//
Adam Langleyb49b78e2021-09-02 14:57:02 -0700108// This will always be safe, but will only be overridden if the malloc
109// implementation is statically linked with BoringSSL. So, if |sdallocx| is
110// provided in, say, libc.so, we still won't use it because that's dynamically
111// linked. This isn't an ideal result, but its helps in some cases.
112WEAK_SYMBOL_FUNC(void, sdallocx, (void *ptr, size_t size, int flags));
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700113
Adam Langley0313b592020-06-10 14:38:02 -0700114// The following three functions can be defined to override default heap
115// allocation and freeing. If defined, it is the responsibility of
116// |OPENSSL_memory_free| to zero out the memory before returning it to the
117// system. |OPENSSL_memory_free| will not be passed NULL pointers.
David Benjamin20f7bba2021-03-24 02:31:33 -0400118//
119// WARNING: These functions are called on every allocation and free in
120// BoringSSL across the entire process. They may be called by any code in the
121// process which calls BoringSSL, including in process initializers and thread
122// destructors. When called, BoringSSL may hold pthreads locks. Any other code
123// in the process which, directly or indirectly, calls BoringSSL may be on the
124// call stack and may itself be using arbitrary synchronization primitives.
125//
126// As a result, these functions may not have the usual programming environment
127// available to most C or C++ code. In particular, they may not call into
128// BoringSSL, or any library which depends on BoringSSL. Any synchronization
129// primitives used must tolerate every other synchronization primitive linked
130// into the process, including pthreads locks. Failing to meet these constraints
131// may result in deadlocks, crashes, or memory corruption.
Bob Beck350f8542023-02-07 16:11:58 -0700132WEAK_SYMBOL_FUNC(void *, OPENSSL_memory_alloc, (size_t size));
Adam Langley0313b592020-06-10 14:38:02 -0700133WEAK_SYMBOL_FUNC(void, OPENSSL_memory_free, (void *ptr));
134WEAK_SYMBOL_FUNC(size_t, OPENSSL_memory_get_size, (void *ptr));
Wiktor Garbacz9ae40ce2020-02-05 18:14:20 +0100135
Adam Langley89386ac2021-10-12 12:43:14 -0700136// kBoringSSLBinaryTag is a distinctive byte sequence to identify binaries that
137// are linking in BoringSSL and, roughly, what version they are using.
138static const uint8_t kBoringSSLBinaryTag[18] = {
139 // 16 bytes of magic tag.
Bob Beck350f8542023-02-07 16:11:58 -0700140 0x8c,
141 0x62,
142 0x20,
143 0x0b,
144 0xd2,
145 0xa0,
146 0x72,
147 0x58,
148 0x44,
149 0xa8,
150 0x96,
151 0x69,
152 0xad,
153 0x55,
154 0x7e,
155 0xec,
Adam Langley89386ac2021-10-12 12:43:14 -0700156 // Current source iteration. Incremented ~monthly.
Bob Beck350f8542023-02-07 16:11:58 -0700157 3,
158 0,
Adam Langley89386ac2021-10-12 12:43:14 -0700159};
160
David Benjamin582904f2023-02-04 18:30:36 -0500161#if defined(BORINGSSL_MALLOC_FAILURE_TESTING)
David Benjamin04c3d402023-06-03 01:26:29 -0400162static CRYPTO_MUTEX malloc_failure_lock = CRYPTO_MUTEX_INIT;
David Benjamin582904f2023-02-04 18:30:36 -0500163static uint64_t current_malloc_count = 0;
164static uint64_t malloc_number_to_fail = 0;
David Benjamin5e356a82023-02-04 19:44:34 -0500165static int malloc_failure_enabled = 0, break_on_malloc_fail = 0,
166 any_malloc_failed = 0;
David Benjamin582904f2023-02-04 18:30:36 -0500167
168static void malloc_exit_handler(void) {
David Benjamin04c3d402023-06-03 01:26:29 -0400169 CRYPTO_MUTEX_lock_read(&malloc_failure_lock);
David Benjamin5e356a82023-02-04 19:44:34 -0500170 if (any_malloc_failed) {
171 // Signal to the test driver that some allocation failed, so it knows to
172 // increment the counter and continue.
David Benjamin582904f2023-02-04 18:30:36 -0500173 _exit(88);
174 }
David Benjamin04c3d402023-06-03 01:26:29 -0400175 CRYPTO_MUTEX_unlock_read(&malloc_failure_lock);
David Benjamin582904f2023-02-04 18:30:36 -0500176}
177
178static void init_malloc_failure(void) {
179 const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
180 if (env != NULL && env[0] != 0) {
181 char *endptr;
182 malloc_number_to_fail = strtoull(env, &endptr, 10);
183 if (*endptr == 0) {
184 malloc_failure_enabled = 1;
185 atexit(malloc_exit_handler);
186 }
187 }
188 break_on_malloc_fail = getenv("MALLOC_BREAK_ON_FAIL") != NULL;
189}
190
191// should_fail_allocation returns one if the current allocation should fail and
192// zero otherwise.
193static int should_fail_allocation() {
194 static CRYPTO_once_t once = CRYPTO_ONCE_INIT;
195 CRYPTO_once(&once, init_malloc_failure);
196 if (!malloc_failure_enabled) {
197 return 0;
198 }
199
200 // We lock just so multi-threaded tests are still correct, but we won't test
201 // every malloc exhaustively.
David Benjamin04c3d402023-06-03 01:26:29 -0400202 CRYPTO_MUTEX_lock_write(&malloc_failure_lock);
David Benjamin582904f2023-02-04 18:30:36 -0500203 int should_fail = current_malloc_count == malloc_number_to_fail;
204 current_malloc_count++;
David Benjamin5e356a82023-02-04 19:44:34 -0500205 any_malloc_failed = any_malloc_failed || should_fail;
David Benjamin04c3d402023-06-03 01:26:29 -0400206 CRYPTO_MUTEX_unlock_write(&malloc_failure_lock);
David Benjamin582904f2023-02-04 18:30:36 -0500207
208 if (should_fail && break_on_malloc_fail) {
209 raise(SIGTRAP);
210 }
211 if (should_fail) {
212 errno = ENOMEM;
213 }
214 return should_fail;
215}
216
David Benjamin5e356a82023-02-04 19:44:34 -0500217void OPENSSL_reset_malloc_counter_for_testing(void) {
David Benjamin04c3d402023-06-03 01:26:29 -0400218 CRYPTO_MUTEX_lock_write(&malloc_failure_lock);
David Benjamin5e356a82023-02-04 19:44:34 -0500219 current_malloc_count = 0;
David Benjamin04c3d402023-06-03 01:26:29 -0400220 CRYPTO_MUTEX_unlock_write(&malloc_failure_lock);
David Benjamin5e356a82023-02-04 19:44:34 -0500221}
222
David Benjamin582904f2023-02-04 18:30:36 -0500223#else
224static int should_fail_allocation(void) { return 0; }
225#endif
226
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700227void *OPENSSL_malloc(size_t size) {
David Benjamin582904f2023-02-04 18:30:36 -0500228 if (should_fail_allocation()) {
Bob Beckdcabfe22023-02-07 19:06:08 -0700229 goto err;
David Benjamin582904f2023-02-04 18:30:36 -0500230 }
231
Adam Langley0313b592020-06-10 14:38:02 -0700232 if (OPENSSL_memory_alloc != NULL) {
233 assert(OPENSSL_memory_free != NULL);
234 assert(OPENSSL_memory_get_size != NULL);
Bob Beckdcabfe22023-02-07 19:06:08 -0700235 void *ptr = OPENSSL_memory_alloc(size);
236 if (ptr == NULL && size != 0) {
237 goto err;
238 }
239 return ptr;
Adam Langley0313b592020-06-10 14:38:02 -0700240 }
241
Adam Langley7964a1d2020-02-05 15:23:07 -0800242 if (size + OPENSSL_MALLOC_PREFIX < size) {
Adam Langley89386ac2021-10-12 12:43:14 -0700243 // |OPENSSL_malloc| is a central function in BoringSSL thus a reference to
244 // |kBoringSSLBinaryTag| is created here so that the tag isn't discarded by
245 // the linker. The following is sufficient to stop GCC, Clang, and MSVC
246 // optimising away the reference at the time of writing. Since this
247 // probably results in an actual memory reference, it is put in this very
248 // rare code path.
249 uint8_t unused = *(volatile uint8_t *)kBoringSSLBinaryTag;
250 (void) unused;
Bob Beckdcabfe22023-02-07 19:06:08 -0700251 goto err;
Adam Langley7964a1d2020-02-05 15:23:07 -0800252 }
253
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700254 void *ptr = malloc(size + OPENSSL_MALLOC_PREFIX);
Adam Langley95c29f32014-06-20 12:00:00 -0700255 if (ptr == NULL) {
Bob Beckdcabfe22023-02-07 19:06:08 -0700256 goto err;
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700257 }
258
259 *(size_t *)ptr = size;
260
David Benjaminda8bb842019-02-26 22:13:28 -0600261 __asan_poison_memory_region(ptr, OPENSSL_MALLOC_PREFIX);
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700262 return ((uint8_t *)ptr) + OPENSSL_MALLOC_PREFIX;
Bob Beckdcabfe22023-02-07 19:06:08 -0700263
264 err:
265 // This only works because ERR does not call OPENSSL_malloc.
266 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
267 return NULL;
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700268}
269
270void OPENSSL_free(void *orig_ptr) {
271 if (orig_ptr == NULL) {
272 return;
273 }
274
Adam Langley0313b592020-06-10 14:38:02 -0700275 if (OPENSSL_memory_free != NULL) {
276 OPENSSL_memory_free(orig_ptr);
277 return;
278 }
279
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700280 void *ptr = ((uint8_t *)orig_ptr) - OPENSSL_MALLOC_PREFIX;
David Benjaminda8bb842019-02-26 22:13:28 -0600281 __asan_unpoison_memory_region(ptr, OPENSSL_MALLOC_PREFIX);
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700282
283 size_t size = *(size_t *)ptr;
284 OPENSSL_cleanse(ptr, size + OPENSSL_MALLOC_PREFIX);
nieweif94a7ce2022-03-16 10:02:19 +0800285
286// ASan knows to intercept malloc and free, but not sdallocx.
287#if defined(OPENSSL_ASAN)
David Benjamin28883d42022-07-19 19:39:53 -0400288 (void)sdallocx;
nieweif94a7ce2022-03-16 10:02:19 +0800289 free(ptr);
290#else
Adam Langleyb49b78e2021-09-02 14:57:02 -0700291 if (sdallocx) {
292 sdallocx(ptr, size + OPENSSL_MALLOC_PREFIX, 0 /* flags */);
293 } else {
294 free(ptr);
295 }
nieweif94a7ce2022-03-16 10:02:19 +0800296#endif
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700297}
298
299void *OPENSSL_realloc(void *orig_ptr, size_t new_size) {
300 if (orig_ptr == NULL) {
Adam Langley95c29f32014-06-20 12:00:00 -0700301 return OPENSSL_malloc(new_size);
302 }
303
Adam Langley0313b592020-06-10 14:38:02 -0700304 size_t old_size;
305 if (OPENSSL_memory_get_size != NULL) {
306 old_size = OPENSSL_memory_get_size(orig_ptr);
307 } else {
308 void *ptr = ((uint8_t *)orig_ptr) - OPENSSL_MALLOC_PREFIX;
309 __asan_unpoison_memory_region(ptr, OPENSSL_MALLOC_PREFIX);
310 old_size = *(size_t *)ptr;
311 __asan_poison_memory_region(ptr, OPENSSL_MALLOC_PREFIX);
312 }
Adam Langley95c29f32014-06-20 12:00:00 -0700313
David Benjamin0ee31932016-07-11 19:38:56 -0400314 void *ret = OPENSSL_malloc(new_size);
Adam Langley95c29f32014-06-20 12:00:00 -0700315 if (ret == NULL) {
316 return NULL;
317 }
318
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700319 size_t to_copy = new_size;
320 if (old_size < to_copy) {
321 to_copy = old_size;
322 }
323
324 memcpy(ret, orig_ptr, to_copy);
325 OPENSSL_free(orig_ptr);
326
Adam Langley95c29f32014-06-20 12:00:00 -0700327 return ret;
328}
329
Adam Langleyad1907f2014-07-30 11:55:17 -0700330void OPENSSL_cleanse(void *ptr, size_t len) {
Adam Langleyded93582014-07-31 15:23:51 -0700331#if defined(OPENSSL_WINDOWS)
David Benjaminc3774c12015-12-30 21:37:50 -0500332 SecureZeroMemory(ptr, len);
Adam Langleyded93582014-07-31 15:23:51 -0700333#else
David Benjamin17cf2cb2016-12-13 01:07:13 -0500334 OPENSSL_memset(ptr, 0, len);
Adam Langleyad1907f2014-07-30 11:55:17 -0700335
Adam Langleycf052cf2014-07-31 18:46:35 -0700336#if !defined(OPENSSL_NO_ASM)
Adam Langleyad1907f2014-07-30 11:55:17 -0700337 /* As best as we can tell, this is sufficient to break any optimisations that
338 might try to eliminate "superfluous" memsets. If there's an easy way to
339 detect memset_s, it would be better to use that. */
Adam Langleyad1907f2014-07-30 11:55:17 -0700340 __asm__ __volatile__("" : : "r"(ptr) : "memory");
341#endif
David Benjamin808f8322017-08-18 14:06:02 -0400342#endif // !OPENSSL_NO_ASM
Adam Langleyad1907f2014-07-30 11:55:17 -0700343}
344
Bob Beck350f8542023-02-07 16:11:58 -0700345void OPENSSL_clear_free(void *ptr, size_t unused) { OPENSSL_free(ptr); }
Jeremy Apthorp1fa5abc2019-03-04 11:09:13 -0800346
David Benjamin8a1542f2022-09-06 12:40:08 -0400347int CRYPTO_secure_malloc_init(size_t size, size_t min_size) { return 0; }
348
349int CRYPTO_secure_malloc_initialized(void) { return 0; }
350
351size_t CRYPTO_secure_used(void) { return 0; }
352
353void *OPENSSL_secure_malloc(size_t size) { return OPENSSL_malloc(size); }
354
355void OPENSSL_secure_clear_free(void *ptr, size_t len) {
356 OPENSSL_clear_free(ptr, len);
357}
358
Adam Langley95c29f32014-06-20 12:00:00 -0700359int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700360 const uint8_t *a = in_a;
361 const uint8_t *b = in_b;
362 uint8_t x = 0;
363
David Benjamin2e8ba2d2016-06-09 16:22:26 -0400364 for (size_t i = 0; i < len; i++) {
Adam Langley95c29f32014-06-20 12:00:00 -0700365 x |= a[i] ^ b[i];
366 }
367
368 return x;
369}
370
371uint32_t OPENSSL_hash32(const void *ptr, size_t len) {
David Benjamin808f8322017-08-18 14:06:02 -0400372 // These are the FNV-1a parameters for 32 bits.
Adam Langley95c29f32014-06-20 12:00:00 -0700373 static const uint32_t kPrime = 16777619u;
374 static const uint32_t kOffsetBasis = 2166136261u;
375
376 const uint8_t *in = ptr;
Adam Langley95c29f32014-06-20 12:00:00 -0700377 uint32_t h = kOffsetBasis;
378
David Benjamin0ee31932016-07-11 19:38:56 -0400379 for (size_t i = 0; i < len; i++) {
Adam Langley95c29f32014-06-20 12:00:00 -0700380 h ^= in[i];
381 h *= kPrime;
382 }
383
384 return h;
385}
386
David Benjaminec8c67d2021-06-21 17:10:53 -0400387uint32_t OPENSSL_strhash(const char *s) { return OPENSSL_hash32(s, strlen(s)); }
388
Adam Langley01797e32014-06-20 12:00:00 -0700389size_t OPENSSL_strnlen(const char *s, size_t len) {
David Benjamin0ee31932016-07-11 19:38:56 -0400390 for (size_t i = 0; i < len; i++) {
Adam Langley01797e32014-06-20 12:00:00 -0700391 if (s[i] == 0) {
392 return i;
393 }
394 }
395
396 return len;
397}
398
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700399char *OPENSSL_strdup(const char *s) {
David Benjamin3ba95862019-10-21 16:14:33 -0400400 if (s == NULL) {
401 return NULL;
402 }
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -0700403 const size_t len = strlen(s) + 1;
404 char *ret = OPENSSL_malloc(len);
405 if (ret == NULL) {
406 return NULL;
407 }
408 OPENSSL_memcpy(ret, s, len);
409 return ret;
410}
Adam Langleyccf80572017-07-25 14:49:30 -0700411
Bob Beck00c70b82023-02-01 12:41:49 -0700412int OPENSSL_isalpha(int c) {
413 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
414}
415
Bob Beck350f8542023-02-07 16:11:58 -0700416int OPENSSL_isdigit(int c) { return c >= '0' && c <= '9'; }
Bob Beckf86a63c2023-01-30 12:17:39 -0700417
Bob Beck00c70b82023-02-01 12:41:49 -0700418int OPENSSL_isxdigit(int c) {
419 return OPENSSL_isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
420}
421
422int OPENSSL_fromxdigit(uint8_t *out, int c) {
423 if (OPENSSL_isdigit(c)) {
424 *out = c - '0';
425 return 1;
426 }
427 if ('a' <= c && c <= 'f') {
428 *out = c - 'a' + 10;
429 return 1;
430 }
431 if ('A' <= c && c <= 'F') {
432 *out = c - 'A' + 10;
433 return 1;
434 }
435 return 0;
436}
437
Bob Beck350f8542023-02-07 16:11:58 -0700438int OPENSSL_isalnum(int c) { return OPENSSL_isalpha(c) || OPENSSL_isdigit(c); }
Bob Beck00c70b82023-02-01 12:41:49 -0700439
Adam Langleyccf80572017-07-25 14:49:30 -0700440int OPENSSL_tolower(int c) {
441 if (c >= 'A' && c <= 'Z') {
442 return c + ('a' - 'A');
443 }
444 return c;
445}
446
David Benjamin42b7b352023-01-27 21:02:34 -0500447int OPENSSL_isspace(int c) {
448 return c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r' ||
449 c == ' ';
450}
451
Adam Langleyb0d5fb62014-06-20 12:00:00 -0700452int OPENSSL_strcasecmp(const char *a, const char *b) {
Adam Langleyccf80572017-07-25 14:49:30 -0700453 for (size_t i = 0;; i++) {
454 const int aa = OPENSSL_tolower(a[i]);
455 const int bb = OPENSSL_tolower(b[i]);
456
457 if (aa < bb) {
458 return -1;
459 } else if (aa > bb) {
460 return 1;
461 } else if (aa == 0) {
462 return 0;
463 }
464 }
Adam Langleyb0d5fb62014-06-20 12:00:00 -0700465}
466
467int OPENSSL_strncasecmp(const char *a, const char *b, size_t n) {
Adam Langleyccf80572017-07-25 14:49:30 -0700468 for (size_t i = 0; i < n; i++) {
469 const int aa = OPENSSL_tolower(a[i]);
470 const int bb = OPENSSL_tolower(b[i]);
Adam Langleyb0d5fb62014-06-20 12:00:00 -0700471
Adam Langleyccf80572017-07-25 14:49:30 -0700472 if (aa < bb) {
473 return -1;
474 } else if (aa > bb) {
475 return 1;
476 } else if (aa == 0) {
477 return 0;
478 }
479 }
480
481 return 0;
482}
Adam Langleyb0d5fb62014-06-20 12:00:00 -0700483
Adam Langley95c29f32014-06-20 12:00:00 -0700484int BIO_snprintf(char *buf, size_t n, const char *format, ...) {
485 va_list args;
Adam Langley95c29f32014-06-20 12:00:00 -0700486 va_start(args, format);
David Benjamin0ee31932016-07-11 19:38:56 -0400487 int ret = BIO_vsnprintf(buf, n, format, args);
Adam Langley95c29f32014-06-20 12:00:00 -0700488 va_end(args);
489 return ret;
490}
491
492int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) {
493 return vsnprintf(buf, n, format, args);
494}
David Benjamin3ba95862019-10-21 16:14:33 -0400495
Bob Beck350f8542023-02-07 16:11:58 -0700496int OPENSSL_vasprintf_internal(char **str, const char *format, va_list args,
497 int system_malloc) {
498 void *(*allocate)(size_t) = system_malloc ? malloc : OPENSSL_malloc;
499 void (*deallocate)(void *) = system_malloc ? free : OPENSSL_free;
500 void *(*reallocate)(void *, size_t) =
501 system_malloc ? realloc : OPENSSL_realloc;
502 char *candidate = NULL;
503 size_t candidate_len = 64; // TODO(bbe) what's the best initial size?
504
505 if ((candidate = allocate(candidate_len)) == NULL) {
506 goto err;
507 }
508 va_list args_copy;
509 va_copy(args_copy, args);
510 int ret = vsnprintf(candidate, candidate_len, format, args_copy);
511 va_end(args_copy);
Bob Beckdcabfe22023-02-07 19:06:08 -0700512 if (ret < 0) {
Bob Beck350f8542023-02-07 16:11:58 -0700513 goto err;
514 }
515 if ((size_t)ret >= candidate_len) {
516 // Too big to fit in allocation.
517 char *tmp;
518
Bob Beckdcabfe22023-02-07 19:06:08 -0700519 candidate_len = (size_t)ret + 1;
Bob Beck350f8542023-02-07 16:11:58 -0700520 if ((tmp = reallocate(candidate, candidate_len)) == NULL) {
521 goto err;
522 }
523 candidate = tmp;
Bob Beckdcabfe22023-02-07 19:06:08 -0700524 ret = vsnprintf(candidate, candidate_len, format, args);
Bob Beck350f8542023-02-07 16:11:58 -0700525 }
Bob Beckdcabfe22023-02-07 19:06:08 -0700526 // At this point this should not happen unless vsnprintf is insane.
Bob Beck350f8542023-02-07 16:11:58 -0700527 if (ret < 0 || (size_t)ret >= candidate_len) {
528 goto err;
529 }
530 *str = candidate;
531 return ret;
532
533 err:
534 deallocate(candidate);
535 *str = NULL;
536 errno = ENOMEM;
537 return -1;
538}
539
540int OPENSSL_vasprintf(char **str, const char *format, va_list args) {
541 return OPENSSL_vasprintf_internal(str, format, args, /*system_malloc=*/0);
542}
543
544int OPENSSL_asprintf(char **str, const char *format, ...) {
545 va_list args;
546 va_start(args, format);
547 int ret = OPENSSL_vasprintf(str, format, args);
548 va_end(args);
549 return ret;
550}
551
David Benjamin3ba95862019-10-21 16:14:33 -0400552char *OPENSSL_strndup(const char *str, size_t size) {
David Benjamin3ba95862019-10-21 16:14:33 -0400553 size = OPENSSL_strnlen(str, size);
554
David Benjamin5984cfe2021-08-24 16:03:34 -0400555 size_t alloc_size = size + 1;
David Benjamin3ba95862019-10-21 16:14:33 -0400556 if (alloc_size < size) {
557 // overflow
558 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
559 return NULL;
560 }
David Benjamin5984cfe2021-08-24 16:03:34 -0400561 char *ret = OPENSSL_malloc(alloc_size);
David Benjamin3ba95862019-10-21 16:14:33 -0400562 if (ret == NULL) {
David Benjamin3ba95862019-10-21 16:14:33 -0400563 return NULL;
564 }
565
566 OPENSSL_memcpy(ret, str, size);
567 ret[size] = '\0';
568 return ret;
569}
570
571size_t OPENSSL_strlcpy(char *dst, const char *src, size_t dst_size) {
572 size_t l = 0;
573
574 for (; dst_size > 1 && *src; dst_size--) {
575 *dst++ = *src++;
576 l++;
577 }
578
579 if (dst_size) {
580 *dst = 0;
581 }
582
583 return l + strlen(src);
584}
585
586size_t OPENSSL_strlcat(char *dst, const char *src, size_t dst_size) {
587 size_t l = 0;
588 for (; dst_size > 0 && *dst; dst_size--, dst++) {
589 l++;
590 }
591 return l + OPENSSL_strlcpy(dst, src, dst_size);
592}
593
594void *OPENSSL_memdup(const void *data, size_t size) {
595 if (size == 0) {
596 return NULL;
597 }
598
599 void *ret = OPENSSL_malloc(size);
600 if (ret == NULL) {
David Benjamin3ba95862019-10-21 16:14:33 -0400601 return NULL;
602 }
603
604 OPENSSL_memcpy(ret, data, size);
605 return ret;
606}
David Benjamin551ccd72021-09-28 11:55:10 -0400607
608void *CRYPTO_malloc(size_t size, const char *file, int line) {
609 return OPENSSL_malloc(size);
610}
611
612void *CRYPTO_realloc(void *ptr, size_t new_size, const char *file, int line) {
613 return OPENSSL_realloc(ptr, new_size);
614}
615
616void CRYPTO_free(void *ptr, const char *file, int line) { OPENSSL_free(ptr); }