1 | /*
|
---|
2 | * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (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 | return NULL;
|
---|
38 | return ret;
|
---|
39 | }
|
---|
40 |
|
---|
41 | void BUF_MEM_free(BUF_MEM *a)
|
---|
42 | {
|
---|
43 | if (a == NULL)
|
---|
44 | return;
|
---|
45 | if (a->data != NULL) {
|
---|
46 | if (a->flags & BUF_MEM_FLAG_SECURE)
|
---|
47 | OPENSSL_secure_clear_free(a->data, a->max);
|
---|
48 | else
|
---|
49 | OPENSSL_clear_free(a->data, a->max);
|
---|
50 | }
|
---|
51 | OPENSSL_free(a);
|
---|
52 | }
|
---|
53 |
|
---|
54 | /* Allocate a block of secure memory; copy over old data if there
|
---|
55 | * was any, and then free it. */
|
---|
56 | static char *sec_alloc_realloc(BUF_MEM *str, size_t len)
|
---|
57 | {
|
---|
58 | char *ret;
|
---|
59 |
|
---|
60 | ret = OPENSSL_secure_malloc(len);
|
---|
61 | if (str->data != NULL) {
|
---|
62 | if (ret != NULL) {
|
---|
63 | memcpy(ret, str->data, str->length);
|
---|
64 | OPENSSL_secure_clear_free(str->data, str->length);
|
---|
65 | str->data = NULL;
|
---|
66 | }
|
---|
67 | }
|
---|
68 | return ret;
|
---|
69 | }
|
---|
70 |
|
---|
71 | size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
|
---|
72 | {
|
---|
73 | char *ret;
|
---|
74 | size_t n;
|
---|
75 |
|
---|
76 | if (str->length >= len) {
|
---|
77 | str->length = len;
|
---|
78 | return len;
|
---|
79 | }
|
---|
80 | if (str->max >= len) {
|
---|
81 | if (str->data != NULL)
|
---|
82 | memset(&str->data[str->length], 0, len - str->length);
|
---|
83 | str->length = len;
|
---|
84 | return len;
|
---|
85 | }
|
---|
86 | /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
|
---|
87 | if (len > LIMIT_BEFORE_EXPANSION) {
|
---|
88 | ERR_raise(ERR_LIB_BUF, ERR_R_PASSED_INVALID_ARGUMENT);
|
---|
89 | return 0;
|
---|
90 | }
|
---|
91 | n = (len + 3) / 3 * 4;
|
---|
92 | if ((str->flags & BUF_MEM_FLAG_SECURE))
|
---|
93 | ret = sec_alloc_realloc(str, n);
|
---|
94 | else
|
---|
95 | ret = OPENSSL_realloc(str->data, n);
|
---|
96 | if (ret == NULL) {
|
---|
97 | len = 0;
|
---|
98 | } else {
|
---|
99 | str->data = ret;
|
---|
100 | str->max = n;
|
---|
101 | memset(&str->data[str->length], 0, len - str->length);
|
---|
102 | str->length = len;
|
---|
103 | }
|
---|
104 | return len;
|
---|
105 | }
|
---|
106 |
|
---|
107 | size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
|
---|
108 | {
|
---|
109 | char *ret;
|
---|
110 | size_t n;
|
---|
111 |
|
---|
112 | if (str->length >= len) {
|
---|
113 | if (str->data != NULL)
|
---|
114 | memset(&str->data[len], 0, str->length - len);
|
---|
115 | str->length = len;
|
---|
116 | return len;
|
---|
117 | }
|
---|
118 | if (str->max >= len) {
|
---|
119 | memset(&str->data[str->length], 0, len - str->length);
|
---|
120 | str->length = len;
|
---|
121 | return len;
|
---|
122 | }
|
---|
123 | /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */
|
---|
124 | if (len > LIMIT_BEFORE_EXPANSION) {
|
---|
125 | ERR_raise(ERR_LIB_BUF, ERR_R_PASSED_INVALID_ARGUMENT);
|
---|
126 | return 0;
|
---|
127 | }
|
---|
128 | n = (len + 3) / 3 * 4;
|
---|
129 | if ((str->flags & BUF_MEM_FLAG_SECURE))
|
---|
130 | ret = sec_alloc_realloc(str, n);
|
---|
131 | else
|
---|
132 | ret = OPENSSL_clear_realloc(str->data, str->max, n);
|
---|
133 | if (ret == NULL) {
|
---|
134 | len = 0;
|
---|
135 | } else {
|
---|
136 | str->data = ret;
|
---|
137 | str->max = n;
|
---|
138 | memset(&str->data[str->length], 0, len - str->length);
|
---|
139 | str->length = len;
|
---|
140 | }
|
---|
141 | return len;
|
---|
142 | }
|
---|
143 |
|
---|
144 | void BUF_reverse(unsigned char *out, const unsigned char *in, size_t size)
|
---|
145 | {
|
---|
146 | size_t i;
|
---|
147 | if (in) {
|
---|
148 | out += size - 1;
|
---|
149 | for (i = 0; i < size; i++)
|
---|
150 | *out-- = *in++;
|
---|
151 | } else {
|
---|
152 | unsigned char *q;
|
---|
153 | char c;
|
---|
154 | q = out + size - 1;
|
---|
155 | for (i = 0; i < size / 2; i++) {
|
---|
156 | c = *q;
|
---|
157 | *q-- = *out;
|
---|
158 | *out++ = c;
|
---|
159 | }
|
---|
160 | }
|
---|
161 | }
|
---|