summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/bio/bss_mem.c128
-rw-r--r--include/openssl/bio.h.in1
-rw-r--r--util/libcrypto.num1
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: