diff options
-rw-r--r-- | crypto/bio/bss_mem.c | 128 | ||||
-rw-r--r-- | include/openssl/bio.h.in | 1 | ||||
-rw-r--r-- | util/libcrypto.num | 1 |
3 files changed, 122 insertions, 8 deletions
diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c index 9153c1f1cd..a753380e64 100644 --- a/crypto/bio/bss_mem.c +++ b/crypto/bio/bss_mem.c @@ -18,6 +18,7 @@ static int mem_puts(BIO *h, const char *str); static int mem_gets(BIO *h, char *str, int size); static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int mem_new(BIO *h); +static int dgram_mem_new(BIO *h); static int secmem_new(BIO *h); static int mem_free(BIO *data); static int mem_buf_free(BIO *data); @@ -38,6 +39,21 @@ static const BIO_METHOD mem_method = { NULL, /* mem_callback_ctrl */ }; +static const BIO_METHOD dgram_mem_method = { + BIO_TYPE_MEM, + "datagram memory buffer", + bwrite_conv, + mem_write, + bread_conv, + mem_read, + mem_puts, + mem_gets, + mem_ctrl, + dgram_mem_new, + mem_free, + NULL, /* mem_callback_ctrl */ +}; + static const BIO_METHOD secmem_method = { BIO_TYPE_MEM, "secure memory buffer", @@ -53,6 +69,12 @@ static const BIO_METHOD secmem_method = { NULL, /* mem_callback_ctrl */ }; +struct buf_mem_dgram_st { + char *dgram; /* Pointer into the buffer for where the dgram starts */ + size_t dgramlen; /* Length of the dgram */ + struct buf_mem_dgram_st *next; /* Next dgram to read */ +}; + /* * BIO memory stores buffer and read pointer * however the roles are different for read only BIOs. @@ -62,6 +84,9 @@ static const BIO_METHOD secmem_method = { typedef struct bio_buf_mem_st { struct buf_mem_st *buf; /* allocated buffer */ struct buf_mem_st *readp; /* read pointer */ + struct buf_mem_dgram_st *dgrams; /* linked list of dgram data */ + struct buf_mem_dgram_st *last; /* last dgram in the linked list */ + int use_dgrams; } BIO_BUF_MEM; /* @@ -74,6 +99,11 @@ const BIO_METHOD *BIO_s_mem(void) return &mem_method; } +const BIO_METHOD *BIO_s_dgram_mem(void) +{ + return &dgram_mem_method; +} + const BIO_METHOD *BIO_s_secmem(void) { return(&secmem_method); @@ -134,11 +164,39 @@ static int mem_new(BIO *bi) return mem_init(bi, 0L); } +static int dgram_mem_new(BIO *bi) +{ + BIO_BUF_MEM *bbm; + + if (!mem_init(bi, 0L)) + return 0; + + bbm = (BIO_BUF_MEM *)bi->ptr; + + bbm->use_dgrams = 1; + bi->num = -1; + + return 1; +} + static int secmem_new(BIO *bi) { return mem_init(bi, BUF_MEM_FLAG_SECURE); } +static void clear_all_dgrams(BIO_BUF_MEM *bbm) +{ + struct buf_mem_dgram_st *dgrams = bbm->dgrams; + + while (dgrams != NULL) { + struct buf_mem_dgram_st *tmp = dgrams; + + dgrams = dgrams->next; + OPENSSL_free(tmp); + } + bbm->dgrams = NULL; +} + static int mem_free(BIO *a) { BIO_BUF_MEM *bb; @@ -150,6 +208,7 @@ static int mem_free(BIO *a) if (!mem_buf_free(a)) return 0; OPENSSL_free(bb->readp); + clear_all_dgrams(bb); OPENSSL_free(bb); return 1; } @@ -193,17 +252,43 @@ static int mem_read(BIO *b, char *out, int outl) int ret = -1; BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; BUF_MEM *bm = bbm->readp; + size_t maxreadlen = 0; + int eof = 0; if (b->flags & BIO_FLAGS_MEM_RDONLY) bm = bbm->buf; BIO_clear_retry_flags(b); - ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl; + if (bbm->use_dgrams) { + if (bbm->dgrams != NULL) { + maxreadlen = bbm->dgrams->dgramlen; + if (!ossl_assert(maxreadlen <= bm->length)) + return 0; + } else { + eof = 1; + } + } else { + maxreadlen = bm->length; + eof = (maxreadlen == 0); + } + ret = (outl >= 0 && (size_t)outl > maxreadlen) ? (int)maxreadlen : outl; if ((out != NULL) && (ret > 0)) { + size_t flushlen; + memcpy(out, bm->data, ret); - bm->length -= ret; - bm->max -= ret; - bm->data += ret; - } else if (bm->length == 0) { + flushlen = bbm->use_dgrams ? maxreadlen : (size_t)ret; + + bm->length -= flushlen; + bm->max -= flushlen; + bm->data += flushlen; + if (bbm->use_dgrams) { + struct buf_mem_dgram_st *tmp = bbm->dgrams; + + bbm->dgrams = tmp->next; + OPENSSL_free(tmp); + if (bbm->dgrams == NULL) + bbm->last = NULL; + } + } else if (eof) { ret = b->num; if (ret != 0) BIO_set_retry_read(b); @@ -222,8 +307,10 @@ static int mem_write(BIO *b, const char *in, int inl) goto end; } BIO_clear_retry_flags(b); + if (inl == 0) return 0; + if (in == NULL) { ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); goto end; @@ -232,8 +319,28 @@ static int mem_write(BIO *b, const char *in, int inl) mem_buf_sync(b); if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) goto end; + memcpy(bbm->buf->data + blen, in, inl); *bbm->readp = *bbm->buf; + + if (bbm->use_dgrams) { + struct buf_mem_dgram_st *dgram = OPENSSL_malloc(sizeof(*dgram)); + + if (dgram == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + goto end; + } + + dgram->dgram = bbm->buf->data + blen; + dgram->dgramlen = inl; + dgram->next = NULL; + if (bbm->dgrams == NULL) + bbm->dgrams = dgram; + else + bbm->last->next = dgram; + bbm->last = dgram; + } + ret = inl; end: return ret; @@ -272,6 +379,7 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) *bbm->buf = *bbm->readp; } } + clear_all_dgrams(bbm); break; case BIO_C_FILE_SEEK: if (num < 0 || num > off + remain) @@ -286,10 +394,13 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) ret = off; break; case BIO_CTRL_EOF: - ret = (long)(bm->length == 0); + ret = (long)(bm->length == 0 && bbm->use_dgrams == 0); break; case BIO_C_SET_BUF_MEM_EOF_RETURN: - b->num = (int)num; + if (!bbm->use_dgrams) + b->num = (int)num; + else + ret = -1; break; case BIO_CTRL_INFO: ret = (long)bm->length; @@ -349,7 +460,8 @@ static int mem_gets(BIO *bp, char *buf, int size) if (bp->flags & BIO_FLAGS_MEM_RDONLY) bm = bbm->buf; BIO_clear_retry_flags(bp); - j = bm->length; + j = (!bbm->use_dgrams || bbm->dgrams == NULL) ? bm->length + : bbm->dgrams->dgramlen; if ((size - 1) < j) j = size - 1; if (j <= 0) { diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index 46697ce3d7..1de1790ba7 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -649,6 +649,7 @@ int BIO_nwrite0(BIO *bio, char **buf); int BIO_nwrite(BIO *bio, char **buf, int num); const BIO_METHOD *BIO_s_mem(void); +const BIO_METHOD *BIO_s_dgram_mem(void); const BIO_METHOD *BIO_s_secmem(void); BIO *BIO_new_mem_buf(const void *buf, int len); # ifndef OPENSSL_NO_SOCK diff --git a/util/libcrypto.num b/util/libcrypto.num index e9338aabab..6406849f3f 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5447,3 +5447,4 @@ CMS_SignedData_new ? 3_1_0 EXIST::FUNCTION:CMS CMS_SignedData_verify ? 3_1_0 EXIST::FUNCTION:CMS OPENSSL_strcasecmp ? 3_0_3 EXIST::FUNCTION: OPENSSL_strncasecmp ? 3_0_3 EXIST::FUNCTION: +BIO_s_dgram_mem ? 3_1_0 EXIST::FUNCTION: |