mem.c revision 296341
1/* crypto/mem.c */
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#include <stdio.h>
60#include <stdlib.h>
61#include <openssl/crypto.h>
62#include "cryptlib.h"
63
64static int allow_customize = 1; /* we provide flexible functions for */
65static int allow_customize_debug = 1; /* exchanging memory-related functions
66                                       * at run-time, but this must be done
67                                       * before any blocks are actually
68                                       * allocated; or we'll run into huge
69                                       * problems when malloc/free pairs
70                                       * don't match etc. */
71
72/*
73 * the following pointers may be changed as long as 'allow_customize' is set
74 */
75
76static void *(*malloc_func) (size_t) = malloc;
77static void *default_malloc_ex(size_t num, const char *file, int line)
78{
79    return malloc_func(num);
80}
81
82static void *(*malloc_ex_func) (size_t, const char *file, int line)
83    = default_malloc_ex;
84
85static void *(*realloc_func) (void *, size_t) = realloc;
86static void *default_realloc_ex(void *str, size_t num,
87                                const char *file, int line)
88{
89    return realloc_func(str, num);
90}
91
92static void *(*realloc_ex_func) (void *, size_t, const char *file, int line)
93    = default_realloc_ex;
94
95static void (*free_func) (void *) = free;
96
97static void *(*malloc_locked_func) (size_t) = malloc;
98static void *default_malloc_locked_ex(size_t num, const char *file, int line)
99{
100    return malloc_locked_func(num);
101}
102
103static void *(*malloc_locked_ex_func) (size_t, const char *file, int line)
104    = default_malloc_locked_ex;
105
106static void (*free_locked_func) (void *) = free;
107
108/* may be changed as long as 'allow_customize_debug' is set */
109/* XXX use correct function pointer types */
110#ifdef CRYPTO_MDEBUG
111/* use default functions from mem_dbg.c */
112static void (*malloc_debug_func) (void *, int, const char *, int, int)
113    = CRYPTO_dbg_malloc;
114static void (*realloc_debug_func) (void *, void *, int, const char *, int,
115                                   int)
116    = CRYPTO_dbg_realloc;
117static void (*free_debug_func) (void *, int) = CRYPTO_dbg_free;
118static void (*set_debug_options_func) (long) = CRYPTO_dbg_set_options;
119static long (*get_debug_options_func) (void) = CRYPTO_dbg_get_options;
120#else
121/*
122 * applications can use CRYPTO_malloc_debug_init() to select above case at
123 * run-time
124 */
125static void (*malloc_debug_func) (void *, int, const char *, int, int) = NULL;
126static void (*realloc_debug_func) (void *, void *, int, const char *, int,
127                                   int)
128    = NULL;
129static void (*free_debug_func) (void *, int) = NULL;
130static void (*set_debug_options_func) (long) = NULL;
131static long (*get_debug_options_func) (void) = NULL;
132#endif
133
134int CRYPTO_set_mem_functions(void *(*m) (size_t), void *(*r) (void *, size_t),
135                             void (*f) (void *))
136{
137    /* Dummy call just to ensure OPENSSL_init() gets linked in */
138    OPENSSL_init();
139    if (!allow_customize)
140        return 0;
141    if ((m == 0) || (r == 0) || (f == 0))
142        return 0;
143    malloc_func = m;
144    malloc_ex_func = default_malloc_ex;
145    realloc_func = r;
146    realloc_ex_func = default_realloc_ex;
147    free_func = f;
148    malloc_locked_func = m;
149    malloc_locked_ex_func = default_malloc_locked_ex;
150    free_locked_func = f;
151    return 1;
152}
153
154int CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
155                                void *(*r) (void *, size_t, const char *,
156                                            int), void (*f) (void *))
157{
158    if (!allow_customize)
159        return 0;
160    if ((m == 0) || (r == 0) || (f == 0))
161        return 0;
162    malloc_func = 0;
163    malloc_ex_func = m;
164    realloc_func = 0;
165    realloc_ex_func = r;
166    free_func = f;
167    malloc_locked_func = 0;
168    malloc_locked_ex_func = m;
169    free_locked_func = f;
170    return 1;
171}
172
173int CRYPTO_set_locked_mem_functions(void *(*m) (size_t), void (*f) (void *))
174{
175    if (!allow_customize)
176        return 0;
177    if ((m == NULL) || (f == NULL))
178        return 0;
179    malloc_locked_func = m;
180    malloc_locked_ex_func = default_malloc_locked_ex;
181    free_locked_func = f;
182    return 1;
183}
184
185int CRYPTO_set_locked_mem_ex_functions(void *(*m) (size_t, const char *, int),
186                                       void (*f) (void *))
187{
188    if (!allow_customize)
189        return 0;
190    if ((m == NULL) || (f == NULL))
191        return 0;
192    malloc_locked_func = 0;
193    malloc_locked_ex_func = m;
194    free_func = f;
195    return 1;
196}
197
198int CRYPTO_set_mem_debug_functions(void (*m)
199                                    (void *, int, const char *, int, int),
200                                   void (*r) (void *, void *, int,
201                                              const char *, int, int),
202                                   void (*f) (void *, int), void (*so) (long),
203                                   long (*go) (void))
204{
205    if (!allow_customize_debug)
206        return 0;
207    OPENSSL_init();
208    malloc_debug_func = m;
209    realloc_debug_func = r;
210    free_debug_func = f;
211    set_debug_options_func = so;
212    get_debug_options_func = go;
213    return 1;
214}
215
216void CRYPTO_get_mem_functions(void *(**m) (size_t),
217                              void *(**r) (void *, size_t),
218                              void (**f) (void *))
219{
220    if (m != NULL)
221        *m = (malloc_ex_func == default_malloc_ex) ? malloc_func : 0;
222    if (r != NULL)
223        *r = (realloc_ex_func == default_realloc_ex) ? realloc_func : 0;
224    if (f != NULL)
225        *f = free_func;
226}
227
228void CRYPTO_get_mem_ex_functions(void *(**m) (size_t, const char *, int),
229                                 void *(**r) (void *, size_t, const char *,
230                                              int), void (**f) (void *))
231{
232    if (m != NULL)
233        *m = (malloc_ex_func != default_malloc_ex) ? malloc_ex_func : 0;
234    if (r != NULL)
235        *r = (realloc_ex_func != default_realloc_ex) ? realloc_ex_func : 0;
236    if (f != NULL)
237        *f = free_func;
238}
239
240void CRYPTO_get_locked_mem_functions(void *(**m) (size_t),
241                                     void (**f) (void *))
242{
243    if (m != NULL)
244        *m = (malloc_locked_ex_func == default_malloc_locked_ex) ?
245            malloc_locked_func : 0;
246    if (f != NULL)
247        *f = free_locked_func;
248}
249
250void CRYPTO_get_locked_mem_ex_functions(void
251                                        *(**m) (size_t, const char *, int),
252                                        void (**f) (void *))
253{
254    if (m != NULL)
255        *m = (malloc_locked_ex_func != default_malloc_locked_ex) ?
256            malloc_locked_ex_func : 0;
257    if (f != NULL)
258        *f = free_locked_func;
259}
260
261void CRYPTO_get_mem_debug_functions(void (**m)
262                                     (void *, int, const char *, int, int),
263                                    void (**r) (void *, void *, int,
264                                                const char *, int, int),
265                                    void (**f) (void *, int),
266                                    void (**so) (long), long (**go) (void))
267{
268    if (m != NULL)
269        *m = malloc_debug_func;
270    if (r != NULL)
271        *r = realloc_debug_func;
272    if (f != NULL)
273        *f = free_debug_func;
274    if (so != NULL)
275        *so = set_debug_options_func;
276    if (go != NULL)
277        *go = get_debug_options_func;
278}
279
280void *CRYPTO_malloc_locked(int num, const char *file, int line)
281{
282    void *ret = NULL;
283
284    if (num <= 0)
285        return NULL;
286
287    if (allow_customize)
288        allow_customize = 0;
289    if (malloc_debug_func != NULL) {
290        if (allow_customize_debug)
291            allow_customize_debug = 0;
292        malloc_debug_func(NULL, num, file, line, 0);
293    }
294    ret = malloc_locked_ex_func(num, file, line);
295#ifdef LEVITTE_DEBUG_MEM
296    fprintf(stderr, "LEVITTE_DEBUG_MEM:         > 0x%p (%d)\n", ret, num);
297#endif
298    if (malloc_debug_func != NULL)
299        malloc_debug_func(ret, num, file, line, 1);
300
301#ifndef OPENSSL_CPUID_OBJ
302    /*
303     * Create a dependency on the value of 'cleanse_ctr' so our memory
304     * sanitisation function can't be optimised out. NB: We only do this for
305     * >2Kb so the overhead doesn't bother us.
306     */
307    if (ret && (num > 2048)) {
308        extern unsigned char cleanse_ctr;
309        ((unsigned char *)ret)[0] = cleanse_ctr;
310    }
311#endif
312
313    return ret;
314}
315
316void CRYPTO_free_locked(void *str)
317{
318    if (free_debug_func != NULL)
319        free_debug_func(str, 0);
320#ifdef LEVITTE_DEBUG_MEM
321    fprintf(stderr, "LEVITTE_DEBUG_MEM:         < 0x%p\n", str);
322#endif
323    free_locked_func(str);
324    if (free_debug_func != NULL)
325        free_debug_func(NULL, 1);
326}
327
328void *CRYPTO_malloc(int num, const char *file, int line)
329{
330    void *ret = NULL;
331
332    if (num <= 0)
333        return NULL;
334
335    if (allow_customize)
336        allow_customize = 0;
337    if (malloc_debug_func != NULL) {
338        if (allow_customize_debug)
339            allow_customize_debug = 0;
340        malloc_debug_func(NULL, num, file, line, 0);
341    }
342    ret = malloc_ex_func(num, file, line);
343#ifdef LEVITTE_DEBUG_MEM
344    fprintf(stderr, "LEVITTE_DEBUG_MEM:         > 0x%p (%d)\n", ret, num);
345#endif
346    if (malloc_debug_func != NULL)
347        malloc_debug_func(ret, num, file, line, 1);
348
349#ifndef OPENSSL_CPUID_OBJ
350    /*
351     * Create a dependency on the value of 'cleanse_ctr' so our memory
352     * sanitisation function can't be optimised out. NB: We only do this for
353     * >2Kb so the overhead doesn't bother us.
354     */
355    if (ret && (num > 2048)) {
356        extern unsigned char cleanse_ctr;
357        ((unsigned char *)ret)[0] = cleanse_ctr;
358    }
359#endif
360
361    return ret;
362}
363
364char *CRYPTO_strdup(const char *str, const char *file, int line)
365{
366    char *ret = CRYPTO_malloc(strlen(str) + 1, file, line);
367
368    if (ret == NULL)
369        return NULL;
370
371    strcpy(ret, str);
372    return ret;
373}
374
375void *CRYPTO_realloc(void *str, int num, const char *file, int line)
376{
377    void *ret = NULL;
378
379    if (str == NULL)
380        return CRYPTO_malloc(num, file, line);
381
382    if (num <= 0)
383        return NULL;
384
385    if (realloc_debug_func != NULL)
386        realloc_debug_func(str, NULL, num, file, line, 0);
387    ret = realloc_ex_func(str, num, file, line);
388#ifdef LEVITTE_DEBUG_MEM
389    fprintf(stderr, "LEVITTE_DEBUG_MEM:         | 0x%p -> 0x%p (%d)\n", str,
390            ret, num);
391#endif
392    if (realloc_debug_func != NULL)
393        realloc_debug_func(str, ret, num, file, line, 1);
394
395    return ret;
396}
397
398void *CRYPTO_realloc_clean(void *str, int old_len, int num, const char *file,
399                           int line)
400{
401    void *ret = NULL;
402
403    if (str == NULL)
404        return CRYPTO_malloc(num, file, line);
405
406    if (num <= 0)
407        return NULL;
408
409    /*
410     * We don't support shrinking the buffer. Note the memcpy that copies
411     * |old_len| bytes to the new buffer, below.
412     */
413    if (num < old_len)
414        return NULL;
415
416    if (realloc_debug_func != NULL)
417        realloc_debug_func(str, NULL, num, file, line, 0);
418    ret = malloc_ex_func(num, file, line);
419    if (ret) {
420        memcpy(ret, str, old_len);
421        OPENSSL_cleanse(str, old_len);
422        free_func(str);
423    }
424#ifdef LEVITTE_DEBUG_MEM
425    fprintf(stderr,
426            "LEVITTE_DEBUG_MEM:         | 0x%p -> 0x%p (%d)\n",
427            str, ret, num);
428#endif
429    if (realloc_debug_func != NULL)
430        realloc_debug_func(str, ret, num, file, line, 1);
431
432    return ret;
433}
434
435void CRYPTO_free(void *str)
436{
437    if (free_debug_func != NULL)
438        free_debug_func(str, 0);
439#ifdef LEVITTE_DEBUG_MEM
440    fprintf(stderr, "LEVITTE_DEBUG_MEM:         < 0x%p\n", str);
441#endif
442    free_func(str);
443    if (free_debug_func != NULL)
444        free_debug_func(NULL, 1);
445}
446
447void *CRYPTO_remalloc(void *a, int num, const char *file, int line)
448{
449    if (a != NULL)
450        OPENSSL_free(a);
451    a = (char *)OPENSSL_malloc(num);
452    return (a);
453}
454
455void CRYPTO_set_mem_debug_options(long bits)
456{
457    if (set_debug_options_func != NULL)
458        set_debug_options_func(bits);
459}
460
461long CRYPTO_get_mem_debug_options(void)
462{
463    if (get_debug_options_func != NULL)
464        return get_debug_options_func();
465    return 0;
466}
467