Loading CHANGES +10 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,16 @@ Changes between 0.9.3a and 0.9.4 *) Add missing case to s3_clnt.c state machine -- one of the new SSL tests through a BIO pair triggered the default case, i.e. SSLerr(...,SSL_R_UNKNOWN_STATE). [Bodo Moeller] *) New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications can use the SSL library even if none of the specific BIOs is appropriate. [Bodo Moeller] *) Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value for the encoded length. [Jeon KyoungHo <khjeon@sds.samsung.co.kr>] Loading crypto/bio/bio.h +35 −1 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ extern "C" { #endif #include <stdio.h> #include <stdlib.h> #include <openssl/crypto.h> /* These are the 'types' of BIOs */ Loading Loading @@ -317,6 +318,15 @@ typedef struct bio_f_buffer_ctx_struct #define BIO_C_GET_SOCKS 134 #define BIO_C_SET_SOCKS 135 #define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ #define BIO_C_GET_WRITE_BUF_SIZE 137 #define BIO_C_MAKE_BIO_PAIR 138 #define BIO_C_DESTROY_BIO_PAIR 139 #define BIO_C_GET_WRITE_GUARANTEE 140 #define BIO_C_GET_READ_REQUEST 141 #define BIO_C_SHUTDOWN_WR 142 #define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,(char *)arg) #define BIO_get_app_data(s) BIO_get_ex_data(s,0) Loading Loading @@ -431,6 +441,9 @@ int BIO_read_filename(BIO *b,const char *name); #define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) #define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) #define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) /* ...pending macros have inappropriate return type */ size_t BIO_ctrl_pending(BIO *b); size_t BIO_ctrl_wpending(BIO *b); #define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) #define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0,(char *)cbp) #define BIO_set_info_callback(b,cb) (int)BIO_ctrl(b,BIO_CTRL_SET_CALLBACK,0,(char *)cb) Loading @@ -438,6 +451,19 @@ int BIO_read_filename(BIO *b,const char *name); /* For the BIO_f_buffer() type */ #define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) /* For BIO_s_bio() */ #define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) #define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) #define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) #define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) /* macros with inappropriate type -- but ...pending macros use int too: */ #define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) #define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) size_t BIO_ctrl_get_write_guarantee(BIO *b); size_t BIO_ctrl_get_read_request(BIO *b); #ifdef NO_STDIO #define NO_FP_API #endif Loading Loading @@ -473,7 +499,7 @@ int BIO_read(BIO *b, void *data, int len); int BIO_gets(BIO *bp,char *buf, int size); int BIO_write(BIO *b, const char *data, int len); int BIO_puts(BIO *bp,const char *buf); long BIO_ctrl(BIO *bp,int cmd,long larg,char *parg); long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg); char * BIO_ptr_ctrl(BIO *bp,int cmd,long larg); long BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg); BIO * BIO_push(BIO *b,BIO *append); Loading Loading @@ -538,6 +564,13 @@ BIO *BIO_new_fd(int fd, int close_flag); BIO *BIO_new_connect(char *host_port); BIO *BIO_new_accept(char *host_port); int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2); /* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. * Size 0 uses default value. */ void BIO_copy_next_retry(BIO *b); long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); Loading Loading @@ -579,6 +612,7 @@ int BIO_printf(BIO *bio, ...); #define BIO_R_ACCEPT_ERROR 100 #define BIO_R_BAD_FOPEN_MODE 101 #define BIO_R_BAD_HOSTNAME_LOOKUP 102 #define BIO_R_BROKEN_PIPE 124 #define BIO_R_CONNECT_ERROR 103 #define BIO_R_ERROR_SETTING_NBIO 104 #define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105 Loading crypto/bio/bio_err.c +1 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ static ERR_STRING_DATA BIO_str_reasons[]= {BIO_R_ACCEPT_ERROR ,"accept error"}, {BIO_R_BAD_FOPEN_MODE ,"bad fopen mode"}, {BIO_R_BAD_HOSTNAME_LOOKUP ,"bad hostname lookup"}, {BIO_R_BROKEN_PIPE ,"broken pipe"}, {BIO_R_CONNECT_ERROR ,"connect error"}, {BIO_R_ERROR_SETTING_NBIO ,"error setting nbio"}, {BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET,"error setting nbio on accepted socket"}, Loading crypto/bio/bio_lib.c +15 −1 Original line number Diff line number Diff line Loading @@ -290,7 +290,7 @@ char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) return(p); } long BIO_ctrl(BIO *b, int cmd, long larg, char *parg) long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) { long ret; long (*cb)(); Loading @@ -317,6 +317,20 @@ long BIO_ctrl(BIO *b, int cmd, long larg, char *parg) return(ret); } /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros * do; but those macros have inappropriate return type, and for interfacing * from other programming languages, C macros aren't much of a help anyway. */ size_t BIO_ctrl_pending(BIO *bio) { return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); } size_t BIO_ctrl_wpending(BIO *bio) { return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); } /* put the 'bio' on the end of b's list of operators */ BIO *BIO_push(BIO *b, BIO *bio) { Loading crypto/bio/bss_bio.c +326 −23 Original line number Diff line number Diff line /* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ /* *** Not yet finished (or even tested). *** */ /* Special method for a BIO where the other endpoint is also a BIO * of this kind, handled by the same thread. * of this kind, handled by the same thread (i.e. the "peer" is actually * ourselves, wearing a different hat). * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces * for which no specific BIO method is available. */ * for which no specific BIO method is available. * See ssl/ssltest.c for some hints on how this can be used. */ #include <assert.h> #include <stdlib.h> Loading @@ -19,7 +19,7 @@ static int bio_new(BIO *bio); static int bio_free(BIO *bio); static int bio_read(BIO *bio, char *buf, int size); static int bio_write(BIO *bio, char *buf, int num); static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr); static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); static int bio_puts(BIO *bio, char *str); static int bio_make_pair(BIO *bio1, BIO *bio2); Loading Loading @@ -74,6 +74,7 @@ static int bio_new(BIO *bio) b->size = 17*1024; /* enough for one TLS record (just a default) */ b->buf = NULL; bio->ptr = b; return 1; } Loading Loading @@ -103,19 +104,167 @@ static int bio_free(BIO *bio) static int bio_read(BIO *bio, char *buf, int size) static int bio_read(BIO *bio, char *buf, int size_) { size_t size = size_; size_t rest; struct bio_bio_st *b, *peer_b; BIO_clear_retry_flags(bio); if (!bio->init) return 0; b = bio->ptr; assert(b != NULL); assert(b->peer != NULL); peer_b = b->peer->ptr; assert(peer_b != NULL); assert(peer_b->buf != NULL); peer_b->request = 0; /* will be set in "retry_read" situation */ if (buf == NULL || size == 0) return 0; if (peer_b->len == 0) { if (peer_b->closed) return 0; /* writer has closed, and no data is left */ else { BIO_set_retry_read(bio); /* buffer is empty */ if (size <= peer_b->size) peer_b->request = size; else peer_b->request = peer_b->size; /* don't ask for more than * the peer can deliver * in one write */ return -1; } } /* we can read */ if (peer_b->len < size) size = peer_b->len; /* now read "size" bytes */ rest = size; assert(rest > 0); do /* one or two iterations */ { size_t chunk; assert(rest <= peer_b->len); if (peer_b->offset + rest <= peer_b->size) chunk = rest; else /* wrap around ring buffer */ chunk = peer_b->size - peer_b->offset; assert(peer_b->offset + chunk <= peer_b->size); memcpy(buf, peer_b->buf + peer_b->offset, chunk); peer_b->len -= chunk; if (peer_b->len) { peer_b->offset += chunk; assert(peer_b->offset <= peer_b->size); if (peer_b->offset == peer_b->size) peer_b->offset = 0; buf += chunk; } else { /* buffer now empty, no need to advance "buf" */ assert(chunk == rest); peer_b->offset = 0; } rest -= chunk; } while (rest); peer_b->request -= size; return size; } static int bio_write(BIO *bio, char *buf, int num_) { size_t num = num_; size_t rest; struct bio_bio_st *b; BIO_clear_retry_flags(bio); if (!bio->init || buf == NULL || num == 0) return 0; b = bio->ptr; assert(b != NULL); assert(b->peer != NULL); assert(b->buf != NULL); b->request = 0; if (b->closed) { /* XXX */ /* we already closed */ BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); return -1; } static int bio_write(BIO *bio, char *buf, int num) assert(b->len <= b->size); if (b->len == b->size) { /* XXX */ BIO_set_retry_write(bio); /* buffer is full */ return -1; } static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) /* we can write */ if (num > b->size - b->len) num = b->size - b->len; /* now write "num" bytes */ rest = num; assert(rest > 0); do /* one or two iterations */ { size_t write_offset; size_t chunk; assert(b->len + rest <= b->size); write_offset = b->offset + b->len; if (write_offset >= b->size) write_offset -= b->size; /* b->buf[write_offset] is the first byte we can write to. */ if (write_offset + rest <= b->size) chunk = rest; else /* wrap around ring buffer */ chunk = b->size - write_offset; memcpy(b->buf + write_offset, buf, chunk); b->len += chunk; assert(b->len <= b->size); rest -= chunk; buf += chunk; } while (rest); return num; } static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { long ret; struct bio_bio_st *b = bio->ptr; Loading @@ -124,13 +273,76 @@ static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) switch (cmd) { /* XXX Additional commands: */ /* - Set buffer size */ /* - make pair */ /* - destroy pair */ /* - get number of bytes that the next write will accept */ /* - get number of bytes requested by peer */ /* - send "close" */ /* specific CTRL codes */ case BIO_C_SET_WRITE_BUF_SIZE: if (b->peer) { BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); ret = 0; } else { size_t new_size = num; if (b->size != new_size) { if (b->buf) { Free(b->buf); b->buf = NULL; } b->size = new_size; } ret = 1; } break; case BIO_C_GET_WRITE_BUF_SIZE: num = (long) b->size; case BIO_C_MAKE_BIO_PAIR: { BIO *other_bio = ptr; if (bio_make_pair(bio, other_bio)) ret = 1; else ret = 0; } break; case BIO_C_DESTROY_BIO_PAIR: /* Effects both BIOs in the pair -- call just once! * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ bio_destroy_pair(bio); ret = 1; break; case BIO_C_GET_WRITE_GUARANTEE: /* How many bytes can the caller feed to the next write * withouth having to keep any? */ if (b->peer == NULL || b->closed) ret = 0; else ret = (long) b->size - b->len; break; case BIO_C_GET_READ_REQUEST: /* If the peer unsuccesfully tried to read, how many bytes * were requested? (As with BIO_CTRL_PENDING, that number * can usually be treated as boolean.) */ ret = (long) b->request; break; case BIO_C_SHUTDOWN_WR: /* similar to shutdown(..., SHUT_WR) */ b->closed = 1; ret = 1; break; /* standard CTRL codes follow */ case BIO_CTRL_RESET: if (b->buf != NULL) Loading Loading @@ -169,7 +381,20 @@ static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) break; case BIO_CTRL_DUP: /* XXX */ /* See BIO_dup_chain for circumstances we have to expect. */ { BIO *other_bio = ptr; struct bio_bio_st *other_b; assert(other_bio != NULL); other_b = other_bio->ptr; assert(other_b != NULL); assert(other_b->buf == NULL); /* other_bio is always fresh */ other_b->size = b->size; } ret = 1; break; Loading @@ -177,6 +402,22 @@ static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) ret = 1; break; case BIO_CTRL_EOF: { BIO *other_bio = ptr; if (other_bio) { struct bio_bio_st *other_b = other_bio->ptr; assert(other_b != NULL); ret = other_b->len == 0 && other_b->closed; } else ret = 1; } break; default: ret = 0; } Loading @@ -188,8 +429,6 @@ static int bio_puts(BIO *bio, char *str) return bio_write(bio, str, strlen(str)); } /* Until bio_make_pair is used, make a dummy function use it for -pedantic */ void dummy() { bio_make_pair(NULL,NULL); } static int bio_make_pair(BIO *bio1, BIO *bio2) { Loading Loading @@ -273,3 +512,67 @@ static void bio_destroy_pair(BIO *bio) } } } /* Exported convenience functions */ int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p, size_t writebuf2) { BIO *bio1 = NULL, *bio2 = NULL; long r; int ret = 0; bio1 = BIO_new(BIO_s_bio()); if (bio1 == NULL) goto err; bio2 = BIO_new(BIO_s_bio()); if (bio2 == NULL) goto err; if (writebuf1) { r = BIO_set_write_buf_size(bio1, writebuf1); if (!r) goto err; } if (writebuf2) { r = BIO_set_write_buf_size(bio2, writebuf2); if (!r) goto err; } r = BIO_make_bio_pair(bio1, bio2); if (!r) goto err; ret = 1; err: if (ret == 0) { if (bio1) { BIO_free(bio1); bio1 = NULL; } if (bio2) { BIO_free(bio2); bio2 = NULL; } } *bio1_p = bio1; *bio2_p = bio2; return ret; } size_t BIO_ctrl_get_write_guarantee(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); } size_t BIO_ctrl_read_request(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); } Loading
CHANGES +10 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,16 @@ Changes between 0.9.3a and 0.9.4 *) Add missing case to s3_clnt.c state machine -- one of the new SSL tests through a BIO pair triggered the default case, i.e. SSLerr(...,SSL_R_UNKNOWN_STATE). [Bodo Moeller] *) New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications can use the SSL library even if none of the specific BIOs is appropriate. [Bodo Moeller] *) Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value for the encoded length. [Jeon KyoungHo <khjeon@sds.samsung.co.kr>] Loading
crypto/bio/bio.h +35 −1 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ extern "C" { #endif #include <stdio.h> #include <stdlib.h> #include <openssl/crypto.h> /* These are the 'types' of BIOs */ Loading Loading @@ -317,6 +318,15 @@ typedef struct bio_f_buffer_ctx_struct #define BIO_C_GET_SOCKS 134 #define BIO_C_SET_SOCKS 135 #define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ #define BIO_C_GET_WRITE_BUF_SIZE 137 #define BIO_C_MAKE_BIO_PAIR 138 #define BIO_C_DESTROY_BIO_PAIR 139 #define BIO_C_GET_WRITE_GUARANTEE 140 #define BIO_C_GET_READ_REQUEST 141 #define BIO_C_SHUTDOWN_WR 142 #define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,(char *)arg) #define BIO_get_app_data(s) BIO_get_ex_data(s,0) Loading Loading @@ -431,6 +441,9 @@ int BIO_read_filename(BIO *b,const char *name); #define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) #define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) #define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) /* ...pending macros have inappropriate return type */ size_t BIO_ctrl_pending(BIO *b); size_t BIO_ctrl_wpending(BIO *b); #define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) #define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0,(char *)cbp) #define BIO_set_info_callback(b,cb) (int)BIO_ctrl(b,BIO_CTRL_SET_CALLBACK,0,(char *)cb) Loading @@ -438,6 +451,19 @@ int BIO_read_filename(BIO *b,const char *name); /* For the BIO_f_buffer() type */ #define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) /* For BIO_s_bio() */ #define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) #define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) #define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) #define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) /* macros with inappropriate type -- but ...pending macros use int too: */ #define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) #define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) size_t BIO_ctrl_get_write_guarantee(BIO *b); size_t BIO_ctrl_get_read_request(BIO *b); #ifdef NO_STDIO #define NO_FP_API #endif Loading Loading @@ -473,7 +499,7 @@ int BIO_read(BIO *b, void *data, int len); int BIO_gets(BIO *bp,char *buf, int size); int BIO_write(BIO *b, const char *data, int len); int BIO_puts(BIO *bp,const char *buf); long BIO_ctrl(BIO *bp,int cmd,long larg,char *parg); long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg); char * BIO_ptr_ctrl(BIO *bp,int cmd,long larg); long BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg); BIO * BIO_push(BIO *b,BIO *append); Loading Loading @@ -538,6 +564,13 @@ BIO *BIO_new_fd(int fd, int close_flag); BIO *BIO_new_connect(char *host_port); BIO *BIO_new_accept(char *host_port); int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2); /* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. * Size 0 uses default value. */ void BIO_copy_next_retry(BIO *b); long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); Loading Loading @@ -579,6 +612,7 @@ int BIO_printf(BIO *bio, ...); #define BIO_R_ACCEPT_ERROR 100 #define BIO_R_BAD_FOPEN_MODE 101 #define BIO_R_BAD_HOSTNAME_LOOKUP 102 #define BIO_R_BROKEN_PIPE 124 #define BIO_R_CONNECT_ERROR 103 #define BIO_R_ERROR_SETTING_NBIO 104 #define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105 Loading
crypto/bio/bio_err.c +1 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ static ERR_STRING_DATA BIO_str_reasons[]= {BIO_R_ACCEPT_ERROR ,"accept error"}, {BIO_R_BAD_FOPEN_MODE ,"bad fopen mode"}, {BIO_R_BAD_HOSTNAME_LOOKUP ,"bad hostname lookup"}, {BIO_R_BROKEN_PIPE ,"broken pipe"}, {BIO_R_CONNECT_ERROR ,"connect error"}, {BIO_R_ERROR_SETTING_NBIO ,"error setting nbio"}, {BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET,"error setting nbio on accepted socket"}, Loading
crypto/bio/bio_lib.c +15 −1 Original line number Diff line number Diff line Loading @@ -290,7 +290,7 @@ char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) return(p); } long BIO_ctrl(BIO *b, int cmd, long larg, char *parg) long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) { long ret; long (*cb)(); Loading @@ -317,6 +317,20 @@ long BIO_ctrl(BIO *b, int cmd, long larg, char *parg) return(ret); } /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros * do; but those macros have inappropriate return type, and for interfacing * from other programming languages, C macros aren't much of a help anyway. */ size_t BIO_ctrl_pending(BIO *bio) { return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); } size_t BIO_ctrl_wpending(BIO *bio) { return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); } /* put the 'bio' on the end of b's list of operators */ BIO *BIO_push(BIO *b, BIO *bio) { Loading
crypto/bio/bss_bio.c +326 −23 Original line number Diff line number Diff line /* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ /* *** Not yet finished (or even tested). *** */ /* Special method for a BIO where the other endpoint is also a BIO * of this kind, handled by the same thread. * of this kind, handled by the same thread (i.e. the "peer" is actually * ourselves, wearing a different hat). * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces * for which no specific BIO method is available. */ * for which no specific BIO method is available. * See ssl/ssltest.c for some hints on how this can be used. */ #include <assert.h> #include <stdlib.h> Loading @@ -19,7 +19,7 @@ static int bio_new(BIO *bio); static int bio_free(BIO *bio); static int bio_read(BIO *bio, char *buf, int size); static int bio_write(BIO *bio, char *buf, int num); static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr); static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); static int bio_puts(BIO *bio, char *str); static int bio_make_pair(BIO *bio1, BIO *bio2); Loading Loading @@ -74,6 +74,7 @@ static int bio_new(BIO *bio) b->size = 17*1024; /* enough for one TLS record (just a default) */ b->buf = NULL; bio->ptr = b; return 1; } Loading Loading @@ -103,19 +104,167 @@ static int bio_free(BIO *bio) static int bio_read(BIO *bio, char *buf, int size) static int bio_read(BIO *bio, char *buf, int size_) { size_t size = size_; size_t rest; struct bio_bio_st *b, *peer_b; BIO_clear_retry_flags(bio); if (!bio->init) return 0; b = bio->ptr; assert(b != NULL); assert(b->peer != NULL); peer_b = b->peer->ptr; assert(peer_b != NULL); assert(peer_b->buf != NULL); peer_b->request = 0; /* will be set in "retry_read" situation */ if (buf == NULL || size == 0) return 0; if (peer_b->len == 0) { if (peer_b->closed) return 0; /* writer has closed, and no data is left */ else { BIO_set_retry_read(bio); /* buffer is empty */ if (size <= peer_b->size) peer_b->request = size; else peer_b->request = peer_b->size; /* don't ask for more than * the peer can deliver * in one write */ return -1; } } /* we can read */ if (peer_b->len < size) size = peer_b->len; /* now read "size" bytes */ rest = size; assert(rest > 0); do /* one or two iterations */ { size_t chunk; assert(rest <= peer_b->len); if (peer_b->offset + rest <= peer_b->size) chunk = rest; else /* wrap around ring buffer */ chunk = peer_b->size - peer_b->offset; assert(peer_b->offset + chunk <= peer_b->size); memcpy(buf, peer_b->buf + peer_b->offset, chunk); peer_b->len -= chunk; if (peer_b->len) { peer_b->offset += chunk; assert(peer_b->offset <= peer_b->size); if (peer_b->offset == peer_b->size) peer_b->offset = 0; buf += chunk; } else { /* buffer now empty, no need to advance "buf" */ assert(chunk == rest); peer_b->offset = 0; } rest -= chunk; } while (rest); peer_b->request -= size; return size; } static int bio_write(BIO *bio, char *buf, int num_) { size_t num = num_; size_t rest; struct bio_bio_st *b; BIO_clear_retry_flags(bio); if (!bio->init || buf == NULL || num == 0) return 0; b = bio->ptr; assert(b != NULL); assert(b->peer != NULL); assert(b->buf != NULL); b->request = 0; if (b->closed) { /* XXX */ /* we already closed */ BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); return -1; } static int bio_write(BIO *bio, char *buf, int num) assert(b->len <= b->size); if (b->len == b->size) { /* XXX */ BIO_set_retry_write(bio); /* buffer is full */ return -1; } static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) /* we can write */ if (num > b->size - b->len) num = b->size - b->len; /* now write "num" bytes */ rest = num; assert(rest > 0); do /* one or two iterations */ { size_t write_offset; size_t chunk; assert(b->len + rest <= b->size); write_offset = b->offset + b->len; if (write_offset >= b->size) write_offset -= b->size; /* b->buf[write_offset] is the first byte we can write to. */ if (write_offset + rest <= b->size) chunk = rest; else /* wrap around ring buffer */ chunk = b->size - write_offset; memcpy(b->buf + write_offset, buf, chunk); b->len += chunk; assert(b->len <= b->size); rest -= chunk; buf += chunk; } while (rest); return num; } static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { long ret; struct bio_bio_st *b = bio->ptr; Loading @@ -124,13 +273,76 @@ static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) switch (cmd) { /* XXX Additional commands: */ /* - Set buffer size */ /* - make pair */ /* - destroy pair */ /* - get number of bytes that the next write will accept */ /* - get number of bytes requested by peer */ /* - send "close" */ /* specific CTRL codes */ case BIO_C_SET_WRITE_BUF_SIZE: if (b->peer) { BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); ret = 0; } else { size_t new_size = num; if (b->size != new_size) { if (b->buf) { Free(b->buf); b->buf = NULL; } b->size = new_size; } ret = 1; } break; case BIO_C_GET_WRITE_BUF_SIZE: num = (long) b->size; case BIO_C_MAKE_BIO_PAIR: { BIO *other_bio = ptr; if (bio_make_pair(bio, other_bio)) ret = 1; else ret = 0; } break; case BIO_C_DESTROY_BIO_PAIR: /* Effects both BIOs in the pair -- call just once! * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ bio_destroy_pair(bio); ret = 1; break; case BIO_C_GET_WRITE_GUARANTEE: /* How many bytes can the caller feed to the next write * withouth having to keep any? */ if (b->peer == NULL || b->closed) ret = 0; else ret = (long) b->size - b->len; break; case BIO_C_GET_READ_REQUEST: /* If the peer unsuccesfully tried to read, how many bytes * were requested? (As with BIO_CTRL_PENDING, that number * can usually be treated as boolean.) */ ret = (long) b->request; break; case BIO_C_SHUTDOWN_WR: /* similar to shutdown(..., SHUT_WR) */ b->closed = 1; ret = 1; break; /* standard CTRL codes follow */ case BIO_CTRL_RESET: if (b->buf != NULL) Loading Loading @@ -169,7 +381,20 @@ static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) break; case BIO_CTRL_DUP: /* XXX */ /* See BIO_dup_chain for circumstances we have to expect. */ { BIO *other_bio = ptr; struct bio_bio_st *other_b; assert(other_bio != NULL); other_b = other_bio->ptr; assert(other_b != NULL); assert(other_b->buf == NULL); /* other_bio is always fresh */ other_b->size = b->size; } ret = 1; break; Loading @@ -177,6 +402,22 @@ static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr) ret = 1; break; case BIO_CTRL_EOF: { BIO *other_bio = ptr; if (other_bio) { struct bio_bio_st *other_b = other_bio->ptr; assert(other_b != NULL); ret = other_b->len == 0 && other_b->closed; } else ret = 1; } break; default: ret = 0; } Loading @@ -188,8 +429,6 @@ static int bio_puts(BIO *bio, char *str) return bio_write(bio, str, strlen(str)); } /* Until bio_make_pair is used, make a dummy function use it for -pedantic */ void dummy() { bio_make_pair(NULL,NULL); } static int bio_make_pair(BIO *bio1, BIO *bio2) { Loading Loading @@ -273,3 +512,67 @@ static void bio_destroy_pair(BIO *bio) } } } /* Exported convenience functions */ int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p, size_t writebuf2) { BIO *bio1 = NULL, *bio2 = NULL; long r; int ret = 0; bio1 = BIO_new(BIO_s_bio()); if (bio1 == NULL) goto err; bio2 = BIO_new(BIO_s_bio()); if (bio2 == NULL) goto err; if (writebuf1) { r = BIO_set_write_buf_size(bio1, writebuf1); if (!r) goto err; } if (writebuf2) { r = BIO_set_write_buf_size(bio2, writebuf2); if (!r) goto err; } r = BIO_make_bio_pair(bio1, bio2); if (!r) goto err; ret = 1; err: if (ret == 0) { if (bio1) { BIO_free(bio1); bio1 = NULL; } if (bio2) { BIO_free(bio2); bio2 = NULL; } } *bio1_p = bio1; *bio2_p = bio2; return ret; } size_t BIO_ctrl_get_write_guarantee(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); } size_t BIO_ctrl_read_request(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); }