提交 8484721a 编写于 作者: D Dr. Stephen Henson

Allow memory bios to be read only and change PKCS#7 routines to use them.

上级 de1915e4
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册