]>
Commit | Line | Data |
---|---|---|
b1322259 | 1 | /* |
83cf7abf | 2 | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
09abbca1 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
b1322259 RS |
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 | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
11 | #include <errno.h> | |
706457b7 | 12 | #include "bio_local.h" |
b39fc560 | 13 | #include "internal/cryptlib.h" |
d02b48c6 | 14 | |
0e1c0612 UM |
15 | static int mem_write(BIO *h, const char *buf, int num); |
16 | static int mem_read(BIO *h, char *buf, int size); | |
17 | static int mem_puts(BIO *h, const char *str); | |
18 | static int mem_gets(BIO *h, char *str, int size); | |
19 | static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); | |
d02b48c6 | 20 | static int mem_new(BIO *h); |
74924dcb | 21 | static int secmem_new(BIO *h); |
d02b48c6 | 22 | static int mem_free(BIO *data); |
c6048af2 | 23 | static int mem_buf_free(BIO *data); |
9fe9d046 | 24 | static int mem_buf_sync(BIO *h); |
d3e6d6bc | 25 | |
04f6b0fd | 26 | static const BIO_METHOD mem_method = { |
0f113f3e MC |
27 | BIO_TYPE_MEM, |
28 | "memory buffer", | |
3befffa3 MC |
29 | /* TODO: Convert to new style write function */ |
30 | bwrite_conv, | |
0f113f3e | 31 | mem_write, |
d07aee2c MC |
32 | /* TODO: Convert to new style read function */ |
33 | bread_conv, | |
0f113f3e MC |
34 | mem_read, |
35 | mem_puts, | |
36 | mem_gets, | |
37 | mem_ctrl, | |
38 | mem_new, | |
39 | mem_free, | |
b4ff6622 | 40 | NULL, /* mem_callback_ctrl */ |
0f113f3e | 41 | }; |
d3e6d6bc | 42 | |
04f6b0fd | 43 | static const BIO_METHOD secmem_method = { |
74924dcb RS |
44 | BIO_TYPE_MEM, |
45 | "secure memory buffer", | |
3befffa3 MC |
46 | /* TODO: Convert to new style write function */ |
47 | bwrite_conv, | |
74924dcb | 48 | mem_write, |
d07aee2c MC |
49 | /* TODO: Convert to new style read function */ |
50 | bread_conv, | |
74924dcb RS |
51 | mem_read, |
52 | mem_puts, | |
53 | mem_gets, | |
54 | mem_ctrl, | |
55 | secmem_new, | |
56 | mem_free, | |
b4ff6622 | 57 | NULL, /* mem_callback_ctrl */ |
74924dcb | 58 | }; |
d02b48c6 | 59 | |
b238fb79 TM |
60 | /* |
61 | * BIO memory stores buffer and read pointer | |
62 | * however the roles are different for read only BIOs. | |
63 | * In that case the readp just stores the original state | |
64 | * to be used for reset. | |
65 | */ | |
d3e6d6bc KM |
66 | typedef struct bio_buf_mem_st { |
67 | struct buf_mem_st *buf; /* allocated buffer */ | |
68 | struct buf_mem_st *readp; /* read pointer */ | |
69 | } BIO_BUF_MEM; | |
70 | ||
0f113f3e MC |
71 | /* |
72 | * bio->num is used to hold the value to return on 'empty', if it is 0, | |
73 | * should_retry is not set | |
74 | */ | |
dfeab068 | 75 | |
04f6b0fd | 76 | const BIO_METHOD *BIO_s_mem(void) |
0f113f3e | 77 | { |
26a7d938 | 78 | return &mem_method; |
0f113f3e | 79 | } |
d02b48c6 | 80 | |
04f6b0fd | 81 | const BIO_METHOD *BIO_s_secmem(void) |
74924dcb RS |
82 | { |
83 | return(&secmem_method); | |
84 | } | |
85 | ||
8ab31975 | 86 | BIO *BIO_new_mem_buf(const void *buf, int len) |
8484721a | 87 | { |
0f113f3e MC |
88 | BIO *ret; |
89 | BUF_MEM *b; | |
9fe9d046 | 90 | BIO_BUF_MEM *bb; |
0f113f3e | 91 | size_t sz; |
ae1552ee | 92 | |
75ebbd9a | 93 | if (buf == NULL) { |
0f113f3e MC |
94 | BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER); |
95 | return NULL; | |
96 | } | |
97 | sz = (len < 0) ? strlen(buf) : (size_t)len; | |
75ebbd9a | 98 | if ((ret = BIO_new(BIO_s_mem())) == NULL) |
0f113f3e | 99 | return NULL; |
9fe9d046 KM |
100 | bb = (BIO_BUF_MEM *)ret->ptr; |
101 | b = bb->buf; | |
8ab31975 DKG |
102 | /* Cast away const and trust in the MEM_RDONLY flag. */ |
103 | b->data = (void *)buf; | |
0f113f3e MC |
104 | b->length = sz; |
105 | b->max = sz; | |
9fe9d046 | 106 | *bb->readp = *bb->buf; |
0f113f3e | 107 | ret->flags |= BIO_FLAGS_MEM_RDONLY; |
60250017 | 108 | /* Since this is static data retrying won't help */ |
0f113f3e MC |
109 | ret->num = 0; |
110 | return ret; | |
8484721a DSH |
111 | } |
112 | ||
74924dcb | 113 | static int mem_init(BIO *bi, unsigned long flags) |
0f113f3e | 114 | { |
fc9755ee | 115 | BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb)); |
d02b48c6 | 116 | |
9fe9d046 | 117 | if (bb == NULL) |
b0b6ba2d MC |
118 | return 0; |
119 | if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) { | |
120 | OPENSSL_free(bb); | |
121 | return 0; | |
122 | } | |
123 | if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) { | |
124 | BUF_MEM_free(bb->buf); | |
125 | OPENSSL_free(bb); | |
126 | return 0; | |
127 | } | |
9fe9d046 | 128 | *bb->readp = *bb->buf; |
0f113f3e MC |
129 | bi->shutdown = 1; |
130 | bi->init = 1; | |
131 | bi->num = -1; | |
9fe9d046 | 132 | bi->ptr = (char *)bb; |
b0b6ba2d | 133 | return 1; |
74924dcb RS |
134 | } |
135 | ||
136 | static int mem_new(BIO *bi) | |
137 | { | |
26a7d938 | 138 | return mem_init(bi, 0L); |
74924dcb RS |
139 | } |
140 | ||
141 | static int secmem_new(BIO *bi) | |
142 | { | |
26a7d938 | 143 | return mem_init(bi, BUF_MEM_FLAG_SECURE); |
0f113f3e | 144 | } |
d02b48c6 | 145 | |
6b691a5c | 146 | static int mem_free(BIO *a) |
9fe9d046 | 147 | { |
c6048af2 CM |
148 | BIO_BUF_MEM *bb; |
149 | ||
150 | if (a == NULL) | |
151 | return 0; | |
152 | ||
153 | bb = (BIO_BUF_MEM *)a->ptr; | |
154 | if (!mem_buf_free(a)) | |
155 | return 0; | |
156 | OPENSSL_free(bb->readp); | |
157 | OPENSSL_free(bb); | |
158 | return 1; | |
9fe9d046 KM |
159 | } |
160 | ||
c6048af2 | 161 | static int mem_buf_free(BIO *a) |
0f113f3e MC |
162 | { |
163 | if (a == NULL) | |
26a7d938 | 164 | return 0; |
a0fda2cf F |
165 | |
166 | if (a->shutdown && a->init && a->ptr != NULL) { | |
167 | BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr; | |
168 | BUF_MEM *b = bb->buf; | |
169 | ||
170 | if (a->flags & BIO_FLAGS_MEM_RDONLY) | |
171 | b->data = NULL; | |
172 | BUF_MEM_free(b); | |
0f113f3e | 173 | } |
208fb891 | 174 | return 1; |
0f113f3e MC |
175 | } |
176 | ||
9fe9d046 KM |
177 | /* |
178 | * Reallocate memory buffer if read pointer differs | |
179 | */ | |
180 | static int mem_buf_sync(BIO *b) | |
181 | { | |
e8aa8b6c | 182 | if (b != NULL && b->init != 0 && b->ptr != NULL) { |
9fe9d046 KM |
183 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
184 | ||
e8aa8b6c | 185 | if (bbm->readp->data != bbm->buf->data) { |
9fe9d046 KM |
186 | memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length); |
187 | bbm->buf->length = bbm->readp->length; | |
188 | bbm->readp->data = bbm->buf->data; | |
189 | } | |
190 | } | |
26a7d938 | 191 | return 0; |
9fe9d046 KM |
192 | } |
193 | ||
6b691a5c | 194 | static int mem_read(BIO *b, char *out, int outl) |
0f113f3e MC |
195 | { |
196 | int ret = -1; | |
9fe9d046 KM |
197 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
198 | BUF_MEM *bm = bbm->readp; | |
d02b48c6 | 199 | |
b238fb79 TM |
200 | if (b->flags & BIO_FLAGS_MEM_RDONLY) |
201 | bm = bbm->buf; | |
0f113f3e MC |
202 | BIO_clear_retry_flags(b); |
203 | ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl; | |
204 | if ((out != NULL) && (ret > 0)) { | |
205 | memcpy(out, bm->data, ret); | |
206 | bm->length -= ret; | |
d34bce03 | 207 | bm->max -= ret; |
9fe9d046 | 208 | bm->data += ret; |
0f113f3e MC |
209 | } else if (bm->length == 0) { |
210 | ret = b->num; | |
211 | if (ret != 0) | |
212 | BIO_set_retry_read(b); | |
213 | } | |
26a7d938 | 214 | return ret; |
0f113f3e | 215 | } |
d02b48c6 | 216 | |
0e1c0612 | 217 | static int mem_write(BIO *b, const char *in, int inl) |
0f113f3e MC |
218 | { |
219 | int ret = -1; | |
220 | int blen; | |
9fe9d046 | 221 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
d02b48c6 | 222 | |
0f113f3e MC |
223 | if (in == NULL) { |
224 | BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); | |
225 | goto end; | |
226 | } | |
0f113f3e MC |
227 | if (b->flags & BIO_FLAGS_MEM_RDONLY) { |
228 | BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO); | |
229 | goto end; | |
230 | } | |
0f113f3e | 231 | BIO_clear_retry_flags(b); |
0d94212a RL |
232 | if (inl == 0) |
233 | return 0; | |
9fe9d046 KM |
234 | blen = bbm->readp->length; |
235 | mem_buf_sync(b); | |
236 | if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) | |
0f113f3e | 237 | goto end; |
9fe9d046 KM |
238 | memcpy(bbm->buf->data + blen, in, inl); |
239 | *bbm->readp = *bbm->buf; | |
0f113f3e MC |
240 | ret = inl; |
241 | end: | |
26a7d938 | 242 | return ret; |
0f113f3e | 243 | } |
d02b48c6 | 244 | |
0e1c0612 | 245 | static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) |
0f113f3e MC |
246 | { |
247 | long ret = 1; | |
248 | char **pptr; | |
9fe9d046 KM |
249 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
250 | BUF_MEM *bm; | |
d02b48c6 | 251 | |
b238fb79 TM |
252 | if (b->flags & BIO_FLAGS_MEM_RDONLY) |
253 | bm = bbm->buf; | |
254 | else | |
255 | bm = bbm->readp; | |
256 | ||
0f113f3e MC |
257 | switch (cmd) { |
258 | case BIO_CTRL_RESET: | |
9fe9d046 | 259 | bm = bbm->buf; |
0f113f3e | 260 | if (bm->data != NULL) { |
b238fb79 | 261 | if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) { |
8b7b3292 | 262 | if (!(b->flags & BIO_FLAGS_NONCLEAR_RST)) { |
b238fb79 TM |
263 | memset(bm->data, 0, bm->max); |
264 | bm->length = 0; | |
265 | } | |
266 | *bbm->readp = *bbm->buf; | |
0f113f3e | 267 | } else { |
b238fb79 TM |
268 | /* For read only case just reset to the start again */ |
269 | *bbm->buf = *bbm->readp; | |
0f113f3e MC |
270 | } |
271 | } | |
272 | break; | |
273 | case BIO_CTRL_EOF: | |
274 | ret = (long)(bm->length == 0); | |
275 | break; | |
276 | case BIO_C_SET_BUF_MEM_EOF_RETURN: | |
277 | b->num = (int)num; | |
278 | break; | |
279 | case BIO_CTRL_INFO: | |
280 | ret = (long)bm->length; | |
281 | if (ptr != NULL) { | |
282 | pptr = (char **)ptr; | |
283 | *pptr = (char *)&(bm->data[0]); | |
284 | } | |
285 | break; | |
286 | case BIO_C_SET_BUF_MEM: | |
c6048af2 | 287 | mem_buf_free(b); |
0f113f3e | 288 | b->shutdown = (int)num; |
9fe9d046 KM |
289 | bbm->buf = ptr; |
290 | *bbm->readp = *bbm->buf; | |
0f113f3e MC |
291 | break; |
292 | case BIO_C_GET_BUF_MEM_PTR: | |
293 | if (ptr != NULL) { | |
b238fb79 TM |
294 | if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) |
295 | mem_buf_sync(b); | |
296 | bm = bbm->buf; | |
0f113f3e MC |
297 | pptr = (char **)ptr; |
298 | *pptr = (char *)bm; | |
299 | } | |
300 | break; | |
301 | case BIO_CTRL_GET_CLOSE: | |
302 | ret = (long)b->shutdown; | |
303 | break; | |
304 | case BIO_CTRL_SET_CLOSE: | |
305 | b->shutdown = (int)num; | |
306 | break; | |
0f113f3e MC |
307 | case BIO_CTRL_WPENDING: |
308 | ret = 0L; | |
309 | break; | |
310 | case BIO_CTRL_PENDING: | |
311 | ret = (long)bm->length; | |
312 | break; | |
313 | case BIO_CTRL_DUP: | |
314 | case BIO_CTRL_FLUSH: | |
315 | ret = 1; | |
316 | break; | |
317 | case BIO_CTRL_PUSH: | |
318 | case BIO_CTRL_POP: | |
319 | default: | |
320 | ret = 0; | |
321 | break; | |
322 | } | |
26a7d938 | 323 | return ret; |
0f113f3e | 324 | } |
d02b48c6 | 325 | |
6b691a5c | 326 | static int mem_gets(BIO *bp, char *buf, int size) |
0f113f3e MC |
327 | { |
328 | int i, j; | |
329 | int ret = -1; | |
330 | char *p; | |
9fe9d046 KM |
331 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr; |
332 | BUF_MEM *bm = bbm->readp; | |
d02b48c6 | 333 | |
b238fb79 TM |
334 | if (bp->flags & BIO_FLAGS_MEM_RDONLY) |
335 | bm = bbm->buf; | |
0f113f3e MC |
336 | BIO_clear_retry_flags(bp); |
337 | j = bm->length; | |
338 | if ((size - 1) < j) | |
339 | j = size - 1; | |
340 | if (j <= 0) { | |
341 | *buf = '\0'; | |
342 | return 0; | |
343 | } | |
344 | p = bm->data; | |
345 | for (i = 0; i < j; i++) { | |
346 | if (p[i] == '\n') { | |
347 | i++; | |
348 | break; | |
349 | } | |
350 | } | |
77202a85 | 351 | |
0f113f3e MC |
352 | /* |
353 | * i is now the max num of bytes to copy, either j or up to | |
354 | * and including the first newline | |
355 | */ | |
77202a85 | 356 | |
0f113f3e MC |
357 | i = mem_read(bp, buf, i); |
358 | if (i > 0) | |
359 | buf[i] = '\0'; | |
360 | ret = i; | |
26a7d938 | 361 | return ret; |
0f113f3e | 362 | } |
d02b48c6 | 363 | |
0e1c0612 | 364 | static int mem_puts(BIO *bp, const char *str) |
0f113f3e MC |
365 | { |
366 | int n, ret; | |
d02b48c6 | 367 | |
0f113f3e MC |
368 | n = strlen(str); |
369 | ret = mem_write(bp, str, n); | |
370 | /* memory semantics is that it will always work */ | |
26a7d938 | 371 | return ret; |
0f113f3e | 372 | } |