Allow memory bios to be read only and change PKCS#7 routines to use them.
This commit is contained in:
parent
de1915e48c
commit
8484721adb
12
CHANGES
12
CHANGES
@ -4,6 +4,18 @@
|
||||
|
||||
Changes between 0.9.4 and 0.9.5 [xx XXX 1999]
|
||||
|
||||
*) Add a new flag to memory BIOs, BIO_FLAG_MEM_RDONLY. This marks the BIO
|
||||
as "read only": it can't be written to and the buffer it points to will
|
||||
not be freed. Reading from a read only BIO is much more efficient than
|
||||
a normal memory BIO. This was added because there are several times when
|
||||
an area of memory needs to be read from a BIO. The previous method was
|
||||
to create a memory BIO and write the data to it, this results in two
|
||||
copies of the data and an O(n^2) reading algorithm. There is a new
|
||||
function BIO_new_mem_buf() which creates a read only memory BIO from
|
||||
an area of memory. Also modified the PKCS#7 routines to use read only
|
||||
memory BIOSs.
|
||||
[Steve Henson]
|
||||
|
||||
*) Bugfix: ssl23_get_client_hello did not work properly when called in
|
||||
state SSL23_ST_SR_CLNT_HELLO_B, i.e. when the first 7 bytes of
|
||||
a SSLv2-compatible client hello for SSLv3 or TLSv1 could be read,
|
||||
|
@ -147,6 +147,11 @@ extern "C" {
|
||||
|
||||
#define BIO_FLAGS_BASE64_NO_NL 0x100
|
||||
|
||||
/* This is used with memory BIOs: it means we shouldn't free up or change the
|
||||
* data in any way.
|
||||
*/
|
||||
#define BIO_FLAGS_MEM_RDONLY 0x200
|
||||
|
||||
#define BIO_set_flags(b,f) ((b)->flags|=(f))
|
||||
#define BIO_get_flags(b) ((b)->flags)
|
||||
#define BIO_set_retry_special(b) \
|
||||
@ -526,6 +531,7 @@ long _far _loadds BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
|
||||
#endif
|
||||
|
||||
BIO_METHOD *BIO_s_mem(void);
|
||||
BIO *BIO_new_mem_buf(void *buf, int len);
|
||||
BIO_METHOD *BIO_s_socket(void);
|
||||
BIO_METHOD *BIO_s_connect(void);
|
||||
BIO_METHOD *BIO_s_accept(void);
|
||||
@ -604,6 +610,7 @@ int BIO_printf(BIO *bio, ...);
|
||||
#define BIO_F_BIO_MAKE_PAIR 121
|
||||
#define BIO_F_BIO_NEW 108
|
||||
#define BIO_F_BIO_NEW_FILE 109
|
||||
#define BIO_F_BIO_NEW_MEM_BUF 126
|
||||
#define BIO_F_BIO_NREAD 123
|
||||
#define BIO_F_BIO_NREAD0 124
|
||||
#define BIO_F_BIO_NWRITE 125
|
||||
@ -645,6 +652,7 @@ int BIO_printf(BIO *bio, ...);
|
||||
#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
|
||||
#define BIO_R_UNINITIALIZED 120
|
||||
#define BIO_R_UNSUPPORTED_METHOD 121
|
||||
#define BIO_R_WRITE_TO_READ_ONLY_BIO 126
|
||||
#define BIO_R_WSASTARTUP 122
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -77,6 +77,7 @@ static ERR_STRING_DATA BIO_str_functs[]=
|
||||
{ERR_PACK(0,BIO_F_BIO_MAKE_PAIR,0), "BIO_MAKE_PAIR"},
|
||||
{ERR_PACK(0,BIO_F_BIO_NEW,0), "BIO_new"},
|
||||
{ERR_PACK(0,BIO_F_BIO_NEW_FILE,0), "BIO_new_file"},
|
||||
{ERR_PACK(0,BIO_F_BIO_NEW_MEM_BUF,0), "BIO_new_mem_buf"},
|
||||
{ERR_PACK(0,BIO_F_BIO_NREAD,0), "BIO_nread"},
|
||||
{ERR_PACK(0,BIO_F_BIO_NREAD0,0), "BIO_nread0"},
|
||||
{ERR_PACK(0,BIO_F_BIO_NWRITE,0), "BIO_nwrite"},
|
||||
@ -121,6 +122,7 @@ static ERR_STRING_DATA BIO_str_reasons[]=
|
||||
{BIO_R_UNABLE_TO_LISTEN_SOCKET ,"unable to listen socket"},
|
||||
{BIO_R_UNINITIALIZED ,"uninitialized"},
|
||||
{BIO_R_UNSUPPORTED_METHOD ,"unsupported method"},
|
||||
{BIO_R_WRITE_TO_READ_ONLY_BIO ,"write to read only bio"},
|
||||
{BIO_R_WSASTARTUP ,"wsastartup"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
@ -89,6 +89,26 @@ BIO_METHOD *BIO_s_mem(void)
|
||||
return(&mem_method);
|
||||
}
|
||||
|
||||
BIO *BIO_new_mem_buf(void *buf, int len)
|
||||
{
|
||||
BIO *ret;
|
||||
BUF_MEM *b;
|
||||
if (!buf) {
|
||||
BIOerr(BIO_F_BIO_NEW_MEM_BUF,BIO_R_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
if(len == -1) len = strlen(buf);
|
||||
if(!(ret = BIO_new(BIO_s_mem())) ) return NULL;
|
||||
b = (BUF_MEM *)ret->ptr;
|
||||
b->data = buf;
|
||||
b->length = len;
|
||||
b->max = len;
|
||||
ret->flags |= BIO_FLAGS_MEM_RDONLY;
|
||||
/* Since this is static data retrying wont help */
|
||||
ret->num = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_new(BIO *bi)
|
||||
{
|
||||
BUF_MEM *b;
|
||||
@ -109,7 +129,10 @@ static int mem_free(BIO *a)
|
||||
{
|
||||
if ((a->init) && (a->ptr != NULL))
|
||||
{
|
||||
BUF_MEM_free((BUF_MEM *)a->ptr);
|
||||
BUF_MEM *b;
|
||||
b = (BUF_MEM *)a->ptr;
|
||||
if(a->flags & BIO_FLAGS_MEM_RDONLY) b->data = NULL;
|
||||
BUF_MEM_free(b);
|
||||
a->ptr=NULL;
|
||||
}
|
||||
}
|
||||
@ -126,17 +149,18 @@ static int mem_read(BIO *b, char *out, int outl)
|
||||
bm=(BUF_MEM *)b->ptr;
|
||||
BIO_clear_retry_flags(b);
|
||||
ret=(outl > bm->length)?bm->length:outl;
|
||||
if ((out != NULL) && (ret > 0))
|
||||
{
|
||||
if ((out != NULL) && (ret > 0)) {
|
||||
memcpy(out,bm->data,ret);
|
||||
bm->length-=ret;
|
||||
/* memmove(&(bm->data[0]),&(bm->data[ret]), bm->length); */
|
||||
from=(char *)&(bm->data[ret]);
|
||||
to=(char *)&(bm->data[0]);
|
||||
for (i=0; i<bm->length; i++)
|
||||
to[i]=from[i];
|
||||
if(b->flags & BIO_FLAGS_MEM_RDONLY) bm->data += ret;
|
||||
else {
|
||||
from=(char *)&(bm->data[ret]);
|
||||
to=(char *)&(bm->data[0]);
|
||||
for (i=0; i<bm->length; i++)
|
||||
to[i]=from[i];
|
||||
}
|
||||
else if (bm->length == 0)
|
||||
} else if (bm->length == 0)
|
||||
{
|
||||
if (b->num != 0)
|
||||
BIO_set_retry_read(b);
|
||||
@ -158,6 +182,11 @@ static int mem_write(BIO *b, char *in, int inl)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(b->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
BIOerr(BIO_F_MEM_WRITE,BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
goto end;
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
blen=bm->length;
|
||||
if (BUF_MEM_grow(bm,blen+inl) != (blen+inl))
|
||||
@ -178,9 +207,15 @@ static long mem_ctrl(BIO *b, int cmd, long num, char *ptr)
|
||||
switch (cmd)
|
||||
{
|
||||
case BIO_CTRL_RESET:
|
||||
if (bm->data != NULL)
|
||||
memset(bm->data,0,bm->max);
|
||||
bm->length=0;
|
||||
if (bm->data != NULL) {
|
||||
/* For read only case reset to the start again */
|
||||
if(b->flags & BIO_FLAGS_MEM_RDONLY)
|
||||
bm->data -= bm->max - bm->length;
|
||||
else {
|
||||
memset(bm->data,0,bm->max);
|
||||
bm->length=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret=(long)(bm->length == 0);
|
||||
|
@ -216,30 +216,22 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
|
||||
btmp=NULL;
|
||||
}
|
||||
|
||||
if (bio == NULL) /* ??????????? */
|
||||
{
|
||||
if (bio == NULL) {
|
||||
if (p7->detached)
|
||||
bio=BIO_new(BIO_s_null());
|
||||
else
|
||||
{
|
||||
bio=BIO_new(BIO_s_mem());
|
||||
/* We need to set this so that when we have read all
|
||||
* the data, the encrypt BIO, if present, will read
|
||||
* EOF and encode the last few bytes */
|
||||
BIO_set_mem_eof_return(bio,0);
|
||||
|
||||
else {
|
||||
if (PKCS7_type_is_signed(p7) &&
|
||||
PKCS7_type_is_data(p7->d.sign->contents))
|
||||
{
|
||||
PKCS7_type_is_data(p7->d.sign->contents)) {
|
||||
ASN1_OCTET_STRING *os;
|
||||
|
||||
os=p7->d.sign->contents->d.data;
|
||||
if (os->length > 0)
|
||||
BIO_write(bio,(char *)os->data,
|
||||
os->length);
|
||||
}
|
||||
if (os->length > 0) bio =
|
||||
BIO_new_mem_buf(os->data, os->length);
|
||||
} else {
|
||||
bio=BIO_new(BIO_s_mem());
|
||||
BIO_set_mem_eof_return(bio,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIO_push(out,bio);
|
||||
bio=NULL;
|
||||
if (0)
|
||||
@ -430,6 +422,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
bio=BIO_new(BIO_s_mem());
|
||||
/* We need to set this so that when we have read all
|
||||
* the data, the encrypt BIO, if present, will read
|
||||
@ -438,6 +431,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
|
||||
|
||||
if (data_body->length > 0)
|
||||
BIO_write(bio,(char *)data_body->data,data_body->length);
|
||||
#else
|
||||
if (data_body->length > 0)
|
||||
bio = BIO_new_mem_buf(data_body->data,data_body->length);
|
||||
else {
|
||||
bio=BIO_new(BIO_s_mem());
|
||||
BIO_set_mem_eof_return(bio,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
BIO_push(out,bio);
|
||||
bio=NULL;
|
||||
@ -611,8 +612,17 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
|
||||
goto err;
|
||||
}
|
||||
BIO_get_mem_ptr(btmp,&buf_mem);
|
||||
/* Mark the BIO read only then we can use its copy of the data
|
||||
* instead of making an extra copy.
|
||||
*/
|
||||
BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
|
||||
BIO_set_mem_eof_return(btmp, 0);
|
||||
os->data = (unsigned char *)buf_mem->data;
|
||||
os->length = buf_mem->length;
|
||||
#if 0
|
||||
ASN1_OCTET_STRING_set(os,
|
||||
(unsigned char *)buf_mem->data,buf_mem->length);
|
||||
#endif
|
||||
}
|
||||
if (pp != NULL) Free(pp);
|
||||
pp=NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user