1 /* 2 * Copyright 1995-2019 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 <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