Use OPENSSL_secure_clear_free for secure mem BIOs and X25519 private keys
[openssl.git] / crypto / buffer / buffer.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/buffer.h>
13
14 /*
15  * LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That
16  * function is applied in several functions in this file and this limit
17  * ensures that the result fits in an int.
18  */
19 #define LIMIT_BEFORE_EXPANSION 0x5ffffffc
20
21 BUF_MEM *BUF_MEM_new_ex(unsigned long flags)
22 {
23     BUF_MEM *ret;
24
25     ret = BUF_MEM_new();
26     if (ret != NULL)
27         ret->flags = flags;
28     return (ret);
29 }
30
31 BUF_MEM *BUF_MEM_new(void)
32 {
33     BUF_MEM *ret;
34
35     ret = OPENSSL_zalloc(sizeof(*ret));
36     if (ret == NULL) {
37         BUFerr(BUF_F_BUF_MEM_NEW, ERR_R_MALLOC_FAILURE);
38         return (NULL);
39     }
40     return (ret);
41 }
42
43 void BUF_MEM_free(BUF_MEM *a)
44 {
45     if (a == NULL)
46         return;
47
48     if (a->data != NULL) {
49         if (a->flags & BUF_MEM_FLAG_SECURE)
50             OPENSSL_secure_clear_free(a->data, a->max);
51         else
52             OPENSSL_clear_free(a->data, a->max);
53     }
54     OPENSSL_free(a);
55 }
56
57 /* Allocate a block of secure memory; copy over old data if there
58  * was any, and then free it. */
59 static char *sec_alloc_realloc(BUF_MEM *str, size_t len)
60 {
61     char *ret;
62
63     ret = OPENSSL_secure_malloc(len);
64     if (str->data != NULL) {
65         if (ret != NULL) {
66             memcpy(ret, str->data, str->length);
67             OPENSSL_secure_clear_free(str->data, str->length);
68             str->data = NULL;
69         }
70     }
71     return (ret);
72 }
73
74 size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
75 {
76     char *ret;
77     size_t n;
78
79     if (str->length >= len) {
80         str->length = len;
81         return (len);
82     }
83     if (str->max >= len) {
84         if (str->data != NULL)
85             memset(&str->data[str->length], 0, len - str->length);
86         str->length = len;
87         return (len);
88     }
89     /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
90     if (len > LIMIT_BEFORE_EXPANSION) {
91         BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);
92         return 0;
93     }
94     n = (len + 3) / 3 * 4;
95     if ((str->flags & BUF_MEM_FLAG_SECURE))
96         ret = sec_alloc_realloc(str, n);
97     else
98         ret = OPENSSL_realloc(str->data, n);
99     if (ret == NULL) {
100         BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);
101         len = 0;
102     } else {
103         str->data = ret;
104         str->max = n;
105         memset(&str->data[str->length], 0, len - str->length);
106         str->length = len;
107     }
108     return (len);
109 }
110
111 size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
112 {
113     char *ret;
114     size_t n;
115
116     if (str->length >= len) {
117         if (str->data != NULL)
118             memset(&str->data[len], 0, str->length - len);
119         str->length = len;
120         return (len);
121     }
122     if (str->max >= len) {
123         memset(&str->data[str->length], 0, len - str->length);
124         str->length = len;
125         return (len);
126     }
127     /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
128     if (len > LIMIT_BEFORE_EXPANSION) {
129         BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE);
130         return 0;
131     }
132     n = (len + 3) / 3 * 4;
133     if ((str->flags & BUF_MEM_FLAG_SECURE))
134         ret = sec_alloc_realloc(str, n);
135     else
136         ret = OPENSSL_clear_realloc(str->data, str->max, n);
137     if (ret == NULL) {
138         BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE);
139         len = 0;
140     } else {
141         str->data = ret;
142         str->max = n;
143         memset(&str->data[str->length], 0, len - str->length);
144         str->length = len;
145     }
146     return (len);
147 }
148
149 void BUF_reverse(unsigned char *out, const unsigned char *in, size_t size)
150 {
151     size_t i;
152     if (in) {
153         out += size - 1;
154         for (i = 0; i < size; i++)
155             *out-- = *in++;
156     } else {
157         unsigned char *q;
158         char c;
159         q = out + size - 1;
160         for (i = 0; i < size / 2; i++) {
161             c = *q;
162             *q-- = *out;
163             *out++ = c;
164         }
165     }
166 }