1 | /* |
2 | * Copyright 1995-2018 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 <errno.h> |
12 | #include "bio_local.h" |
13 | #include "internal/cryptlib.h" |
14 | |
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); |
20 | static int mem_new(BIO *h); |
21 | static int secmem_new(BIO *h); |
22 | static int mem_free(BIO *data); |
23 | static int mem_buf_free(BIO *data); |
24 | static int mem_buf_sync(BIO *h); |
25 | |
26 | static const BIO_METHOD mem_method = { |
27 | BIO_TYPE_MEM, |
28 | "memory buffer" , |
29 | /* TODO: Convert to new style write function */ |
30 | bwrite_conv, |
31 | mem_write, |
32 | /* TODO: Convert to new style read function */ |
33 | bread_conv, |
34 | mem_read, |
35 | mem_puts, |
36 | mem_gets, |
37 | mem_ctrl, |
38 | mem_new, |
39 | mem_free, |
40 | NULL, /* mem_callback_ctrl */ |
41 | }; |
42 | |
43 | static const BIO_METHOD secmem_method = { |
44 | BIO_TYPE_MEM, |
45 | "secure memory buffer" , |
46 | /* TODO: Convert to new style write function */ |
47 | bwrite_conv, |
48 | mem_write, |
49 | /* TODO: Convert to new style read function */ |
50 | bread_conv, |
51 | mem_read, |
52 | mem_puts, |
53 | mem_gets, |
54 | mem_ctrl, |
55 | secmem_new, |
56 | mem_free, |
57 | NULL, /* mem_callback_ctrl */ |
58 | }; |
59 | |
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 | */ |
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 | |
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 | */ |
75 | |
76 | const BIO_METHOD *BIO_s_mem(void) |
77 | { |
78 | return &mem_method; |
79 | } |
80 | |
81 | const BIO_METHOD *BIO_s_secmem(void) |
82 | { |
83 | return(&secmem_method); |
84 | } |
85 | |
86 | BIO *BIO_new_mem_buf(const void *buf, int len) |
87 | { |
88 | BIO *ret; |
89 | BUF_MEM *b; |
90 | BIO_BUF_MEM *bb; |
91 | size_t sz; |
92 | |
93 | if (buf == NULL) { |
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; |
98 | if ((ret = BIO_new(BIO_s_mem())) == NULL) |
99 | return NULL; |
100 | bb = (BIO_BUF_MEM *)ret->ptr; |
101 | b = bb->buf; |
102 | /* Cast away const and trust in the MEM_RDONLY flag. */ |
103 | b->data = (void *)buf; |
104 | b->length = sz; |
105 | b->max = sz; |
106 | *bb->readp = *bb->buf; |
107 | ret->flags |= BIO_FLAGS_MEM_RDONLY; |
108 | /* Since this is static data retrying won't help */ |
109 | ret->num = 0; |
110 | return ret; |
111 | } |
112 | |
113 | static int mem_init(BIO *bi, unsigned long flags) |
114 | { |
115 | BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb)); |
116 | |
117 | if (bb == NULL) |
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 | } |
128 | *bb->readp = *bb->buf; |
129 | bi->shutdown = 1; |
130 | bi->init = 1; |
131 | bi->num = -1; |
132 | bi->ptr = (char *)bb; |
133 | return 1; |
134 | } |
135 | |
136 | static int mem_new(BIO *bi) |
137 | { |
138 | return mem_init(bi, 0L); |
139 | } |
140 | |
141 | static int secmem_new(BIO *bi) |
142 | { |
143 | return mem_init(bi, BUF_MEM_FLAG_SECURE); |
144 | } |
145 | |
146 | static int mem_free(BIO *a) |
147 | { |
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; |
159 | } |
160 | |
161 | static int mem_buf_free(BIO *a) |
162 | { |
163 | if (a == NULL) |
164 | return 0; |
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); |
173 | } |
174 | return 1; |
175 | } |
176 | |
177 | /* |
178 | * Reallocate memory buffer if read pointer differs |
179 | */ |
180 | static int mem_buf_sync(BIO *b) |
181 | { |
182 | if (b != NULL && b->init != 0 && b->ptr != NULL) { |
183 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
184 | |
185 | if (bbm->readp->data != bbm->buf->data) { |
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 | } |
191 | return 0; |
192 | } |
193 | |
194 | static int mem_read(BIO *b, char *out, int outl) |
195 | { |
196 | int ret = -1; |
197 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
198 | BUF_MEM *bm = bbm->readp; |
199 | |
200 | if (b->flags & BIO_FLAGS_MEM_RDONLY) |
201 | bm = bbm->buf; |
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; |
207 | bm->max -= ret; |
208 | bm->data += ret; |
209 | } else if (bm->length == 0) { |
210 | ret = b->num; |
211 | if (ret != 0) |
212 | BIO_set_retry_read(b); |
213 | } |
214 | return ret; |
215 | } |
216 | |
217 | static int mem_write(BIO *b, const char *in, int inl) |
218 | { |
219 | int ret = -1; |
220 | int blen; |
221 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
222 | |
223 | if (in == NULL) { |
224 | BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); |
225 | goto end; |
226 | } |
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 | } |
231 | BIO_clear_retry_flags(b); |
232 | if (inl == 0) |
233 | return 0; |
234 | blen = bbm->readp->length; |
235 | mem_buf_sync(b); |
236 | if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) |
237 | goto end; |
238 | memcpy(bbm->buf->data + blen, in, inl); |
239 | *bbm->readp = *bbm->buf; |
240 | ret = inl; |
241 | end: |
242 | return ret; |
243 | } |
244 | |
245 | static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) |
246 | { |
247 | long ret = 1; |
248 | char **pptr; |
249 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; |
250 | BUF_MEM *bm; |
251 | |
252 | if (b->flags & BIO_FLAGS_MEM_RDONLY) |
253 | bm = bbm->buf; |
254 | else |
255 | bm = bbm->readp; |
256 | |
257 | switch (cmd) { |
258 | case BIO_CTRL_RESET: |
259 | bm = bbm->buf; |
260 | if (bm->data != NULL) { |
261 | if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) { |
262 | if (!(b->flags & BIO_FLAGS_NONCLEAR_RST)) { |
263 | memset(bm->data, 0, bm->max); |
264 | bm->length = 0; |
265 | } |
266 | *bbm->readp = *bbm->buf; |
267 | } else { |
268 | /* For read only case just reset to the start again */ |
269 | *bbm->buf = *bbm->readp; |
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: |
287 | mem_buf_free(b); |
288 | b->shutdown = (int)num; |
289 | bbm->buf = ptr; |
290 | *bbm->readp = *bbm->buf; |
291 | break; |
292 | case BIO_C_GET_BUF_MEM_PTR: |
293 | if (ptr != NULL) { |
294 | if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) |
295 | mem_buf_sync(b); |
296 | bm = bbm->buf; |
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; |
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 | } |
323 | return ret; |
324 | } |
325 | |
326 | static int mem_gets(BIO *bp, char *buf, int size) |
327 | { |
328 | int i, j; |
329 | int ret = -1; |
330 | char *p; |
331 | BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr; |
332 | BUF_MEM *bm = bbm->readp; |
333 | |
334 | if (bp->flags & BIO_FLAGS_MEM_RDONLY) |
335 | bm = bbm->buf; |
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 | } |
351 | |
352 | /* |
353 | * i is now the max num of bytes to copy, either j or up to |
354 | * and including the first newline |
355 | */ |
356 | |
357 | i = mem_read(bp, buf, i); |
358 | if (i > 0) |
359 | buf[i] = '\0'; |
360 | ret = i; |
361 | return ret; |
362 | } |
363 | |
364 | static int mem_puts(BIO *bp, const char *str) |
365 | { |
366 | int n, ret; |
367 | |
368 | n = strlen(str); |
369 | ret = mem_write(bp, str, n); |
370 | /* memory semantics is that it will always work */ |
371 | return ret; |
372 | } |
373 | |