14ec2eca9Schristos /*
2*3afa6631Schristos  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
3a89c9211Schristos  *
44ec2eca9Schristos  * Licensed under the OpenSSL license (the "License").  You may not use
54ec2eca9Schristos  * this file except in compliance with the License.  You can obtain a copy
64ec2eca9Schristos  * in the file LICENSE in the source distribution or at
74ec2eca9Schristos  * https://www.openssl.org/source/license.html
8a89c9211Schristos  */
9a89c9211Schristos 
10a89c9211Schristos #include <stdio.h>
11a89c9211Schristos #include <stdlib.h>
124ec2eca9Schristos #include <limits.h>
13a89c9211Schristos #include <openssl/crypto.h>
144ec2eca9Schristos #include "internal/cryptlib.h"
15a89c9211Schristos 
16d572d25fSspz /*
17d572d25fSspz  * the following pointers may be changed as long as 'allow_customize' is set
18d572d25fSspz  */
194ec2eca9Schristos static int allow_customize = 1;
20a89c9211Schristos 
214ec2eca9Schristos static void *(*malloc_impl)(size_t, const char *, int)
224ec2eca9Schristos     = CRYPTO_malloc;
234ec2eca9Schristos static void *(*realloc_impl)(void *, size_t, const char *, int)
244ec2eca9Schristos     = CRYPTO_realloc;
254ec2eca9Schristos static void (*free_impl)(void *, const char *, int)
264ec2eca9Schristos     = CRYPTO_free;
274ec2eca9Schristos 
284ec2eca9Schristos #ifndef OPENSSL_NO_CRYPTO_MDEBUG
294ec2eca9Schristos static int call_malloc_debug = 1;
304ec2eca9Schristos #else
314ec2eca9Schristos static int call_malloc_debug = 0;
324ec2eca9Schristos #endif
334ec2eca9Schristos 
344ec2eca9Schristos int CRYPTO_set_mem_functions(
354ec2eca9Schristos         void *(*m)(size_t, const char *, int),
364ec2eca9Schristos         void *(*r)(void *, size_t, const char *, int),
374ec2eca9Schristos         void (*f)(void *, const char *, int))
38d572d25fSspz {
394ec2eca9Schristos     if (!allow_customize)
404ec2eca9Schristos         return 0;
414ec2eca9Schristos     if (m)
424ec2eca9Schristos         malloc_impl = m;
434ec2eca9Schristos     if (r)
444ec2eca9Schristos         realloc_impl = r;
454ec2eca9Schristos     if (f)
464ec2eca9Schristos         free_impl = f;
474ec2eca9Schristos     return 1;
48d572d25fSspz }
49d572d25fSspz 
504ec2eca9Schristos int CRYPTO_set_mem_debug(int flag)
514ec2eca9Schristos {
524ec2eca9Schristos     if (!allow_customize)
534ec2eca9Schristos         return 0;
544ec2eca9Schristos     call_malloc_debug = flag;
554ec2eca9Schristos     return 1;
564ec2eca9Schristos }
57a89c9211Schristos 
584ec2eca9Schristos void CRYPTO_get_mem_functions(
594ec2eca9Schristos         void *(**m)(size_t, const char *, int),
604ec2eca9Schristos         void *(**r)(void *, size_t, const char *, int),
614ec2eca9Schristos         void (**f)(void *, const char *, int))
624ec2eca9Schristos {
634ec2eca9Schristos     if (m != NULL)
644ec2eca9Schristos         *m = malloc_impl;
654ec2eca9Schristos     if (r != NULL)
664ec2eca9Schristos         *r = realloc_impl;
674ec2eca9Schristos     if (f != NULL)
684ec2eca9Schristos         *f = free_impl;
694ec2eca9Schristos }
704ec2eca9Schristos 
714ec2eca9Schristos void *CRYPTO_malloc(size_t num, const char *file, int line)
724ec2eca9Schristos {
734ec2eca9Schristos     void *ret = NULL;
744ec2eca9Schristos 
754ec2eca9Schristos     if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc)
764ec2eca9Schristos         return malloc_impl(num, file, line);
774ec2eca9Schristos 
784ec2eca9Schristos     if (num == 0)
794ec2eca9Schristos         return NULL;
804ec2eca9Schristos 
81*3afa6631Schristos     if (allow_customize) {
82*3afa6631Schristos         /*
83*3afa6631Schristos          * Disallow customization after the first allocation. We only set this
84*3afa6631Schristos          * if necessary to avoid a store to the same cache line on every
85*3afa6631Schristos          * allocation.
86*3afa6631Schristos          */
874ec2eca9Schristos         allow_customize = 0;
88*3afa6631Schristos     }
894ec2eca9Schristos #ifndef OPENSSL_NO_CRYPTO_MDEBUG
904ec2eca9Schristos     if (call_malloc_debug) {
914ec2eca9Schristos         CRYPTO_mem_debug_malloc(NULL, num, 0, file, line);
924ec2eca9Schristos         ret = malloc(num);
934ec2eca9Schristos         CRYPTO_mem_debug_malloc(ret, num, 1, file, line);
944ec2eca9Schristos     } else {
954ec2eca9Schristos         ret = malloc(num);
964ec2eca9Schristos     }
974ec2eca9Schristos #else
984ec2eca9Schristos     osslargused(file); osslargused(line);
994ec2eca9Schristos     ret = malloc(num);
1007fa80bafSspz #endif
1017fa80bafSspz 
1024ec2eca9Schristos     return ret;
1034ec2eca9Schristos }
1044ec2eca9Schristos 
1054ec2eca9Schristos void *CRYPTO_zalloc(size_t num, const char *file, int line)
1064ec2eca9Schristos {
1074ec2eca9Schristos     void *ret = CRYPTO_malloc(num, file, line);
1084ec2eca9Schristos 
1094ec2eca9Schristos     if (ret != NULL)
1104ec2eca9Schristos         memset(ret, 0, num);
1114ec2eca9Schristos     return ret;
1124ec2eca9Schristos }
1134ec2eca9Schristos 
1144ec2eca9Schristos void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
1154ec2eca9Schristos {
1164ec2eca9Schristos     if (realloc_impl != NULL && realloc_impl != &CRYPTO_realloc)
1174ec2eca9Schristos         return realloc_impl(str, num, file, line);
1184ec2eca9Schristos 
1194ec2eca9Schristos     if (str == NULL)
1204ec2eca9Schristos         return CRYPTO_malloc(num, file, line);
1214ec2eca9Schristos 
1224ec2eca9Schristos     if (num == 0) {
1234ec2eca9Schristos         CRYPTO_free(str, file, line);
1244ec2eca9Schristos         return NULL;
1254ec2eca9Schristos     }
1264ec2eca9Schristos 
1274ec2eca9Schristos #ifndef OPENSSL_NO_CRYPTO_MDEBUG
1284ec2eca9Schristos     if (call_malloc_debug) {
1294ec2eca9Schristos         void *ret;
1304ec2eca9Schristos         CRYPTO_mem_debug_realloc(str, NULL, num, 0, file, line);
1314ec2eca9Schristos         ret = realloc(str, num);
1324ec2eca9Schristos         CRYPTO_mem_debug_realloc(str, ret, num, 1, file, line);
1334ec2eca9Schristos         return ret;
1344ec2eca9Schristos     }
1354ec2eca9Schristos #else
1364ec2eca9Schristos     osslargused(file); osslargused(line);
1374ec2eca9Schristos #endif
1384ec2eca9Schristos     return realloc(str, num);
1394ec2eca9Schristos 
1404ec2eca9Schristos }
1414ec2eca9Schristos 
1424ec2eca9Schristos void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num,
143a89c9211Schristos                            const char *file, int line)
144d572d25fSspz {
145a89c9211Schristos     void *ret = NULL;
146a89c9211Schristos 
147a89c9211Schristos     if (str == NULL)
148a89c9211Schristos         return CRYPTO_malloc(num, file, line);
149a89c9211Schristos 
1504ec2eca9Schristos     if (num == 0) {
1514ec2eca9Schristos         CRYPTO_clear_free(str, old_len, file, line);
152d572d25fSspz         return NULL;
153a89c9211Schristos     }
154a89c9211Schristos 
1554ec2eca9Schristos     /* Can't shrink the buffer since memcpy below copies |old_len| bytes. */
1564ec2eca9Schristos     if (num < old_len) {
1574ec2eca9Schristos         OPENSSL_cleanse((char*)str + num, old_len - num);
1584ec2eca9Schristos         return str;
1594ec2eca9Schristos     }
160a89c9211Schristos 
1614ec2eca9Schristos     ret = CRYPTO_malloc(num, file, line);
1624ec2eca9Schristos     if (ret != NULL) {
163a89c9211Schristos         memcpy(ret, str, old_len);
1644ec2eca9Schristos         CRYPTO_clear_free(str, old_len, file, line);
165a89c9211Schristos     }
166a89c9211Schristos     return ret;
167a89c9211Schristos }
168a89c9211Schristos 
1694ec2eca9Schristos void CRYPTO_free(void *str, const char *file, int line)
170a89c9211Schristos {
1714ec2eca9Schristos     if (free_impl != NULL && free_impl != &CRYPTO_free) {
1724ec2eca9Schristos         free_impl(str, file, line);
1734ec2eca9Schristos         return;
1744ec2eca9Schristos     }
1754ec2eca9Schristos 
1764ec2eca9Schristos #ifndef OPENSSL_NO_CRYPTO_MDEBUG
1774ec2eca9Schristos     if (call_malloc_debug) {
1784ec2eca9Schristos         CRYPTO_mem_debug_free(str, 0, file, line);
1794ec2eca9Schristos         free(str);
1804ec2eca9Schristos         CRYPTO_mem_debug_free(str, 1, file, line);
1814ec2eca9Schristos     } else {
1824ec2eca9Schristos         free(str);
1834ec2eca9Schristos     }
1844ec2eca9Schristos #else
1854ec2eca9Schristos     free(str);
186a89c9211Schristos #endif
187a89c9211Schristos }
188a89c9211Schristos 
1894ec2eca9Schristos void CRYPTO_clear_free(void *str, size_t num, const char *file, int line)
190a89c9211Schristos {
1914ec2eca9Schristos     if (str == NULL)
1924ec2eca9Schristos         return;
1934ec2eca9Schristos     if (num)
1944ec2eca9Schristos         OPENSSL_cleanse(str, num);
1954ec2eca9Schristos     CRYPTO_free(str, file, line);
196a89c9211Schristos }
197