1 /* 2 * Copyright 1995-2021 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 bwrite_conv, 30 mem_write, 31 bread_conv, 32 mem_read, 33 mem_puts, 34 mem_gets, 35 mem_ctrl, 36 mem_new, 37 mem_free, 38 NULL, /* mem_callback_ctrl */ 39 }; 40 41 static const BIO_METHOD secmem_method = { 42 BIO_TYPE_MEM, 43 "secure memory buffer", 44 bwrite_conv, 45 mem_write, 46 bread_conv, 47 mem_read, 48 mem_puts, 49 mem_gets, 50 mem_ctrl, 51 secmem_new, 52 mem_free, 53 NULL, /* mem_callback_ctrl */ 54 }; 55 56 /* 57 * BIO memory stores buffer and read pointer 58 * however the roles are different for read only BIOs. 59 * In that case the readp just stores the original state 60 * to be used for reset. 61 */ 62 typedef struct bio_buf_mem_st { 63 struct buf_mem_st *buf; /* allocated buffer */ 64 struct buf_mem_st *readp; /* read pointer */ 65 } BIO_BUF_MEM; 66 67 /* 68 * bio->num is used to hold the value to return on 'empty', if it is 0, 69 * should_retry is not set 70 */ 71 72 const BIO_METHOD *BIO_s_mem(void) 73 { 74 return &mem_method; 75 } 76 77 const BIO_METHOD *BIO_s_secmem(void) 78 { 79 return(&secmem_method); 80 } 81 82 BIO *BIO_new_mem_buf(const void *buf, int len) 83 { 84 BIO *ret; 85 BUF_MEM *b; 86 BIO_BUF_MEM *bb; 87 size_t sz; 88 89 if (buf == NULL) { 90 ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 91 return NULL; 92 } 93 sz = (len < 0) ? strlen(buf) : (size_t)len; 94 if ((ret = BIO_new(BIO_s_mem())) == NULL) 95 return NULL; 96 bb = (BIO_BUF_MEM *)ret->ptr; 97 b = bb->buf; 98 /* Cast away const and trust in the MEM_RDONLY flag. */ 99 b->data = (void *)buf; 100 b->length = sz; 101 b->max = sz; 102 *bb->readp = *bb->buf; 103 ret->flags |= BIO_FLAGS_MEM_RDONLY; 104 /* Since this is static data retrying won't help */ 105 ret->num = 0; 106 return ret; 107 } 108 109 static int mem_init(BIO *bi, unsigned long flags) 110 { 111 BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb)); 112 113 if (bb == NULL) 114 return 0; 115 if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) { 116 OPENSSL_free(bb); 117 return 0; 118 } 119 if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) { 120 BUF_MEM_free(bb->buf); 121 OPENSSL_free(bb); 122 return 0; 123 } 124 *bb->readp = *bb->buf; 125 bi->shutdown = 1; 126 bi->init = 1; 127 bi->num = -1; 128 bi->ptr = (char *)bb; 129 return 1; 130 } 131 132 static int mem_new(BIO *bi) 133 { 134 return mem_init(bi, 0L); 135 } 136 137 static int secmem_new(BIO *bi) 138 { 139 return mem_init(bi, BUF_MEM_FLAG_SECURE); 140 } 141 142 static int mem_free(BIO *a) 143 { 144 BIO_BUF_MEM *bb; 145 146 if (a == NULL) 147 return 0; 148 149 bb = (BIO_BUF_MEM *)a->ptr; 150 if (!mem_buf_free(a)) 151 return 0; 152 OPENSSL_free(bb->readp); 153 OPENSSL_free(bb); 154 return 1; 155 } 156 157 static int mem_buf_free(BIO *a) 158 { 159 if (a == NULL) 160 return 0; 161 162 if (a->shutdown && a->init && a->ptr != NULL) { 163 BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr; 164 BUF_MEM *b = bb->buf; 165 166 if (a->flags & BIO_FLAGS_MEM_RDONLY) 167 b->data = NULL; 168 BUF_MEM_free(b); 169 } 170 return 1; 171 } 172 173 /* 174 * Reallocate memory buffer if read pointer differs 175 * NOT FOR RDONLY 176 */ 177 static int mem_buf_sync(BIO *b) 178 { 179 if (b != NULL && b->init != 0 && b->ptr != NULL) { 180 BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 181 182 if (bbm->readp->data != bbm->buf->data) { 183 memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length); 184 bbm->buf->length = bbm->readp->length; 185 bbm->readp->data = bbm->buf->data; 186 } 187 } 188 return 0; 189 } 190 191 static int mem_read(BIO *b, char *out, int outl) 192 { 193 int ret = -1; 194 BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 195 BUF_MEM *bm = bbm->readp; 196 197 if (b->flags & BIO_FLAGS_MEM_RDONLY) 198 bm = bbm->buf; 199 BIO_clear_retry_flags(b); 200 ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl; 201 if ((out != NULL) && (ret > 0)) { 202 memcpy(out, bm->data, ret); 203 bm->length -= ret; 204 bm->max -= ret; 205 bm->data += ret; 206 } else if (bm->length == 0) { 207 ret = b->num; 208 if (ret != 0) 209 BIO_set_retry_read(b); 210 } 211 return ret; 212 } 213 214 static int mem_write(BIO *b, const char *in, int inl) 215 { 216 int ret = -1; 217 int blen; 218 BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 219 220 if (b->flags & BIO_FLAGS_MEM_RDONLY) { 221 ERR_raise(ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO); 222 goto end; 223 } 224 BIO_clear_retry_flags(b); 225 if (inl == 0) 226 return 0; 227 if (in == NULL) { 228 ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 229 goto end; 230 } 231 blen = bbm->readp->length; 232 mem_buf_sync(b); 233 if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) 234 goto end; 235 memcpy(bbm->buf->data + blen, in, inl); 236 *bbm->readp = *bbm->buf; 237 ret = inl; 238 end: 239 return ret; 240 } 241 242 static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) 243 { 244 long ret = 1; 245 char **pptr; 246 BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 247 BUF_MEM *bm, *bo; /* bio_mem, bio_other */ 248 long off, remain; 249 250 if (b->flags & BIO_FLAGS_MEM_RDONLY) { 251 bm = bbm->buf; 252 bo = bbm->readp; 253 } else { 254 bm = bbm->readp; 255 bo = bbm->buf; 256 } 257 off = (bm->data == bo->data) ? 0 : bm->data - bo->data; 258 remain = bm->length; 259 260 switch (cmd) { 261 case BIO_CTRL_RESET: 262 bm = bbm->buf; 263 if (bm->data != NULL) { 264 if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) { 265 if (!(b->flags & BIO_FLAGS_NONCLEAR_RST)) { 266 memset(bm->data, 0, bm->max); 267 bm->length = 0; 268 } 269 *bbm->readp = *bbm->buf; 270 } else { 271 /* For read only case just reset to the start again */ 272 *bbm->buf = *bbm->readp; 273 } 274 } 275 break; 276 case BIO_C_FILE_SEEK: 277 if (num < 0 || num > off + remain) 278 return -1; /* Can't see outside of the current buffer */ 279 280 bm->data = (num != 0) ? bo->data + num : bo->data; 281 bm->length = bo->length - num; 282 bm->max = bo->max - num; 283 off = num; 284 /* FALLTHRU */ 285 case BIO_C_FILE_TELL: 286 ret = off; 287 break; 288 case BIO_CTRL_EOF: 289 ret = (long)(bm->length == 0); 290 break; 291 case BIO_C_SET_BUF_MEM_EOF_RETURN: 292 b->num = (int)num; 293 break; 294 case BIO_CTRL_INFO: 295 ret = (long)bm->length; 296 if (ptr != NULL) { 297 pptr = (char **)ptr; 298 *pptr = (char *)(bm->data); 299 } 300 break; 301 case BIO_C_SET_BUF_MEM: 302 mem_buf_free(b); 303 b->shutdown = (int)num; 304 bbm->buf = ptr; 305 *bbm->readp = *bbm->buf; 306 break; 307 case BIO_C_GET_BUF_MEM_PTR: 308 if (ptr != NULL) { 309 if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) 310 mem_buf_sync(b); 311 bm = bbm->buf; 312 pptr = (char **)ptr; 313 *pptr = (char *)bm; 314 } 315 break; 316 case BIO_CTRL_GET_CLOSE: 317 ret = (long)b->shutdown; 318 break; 319 case BIO_CTRL_SET_CLOSE: 320 b->shutdown = (int)num; 321 break; 322 case BIO_CTRL_WPENDING: 323 ret = 0L; 324 break; 325 case BIO_CTRL_PENDING: 326 ret = (long)bm->length; 327 break; 328 case BIO_CTRL_DUP: 329 case BIO_CTRL_FLUSH: 330 ret = 1; 331 break; 332 case BIO_CTRL_PUSH: 333 case BIO_CTRL_POP: 334 default: 335 ret = 0; 336 break; 337 } 338 return ret; 339 } 340 341 static int mem_gets(BIO *bp, char *buf, int size) 342 { 343 int i, j; 344 int ret = -1; 345 char *p; 346 BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr; 347 BUF_MEM *bm = bbm->readp; 348 349 if (bp->flags & BIO_FLAGS_MEM_RDONLY) 350 bm = bbm->buf; 351 BIO_clear_retry_flags(bp); 352 j = bm->length; 353 if ((size - 1) < j) 354 j = size - 1; 355 if (j <= 0) { 356 *buf = '\0'; 357 return 0; 358 } 359 p = bm->data; 360 for (i = 0; i < j; i++) { 361 if (p[i] == '\n') { 362 i++; 363 break; 364 } 365 } 366 367 /* 368 * i is now the max num of bytes to copy, either j or up to 369 * and including the first newline 370 */ 371 372 i = mem_read(bp, buf, i); 373 if (i > 0) 374 buf[i] = '\0'; 375 ret = i; 376 return ret; 377 } 378 379 static int mem_puts(BIO *bp, const char *str) 380 { 381 int n, ret; 382 383 n = strlen(str); 384 ret = mem_write(bp, str, n); 385 /* memory semantics is that it will always work */ 386 return ret; 387 } 388