diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/Makefile.ssl | 98 | ||||
-rw-r--r-- | ssl/bio_ssl.c | 432 | ||||
-rw-r--r-- | ssl/bio_ssl.orig.c | 440 | ||||
-rw-r--r-- | ssl/build | 6 | ||||
-rw-r--r-- | ssl/changes.ssl | 10 | ||||
-rw-r--r-- | ssl/f | 40 | ||||
-rw-r--r-- | ssl/readme | 277 | ||||
-rw-r--r-- | ssl/s23_clnt.c | 444 | ||||
-rw-r--r-- | ssl/s23_lib.c | 232 | ||||
-rw-r--r-- | ssl/s23_meth.c | 90 | ||||
-rw-r--r-- | ssl/s23_pkt.c | 120 | ||||
-rw-r--r-- | ssl/s23_srvr.c | 474 | ||||
-rw-r--r-- | ssl/s2_clnt.c | 982 | ||||
-rw-r--r-- | ssl/s2_enc.c | 187 | ||||
-rw-r--r-- | ssl/s2_lib.c | 455 | ||||
-rw-r--r-- | ssl/s2_meth.c | 88 | ||||
-rw-r--r-- | ssl/s2_pkt.c | 651 | ||||
-rw-r--r-- | ssl/s2_srvr.c | 983 | ||||
-rw-r--r-- | ssl/s3_both.c | 444 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 1642 | ||||
-rw-r--r-- | ssl/s3_enc.c | 481 | ||||
-rw-r--r-- | ssl/s3_lib.c | 915 | ||||
-rw-r--r-- | ssl/s3_meth.c | 88 | ||||
-rw-r--r-- | ssl/s3_pkt.c | 963 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 1629 | ||||
-rw-r--r-- | ssl/ssl.c | 162 | ||||
-rw-r--r-- | ssl/ssl.err | 272 | ||||
-rw-r--r-- | ssl/ssl.h | 1290 | ||||
-rw-r--r-- | ssl/ssl2.h | 263 | ||||
-rw-r--r-- | ssl/ssl23.h | 83 | ||||
-rw-r--r-- | ssl/ssl3.h | 417 | ||||
-rw-r--r-- | ssl/ssl_algs.c | 99 | ||||
-rw-r--r-- | ssl/ssl_asn1.c | 313 | ||||
-rw-r--r-- | ssl/ssl_cert.c | 326 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 721 | ||||
-rw-r--r-- | ssl/ssl_err.c | 350 | ||||
-rw-r--r-- | ssl/ssl_err2.c | 70 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 1433 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 520 | ||||
-rw-r--r-- | ssl/ssl_rsa.c | 840 | ||||
-rw-r--r-- | ssl/ssl_sess.c | 425 | ||||
-rw-r--r-- | ssl/ssl_stat.c | 457 | ||||
-rw-r--r-- | ssl/ssl_task.c | 359 | ||||
-rw-r--r-- | ssl/ssl_txt.c | 133 | ||||
-rw-r--r-- | ssl/ssltest.c | 635 | ||||
-rw-r--r-- | ssl/zz | 402 |
46 files changed, 21741 insertions, 0 deletions
diff --git a/ssl/Makefile.ssl b/ssl/Makefile.ssl new file mode 100644 index 0000000000..f6f40e44fc --- /dev/null +++ b/ssl/Makefile.ssl @@ -0,0 +1,98 @@ +# +# SSLeay/ssl/Makefile +# + +DIR= ssl +TOP= .. +CC= cc +INCLUDES= -I../crypto -I../include +CFLAG=-g +INSTALLTOP=/usr/local/ssl +MAKE= make -f Makefile.ssl +MAKEDEPEND= makedepend -f Makefile.ssl +MAKEFILE= Makefile.ssl +AR= ar r + +CFLAGS= $(INCLUDES) $(CFLAG) + +ERR=ssl +ERRC=ssl_err +GENERAL=Makefile README +TEST=ssltest.c +APPS= + +LIB=$(TOP)/libssl.a +LIBSRC= \ + s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_pkt.c s2_enc.c \ + s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_pkt.c s3_enc.c s3_both.c \ + s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ + ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ + ssl_ciph.c ssl_stat.c ssl_rsa.c \ + ssl_asn1.c ssl_txt.c ssl_algs.c \ + bio_ssl.c $(ERRC).c +LIBOBJ= \ + s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_pkt.o s2_enc.o \ + s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_pkt.o s3_enc.o s3_both.o \ + s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ + ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ + ssl_ciph.o ssl_stat.o ssl_rsa.o \ + ssl_asn1.o ssl_txt.o ssl_algs.o \ + bio_ssl.o $(ERRC).o + +SRC= $(LIBSRC) + +EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h +HEADER= $(EXHEADER) ssl_locl.h + +ALL= $(GENERAL) $(SRC) $(HEADER) + +top: + (cd ..; $(MAKE) DIRS=$(DIR) all) + +all: lib + +lib: $(LIBOBJ) + $(AR) $(LIB) $(LIBOBJ) + sh $(TOP)/util/ranlib.sh $(LIB) + @touch lib + +files: + perl $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO + +links: + /bin/rm -f Makefile + $(TOP)/util/point.sh Makefile.ssl Makefile ; + $(TOP)/util/mklink.sh ../include $(EXHEADER) + $(TOP)/util/mklink.sh ../test $(TEST) + $(TOP)/util/mklink.sh ../apps $(APPS) + +install: + @for i in $(EXHEADER) ; \ + do \ + (cp $$i $(INSTALLTOP)/include/$$i; \ + chmod 644 $(INSTALLTOP)/include/$$i ); \ + done; + +tags: + ctags $(SRC) + +tests: + +lint: + lint -DLINT $(INCLUDES) $(SRC)>fluff + +depend: + $(MAKEDEPEND) $(INCLUDES) $(PROGS) $(LIBSRC) + +dclean: + perl -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new + mv -f Makefile.new $(MAKEFILE) + +clean: + /bin/rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + +errors: + perl $(TOP)/util/err-ins.pl $(ERR).err $(ERR).h + perl ../crypto/err/err_genc.pl $(ERR).h $(ERRC).c + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c new file mode 100644 index 0000000000..6c0babaf30 --- /dev/null +++ b/ssl/bio_ssl.c @@ -0,0 +1,432 @@ +/* ssl/bio_ssl.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "bio.h" +#include "err.h" +#include "ssl.h" + +#ifndef NOPROTO +static int ssl_write(BIO *h,char *buf,int num); +static int ssl_read(BIO *h,char *buf,int size); +static int ssl_puts(BIO *h,char *str); +static long ssl_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int ssl_new(BIO *h); +static int ssl_free(BIO *data); +#else +static int ssl_write(); +static int ssl_read(); +static int ssl_puts(); +static long ssl_ctrl(); +static int ssl_new(); +static int ssl_free(); +#endif + +static BIO_METHOD methods_sslp= + { + BIO_TYPE_SSL,"ssl", + ssl_write, + ssl_read, + ssl_puts, + NULL, /* ssl_gets, */ + ssl_ctrl, + ssl_new, + ssl_free, + }; + +BIO_METHOD *BIO_f_ssl() + { + return(&methods_sslp); + } + +static int ssl_new(bi) +BIO *bi; + { + bi->init=0; + bi->ptr=NULL; /* The SSL structure */ + bi->flags=0; + return(1); + } + +static int ssl_free(a) +BIO *a; + { + if (a == NULL) return(0); + if (a->ptr != NULL) SSL_shutdown((SSL *)a->ptr); + if (a->shutdown) + { + if (a->init) SSL_free((SSL *)a->ptr); + a->init=0; + a->flags=0; + a->ptr=NULL; + } + return(1); + } + +static int ssl_read(b,out,outl) +BIO *b; +char *out; +int outl; + { + int ret=1; + int inflags,outflags; + SSL *ssl; + int retry_reason=0; + + if (out == NULL) return(0); + ssl=(SSL *)b->ptr; + + inflags=outflags=b->flags; + + outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY); + + if (!SSL_is_init_finished(ssl)) + { + ret=SSL_do_handshake(ssl); +#if 0 + if (ret > 0) + { + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + ret= -1; + goto end; + } +#endif + } + if (ret > 0) + ret=SSL_read(ssl,out,outl); + + switch (SSL_get_error(ssl,ret)) + { + case SSL_ERROR_NONE: + if (ret <= 0) break; + break; + case SSL_ERROR_WANT_READ: + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_WRITE: + outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + retry_reason=BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_CONNECT: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + retry_reason=BIO_RR_CONNECT; + break; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + case SSL_ERROR_ZERO_RETURN: + default: + break; + } + + b->retry_reason=retry_reason; + b->flags=outflags; + return(ret); + } + +static int ssl_write(b,out,outl) +BIO *b; +char *out; +int outl; + { + int ret; + int inflags,outflags,retry_reason=0; + SSL *ssl; + + if (out == NULL) return(0); + ssl=(SSL *)b->ptr; + + inflags=outflags=b->flags; + + outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY); + + ret=SSL_do_handshake(ssl); + if (ret > 0) + ret=SSL_write(ssl,out,outl); + + switch (SSL_get_error(ssl,ret)) + { + case SSL_ERROR_NONE: + if (ret <= 0) break; + break; + case SSL_ERROR_WANT_WRITE: + outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_READ: + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + retry_reason=BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_CONNECT: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + retry_reason=BIO_RR_CONNECT; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + default: + break; + } + + b->retry_reason=retry_reason; + b->flags=outflags; + return(ret); + } + +static long ssl_ctrl(b,cmd,num,ptr) +BIO *b; +int cmd; +long num; +char *ptr; + { + SSL **sslp,*ssl; + BIO *dbio,*bio; + long ret=1; + + ssl=(SSL *)b->ptr; + switch (cmd) + { + case BIO_CTRL_RESET: + SSL_shutdown(ssl); + + if (ssl->handshake_func == ssl->method->ssl_connect) + SSL_set_connect_state(ssl); + else if (ssl->handshake_func == ssl->method->ssl_accept) + SSL_set_accept_state(ssl); + + SSL_clear(ssl); + + if (b->next_bio != NULL) + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + else if (ssl->rbio != NULL) + ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); + else + ret=1; + break; + case BIO_CTRL_EOF: + case BIO_CTRL_INFO: + ret=0; + break; + case BIO_C_SSL_MODE: + if (num) /* client mode */ + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + break; + case BIO_C_SET_SSL: + ssl_free(b); + b->shutdown=(int)num; + b->ptr=ptr; + ssl=(SSL *)ptr; + bio=SSL_get_rbio(ssl); + if (bio != NULL) + { + if (b->next_bio != NULL) + BIO_push(bio,b->next_bio); + b->next_bio=bio; + } + b->init=1; + break; + case BIO_C_GET_SSL: + if (ptr != NULL) + { + sslp=(SSL **)ptr; + *sslp=ssl; + } + break; + case BIO_CTRL_GET_CLOSE: + ret=b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown=(int)num; + break; + case BIO_CTRL_WPENDING: + ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); + break; + case BIO_CTRL_PENDING: + ret=SSL_pending(ssl); + if (ret == 0) + ret=BIO_pending(ssl->rbio); + break; + case BIO_CTRL_FLUSH: + BIO_clear_retry_flags(b); + ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_PUSH: + if (b->next_bio != NULL) + { + SSL_set_bio(ssl,b->next_bio,b->next_bio); + b->next_bio->references++; + } + break; + case BIO_CTRL_POP: + /* ugly bit of a hack */ + if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */ + { + BIO_free_all(ssl->wbio); + } + ssl->wbio=NULL; + ssl->rbio=NULL; + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + + b->retry_reason=0; + ret=(int)SSL_do_handshake(ssl); + + switch (SSL_get_error(ssl,(int)ret)) + { + case SSL_ERROR_WANT_READ: + BIO_set_flags(b, + BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_flags(b, + BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_flags(b, + BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + b->retry_reason=b->next_bio->retry_reason; + break; + default: + break; + } + break; + case BIO_CTRL_DUP: + dbio=(BIO *)ptr; + if (dbio->ptr != NULL) + SSL_free((SSL *)dbio->ptr); + dbio->ptr=(char *)SSL_dup(ssl); + ret=(dbio->ptr != NULL); + break; + default: + return(0); + break; + } + return(ret); + } + +static int ssl_puts(bp,str) +BIO *bp; +char *str; + { + int n,ret; + + n=strlen(str); + ret=BIO_write(bp,str,n); + return(ret); + } + +BIO *BIO_new_ssl(ctx,client) +SSL_CTX *ctx; +int client; + { + BIO *ret; + SSL *ssl; + + if ((ret=BIO_new(BIO_f_ssl())) == NULL) + return(NULL); + if ((ssl=SSL_new(ctx)) == NULL) + { + BIO_free(ret); + return(NULL); + } + if (client) + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + + BIO_set_ssl(ret,ssl,BIO_CLOSE); + return(ret); + } + +int BIO_ssl_copy_session_id(t,f) +BIO *t,*f; + { + t=BIO_find_type(t,BIO_TYPE_SSL); + f=BIO_find_type(f,BIO_TYPE_SSL); + if ((t == NULL) || (f == NULL)) + return(0); + if ((t->ptr == NULL) || (f->ptr == NULL)) + return(0); + SSL_copy_session_id((SSL *)t->ptr,(SSL *)f->ptr); + return(1); + } + +void BIO_ssl_shutdown(b) +BIO *b; + { + SSL *s; + + while (b != NULL) + { + if (b->method->type == BIO_TYPE_SSL) + { + s=(SSL *)b->ptr; + SSL_shutdown(s); + break; + } + b=b->next_bio; + } + } diff --git a/ssl/bio_ssl.orig.c b/ssl/bio_ssl.orig.c new file mode 100644 index 0000000000..25147d12e7 --- /dev/null +++ b/ssl/bio_ssl.orig.c @@ -0,0 +1,440 @@ +/* ssl/bio_ssl.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "bio.h" +#include "err.h" +#include "ssl.h" + +#ifndef NOPROTO +static int ssl_write(BIO *h,char *buf,int num); +static int ssl_read(BIO *h,char *buf,int size); +static int ssl_puts(BIO *h,char *str); +static long ssl_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int ssl_new(BIO *h); +static int ssl_free(BIO *data); +#else +static int ssl_write(); +static int ssl_read(); +static int ssl_puts(); +static long ssl_ctrl(); +static int ssl_new(); +static int ssl_free(); +#endif + +static BIO_METHOD methods_sslp= + { + BIO_TYPE_SSL,"ssl", + ssl_write, + ssl_read, + ssl_puts, + NULL, /* ssl_gets, */ + ssl_ctrl, + ssl_new, + ssl_free, + }; + +BIO_METHOD *BIO_f_ssl() + { + return(&methods_sslp); + } + +static int ssl_new(bi) +BIO *bi; + { + bi->init=0; + bi->ptr=NULL; /* The SSL structure */ + bi->flags=0; + return(1); + } + +static int ssl_free(a) +BIO *a; + { + if (a == NULL) return(0); + if (a->ptr != NULL) SSL_shutdown((SSL *)a->ptr); + if (a->shutdown) + { + if (a->init) SSL_free((SSL *)a->ptr); + a->init=0; + a->flags=0; + a->ptr=NULL; + } + return(1); + } + +static int ssl_read(b,out,outl) +BIO *b; +char *out; +int outl; + { + int ret=1,dr,dw; + int inflags,outflags; + SSL *ssl; + int retry_reason=0; + + if (out == NULL) return(0); + ssl=(SSL *)b->ptr; + + inflags=outflags=b->flags; + + dr=inflags&BIO_FLAGS_PROTOCOL_DELAYED_READ; + dw=inflags&BIO_FLAGS_PROTOCOL_DELAYED_WRITE; + + outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_WRITE| + BIO_FLAGS_PROTOCOL_DELAYED_READ); + + if (!SSL_is_init_finished(ssl)) + { + ret=SSL_do_handshake(ssl); +#if 0 + if (ret > 0) + { + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_READ|dw); + ret= -1; + goto end; + } +#endif + } + if (ret > 0) + ret=SSL_read(ssl,out,outl); + + switch (SSL_get_error(ssl,ret)) + { + case SSL_ERROR_NONE: + if (ret <= 0) break; + if (dw) + outflags|=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_READ: + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_READ|dw); + break; + case SSL_ERROR_WANT_WRITE: + outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_READ|dw); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_READ|dw); + retry_reason=BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_CONNECT: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_READ|dw); + retry_reason=BIO_RR_CONNECT; + break; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + case SSL_ERROR_ZERO_RETURN: + default: + break; + } + + b->retry_reason=retry_reason; + b->flags=outflags; + return(ret); + } + +static int ssl_write(b,out,outl) +BIO *b; +char *out; +int outl; + { + int ret,dr,dw; + int inflags,outflags,retry_reason=0; + SSL *ssl; + + if (out == NULL) return(0); + ssl=(SSL *)b->ptr; + + inflags=outflags=b->flags; + + dr=inflags&BIO_FLAGS_PROTOCOL_DELAYED_READ; + dw=inflags&BIO_FLAGS_PROTOCOL_DELAYED_WRITE; + + outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_WRITE| + BIO_FLAGS_PROTOCOL_DELAYED_READ); + + ret=SSL_do_handshake(ssl); + if (ret > 0) + ret=SSL_write(ssl,out,outl); + + switch (SSL_get_error(ssl,ret)) + { + case SSL_ERROR_NONE: + if (ret <= 0) break; + if (dr) + outflags|=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_WRITE: + outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_WRITE|dr); + break; + case SSL_ERROR_WANT_READ: + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_WRITE|dr); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_WRITE|dr); + retry_reason=BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_CONNECT: + outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY| + BIO_FLAGS_PROTOCOL_DELAYED_READ|dw); + retry_reason=BIO_RR_CONNECT; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + default: + break; + } + + b->retry_reason=retry_reason; + b->flags=outflags; + return(ret); + } + +static long ssl_ctrl(b,cmd,num,ptr) +BIO *b; +int cmd; +long num; +char *ptr; + { + SSL **sslp,*ssl; + BIO *dbio,*bio; + long ret=1; + + ssl=(SSL *)b->ptr; + switch (cmd) + { + case BIO_CTRL_RESET: + SSL_shutdown(ssl); + + if (ssl->handshake_func == ssl->method->ssl_connect) + SSL_set_connect_state(ssl); + else if (ssl->handshake_func == ssl->method->ssl_accept) + SSL_set_accept_state(ssl); + + SSL_clear(ssl); + + if (b->next_bio != NULL) + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + else if (ssl->rbio != NULL) + ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); + else + ret=1; + break; + case BIO_CTRL_EOF: + case BIO_CTRL_INFO: + ret=0; + break; + case BIO_C_SSL_MODE: + if (num) /* client mode */ + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + break; + case BIO_C_SET_SSL: + ssl_free(b); + b->shutdown=(int)num; + b->ptr=ptr; + ssl=(SSL *)ptr; + bio=SSL_get_rbio(ssl); + if (bio != NULL) + { + if (b->next_bio != NULL) + BIO_push(bio,b->next_bio); + b->next_bio=bio; + } + b->init=1; + break; + case BIO_C_GET_SSL: + if (ptr != NULL) + { + sslp=(SSL **)ptr; + *sslp=ssl; + } + break; + case BIO_CTRL_GET_CLOSE: + ret=b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown=(int)num; + break; + case BIO_CTRL_WPENDING: + ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); + break; + case BIO_CTRL_PENDING: + ret=SSL_pending(ssl); + if (ret == 0) + ret=BIO_pending(ssl->rbio); + break; + case BIO_CTRL_FLUSH: + BIO_clear_retry_flags(b); + ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_PUSH: + if (b->next_bio != NULL) + { + SSL_set_bio(ssl,b->next_bio,b->next_bio); + b->next_bio->references++; + } + break; + case BIO_CTRL_POP: + /* ugly bit of a hack */ + if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */ + { + BIO_free_all(ssl->wbio); + } + ssl->wbio=NULL; + ssl->rbio=NULL; + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + + b->retry_reason=0; + ret=(int)SSL_do_handshake(ssl); + + switch (SSL_get_error(ssl,ret)) + { + case SSL_ERROR_WANT_READ: + BIO_set_flags(b, + BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_flags(b, + BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_flags(b, + BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + b->retry_reason=b->next_bio->retry_reason; + break; + default: + break; + } + break; + case BIO_CTRL_DUP: + dbio=(BIO *)ptr; + if (dbio->ptr != NULL) + SSL_free((SSL *)dbio->ptr); + dbio->ptr=(char *)SSL_dup(ssl); + ret=(dbio->ptr != NULL); + break; + default: + return(0); + break; + } + return(ret); + } + +static int ssl_puts(bp,str) +BIO *bp; +char *str; + { + int n,ret; + + n=strlen(str); + ret=BIO_write(bp,str,n); + return(ret); + } + +BIO *BIO_new_ssl(ctx,client) +SSL_CTX *ctx; +int client; + { + BIO *ret; + SSL *ssl; + + if ((ret=BIO_new(BIO_f_ssl())) == NULL) + return(NULL); + if ((ssl=SSL_new(ctx)) == NULL) + { + BIO_free(ret); + return(NULL); + } + if (client) + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + + BIO_set_ssl(ret,ssl,BIO_CLOSE); + return(ret); + } + +int BIO_ssl_copy_session_id(t,f) +BIO *t,*f; + { + t=BIO_find_type(t,BIO_TYPE_SSL); + f=BIO_find_type(f,BIO_TYPE_SSL); + if ((t == NULL) || (f == NULL)) + return(0); + if ((t->ptr == NULL) || (f->ptr == NULL)) + return(0); + SSL_copy_session_id((SSL *)t->ptr,(SSL *)f->ptr); + return(1); + } + + diff --git a/ssl/build b/ssl/build new file mode 100644 index 0000000000..d3308356b3 --- /dev/null +++ b/ssl/build @@ -0,0 +1,6 @@ +#!/bin/sh +for i in BUILD_SSLV23 BUILD_SSLV2 BUILD_SSLV3 BUILD_SSL_COMMON BUILD_SSL_BIO BUILD_SSL_OPTIONAL +do +time gcc -D$i -o $i.o -c -I. -I../include -O3 -fomit-frame-pointer ssl.c +done + diff --git a/ssl/changes.ssl b/ssl/changes.ssl new file mode 100644 index 0000000000..ab94b95aa0 --- /dev/null +++ b/ssl/changes.ssl @@ -0,0 +1,10 @@ + +Must do a +SSL_init_eay_ciphers(); +before calls to SSL_CTX_new() + +SSL_CTX *SSL_CTX_new(void ) -> SSL_CTX *SSL_CTX_new(SSL_METHOD *meth); + +SSL_CTX_set_cert_verify_cb -> the callback is now +int callback(char *arg,SSL *s,X509 *xs,STACK *cert_chain); +where the 'cert_chain' has been added. @@ -0,0 +1,40 @@ +/* return the actual cipher being used */ +char *SSL_CIPHER_get_name(c) +SSL_CIPHER *c; + { + if (c != NULL) + return(c->name); + return("UNKNOWN"); + } + +/* number of bits for symetric cipher */ +int SSL_CIPHER_get_bits(c,alg_bits) +SSL_CIPHER *c; +int *alg_bits; + { + int ret=0,a=0; + EVP_CIPHER *enc; + + if (c != NULL) + { + if (!ssl_cipher_get_evp(c,&enc,NULL)) + return(0); + + a=EVP_CIPHER_key_length(enc)*8; + + if (s->session->cipher->algorithms & SSL_EXP) + { + if (c->algorithm2 & SSL2_CF_8_BYTE_ENC) + ret=64; + else + ret=40; + } + else + ret=a; + } + + if (alg_bits != NULL) *alg_bits=a; + + return(ret); + } + diff --git a/ssl/readme b/ssl/readme new file mode 100644 index 0000000000..ca174848a1 --- /dev/null +++ b/ssl/readme @@ -0,0 +1,277 @@ +22 Jun 1996 +This file belongs in ../apps, but I'll leave it here because it deals +with SSL :-) It is rather dated but it gives you an idea of how +things work. +=== + +17 Jul 1995 +I have been changing things quite a bit and have not fully updated +this file, so take what you read with a grain of salt +eric +=== +The s_client and s_server programs can be used to test SSL capable +IP/port addresses and the verification of the X509 certificates in use +by these services. I strongly advise having a look at the code to get +an idea of how to use the authentication under SSLeay. Any feedback +on changes and improvements would be greatly accepted. + +This file will probably be gibberish unless you have read +rfc1421, rfc1422, rfc1423 and rfc1424 which describe PEM +authentication. + +A Brief outline (and examples) how to use them to do so. + +NOTE: +The environment variable SSL_CIPER is used to specify the prefered +cipher to use, play around with setting it's value to combinations of +RC4-MD5, EXP-RC4-MD5, CBC-DES-MD5, CBC3-DES-MD5, CFB-DES-NULL +in a : separated list. + +This directory contains 3 X509 certificates which can be used by these programs. +client.pem: a file containing a certificate and private key to be used + by s_client. +server.pem :a file containing a certificate and private key to be used + by s_server. +eay1024.pem:the certificate used to sign client.pem and server.pem. + This would be your CA's certificate. There is also a link + from the file a8556381.0 to eay1024.PEM. The value a8556381 + is returned by 'x509 -hash -noout <eay1024.pem' and is the + value used by X509 verification routines to 'find' this + certificte when search a directory for it. + [the above is not true any more, the CA cert is + ../certs/testca.pem which is signed by ../certs/mincomca.pem] + +When testing the s_server, you may get +bind: Address already in use +errors. These indicate the port is still being held by the unix +kernel and you are going to have to wait for it to let go of it. If +this is the case, remember to use the port commands on the s_server and +s_client to talk on an alternative port. + +===== +s_client. +This program can be used to connect to any IP/hostname:port that is +talking SSL. Once connected, it will attempt to authenticate the +certificate it was passed and if everything works as expected, a 2 +directional channel will be open. Any text typed will be sent to the +other end. type Q<cr> to exit. Flags are as follows. +-host arg : Arg is the host or IP address to connect to. +-port arg : Arg is the port to connect to (https is 443). +-verify arg : Turn on authentication of the server certificate. + : Arg specifies the 'depth', this will covered below. +-cert arg : The optional certificate to use. This certificate + : will be returned to the server if the server + : requests it for client authentication. +-key arg : The private key that matches the certificate + : specified by the -cert option. If this is not + : specified (but -cert is), the -cert file will be + : searched for the Private key. Both files are + : assumed to be in PEM format. +-CApath arg : When to look for certificates when 'verifying' the + : certificate from the server. +-CAfile arg : A file containing certificates to be used for + : 'verifying' the server certificate. +-reconnect : Once a connection has been made, drop it and + : reconnect with same session-id. This is for testing :-). + +The '-verify n' parameter specifies not only to verify the servers +certificate but to also only take notice of 'n' levels. The best way +to explain is to show via examples. +Given +s_server -cert server.PEM is running. + +s_client + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify error:num=1:unable to get issuer certificate + verify return:1 + CIPHER is CBC-DES-MD5 +What has happened is that the 'SSLeay demo server' certificate's +issuer ('CA') could not be found but because verify is not on, we +don't care and the connection has been made anyway. It is now 'up' +using CBC-DES-MD5 mode. This is an unauthenticate secure channel. +You may not be talking to the right person but the data going to them +is encrypted. + +s_client -verify 0 + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify error:num=1:unable to get issuer certificate + verify return:1 + CIPHER is CBC-DES-MD5 +We are 'verifying' but only to depth 0, so since the 'SSLeay demo server' +certificate passed the date and checksum, we are happy to proceed. + +s_client -verify 1 + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify error:num=1:unable to get issuer certificate + verify return:0 + ERROR + verify error:unable to get issuer certificate +In this case we failed to make the connection because we could not +authenticate the certificate because we could not find the +'CA' certificate. + +s_client -verify 1 -CAfile eay1024.PEM + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + CIPHER is CBC-DES-MD5 +We loaded the certificates from the file eay1024.PEM. Everything +checked out and so we made the connection. + +s_client -verify 1 -CApath . + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + CIPHER is CBC-DES-MD5 +We looked in out local directory for issuer certificates and 'found' +a8556381.0 and so everything is ok. + +It is worth noting that 'CA' is a self certified certificate. If you +are passed one of these, it will fail to 'verify' at depth 0 because +we need to lookup the certifier of a certificate from some information +that we trust and keep locally. + +SSL_CIPHER=CBC3-DES-MD5:RC4-MD5 +export SSL_CIPHER +s_client -verify 10 -CApath . -reconnect + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + drop the connection and reconnect with the same session id + CIPHER is CBC3-DES-MD5 +This has done a full connection and then re-estabished it with the +same session id but a new socket. No RSA stuff occures on the second +connection. Note that we said we would prefer to use CBC3-DES-MD5 +encryption and so, since the server supports it, we are. + +===== +s_server +This program accepts SSL connections on a specified port +Once connected, it will estabish an SSL connection and optionaly +attempt to authenticate the client. A 2 directional channel will be +open. Any text typed will be sent to the other end. Type Q<cr> to exit. +Flags are as follows. +-port arg : Arg is the port to listen on. +-verify arg : Turn on authentication of the client if they have a + : certificate. Arg specifies the 'depth'. +-Verify arg : Turn on authentication of the client. If they don't + : have a valid certificate, drop the connection. +-cert arg : The certificate to use. This certificate + : will be passed to the client. If it is not + : specified, it will default to server.PEM +-key arg : The private key that matches the certificate + : specified by the -cert option. If this is not + : specified (but -cert is), the -cert file will be + : searched for the Private key. Both files are + : assumed to be in PEM format. Default is server.PEM +-CApath arg : When to look for certificates when 'verifying' the + : certificate from the client. +-CAfile arg : A file containing certificates to be used for + : 'verifying' the client certificate. + +For the following 'demo' I will specify the s_server command and +the s_client command and then list the output from the s_server. +s_server +s_client + CONNECTED + CIPHER is CBC-DES-MD5 +Everything up and running + +s_server -verify 0 +s_client + CONNECTED + CIPHER is CBC-DES-MD5 +Ok since no certificate was returned and we don't care. + +s_server -verify 0 +./s_client -cert client.PEM + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client + issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify error:num=1:unable to get issuer certificate + verify return:1 + CIPHER is CBC-DES-MD5 +Ok since we were only verifying to level 0 + +s_server -verify 4 +s_client -cert client.PEM + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client + issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify error:num=1:unable to get issuer certificate + verify return:0 + ERROR + verify error:unable to get issuer certificate +Bad because we could not authenticate the returned certificate. + +s_server -verify 4 -CApath . +s_client -cert client.PEM + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + CIPHER is CBC-DES-MD5 +Ok because we could authenticate the returned certificate :-). + +s_server -Verify 0 -CApath . +s_client + CONNECTED + ERROR + SSL error:function is:REQUEST_CERTIFICATE + :error is :client end did not return a certificate +Error because no certificate returned. + +s_server -Verify 4 -CApath . +s_client -cert client.PEM + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + CIPHER is CBC-DES-MD5 +Full authentication of the client. + +So in summary to do full authentication of both ends +s_server -Verify 9 -CApath . +s_client -cert client.PEM -CApath . -verify 9 +From the server side + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + CIPHER is CBC-DES-MD5 +From the client side + CONNECTED + depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server + verify return:1 + depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA + verify return:1 + CIPHER is CBC-DES-MD5 + +For general probing of the 'internet https' servers for the +distribution area, run +s_client -host www.netscape.com -port 443 -verify 4 -CApath ../rsa/hash +Then enter +GET / +and you should be talking to the https server on that host. + +www.rsa.com was refusing to respond to connections on 443 when I was +testing. + +have fun :-). + +eric diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c new file mode 100644 index 0000000000..57d3623f3f --- /dev/null +++ b/ssl/s23_clnt.c @@ -0,0 +1,444 @@ +/* ssl/s23_clnt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "buffer.h" +#include "rand.h" +#include "objects.h" +#include "evp.h" +#include "ssl_locl.h" + +#define BREAK break + +#ifndef NOPROTO +static int ssl23_client_hello(SSL *s); +static int ssl23_get_server_hello(SSL *s); +#else +static int ssl23_client_hello(); +static int ssl23_get_server_hello(); +#endif + +static SSL_METHOD *ssl23_get_client_method(ver) +int ver; + { + if (ver == 2) + return(SSLv2_client_method()); + else if (ver == 3) + return(SSLv3_client_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv23_client_method() + { + static int init=1; + static SSL_METHOD SSLv23_client_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv23_client_data, + (char *)sslv23_base_method(),sizeof(SSL_METHOD)); + SSLv23_client_data.ssl_connect=ssl23_connect; + SSLv23_client_data.get_ssl_method=ssl23_get_client_method; + } + return(&SSLv23_client_data); + } + +int ssl23_connect(s) +SSL *s; + { + BUF_MEM *buf; + unsigned long Time=time(NULL); + void (*cb)()=NULL; + int ret= -1; + int new_state,state; + + RAND_seed((unsigned char *)&Time,sizeof(Time)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + + for (;;) + { + state=s->state; + + switch(s->state) + { + case SSL_ST_BEFORE: + case SSL_ST_CONNECT: + case SSL_ST_BEFORE|SSL_ST_CONNECT: + case SSL_ST_OK|SSL_ST_CONNECT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=3; + s->type=SSL_ST_CONNECT; + + if (s->init_buf == NULL) + { + if ((buf=BUF_MEM_new()) == NULL) + { + ret= -1; + goto end; + } + if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) + { + ret= -1; + goto end; + } + s->init_buf=buf; + } + + if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } + + ssl3_init_finished_mac(s); + + s->state=SSL23_ST_CW_CLNT_HELLO_A; + s->ctx->sess_connect++; + s->init_num=0; + break; + + case SSL23_ST_CW_CLNT_HELLO_A: + case SSL23_ST_CW_CLNT_HELLO_B: + + s->shutdown=0; + ret=ssl23_client_hello(s); + if (ret <= 0) goto end; + s->state=SSL23_ST_CR_SRVR_HELLO_A; + s->init_num=0; + + break; + + case SSL23_ST_CR_SRVR_HELLO_A: + case SSL23_ST_CR_SRVR_HELLO_B: + ret=ssl23_get_server_hello(s); + if (ret >= 0) cb=NULL; + goto end; + break; + + default: + SSLerr(SSL_F_SSL23_CONNECT,SSL_R_UNKNOWN_STATE); + ret= -1; + goto end; + /* break; */ + } + + if (s->debug) BIO_flush(s->wbio); + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_CONNECT_LOOP,1); + s->state=new_state; + } + } +end: + s->in_handshake--; + if (cb != NULL) + cb(s,SSL_CB_CONNECT_EXIT,ret); + return(ret); + } + + +static int ssl23_client_hello(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p,*d; + int i,ch_len; + + buf=(unsigned char *)s->init_buf->data; + if (s->state == SSL23_ST_CW_CLNT_HELLO_A) + { +#if 0 + /* don't reuse session-id's */ + if (!ssl_get_new_session(s,0)) + { + return(-1); + } +#endif + + p=s->s3->client_random; + RAND_bytes(p,SSL3_RANDOM_SIZE); + + /* Do the message type and length last */ + d= &(buf[2]); + p=d+9; + + *(d++)=SSL2_MT_CLIENT_HELLO; + *(d++)=SSL3_VERSION_MAJOR; + *(d++)=SSL3_VERSION_MINOR; + + /* Ciphers supported */ + i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p); + if (i == 0) + { + /* no ciphers */ + SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); + return(-1); + } + s2n(i,d); + p+=i; + + /* put in the session-id, zero since there is no + * reuse. */ +#if 0 + s->session->session_id_length=0; +#endif + s2n(0,d); + + if (s->ctx->options & SSL_OP_NETSCAPE_CHALLENGE_BUG) + ch_len=SSL2_CHALLENGE_LENGTH; + else + ch_len=SSL2_MAX_CHALLENGE_LENGTH; + + /* write out sslv2 challenge */ + if (SSL3_RANDOM_SIZE < ch_len) + i=SSL3_RANDOM_SIZE; + else + i=ch_len; + s2n(i,d); + memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE); + RAND_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i); + memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i); + p+=i; + + i= p- &(buf[2]); + buf[0]=((i>>8)&0xff)|0x80; + buf[1]=(i&0xff); + + s->state=SSL23_ST_CW_CLNT_HELLO_B; + /* number of bytes to write */ + s->init_num=i+2; + s->init_off=0; + + ssl3_finish_mac(s,&(buf[2]),i); + } + + /* SSL3_ST_CW_CLNT_HELLO_B */ + return(ssl23_write_bytes(s)); + } + +static int ssl23_get_server_hello(s) +SSL *s; + { + char buf[8]; + unsigned char *p; + int i,ch_len; + int n; + BIO *bbio; + + n=ssl23_read_bytes(s,7); + + if (n != 7) return(n); + p=s->packet; + + memcpy(buf,p,n); + + if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) && + (p[5] == 0x00) && (p[6] == 0x02)) + { + /* we are talking sslv2 */ + /* we need to clean up the SSLv3 setup and put in the + * sslv2 stuff. */ + + if (s->s2 == NULL) + { + if (!ssl2_new(s)) + goto err; + } + else + ssl2_clear(s); + + if (s->ctx->options & SSL_OP_NETSCAPE_CHALLENGE_BUG) + ch_len=SSL2_CHALLENGE_LENGTH; + else + ch_len=SSL2_MAX_CHALLENGE_LENGTH; + + /* write out sslv2 challenge */ + i=(SSL3_RANDOM_SIZE < ch_len) + ?SSL3_RANDOM_SIZE:ch_len; + s->s2->challenge_length=i; + memcpy(s->s2->challenge, + &(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i); + + if (s->s3 != NULL) ssl3_free(s); + + if (!BUF_MEM_grow(s->init_buf, + SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) + { + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB); + goto err; + } + + s->state=SSL2_ST_GET_SERVER_HELLO_A; + s->s2->ssl2_rollback=1; + + /* setup the 5 bytes we have read so we get them from + * the sslv2 buffer */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + s->packet= &(s->s2->rbuf[0]); + memcpy(s->packet,buf,n); + s->s2->rbuf_left=n; + s->s2->rbuf_offs=0; + + /* we have already written one */ + s->s2->write_sequence=1; + + s->method=SSLv2_client_method(); + s->handshake_func=s->method->ssl_connect; + } + else if ((p[0] == SSL3_RT_HANDSHAKE) && + (p[1] == SSL3_VERSION_MAJOR) && + (p[2] == SSL3_VERSION_MINOR) && + (p[5] == SSL3_MT_SERVER_HELLO)) + { + /* we have sslv3 */ + + if (s->bbio == NULL) + { + bbio=BIO_new(BIO_f_buffer()); + if (bbio == NULL) + { + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB); + goto err; + } + s->bbio=bbio; + } + else + bbio=s->bbio; + + BIO_reset(bbio); + if (!BIO_set_write_buffer_size(bbio,16*1024)) + { + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB); + goto err; + } + + /* start the buffering */ + s->wbio=BIO_push(s->bbio,s->wbio); + + /* we are in this state */ + s->state=SSL3_ST_CR_SRVR_HELLO_A; + + /* put the 5 bytes we have read into the input buffer + * for SSLv3 */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + s->packet= &(s->s3->rbuf.buf[0]); + memcpy(s->packet,buf,n); + s->s3->rbuf.left=n; + s->s3->rbuf.offset=0; + + s->method=SSLv3_client_method(); + s->handshake_func=s->method->ssl_connect; + } + else if ((p[0] == SSL3_RT_ALERT) && + (p[1] == SSL3_VERSION_MAJOR) && + (p[2] == SSL3_VERSION_MINOR) && + (p[3] == 0) && + (p[4] == 2)) + { + void (*cb)()=NULL; + int j; + + /* An alert */ + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + i=p[5]; + if (cb != NULL) + { + j=(i<<8)|p[6]; + cb(s,SSL_CB_READ_ALERT,j); + } + + s->rwstate=SSL_NOTHING; + SSLerr(SSL_F_SSL3_READ_BYTES,1000+p[6]); + goto err; + } + else + { + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + s->init_num=0; + + /* Since, if we are sending a ssl23 client hello, we are not + * reusing a session-id */ + if (!ssl_get_new_session(s,0)) + goto err; + + s->first_packet=1; + return(SSL_connect(s)); +err: + return(-1); + } + diff --git a/ssl/s23_lib.c b/ssl/s23_lib.c new file mode 100644 index 0000000000..ff19adc119 --- /dev/null +++ b/ssl/s23_lib.c @@ -0,0 +1,232 @@ +/* ssl/s23_lib.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "ssl_locl.h" + +#ifndef NOPROTO +static int ssl23_num_ciphers(void ); +static SSL_CIPHER *ssl23_get_cipher(unsigned int u); +static int ssl23_read(SSL *s, char *buf, int len); +static int ssl23_write(SSL *s, char *buf, int len); +static long ssl23_default_timeout(void ); +static int ssl23_put_cipher_by_char(SSL_CIPHER *c, unsigned char *p); +static SSL_CIPHER *ssl23_get_cipher_by_char(unsigned char *p); +#else +static int ssl23_num_ciphers(); +static SSL_CIPHER *ssl23_get_cipher(); +static int ssl23_read(); +static int ssl23_write(); +static long ssl23_default_timeout(); +static int ssl23_put_cipher_by_char(); +static SSL_CIPHER *ssl23_get_cipher_by_char(); +#endif + +char *SSL23_version_str="SSLv2/3 compatablity part of SSLeay 0.7.0 30-Jan-1997"; + +static SSL_METHOD SSLv23_data= { + 3, + ssl3_new, + ssl3_clear, + ssl3_free, + ssl_undefined_function, + ssl_undefined_function, + ssl23_read, + ssl_undefined_function, + ssl23_write, + ssl_undefined_function, + ssl_undefined_function, + ssl3_ctrl, + ssl3_ctx_ctrl, + ssl23_get_cipher_by_char, + ssl23_put_cipher_by_char, + ssl_undefined_function, + ssl23_num_ciphers, + ssl23_get_cipher, + ssl_bad_method, + ssl23_default_timeout, + }; + +static long ssl23_default_timeout() + { + return(300); + } + +SSL_METHOD *sslv23_base_method() + { + return(&SSLv23_data); + } + +static int ssl23_num_ciphers() + { + return(ssl3_num_ciphers()+ssl2_num_ciphers()); + } + +static SSL_CIPHER *ssl23_get_cipher(u) +unsigned int u; + { + unsigned int uu=ssl3_num_ciphers(); + + if (u < uu) + return(ssl3_get_cipher(u)); + else + return(ssl2_get_cipher(u-uu)); + } + +/* This function needs to check if the ciphers required are actually + * available */ +static SSL_CIPHER *ssl23_get_cipher_by_char(p) +unsigned char *p; + { + SSL_CIPHER c,*cp; + unsigned long id; + int n; + + n=ssl3_num_ciphers(); + id=0x03000000|((unsigned long)p[0]<<16L)| + ((unsigned long)p[1]<<8L)|(unsigned long)p[2]; + c.id=id; + cp=ssl3_get_cipher_by_char(p); + if (cp == NULL) + cp=ssl2_get_cipher_by_char(p); + return(cp); + } + +static int ssl23_put_cipher_by_char(c,p) +SSL_CIPHER *c; +unsigned char *p; + { + long l; + + /* We can write SSLv2 and SSLv3 ciphers */ + if (p != NULL) + { + l=c->id; + p[0]=((unsigned char)(l>>16L))&0xFF; + p[1]=((unsigned char)(l>> 8L))&0xFF; + p[2]=((unsigned char)(l ))&0xFF; + } + return(3); + } + +static int ssl23_read(s,buf,len) +SSL *s; +char *buf; +int len; + { + int n; + +#if 0 + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) + { + s->rwstate=SSL_NOTHING; + return(0); + } +#endif + errno=0; + if (SSL_in_init(s) && (!s->in_handshake)) + { + n=s->handshake_func(s); + if (n < 0) return(n); + if (n == 0) + { + SSLerr(SSL_F_SSL23_READ,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + return(SSL_read(s,buf,len)); + } + else + { + ssl_undefined_function(s); + return(-1); + } + } + +static int ssl23_write(s,buf,len) +SSL *s; +char *buf; +int len; + { + int n; + +#if 0 + if (s->shutdown & SSL_SENT_SHUTDOWN) + { + s->rwstate=SSL_NOTHING; + return(0); + } +#endif + errno=0; + if (SSL_in_init(s) && (!s->in_handshake)) + { + n=s->handshake_func(s); + if (n < 0) return(n); + if (n == 0) + { + SSLerr(SSL_F_SSL23_WRITE,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + return(SSL_write(s,buf,len)); + } + else + { + ssl_undefined_function(s); + return(-1); + } + } diff --git a/ssl/s23_meth.c b/ssl/s23_meth.c new file mode 100644 index 0000000000..dbe282bfd0 --- /dev/null +++ b/ssl/s23_meth.c @@ -0,0 +1,90 @@ +/* ssl/s23_meth.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "ssl_locl.h" + +static SSL_METHOD *ssl23_get_method(ver) +int ver; + { + if (ver == 2) + return(SSLv23_method()); + else if (ver == 3) + return(SSLv3_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv23_method() + { + static int init=1; + static SSL_METHOD SSLv23_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv23_data,(char *)sslv23_base_method(), + sizeof(SSL_METHOD)); + SSLv23_data.ssl_connect=ssl23_connect; + SSLv23_data.ssl_accept=ssl23_accept; + SSLv23_data.get_ssl_method=ssl23_get_method; + } + return(&SSLv23_data); + } + diff --git a/ssl/s23_pkt.c b/ssl/s23_pkt.c new file mode 100644 index 0000000000..e9b2add0b8 --- /dev/null +++ b/ssl/s23_pkt.c @@ -0,0 +1,120 @@ +/* ssl/s23_pkt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <errno.h> +#define USE_SOCKETS +#include "evp.h" +#include "buffer.h" +#include "ssl_locl.h" + +int ssl23_write_bytes(s) +SSL *s; + { + int i,num,tot; + char *buf; + + buf=s->init_buf->data; + tot=s->init_off; + num=s->init_num; + for (;;) + { + s->rwstate=SSL_WRITING; + i=BIO_write(s->wbio,&(buf[tot]),num); + if (i < 0) + { + s->init_off=tot; + s->init_num=num; + return(i); + } + s->rwstate=SSL_NOTHING; + if (i == num) return(tot+i); + + num-=i; + tot+=i; + } + } + +/* only return when we have read 'n' bytes */ +int ssl23_read_bytes(s,n) +SSL *s; +int n; + { + unsigned char *p; + int j; + + if (s->packet_length < (unsigned int)n) + { + p=s->packet; + + for (;;) + { + s->rwstate=SSL_READING; + j=BIO_read(s->rbio,(char *)&(p[s->packet_length]), + n-s->packet_length); + if (j <= 0) + return(j); + s->rwstate=SSL_NOTHING; + s->packet_length+=j; + if (s->packet_length >= (unsigned int)n) + return(s->packet_length); + } + } + return(n); + } + diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c new file mode 100644 index 0000000000..398f005821 --- /dev/null +++ b/ssl/s23_srvr.c @@ -0,0 +1,474 @@ +/* ssl/s23_srvr.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "buffer.h" +#include "rand.h" +#include "objects.h" +#include "evp.h" +#include "ssl_locl.h" + +#define BREAK break + +#ifndef NOPROTO +int ssl23_get_client_hello(SSL *s); +#else +int ssl23_get_client_hello(); +#endif + +static SSL_METHOD *ssl23_get_server_method(ver) +int ver; + { + if (ver == 2) + return(SSLv2_server_method()); + else if (ver == 3) + return(SSLv3_server_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv23_server_method() + { + static int init=1; + static SSL_METHOD SSLv23_server_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv23_server_data, + (char *)sslv23_base_method(),sizeof(SSL_METHOD)); + SSLv23_server_data.ssl_accept=ssl23_accept; + SSLv23_server_data.get_ssl_method=ssl23_get_server_method; + } + return(&SSLv23_server_data); + } + +int ssl23_accept(s) +SSL *s; + { + BUF_MEM *buf; + unsigned long Time=time(NULL); + void (*cb)()=NULL; + int ret= -1; + int new_state,state; + + RAND_seed((unsigned char *)&Time,sizeof(Time)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + + for (;;) + { + state=s->state; + + switch(s->state) + { + case SSL_ST_BEFORE: + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + case SSL_ST_OK|SSL_ST_ACCEPT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=3; + s->type=SSL_ST_ACCEPT; + + if (s->init_buf == NULL) + { + if ((buf=BUF_MEM_new()) == NULL) + { + ret= -1; + goto end; + } + if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) + { + ret= -1; + goto end; + } + s->init_buf=buf; + } + + ssl3_init_finished_mac(s); + + s->state=SSL23_ST_SR_CLNT_HELLO_A; + s->ctx->sess_accept++; + s->init_num=0; + break; + + case SSL23_ST_SR_CLNT_HELLO_A: + case SSL23_ST_SR_CLNT_HELLO_B: + + s->shutdown=0; + ret=ssl23_get_client_hello(s); + if (ret >= 0) cb=NULL; + goto end; + break; + + default: + SSLerr(SSL_F_SSL23_ACCEPT,SSL_R_UNKNOWN_STATE); + ret= -1; + goto end; + /* break; */ + } + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_ACCEPT_LOOP,1); + s->state=new_state; + } + } +end: + if (cb != NULL) + cb(s,SSL_CB_ACCEPT_EXIT,ret); + s->in_handshake--; + return(ret); + } + + +int ssl23_get_client_hello(s) +SSL *s; + { + char buf_space[8]; + char *buf= &(buf_space[0]); + unsigned char *p,*d,*dd; + unsigned int i; + unsigned int csl,sil,cl; + int n=0,j; + BIO *bbio; + int type=0,use_sslv2_strong=0; + + /* read the initial header */ + if (s->state == SSL23_ST_SR_CLNT_HELLO_A) + { + if (!ssl3_setup_buffers(s)) goto err; + + n=ssl23_read_bytes(s,7); + if (n != 7) return(n); + + p=s->packet; + + memcpy(buf,p,n); + + if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) + { + /* SSLv2 header */ + if ((p[3] == 0x00) && (p[4] == 0x02)) + { + /* SSLv2 */ + type=1; + } + else if (p[3] == SSL3_VERSION_MAJOR) + { + if (s->ctx->options & SSL_OP_NON_EXPORT_FIRST) + { + STACK *sk; + SSL_CIPHER *c; + int ne2,ne3; + + j=((p[0]&0x7f)<<8)|p[1]; + if (j > (1024*4)) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); + goto err; + } + + n=ssl23_read_bytes(s,j+2); + if (n <= 0) return(n); + p=s->packet; + + if ((buf=Malloc(n)) == NULL) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(buf,p,n); + + p+=5; + n2s(p,csl); + p+=4; + + sk=ssl_bytes_to_cipher_list( + s,p,csl,NULL); + if (sk != NULL) + { + ne2=ne3=0; + for (j=0; j<sk_num(sk); j++) + { + c=(SSL_CIPHER *)sk_value(sk,j); + if (!(c->algorithms & SSL_EXP)) + { + if ((c->id>>24L) == 2L) + ne2=1; + else + ne3=1; + } + } + if (ne2 && !ne3) + { + type=1; + use_sslv2_strong=1; + goto next_bit; + } + } + } + /* SSLv3 */ + s->state=SSL23_ST_SR_CLNT_HELLO_B; + } + } + else if ((p[0] == SSL3_RT_HANDSHAKE) && + (p[1] == SSL3_VERSION_MAJOR) && + (p[5] == SSL3_MT_CLIENT_HELLO)) + { + /* true SSLv3 */ + type=3; + } + /* I will not introduce error codes since that will probably + * disrupt the error codes alread allocated and could play + * havoc with dynamic allocation. Upgrade to 0.9.x :-) + */ + else if ((strncmp("GET ", (char *)p,4) == 0) || + (strncmp("POST ",(char *)p,5) == 0) || + (strncmp("HEAD ",(char *)p,5) == 0) || + (strncmp("PUT ", (char *)p,4) == 0)) + { + goto err; + } + else if (strncmp("CONNECT",(char *)p,7) == 0) + { + goto err; + } + } + +next_bit: + if (s->state == SSL23_ST_SR_CLNT_HELLO_B) + { + /* we have a SSLv3 in a SSLv2 header */ + type=2; + p=s->packet; + n=((p[0]&0x7f)<<8)|p[1]; + if (n > (1024*4)) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); + goto err; + } + + j=ssl23_read_bytes(s,n+2); + if (j <= 0) return(j); + + ssl3_finish_mac(s,&(s->packet[2]),s->packet_length-2); + + p=s->packet; + p+=5; + n2s(p,csl); + n2s(p,sil); + n2s(p,cl); + d=(unsigned char *)s->init_buf->data; + if ((csl+sil+cl+11) != s->packet_length) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } + + *(d++)=SSL3_VERSION_MAJOR; + *(d++)=SSL3_VERSION_MINOR; + + /* lets populate the random area */ + /* get the chalenge_length */ + i=(cl > SSL3_RANDOM_SIZE)?SSL3_RANDOM_SIZE:cl; + memset(d,0,SSL3_RANDOM_SIZE); + memcpy(&(d[SSL3_RANDOM_SIZE-i]),&(p[csl+sil]),i); + d+=SSL3_RANDOM_SIZE; + + /* no session-id reuse */ + *(d++)=0; + + /* ciphers */ + j=0; + dd=d; + d+=2; + for (i=0; i<csl; i+=3) + { + if (p[i] != 0) continue; + *(d++)=p[i+1]; + *(d++)=p[i+2]; + j+=2; + } + s2n(j,dd); + + /* compression */ + *(d++)=1; + *(d++)=0; + + i=(d-(unsigned char *)s->init_buf->data); + + /* get the data reused from the init_buf */ + s->s3->tmp.reuse_message=1; + s->s3->tmp.message_type=SSL3_MT_CLIENT_HELLO; + s->s3->tmp.message_size=i; + } + + if (type == 1) + { + /* we are talking sslv2 */ + /* we need to clean up the SSLv3 setup and put in the + * sslv2 stuff. */ + + if (s->s2 == NULL) + { + if (!ssl2_new(s)) + goto err; + } + else + ssl2_clear(s); + + if (s->s3 != NULL) ssl3_free(s); + + if (!BUF_MEM_grow(s->init_buf, + SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) + { + goto err; + } + + s->state=SSL2_ST_GET_CLIENT_HELLO_A; + if ((s->ctx->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) || + use_sslv2_strong) + s->s2->ssl2_rollback=0; + else + s->s2->ssl2_rollback=1; + + /* setup the 5 bytes we have read so we get them from + * the sslv2 buffer */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + s->packet= &(s->s2->rbuf[0]); + memcpy(s->packet,buf,n); + s->s2->rbuf_left=n; + s->s2->rbuf_offs=0; + + s->method=SSLv2_server_method(); + s->handshake_func=s->method->ssl_accept; + } + + if ((type == 2) || (type == 3)) + { + /* we have sslv3 */ + + if (s->bbio == NULL) + { + bbio=BIO_new(BIO_f_buffer()); + if (bbio == NULL) + goto err; + s->bbio=bbio; + } + else + bbio=s->bbio; + BIO_reset(bbio); + if (!BIO_set_write_buffer_size(bbio,16*1024)) + goto err; + s->wbio=BIO_push(bbio,s->wbio); + + /* we are in this state */ + s->state=SSL3_ST_SR_CLNT_HELLO_A; + + if (type == 3) + { + /* put the 'n' bytes we have read into the input buffer + * for SSLv3 */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + s->packet= &(s->s3->rbuf.buf[0]); + memcpy(s->packet,buf,n); + s->s3->rbuf.left=n; + s->s3->rbuf.offset=0; + } + else + { + s->packet_length=0; + s->s3->rbuf.left=0; + s->s3->rbuf.offset=0; + } + + s->method=SSLv3_server_method(); + s->handshake_func=s->method->ssl_accept; + } + + if ((type < 1) || (type > 3)) + { + /* bad, very bad */ + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + s->init_num=0; + + if (buf != buf_space) Free(buf); + s->first_packet=1; + return(SSL_accept(s)); +err: + if (buf != buf_space) Free(buf); + return(-1); + } + diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c new file mode 100644 index 0000000000..67578a45ad --- /dev/null +++ b/ssl/s2_clnt.c @@ -0,0 +1,982 @@ +/* ssl/s2_clnt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#ifndef NO_MD5 +#include "md5.h" +#endif +#include "rand.h" +#include "buffer.h" +#include "objects.h" +#include "ssl_locl.h" +#include "evp.h" + +#ifndef NOPROTO +static int get_server_finished(SSL *s); +static int get_server_verify(SSL *s); +static int get_server_hello(SSL *s); +static int client_hello(SSL *s); +static int client_master_key(SSL *s); +static int client_finished(SSL *s); +static int client_certificate(SSL *s); +static int ssl_rsa_public_encrypt(CERT *c, int len, unsigned char *from, + unsigned char *to,int padding); +#else +static int get_server_finished(); +static int get_server_verify(); +static int get_server_hello(); +static int client_hello(); +static int client_master_key(); +static int client_finished(); +static int client_certificate(); +static int ssl_rsa_public_encrypt(); +#endif + +#define BREAK break + +static SSL_METHOD *ssl2_get_client_method(ver) +int ver; + { + if (ver == 2) + return(SSLv2_client_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv2_client_method() + { + static int init=1; + static SSL_METHOD SSLv2_client_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv2_client_data,(char *)sslv2_base_method(), + sizeof(SSL_METHOD)); + SSLv2_client_data.ssl_connect=ssl2_connect; + SSLv2_client_data.get_ssl_method=ssl2_get_client_method; + } + return(&SSLv2_client_data); + } + +int ssl2_connect(s) +SSL *s; + { + unsigned long l=time(NULL); + BUF_MEM *buf=NULL; + int ret= -1; + void (*cb)()=NULL; + int new_state,state; + + RAND_seed((unsigned char *)&l,sizeof(l)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + /* init things to blank */ + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + + for (;;) + { + state=s->state; + + switch (s->state) + { + case SSL_ST_BEFORE: + case SSL_ST_CONNECT: + case SSL_ST_BEFORE|SSL_ST_CONNECT: + case SSL_ST_OK|SSL_ST_CONNECT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=2; + s->type=SSL_ST_CONNECT; + + buf=s->init_buf; + if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL)) + { + ret= -1; + goto end; + } + if (!BUF_MEM_grow(buf, + SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) + { + ret= -1; + goto end; + } + s->init_buf=buf; + s->init_num=0; + s->state=SSL2_ST_SEND_CLIENT_HELLO_A; + s->ctx->sess_connect++; + s->handshake_func=ssl2_connect; + BREAK; + + case SSL2_ST_SEND_CLIENT_HELLO_A: + case SSL2_ST_SEND_CLIENT_HELLO_B: + s->shutdown=0; + ret=client_hello(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_GET_SERVER_HELLO_A; + BREAK; + + case SSL2_ST_GET_SERVER_HELLO_A: + case SSL2_ST_GET_SERVER_HELLO_B: + ret=get_server_hello(s); + if (ret <= 0) goto end; + s->init_num=0; + if (!s->hit) /* new session */ + { + s->state=SSL2_ST_SEND_CLIENT_MASTER_KEY_A; + BREAK; + } + else + { + s->state=SSL2_ST_CLIENT_START_ENCRYPTION; + break; + } + + case SSL2_ST_SEND_CLIENT_MASTER_KEY_A: + case SSL2_ST_SEND_CLIENT_MASTER_KEY_B: + ret=client_master_key(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_CLIENT_START_ENCRYPTION; + break; + + case SSL2_ST_CLIENT_START_ENCRYPTION: + /* Ok, we now have all the stuff needed to + * start encrypting, so lets fire it up :-) */ + if (!ssl2_enc_init(s,1)) + { + ret= -1; + goto end; + } + s->s2->clear_text=0; + s->state=SSL2_ST_SEND_CLIENT_FINISHED_A; + break; + + case SSL2_ST_SEND_CLIENT_FINISHED_A: + case SSL2_ST_SEND_CLIENT_FINISHED_B: + ret=client_finished(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_GET_SERVER_VERIFY_A; + break; + + case SSL2_ST_GET_SERVER_VERIFY_A: + case SSL2_ST_GET_SERVER_VERIFY_B: + ret=get_server_verify(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_GET_SERVER_FINISHED_A; + break; + + case SSL2_ST_GET_SERVER_FINISHED_A: + case SSL2_ST_GET_SERVER_FINISHED_B: + ret=get_server_finished(s); + if (ret <= 0) goto end; + break; + + case SSL2_ST_SEND_CLIENT_CERTIFICATE_A: + case SSL2_ST_SEND_CLIENT_CERTIFICATE_B: + case SSL2_ST_SEND_CLIENT_CERTIFICATE_C: + case SSL2_ST_SEND_CLIENT_CERTIFICATE_D: + case SSL2_ST_X509_GET_CLIENT_CERTIFICATE: + ret=client_certificate(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_GET_SERVER_FINISHED_A; + break; + + case SSL_ST_OK: + BUF_MEM_free(s->init_buf); + s->init_buf=NULL; + s->init_num=0; + /* ERR_clear_error();*/ + + /* If we want to cache session-ids in the client + * and we sucessfully add the session-id to the + * cache, and there is a callback, then pass it out. + * 26/11/96 - eay - only add if not a re-used session. + */ + + ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); + + ret=1; + /* s->server=0; */ + s->ctx->sess_connect_good++; + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + + goto end; + break; + default: + SSLerr(SSL_F_SSL2_CONNECT,SSL_R_UNKNOWN_STATE); + return(-1); + /* break; */ + } + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_CONNECT_LOOP,1); + s->state=new_state; + } + } +end: + s->in_handshake--; + if (cb != NULL) + cb(s,SSL_CB_CONNECT_EXIT,ret); + return(ret); + } + +static int get_server_hello(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p; + int i,j; + STACK *sk,*cl; + + buf=(unsigned char *)s->init_buf->data; + p=buf; + if (s->state == SSL2_ST_GET_SERVER_HELLO_A) + { + i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num); + if (i < (11-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i)); + + if (*(p++) != SSL2_MT_SERVER_HELLO) + { + if (p[-1] != SSL2_MT_ERROR) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_HELLO, + SSL_R_READ_WRONG_PACKET_TYPE); + } + else + SSLerr(SSL_F_GET_SERVER_HELLO, + SSL_R_PEER_ERROR); + return(-1); + } + s->hit=(*(p++))?1:0; + s->s2->tmp.cert_type= *(p++); + n2s(p,i); + if (i < s->version) s->version=i; + n2s(p,i); s->s2->tmp.cert_length=i; + n2s(p,i); s->s2->tmp.csl=i; + n2s(p,i); s->s2->tmp.conn_id_length=i; + s->state=SSL2_ST_GET_SERVER_HELLO_B; + s->init_num=0; + } + + /* SSL2_ST_GET_SERVER_HELLO_B */ + j=s->s2->tmp.cert_length+s->s2->tmp.csl+s->s2->tmp.conn_id_length + - s->init_num; + i=ssl2_read(s,(char *)&(buf[s->init_num]),j); + if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i)); + + /* things are looking good */ + + p=buf; + if (s->hit) + { + if (s->s2->tmp.cert_length != 0) + { + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO); + return(-1); + } + if (s->s2->tmp.cert_type != 0) + { + if (!(s->ctx->options & + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)) + { + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO); + return(-1); + } + } + if (s->s2->tmp.csl != 0) + { + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO); + return(-1); + } + } + else + { +#ifdef undef + /* very bad */ + memset(s->session->session_id,0, + SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES); + s->session->session_id_length=0; + */ +#endif + + /* we need to do this incase we were trying to reuse a + * client session but others are already reusing it. + * If this was a new 'blank' session ID, the session-id + * length will still be 0 */ + if (s->session->session_id_length > 0) + { + if (!ssl_get_new_session(s,0)) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } + } + + if (ssl2_set_certificate(s,s->s2->tmp.cert_type, + s->s2->tmp.cert_length,p) <= 0) + { + ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE); + return(-1); + } + p+=s->s2->tmp.cert_length; + + if (s->s2->tmp.csl == 0) + { + ssl2_return_error(s,SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST); + return(-1); + } + + /* We have just received a list of ciphers back from the + * server. We need to get the ones that match, then select + * the one we want the most :-). */ + + /* load the ciphers */ + sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl, + &s->session->ciphers); + p+=s->s2->tmp.csl; + if (sk == NULL) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE); + return(-1); + } + + sk_set_cmp_func(sk,ssl_cipher_ptr_id_cmp); + + /* get the array of ciphers we will accept */ + cl=ssl_get_ciphers_by_id(s); + + /* In theory we could have ciphers sent back that we + * don't want to use but that does not matter since we + * will check against the list we origionally sent and + * for performance reasons we should not bother to match + * the two lists up just to check. */ + for (i=0; i<sk_num(cl); i++) + { + if (sk_find(sk,sk_value(cl,i)) >= 0) + break; + } + + if (i >= sk_num(cl)) + { + ssl2_return_error(s,SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH); + return(-1); + } + s->session->cipher=(SSL_CIPHER *)sk_value(cl,i); + } + + if ((s->session != NULL) && (s->session->peer != NULL)) + X509_free(s->session->peer); + + /* hmmm, can we have the problem of the other session with this + * cert, Free's it before we increment the reference count. */ + CRYPTO_w_lock(CRYPTO_LOCK_X509); + s->session->peer=s->session->cert->key->x509; + s->session->peer->references++; + CRYPTO_w_unlock(CRYPTO_LOCK_X509); + + s->s2->conn_id_length=s->s2->tmp.conn_id_length; + memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length); + return(1); + } + +static int client_hello(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p,*d; +/* CIPHER **cipher;*/ + int i,n,j; + + buf=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_SEND_CLIENT_HELLO_A) + { + if ((s->session == NULL) || + (s->session->ssl_version != s->version)) + { + if (!ssl_get_new_session(s,0)) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } + } + /* else use the pre-loaded session */ + + p=buf; /* header */ + d=p+9; /* data section */ + *(p++)=SSL2_MT_CLIENT_HELLO; /* type */ + s2n(SSL2_CLIENT_VERSION,p); /* version */ + n=j=0; + + n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d); + d+=n; + + if (n == 0) + { + SSLerr(SSL_F_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); + return(-1); + } + + s2n(n,p); /* cipher spec num bytes */ + + if ((s->session->session_id_length > 0) && + (s->session->session_id_length <= + SSL2_MAX_SSL_SESSION_ID_LENGTH)) + { + i=s->session->session_id_length; + s2n(i,p); /* session id length */ + memcpy(d,s->session->session_id,(unsigned int)i); + d+=i; + } + else + { + s2n(0,p); + } + + s->s2->challenge_length=SSL2_CHALLENGE_LENGTH; + s2n(SSL2_CHALLENGE_LENGTH,p); /* challenge length */ + /*challenge id data*/ + RAND_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH); + memcpy(d,s->s2->challenge,SSL2_CHALLENGE_LENGTH); + d+=SSL2_CHALLENGE_LENGTH; + + s->state=SSL2_ST_SEND_CLIENT_HELLO_B; + s->init_num=d-buf; + s->init_off=0; + } + /* SSL2_ST_SEND_CLIENT_HELLO_B */ + return(ssl2_do_write(s)); + } + +static int client_master_key(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p,*d; + int clear,enc,karg,i; + SSL_SESSION *sess; + EVP_CIPHER *c; + EVP_MD *md; + + buf=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_SEND_CLIENT_MASTER_KEY_A) + { + + if (!ssl_cipher_get_evp(s->session->cipher,&c,&md)) + { + ssl2_return_error(s,SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS); + return(-1); + } + sess=s->session; + p=buf; + d=p+10; + *(p++)=SSL2_MT_CLIENT_MASTER_KEY;/* type */ + + i=ssl_put_cipher_by_char(s,sess->cipher,p); + p+=i; + + /* make key_arg data */ + i=EVP_CIPHER_iv_length(c); + sess->key_arg_length=i; + if (i > 0) RAND_bytes(sess->key_arg,i); + + /* make a master key */ + i=EVP_CIPHER_key_length(c); + sess->master_key_length=i; + if (i > 0) RAND_bytes(sess->master_key,i); + + if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) + enc=8; + else if (sess->cipher->algorithms & SSL_EXP) + enc=5; + else + enc=i; + + if (i < enc) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_CIPHER_TABLE_SRC_ERROR); + return(-1); + } + clear=i-enc; + s2n(clear,p); + memcpy(d,sess->master_key,(unsigned int)clear); + d+=clear; + + enc=ssl_rsa_public_encrypt(sess->cert,enc, + &(sess->master_key[clear]),d, + (s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING); + if (enc <= 0) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PUBLIC_KEY_ENCRYPT_ERROR); + return(-1); + } + s2n(enc,p); + d+=enc; + karg=sess->key_arg_length; + s2n(karg,p); /* key arg size */ + memcpy(d,sess->key_arg,(unsigned int)karg); + d+=karg; + + s->state=SSL2_ST_SEND_CLIENT_MASTER_KEY_B; + s->init_num=d-buf; + s->init_off=0; + } + + /* SSL2_ST_SEND_CLIENT_MASTER_KEY_B */ + return(ssl2_do_write(s)); + } + +static int client_finished(s) +SSL *s; + { + unsigned char *p; + + if (s->state == SSL2_ST_SEND_CLIENT_FINISHED_A) + { + p=(unsigned char *)s->init_buf->data; + *(p++)=SSL2_MT_CLIENT_FINISHED; + memcpy(p,s->s2->conn_id,(unsigned int)s->s2->conn_id_length); + + s->state=SSL2_ST_SEND_CLIENT_FINISHED_B; + s->init_num=s->s2->conn_id_length+1; + s->init_off=0; + } + return(ssl2_do_write(s)); + } + +/* read the data and then respond */ +static int client_certificate(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p,*d; + int i; + unsigned int n; + int cert_ch_len=0; + unsigned char *cert_ch; + + buf=(unsigned char *)s->init_buf->data; + cert_ch= &(buf[2]); + + /* We have a cert associated with the SSL, so attach it to + * the session if it does not have one */ + + if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_A) + { + i=ssl2_read(s,(char *)&(buf[s->init_num]), + SSL2_MAX_CERT_CHALLENGE_LENGTH+1-s->init_num); + if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+1-s->init_num)) + return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i)); + + /* type=buf[0]; */ + /* type eq x509 */ + if (buf[1] != SSL2_AT_MD5_WITH_RSA_ENCRYPTION) + { + ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE); + SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_AUTHENTICATION_TYPE); + return(-1); + } + cert_ch_len=i-1; + + if ((s->cert == NULL) || + (s->cert->key->x509 == NULL) || + (s->cert->key->privatekey == NULL)) + { + s->state=SSL2_ST_X509_GET_CLIENT_CERTIFICATE; + } + else + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C; + } + + if (s->state == SSL2_ST_X509_GET_CLIENT_CERTIFICATE) + { + X509 *x509=NULL; + EVP_PKEY *pkey=NULL; + + /* If we get an error we need to + * ssl->rwstate=SSL_X509_LOOKUP; + * return(error); + * We should then be retried when things are ok and we + * can get a cert or not */ + + i=0; + if (s->ctx->client_cert_cb != NULL) + { + i=s->ctx->client_cert_cb(s,&(x509),&(pkey)); + } + + if (i < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return(-1); + } + s->rwstate=SSL_NOTHING; + + if ((i == 1) && (pkey != NULL) && (x509 != NULL)) + { + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C; + if ( !SSL_use_certificate(s,x509) || + !SSL_use_PrivateKey(s,pkey)) + { + i=0; + } + X509_free(x509); + EVP_PKEY_free(pkey); + } + else if (i == 1) + { + if (x509 != NULL) X509_free(x509); + if (pkey != NULL) EVP_PKEY_free(pkey); + SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + i=0; + } + + if (i == 0) + { + /* We have no client certificate to respond with + * so send the correct error message back */ + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_B; + p=buf; + *(p++)=SSL2_MT_ERROR; + s2n(SSL2_PE_NO_CERTIFICATE,p); + s->init_off=0; + s->init_num=3; + /* Write is done at the end */ + } + } + + if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_B) + { + return(ssl2_do_write(s)); + } + + if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_C) + { + EVP_MD_CTX ctx; + + /* ok, now we calculate the checksum + * do it first so we can reuse buf :-) */ + p=buf; + EVP_SignInit(&ctx,EVP_md5()); + EVP_SignUpdate(&ctx,s->s2->key_material, + (unsigned int)s->s2->key_material_length); + EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len); + n=i2d_X509(s->session->cert->key->x509,&p); + EVP_SignUpdate(&ctx,buf,(unsigned int)n); + + p=buf; + d=p+6; + *(p++)=SSL2_MT_CLIENT_CERTIFICATE; + *(p++)=SSL2_CT_X509_CERTIFICATE; + n=i2d_X509(s->cert->key->x509,&d); + s2n(n,p); + + if (!EVP_SignFinal(&ctx,d,&n,s->cert->key->privatekey)) + { + /* this is not good. If things have failed it + * means there so something wrong with the key. + * We will contiune with a 0 length signature + */ + } + memset(&ctx,0,sizeof(ctx)); + s2n(n,p); + d+=n; + + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_D; + s->init_num=d-buf; + s->init_off=0; + } + /* if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_D) */ + return(ssl2_do_write(s)); + } + +static int get_server_verify(s) +SSL *s; + { + unsigned char *p; + int i; + + p=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_GET_SERVER_VERIFY_A) + { + i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num); + if (i < (1-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i)); + + s->state= SSL2_ST_GET_SERVER_VERIFY_B; + s->init_num=0; + if (*p != SSL2_MT_SERVER_VERIFY) + { + if (p[0] != SSL2_MT_ERROR) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_VERIFY, + SSL_R_READ_WRONG_PACKET_TYPE); + } + else + SSLerr(SSL_F_GET_SERVER_VERIFY, + SSL_R_PEER_ERROR); + return(-1); + } + } + + p=(unsigned char *)s->init_buf->data; + i=ssl2_read(s,(char *)&(p[s->init_num]), + (unsigned int)s->s2->challenge_length-s->init_num); + if (i < ((int)s->s2->challenge_length-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i)); + if (memcmp(p,s->s2->challenge,(unsigned int)s->s2->challenge_length) != 0) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_CHALLENGE_IS_DIFFERENT); + return(-1); + } + return(1); + } + +static int get_server_finished(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p; + int i; + + buf=(unsigned char *)s->init_buf->data; + p=buf; + if (s->state == SSL2_ST_GET_SERVER_FINISHED_A) + { + i=ssl2_read(s,(char *)&(buf[s->init_num]),1-s->init_num); + if (i < (1-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i)); + s->init_num=i; + if (*p == SSL2_MT_REQUEST_CERTIFICATE) + { + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_A; + return(1); + } + else if (*p != SSL2_MT_SERVER_FINISHED) + { + if (p[0] != SSL2_MT_ERROR) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE); + } + else + SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_PEER_ERROR); + return(-1); + } + s->state=SSL_ST_OK; + s->init_num=0; + } + + i=ssl2_read(s,(char *)&(buf[s->init_num]), + SSL2_SSL_SESSION_ID_LENGTH-s->init_num); + if (i < (SSL2_SSL_SESSION_ID_LENGTH-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i)); + + if (!s->hit) /* new session */ + { + /* new session-id */ + s->session->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; + memcpy(s->session->session_id,p,SSL2_SSL_SESSION_ID_LENGTH); + } + else + { + if (!(s->ctx->options & SSL_OP_MICROSOFT_SESS_ID_BUG)) + { + if (memcmp(buf,s->session->session_id, + (unsigned int)s->session->session_id_length) != 0) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_SSL_SESSION_ID_IS_DIFFERENT); + return(-1); + } + } + } + return(1); + } + +/* loads in the certificate from the server */ +int ssl2_set_certificate(s, type, len, data) +SSL *s; +int type; +int len; +unsigned char *data; + { + STACK *sk=NULL; + EVP_PKEY *pkey=NULL; + CERT *c=NULL; + int i; + X509 *x509=NULL; + int ret=0; + + x509=d2i_X509(NULL,&data,(long)len); + if (x509 == NULL) + { + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_X509_LIB); + goto err; + } + + if (((sk=sk_new_null()) == NULL) || + (!sk_push(sk,(char *)x509))) + { + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto err; + } + + i=ssl_verify_cert_chain(s,sk); + + if ((s->verify_mode != SSL_VERIFY_NONE) && (!i)) + { + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + + /* cert for ssl */ + c=ssl_cert_new(); + if (c == NULL) + { + ret= -1; + goto err; + } + + /* cert for session */ + if (s->session->cert) ssl_cert_free(s->session->cert); + s->session->cert=c; + +/* c->cert_type=type; */ + + c->pkeys[SSL_PKEY_RSA_ENC].x509=x509; + c->key= &(c->pkeys[SSL_PKEY_RSA_ENC]); + + pkey=X509_get_pubkey(x509); + x509=NULL; + if (pkey == NULL) + { + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY); + goto err; + } + if (pkey->type != EVP_PKEY_RSA) + { + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_PUBLIC_KEY_NOT_RSA); + goto err; + } + + if (!ssl_set_cert_type(c,SSL2_CT_X509_CERTIFICATE)) + goto err; + ret=1; +err: + if (sk != NULL) sk_free(sk); + if (x509 != NULL) X509_free(x509); + return(ret); + } + +static int ssl_rsa_public_encrypt(c, len, from, to, padding) +CERT *c; +int len; +unsigned char *from; +unsigned char *to; +int padding; + { + EVP_PKEY *pkey=NULL; + int i= -1; + + if ((c == NULL) || (c->key->x509 == NULL) || + ((pkey=X509_get_pubkey(c->key->x509)) == NULL)) + { + SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_NO_PUBLICKEY); + return(-1); + } + if (pkey->type != EVP_PKEY_RSA) + { + SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA); + goto end; + } + + /* we have the public key */ + i=RSA_public_encrypt(len,from,to,pkey->pkey.rsa,padding); + if (i < 0) + SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,ERR_R_RSA_LIB); +end: + return(i); + } + diff --git a/ssl/s2_enc.c b/ssl/s2_enc.c new file mode 100644 index 0000000000..b915f099e5 --- /dev/null +++ b/ssl/s2_enc.c @@ -0,0 +1,187 @@ +/* ssl/s2_enc.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "ssl_locl.h" + +#define RS 0 +#define WS 1 + +int ssl2_enc_init(s, client) +SSL *s; +int client; + { + /* Max number of bytes needed */ + EVP_CIPHER_CTX *rs,*ws; + EVP_CIPHER *c; + EVP_MD *md; + int num; + + if (!ssl_cipher_get_evp(s->session->cipher,&c,&md)) + { + ssl2_return_error(s,SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS); + return(0); + } + + s->read_hash=md; + s->write_hash=md; + + if ((s->enc_read_ctx == NULL) && + ((s->enc_read_ctx=(EVP_CIPHER_CTX *) + Malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) + goto err; + if ((s->enc_write_ctx == NULL) && + ((s->enc_write_ctx=(EVP_CIPHER_CTX *) + Malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) + goto err; + + rs= s->enc_read_ctx; + ws= s->enc_write_ctx; + + num=c->key_len; + s->s2->key_material_length=num*2; + + ssl2_generate_key_material(s); + + EVP_EncryptInit(ws,c,&(s->s2->key_material[(client)?num:0]), + s->session->key_arg); + EVP_DecryptInit(rs,c,&(s->s2->key_material[(client)?0:num]), + s->session->key_arg); + s->s2->read_key= &(s->s2->key_material[(client)?0:num]); + s->s2->write_key= &(s->s2->key_material[(client)?num:0]); + return(1); +err: + SSLerr(SSL_F_SSL2_ENC_INIT,ERR_R_MALLOC_FAILURE); + return(0); + } + +/* read/writes from s->s2->mac_data using length for encrypt and + * decrypt. It sets the s->s2->padding, s->[rw]length and + * s->s2->pad_data ptr if we are encrypting */ +void ssl2_enc(s,send) +SSL *s; +int send; + { + EVP_CIPHER_CTX *ds; + unsigned long l; + int bs; + + if (send) + { + ds=s->enc_write_ctx; + l=s->s2->wlength; + } + else + { + ds=s->enc_read_ctx; + l=s->s2->rlength; + } + + /* check for NULL cipher */ + if (ds == NULL) return; + + + bs=ds->cipher->block_size; + /* This should be using (bs-1) and bs instead of 7 and 8, but + * what the hell. */ + if (bs == 8) + l=(l+7)/8*8; + + EVP_Cipher(ds,s->s2->mac_data,s->s2->mac_data,l); + } + +void ssl2_mac(s, md,send) +SSL *s; +unsigned char *md; +int send; + { + EVP_MD_CTX c; + unsigned char sequence[4],*p,*sec,*act; + unsigned long seq; + unsigned int len; + + if (send) + { + seq=s->s2->write_sequence; + sec=s->s2->write_key; + len=s->s2->wact_data_length; + act=s->s2->wact_data; + } + else + { + seq=s->s2->read_sequence; + sec=s->s2->read_key; + len=s->s2->ract_data_length; + act=s->s2->ract_data; + } + + p= &(sequence[0]); + l2n(seq,p); + + /* There has to be a MAC algorithm. */ + EVP_DigestInit(&c,s->read_hash); + EVP_DigestUpdate(&c,sec, + EVP_CIPHER_CTX_key_length(s->enc_read_ctx)); + EVP_DigestUpdate(&c,act,len); + /* the above line also does the pad data */ + EVP_DigestUpdate(&c,sequence,4); + EVP_DigestFinal(&c,md,NULL); + /* some would say I should zero the md context */ + } + diff --git a/ssl/s2_lib.c b/ssl/s2_lib.c new file mode 100644 index 0000000000..fb91582217 --- /dev/null +++ b/ssl/s2_lib.c @@ -0,0 +1,455 @@ +/* ssl/s2_lib.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "rsa.h" +#include "objects.h" +#include "ssl_locl.h" + +#ifndef NOPROTO +static int ssl2_ok(SSL *s); +static long ssl2_default_timeout(void ); +#else +static int ssl2_ok(); +static long ssl2_default_timeout(); +#endif + +char *ssl2_version_str="SSLv2 part of SSLeay 0.8.1b 29-Jun-1998"; + +#define SSL2_NUM_CIPHERS (sizeof(ssl2_ciphers)/sizeof(SSL_CIPHER)) + +SSL_CIPHER ssl2_ciphers[]={ +/* NULL_WITH_MD5 v3 */ +#if 0 + { + 1, + SSL2_TXT_NULL_WITH_MD5, + SSL2_CK_NULL_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5|SSL_EXP|SSL_SSLV2, + 0, + SSL_ALL_CIPHERS, + }, +#endif +/* RC4_128_EXPORT40_WITH_MD5 */ + { + 1, + SSL2_TXT_RC4_128_EXPORT40_WITH_MD5, + SSL2_CK_RC4_128_EXPORT40_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5|SSL_EXP|SSL_SSLV2, + SSL2_CF_5_BYTE_ENC, + SSL_ALL_CIPHERS, + }, +/* RC4_128_WITH_MD5 */ + { + 1, + SSL2_TXT_RC4_128_WITH_MD5, + SSL2_CK_RC4_128_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5|SSL_NOT_EXP|SSL_SSLV2|SSL_MEDIUM, + 0, + SSL_ALL_CIPHERS, + }, +/* RC2_128_CBC_EXPORT40_WITH_MD5 */ + { + 1, + SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5, + SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5|SSL_EXP|SSL_SSLV2, + SSL2_CF_5_BYTE_ENC, + SSL_ALL_CIPHERS, + }, +/* RC2_128_CBC_WITH_MD5 */ + { + 1, + SSL2_TXT_RC2_128_CBC_WITH_MD5, + SSL2_CK_RC2_128_CBC_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5|SSL_NOT_EXP|SSL_SSLV2|SSL_MEDIUM, + 0, + SSL_ALL_CIPHERS, + }, +/* IDEA_128_CBC_WITH_MD5 */ + { + 1, + SSL2_TXT_IDEA_128_CBC_WITH_MD5, + SSL2_CK_IDEA_128_CBC_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_IDEA|SSL_MD5|SSL_NOT_EXP|SSL_SSLV2|SSL_MEDIUM, + 0, + SSL_ALL_CIPHERS, + }, +/* DES_64_CBC_WITH_MD5 */ + { + 1, + SSL2_TXT_DES_64_CBC_WITH_MD5, + SSL2_CK_DES_64_CBC_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5|SSL_NOT_EXP|SSL_SSLV2|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +/* DES_64_CBC_WITH_SHA */ +#if 0 + { + 1, + SSL2_TXT_DES_64_CBC_WITH_SHA, + SSL2_CK_DES_64_CBC_WITH_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA0|SSL_NOT_EXP|SSL_SSLV2|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +#endif +/* DES_192_EDE3_CBC_WITH_MD5 */ + { + 1, + SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5, + SSL2_CK_DES_192_EDE3_CBC_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5|SSL_NOT_EXP|SSL_SSLV2|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, +/* DES_192_EDE3_CBC_WITH_SHA */ +#if 0 + { + 1, + SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA, + SSL2_CK_DES_192_EDE3_CBC_WITH_SHA, + SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA0|SSL_NOT_EXP|SSL_SSLV2|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, +#endif +/* RC4_64_WITH_MD5 */ +#if 1 + { + 1, + SSL2_TXT_RC4_64_WITH_MD5, + SSL2_CK_RC4_64_WITH_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5|SSL_SSLV2|SSL_LOW, + SSL2_CF_8_BYTE_ENC, + SSL_ALL_CIPHERS, + }, +#endif +/* NULL SSLeay (testing) */ +#if 0 + { + 0, + SSL2_TXT_NULL, + SSL2_CK_NULL, + 0, + SSL_ALL_CIPHERS, + }, +#endif + +/* end of list :-) */ + }; + +static SSL_METHOD SSLv2_data= { + 2, + ssl2_new, /* local */ + ssl2_clear, /* local */ + ssl2_free, /* local */ + ssl_undefined_function, + ssl_undefined_function, + ssl2_read, + ssl2_peek, + ssl2_write, + ssl2_shutdown, + ssl2_ok, + ssl2_ctrl, /* local */ + ssl2_ctx_ctrl, /* local */ + ssl2_get_cipher_by_char, + ssl2_put_cipher_by_char, + ssl2_pending, + ssl2_num_ciphers, + ssl2_get_cipher, + ssl_bad_method, + ssl2_default_timeout, + }; + +static long ssl2_default_timeout() + { + return(300); + } + +SSL_METHOD *sslv2_base_method() + { + return(&SSLv2_data); + } + +int ssl2_num_ciphers() + { + return(SSL2_NUM_CIPHERS); + } + +SSL_CIPHER *ssl2_get_cipher(u) +unsigned int u; + { + if (u < SSL2_NUM_CIPHERS) + return(&(ssl2_ciphers[SSL2_NUM_CIPHERS-1-u])); + else + return(NULL); + } + +int ssl2_pending(s) +SSL *s; + { + return(s->s2->ract_data_length); + } + +int ssl2_new(s) +SSL *s; + { + SSL2_CTX *s2; + + if ((s2=(SSL2_CTX *)Malloc(sizeof(SSL2_CTX))) == NULL) goto err; + + if ((s2->rbuf=(unsigned char *)Malloc( + SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err; + if ((s2->wbuf=(unsigned char *)Malloc( + SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err; + s->s2=s2; + + ssl2_clear(s); + return(1); +err: + if (s2 != NULL) + { + if (s2->wbuf != NULL) Free(s2->wbuf); + if (s2->rbuf != NULL) Free(s2->rbuf); + Free(s2); + } + return(0); + } + +void ssl2_free(s) +SSL *s; + { + SSL2_CTX *s2; + + s2=s->s2; + if (s2->rbuf != NULL) Free(s2->rbuf); + if (s2->wbuf != NULL) Free(s2->wbuf); + memset(s2,0,sizeof(SSL2_CTX)); + Free(s2); + s->s2=NULL; + } + +void ssl2_clear(s) +SSL *s; + { + SSL2_CTX *s2; + unsigned char *rbuf,*wbuf; + + s2=s->s2; + + rbuf=s2->rbuf; + wbuf=s2->wbuf; + + memset(s2,0,sizeof(SSL2_CTX)); + + s2->rbuf=rbuf; + s2->wbuf=wbuf; + s2->clear_text=1; + s2->first_packet=0; + s->packet=s2->rbuf; + s->version=2; + s->packet_length=0; + } + +long ssl2_ctrl(s,cmd,larg,parg) +SSL *s; +int cmd; +long larg; +char *parg; + { + return(0); + } + +long ssl2_ctx_ctrl(ctx,cmd,larg,parg) +SSL_CTX *ctx; +int cmd; +long larg; +char *parg; + { + return(0); + } + +/* This function needs to check if the ciphers required are actually + * available */ +SSL_CIPHER *ssl2_get_cipher_by_char(p) +unsigned char *p; + { + static int init=1; + static SSL_CIPHER *sorted[SSL2_NUM_CIPHERS]; + SSL_CIPHER c,*cp= &c,**cpp; + unsigned long id; + int i; + + if (init) + { + init=0; + + for (i=0; i<SSL2_NUM_CIPHERS; i++) + sorted[i]= &(ssl2_ciphers[i]); + + qsort( (char *)sorted, + SSL2_NUM_CIPHERS,sizeof(SSL_CIPHER *), + FP_ICC ssl_cipher_ptr_id_cmp); + } + + id=0x02000000L|((unsigned long)p[0]<<16L)| + ((unsigned long)p[1]<<8L)|(unsigned long)p[2]; + c.id=id; + cpp=(SSL_CIPHER **)OBJ_bsearch((char *)&cp, + (char *)sorted, + SSL2_NUM_CIPHERS,sizeof(SSL_CIPHER *), + (int (*)())ssl_cipher_ptr_id_cmp); + if ((cpp == NULL) || !(*cpp)->valid) + return(NULL); + else + return(*cpp); + } + +int ssl2_put_cipher_by_char(c,p) +SSL_CIPHER *c; +unsigned char *p; + { + long l; + + if (p != NULL) + { + l=c->id; + if ((l & 0xff000000) != 0x02000000) return(0); + p[0]=((unsigned char)(l>>16L))&0xFF; + p[1]=((unsigned char)(l>> 8L))&0xFF; + p[2]=((unsigned char)(l ))&0xFF; + } + return(3); + } + +void ssl2_generate_key_material(s) +SSL *s; + { + unsigned int i; + MD5_CTX ctx; + unsigned char *km; + unsigned char c='0'; + + km=s->s2->key_material; + for (i=0; i<s->s2->key_material_length; i+=MD5_DIGEST_LENGTH) + { + MD5_Init(&ctx); + + MD5_Update(&ctx,s->session->master_key,s->session->master_key_length); + MD5_Update(&ctx,(unsigned char *)&c,1); + c++; + MD5_Update(&ctx,s->s2->challenge,s->s2->challenge_length); + MD5_Update(&ctx,s->s2->conn_id,s->s2->conn_id_length); + MD5_Final(km,&ctx); + km+=MD5_DIGEST_LENGTH; + } + } + +void ssl2_return_error(s,err) +SSL *s; +int err; + { + if (!s->error) + { + s->error=3; + s->error_code=err; + + ssl2_write_error(s); + } + } + + +void ssl2_write_error(s) +SSL *s; + { + char buf[3]; + int i,error; + + buf[0]=SSL2_MT_ERROR; + buf[1]=(s->error_code>>8)&0xff; + buf[2]=(s->error_code)&0xff; + +/* state=s->rwstate;*/ + error=s->error; + s->error=0; + i=ssl2_write(s,&(buf[3-error]),error); +/* if (i == error) s->rwstate=state; */ + + if (i < 0) + s->error=error; + else if (i != s->error) + s->error=error-i; + /* else + s->error=0; */ + } + +static int ssl2_ok(s) +SSL *s; + { + return(1); + } + +int ssl2_shutdown(s) +SSL *s; + { + s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); + return(1); + } + diff --git a/ssl/s2_meth.c b/ssl/s2_meth.c new file mode 100644 index 0000000000..0b8c2acb48 --- /dev/null +++ b/ssl/s2_meth.c @@ -0,0 +1,88 @@ +/* ssl/s2_meth.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "ssl_locl.h" + +static SSL_METHOD *ssl2_get_method(ver) +int ver; + { + if (ver == 2) + return(SSLv2_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv2_method() + { + static int init=1; + static SSL_METHOD SSLv2_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv2_data,(char *)sslv2_base_method(), + sizeof(SSL_METHOD)); + SSLv2_data.ssl_connect=ssl2_connect; + SSLv2_data.ssl_accept=ssl2_accept; + SSLv2_data.get_ssl_method=ssl2_get_method; + } + return(&SSLv2_data); + } + diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c new file mode 100644 index 0000000000..84bea33e2e --- /dev/null +++ b/ssl/s2_pkt.c @@ -0,0 +1,651 @@ +/* ssl/s2_pkt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <errno.h> +#define USE_SOCKETS +#include "ssl_locl.h" + +/* SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_NO_CIPHER); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_NO_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_UNKNOWN_REMOTE_ERROR_TYPE); + */ + +#ifndef NOPROTO +static int read_n(SSL *s,unsigned int n,unsigned int max,unsigned int extend); +static int do_ssl_write(SSL *s, const char *buf, unsigned int len); +static int write_pending(SSL *s, const char *buf, unsigned int len); +static int ssl_mt_error(int n); +#else +static int read_n(); +static int do_ssl_write(); +static int write_pending(); +static int ssl_mt_error(); +#endif + +int ssl2_peek(s,buf,len) +SSL *s; +char *buf; +int len; + { + int ret; + + ret=ssl2_read(s,buf,len); + if (ret > 0) + { + s->s2->ract_data_length+=ret; + s->s2->ract_data-=ret; + } + return(ret); + } + +/* SSL_read - + * This routine will return 0 to len bytes, decrypted etc if required. + */ +int ssl2_read(s, buf, len) +SSL *s; +char *buf; +int len; + { + int n; + unsigned char mac[MAX_MAC_SIZE]; + unsigned char *p; + int i; + unsigned int mac_size=0; + + if (SSL_in_init(s) && !s->in_handshake) + { + n=s->handshake_func(s); + if (n < 0) return(n); + if (n == 0) + { + SSLerr(SSL_F_SSL2_READ,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + } + + errno=0; + s->rwstate=SSL_NOTHING; + if (len <= 0) return(len); + + if (s->s2->ract_data_length != 0) /* read from buffer */ + { + if (len > s->s2->ract_data_length) + n=s->s2->ract_data_length; + else + n=len; + + memcpy(buf,s->s2->ract_data,(unsigned int)n); + s->s2->ract_data_length-=n; + s->s2->ract_data+=n; + if (s->s2->ract_data_length == 0) + s->rstate=SSL_ST_READ_HEADER; + return(n); + } + + if (s->rstate == SSL_ST_READ_HEADER) + { + if (s->first_packet) + { + n=read_n(s,5,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0); + if (n <= 0) return(n); /* error or non-blocking */ + s->first_packet=0; + p=s->packet; + if (!((p[0] & 0x80) && ( + (p[2] == SSL2_MT_CLIENT_HELLO) || + (p[2] == SSL2_MT_SERVER_HELLO)))) + { + SSLerr(SSL_F_SSL2_READ,SSL_R_NON_SSLV2_INITIAL_PACKET); + return(-1); + } + } + else + { + n=read_n(s,2,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0); + if (n <= 0) return(n); /* error or non-blocking */ + } + /* part read stuff */ + + s->rstate=SSL_ST_READ_BODY; + p=s->packet; + /* Do header */ + /*s->s2->padding=0;*/ + s->s2->escape=0; + s->s2->rlength=(((unsigned int)p[0])<<8)|((unsigned int)p[1]); + if ((p[0] & TWO_BYTE_BIT)) /* Two byte header? */ + { + s->s2->three_byte_header=0; + s->s2->rlength&=TWO_BYTE_MASK; + } + else + { + s->s2->three_byte_header=1; + s->s2->rlength&=THREE_BYTE_MASK; + + /* security >s2->escape */ + s->s2->escape=((p[0] & SEC_ESC_BIT))?1:0; + } + } + + if (s->rstate == SSL_ST_READ_BODY) + { + n=s->s2->rlength+2+s->s2->three_byte_header; + if (n > (int)s->packet_length) + { + n-=s->packet_length; + i=read_n(s,(unsigned int)n,(unsigned int)n,1); + if (i <= 0) return(i); /* ERROR */ + } + + p= &(s->packet[2]); + s->rstate=SSL_ST_READ_HEADER; + if (s->s2->three_byte_header) + s->s2->padding= *(p++); + else s->s2->padding=0; + + /* Data portion */ + if (s->s2->clear_text) + { + s->s2->mac_data=p; + s->s2->ract_data=p; + s->s2->pad_data=NULL; + } + else + { + mac_size=EVP_MD_size(s->read_hash); + s->s2->mac_data=p; + s->s2->ract_data= &p[mac_size]; + s->s2->pad_data= &p[mac_size+ + s->s2->rlength-s->s2->padding]; + } + + s->s2->ract_data_length=s->s2->rlength; + /* added a check for length > max_size in case + * encryption was not turned on yet due to an error */ + if ((!s->s2->clear_text) && + (s->s2->rlength >= mac_size)) + { + ssl2_enc(s,0); + s->s2->ract_data_length-=mac_size; + ssl2_mac(s,mac,0); + s->s2->ract_data_length-=s->s2->padding; + if ( (memcmp(mac,s->s2->mac_data, + (unsigned int)mac_size) != 0) || + (s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0)) + { + SSLerr(SSL_F_SSL2_READ,SSL_R_BAD_MAC_DECODE); + return(SSL_RWERR_BAD_MAC_DECODE); + } + } + INC32(s->s2->read_sequence); /* expect next number */ + /* s->s2->ract_data is now available for processing */ + + /* If a 0 byte packet was sent, return 0, otherwise + * we play havoc with people using select with + * blocking sockets. Let them handle a packet at a time, + * they should really be using non-blocking sockets. */ + if (s->s2->ract_data_length == 0) + return(0); + return(ssl2_read(s,buf,len)); + } + else + { + SSLerr(SSL_F_SSL2_READ,SSL_R_BAD_STATE); + return(SSL_RWERR_INTERNAL_ERROR); + } + } + +static int read_n(s, n, max, extend) +SSL *s; +unsigned int n; +unsigned int max; +unsigned int extend; + { + int i,off,newb; + + /* if there is stuff still in the buffer from a previous read, + * and there is more than we want, take some. */ + if (s->s2->rbuf_left >= (int)n) + { + if (extend) + s->packet_length+=n; + else + { + s->packet= &(s->s2->rbuf[s->s2->rbuf_offs]); + s->packet_length=n; + } + s->s2->rbuf_left-=n; + s->s2->rbuf_offs+=n; + return(n); + } + + if (!s->read_ahead) max=n; + if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) + max=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2; + + + /* Else we want more than we have. + * First, if there is some left or we want to extend */ + off=0; + if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend)) + { + newb=s->s2->rbuf_left; + if (extend) + { + off=s->packet_length; + if (s->packet != s->s2->rbuf) + memcpy(s->s2->rbuf,s->packet, + (unsigned int)newb+off); + } + else if (s->s2->rbuf_offs != 0) + { + memcpy(s->s2->rbuf,&(s->s2->rbuf[s->s2->rbuf_offs]), + (unsigned int)newb); + s->s2->rbuf_offs=0; + } + s->s2->rbuf_left=0; + } + else + newb=0; + + /* off is the offset to start writing too. + * r->s2->rbuf_offs is the 'unread data', now 0. + * newb is the number of new bytes so far + */ + s->packet=s->s2->rbuf; + while (newb < (int)n) + { + errno=0; + if (s->rbio != NULL) + { + s->rwstate=SSL_READING; + i=BIO_read(s->rbio,(char *)&(s->s2->rbuf[off+newb]), + max-newb); + } + else + { + SSLerr(SSL_F_READ_N,SSL_R_READ_BIO_NOT_SET); + i= -1; + } +#ifdef PKT_DEBUG + if (s->debug & 0x01) sleep(1); +#endif + if (i <= 0) + { + s->s2->rbuf_left+=newb; + return(i); + } + newb+=i; + } + + /* record unread data */ + if (newb > (int)n) + { + s->s2->rbuf_offs=n+off; + s->s2->rbuf_left=newb-n; + } + else + { + s->s2->rbuf_offs=0; + s->s2->rbuf_left=0; + } + if (extend) + s->packet_length+=n; + else + s->packet_length=n; + s->rwstate=SSL_NOTHING; + return(n); + } + +int ssl2_write(s, buf, len) +SSL *s; +const char *buf; +int len; + { + unsigned int n,tot; + int i; + + if (SSL_in_init(s) && !s->in_handshake) + { + i=s->handshake_func(s); + if (i < 0) return(i); + if (i == 0) + { + SSLerr(SSL_F_SSL2_WRITE,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + } + + if (s->error) + { + ssl2_write_error(s); + if (s->error) + return(-1); + } + + errno=0; + s->rwstate=SSL_NOTHING; + if (len <= 0) return(len); + + tot=s->s2->wnum; + s->s2->wnum=0; + + n=(len-tot); + for (;;) + { + i=do_ssl_write(s,&(buf[tot]),n); + if (i <= 0) + { + s->s2->wnum=tot; + return(i); + } + if (i == (int)n) return(tot+i); + + n-=i; + tot+=i; + } + } + +static int write_pending(s,buf,len) +SSL *s; +const char *buf; +unsigned int len; + { + int i; + + /* s->s2->wpend_len != 0 MUST be true. */ + + /* check that they have given us the same buffer to + * write */ + if ((s->s2->wpend_tot != (int)len) || (s->s2->wpend_buf != buf)) + { + SSLerr(SSL_F_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); + return(SSL_RWERR_BAD_WRITE_RETRY); + } + + for (;;) + { + errno=0; + if (s->wbio != NULL) + { + s->rwstate=SSL_WRITING; + i=BIO_write(s->wbio, + (char *)&(s->s2->write_ptr[s->s2->wpend_off]), + (unsigned int)s->s2->wpend_len); + } + else + { + SSLerr(SSL_F_WRITE_PENDING,SSL_R_WRITE_BIO_NOT_SET); + i= -1; + } +#ifdef PKT_DEBUG + if (s->debug & 0x01) sleep(1); +#endif + if (i == s->s2->wpend_len) + { + s->s2->wpend_len=0; + s->rwstate=SSL_NOTHING; + return(s->s2->wpend_ret); + } + else if (i <= 0) + return(i); + s->s2->wpend_off+=i; + s->s2->wpend_len-=i; + } + } + +static int do_ssl_write(s, buf, len) +SSL *s; +const char *buf; +unsigned int len; + { + unsigned int j,k,olen,p,mac_size,bs; + register unsigned char *pp; + + olen=len; + + /* first check if there is data from an encryption waiting to + * be sent - it must be sent because the other end is waiting. + * This will happen with non-blocking IO. We print it and then + * return. + */ + if (s->s2->wpend_len != 0) return(write_pending(s,buf,len)); + + /* set mac_size to mac size */ + if (s->s2->clear_text) + mac_size=0; + else + mac_size=EVP_MD_size(s->write_hash); + + /* lets set the pad p */ + if (s->s2->clear_text) + { + if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER) + len=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER; + p=0; + s->s2->three_byte_header=0; + /* len=len; */ + } + else + { + bs=EVP_CIPHER_CTX_block_size(s->enc_read_ctx); + j=len+mac_size; + if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) && + (!s->s2->escape)) + { + if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER) + j=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER; + /* set k to the max number of bytes with 2 + * byte header */ + k=j-(j%bs); + /* how many data bytes? */ + len=k-mac_size; + s->s2->three_byte_header=0; + p=0; + } + else if ((bs <= 1) && (!s->s2->escape)) + { + /* len=len; */ + s->s2->three_byte_header=0; + p=0; + } + else /* 3 byte header */ + { + /*len=len; */ + p=(j%bs); + p=(p == 0)?0:(bs-p); + if (s->s2->escape) + s->s2->three_byte_header=1; + else + s->s2->three_byte_header=(p == 0)?0:1; + } + } + /* mac_size is the number of MAC bytes + * len is the number of data bytes we are going to send + * p is the number of padding bytes + * if p == 0, it is a 2 byte header */ + + s->s2->wlength=len; + s->s2->padding=p; + s->s2->mac_data= &(s->s2->wbuf[3]); + s->s2->wact_data= &(s->s2->wbuf[3+mac_size]); + /* we copy the data into s->s2->wbuf */ + memcpy(s->s2->wact_data,buf,len); +#ifdef PURIFY + if (p) + memset(&(s->s2->wact_data[len]),0,p); +#endif + + if (!s->s2->clear_text) + { + s->s2->wact_data_length=len+p; + ssl2_mac(s,s->s2->mac_data,1); + s->s2->wlength+=p+mac_size; + ssl2_enc(s,1); + } + + /* package up the header */ + s->s2->wpend_len=s->s2->wlength; + if (s->s2->three_byte_header) /* 3 byte header */ + { + pp=s->s2->mac_data; + pp-=3; + pp[0]=(s->s2->wlength>>8)&(THREE_BYTE_MASK>>8); + if (s->s2->escape) pp[0]|=SEC_ESC_BIT; + pp[1]=s->s2->wlength&0xff; + pp[2]=s->s2->padding; + s->s2->wpend_len+=3; + } + else + { + pp=s->s2->mac_data; + pp-=2; + pp[0]=((s->s2->wlength>>8)&(TWO_BYTE_MASK>>8))|TWO_BYTE_BIT; + pp[1]=s->s2->wlength&0xff; + s->s2->wpend_len+=2; + } + s->s2->write_ptr=pp; + + INC32(s->s2->write_sequence); /* expect next number */ + + /* lets try to actually write the data */ + s->s2->wpend_tot=olen; + s->s2->wpend_buf=(char *)buf; + + s->s2->wpend_ret=len; + + s->s2->wpend_off=0; + return(write_pending(s,buf,olen)); + } + +int ssl2_part_read(s,f,i) +SSL *s; +unsigned long f; +int i; + { + unsigned char *p; + int j; + + /* check for error */ + if ((s->init_num == 0) && (i >= 3)) + { + p=(unsigned char *)s->init_buf->data; + if (p[0] == SSL2_MT_ERROR) + { + j=(p[1]<<8)|p[2]; + SSLerr((int)f,ssl_mt_error(j)); + } + } + + if (i < 0) + { + /* ssl2_return_error(s); */ + /* for non-blocking io, + * this is not fatal */ + return(i); + } + else + { + s->init_num+=i; + return(0); + } + } + +int ssl2_do_write(s) +SSL *s; + { + int ret; + + ret=ssl2_write(s,(char *)&(s->init_buf->data[s->init_off]), + s->init_num); + if (ret == s->init_num) + return(1); + if (ret < 0) + return(-1); + s->init_off+=ret; + s->init_num-=ret; + return(0); + } + +static int ssl_mt_error(n) +int n; + { + int ret; + + switch (n) + { + case SSL2_PE_NO_CIPHER: + ret=SSL_R_PEER_ERROR_NO_CIPHER; + break; + case SSL2_PE_NO_CERTIFICATE: + ret=SSL_R_PEER_ERROR_NO_CERTIFICATE; + break; + case SSL2_PE_BAD_CERTIFICATE: + ret=SSL_R_PEER_ERROR_CERTIFICATE; + break; + case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE: + ret=SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE; + break; + default: + ret=SSL_R_UNKNOWN_REMOTE_ERROR_TYPE; + break; + } + return(ret); + } diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c new file mode 100644 index 0000000000..0112397e53 --- /dev/null +++ b/ssl/s2_srvr.c @@ -0,0 +1,983 @@ +/* ssl/s2_srvr.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#ifdef NO_MD5 +#include "md5.h" +#endif +#include "bio.h" +#include "rand.h" +#include "objects.h" +#include "ssl_locl.h" +#include "evp.h" + +#ifndef NOPROTO +static int get_client_master_key(SSL *s); +static int get_client_hello(SSL *s); +static int server_hello(SSL *s); +static int get_client_finished(SSL *s); +static int server_verify(SSL *s); +static int server_finish(SSL *s); +static int request_certificate(SSL *s); +static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from, + unsigned char *to,int padding); +#else +static int get_client_master_key(); +static int get_client_hello(); +static int server_hello(); +static int get_client_finished(); +static int server_verify(); +static int server_finish(); +static int request_certificate(); +static int ssl_rsa_private_decrypt(); +#endif + +#define BREAK break + +static SSL_METHOD *ssl2_get_server_method(ver) +int ver; + { + if (ver == 2) + return(SSLv2_server_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv2_server_method() + { + static int init=1; + static SSL_METHOD SSLv2_server_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv2_server_data,(char *)sslv2_base_method(), + sizeof(SSL_METHOD)); + SSLv2_server_data.ssl_accept=ssl2_accept; + SSLv2_server_data.get_ssl_method=ssl2_get_server_method; + } + return(&SSLv2_server_data); + } + +int ssl2_accept(s) +SSL *s; + { + unsigned long l=time(NULL); + BUF_MEM *buf=NULL; + int ret= -1; + long num1; + void (*cb)()=NULL; + int new_state,state; + + RAND_seed((unsigned char *)&l,sizeof(l)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + /* init things to blank */ + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + + if (((s->session == NULL) || (s->session->cert == NULL)) && + (s->cert == NULL)) + { + SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET); + return(-1); + } + + errno=0; + for (;;) + { + state=s->state; + + switch (s->state) + { + case SSL_ST_BEFORE: + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + case SSL_ST_OK|SSL_ST_ACCEPT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=2; + s->type=SSL_ST_ACCEPT; + + buf=s->init_buf; + if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL)) + { ret= -1; goto end; } + if (!BUF_MEM_grow(buf,(int) + SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) + { ret= -1; goto end; } + s->init_buf=buf; + s->init_num=0; + s->ctx->sess_accept++; + s->handshake_func=ssl2_accept; + s->state=SSL2_ST_GET_CLIENT_HELLO_A; + BREAK; + + case SSL2_ST_GET_CLIENT_HELLO_A: + case SSL2_ST_GET_CLIENT_HELLO_B: + case SSL2_ST_GET_CLIENT_HELLO_C: + s->shutdown=0; + ret=get_client_hello(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_SEND_SERVER_HELLO_A; + BREAK; + + case SSL2_ST_SEND_SERVER_HELLO_A: + case SSL2_ST_SEND_SERVER_HELLO_B: + ret=server_hello(s); + if (ret <= 0) goto end; + s->init_num=0; + if (!s->hit) + { + s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_A; + BREAK; + } + else + { + s->state=SSL2_ST_SERVER_START_ENCRYPTION; + BREAK; + } + case SSL2_ST_GET_CLIENT_MASTER_KEY_A: + case SSL2_ST_GET_CLIENT_MASTER_KEY_B: + ret=get_client_master_key(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_SERVER_START_ENCRYPTION; + BREAK; + + case SSL2_ST_SERVER_START_ENCRYPTION: + /* Ok we how have sent all the stuff needed to + * start encrypting, the next packet back will + * be encrypted. */ + if (!ssl2_enc_init(s,0)) + { ret= -1; goto end; } + s->s2->clear_text=0; + s->state=SSL2_ST_SEND_SERVER_VERIFY_A; + BREAK; + + case SSL2_ST_SEND_SERVER_VERIFY_A: + case SSL2_ST_SEND_SERVER_VERIFY_B: + ret=server_verify(s); + if (ret <= 0) goto end; + s->init_num=0; + if (s->hit) + { + /* If we are in here, we have been + * buffering the output, so we need to + * flush it and remove buffering from + * future traffic */ + s->state=SSL2_ST_SEND_SERVER_VERIFY_C; + BREAK; + } + else + { + s->state=SSL2_ST_GET_CLIENT_FINISHED_A; + break; + } + + case SSL2_ST_SEND_SERVER_VERIFY_C: + /* get the number of bytes to write */ + num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL); + if (num1 != 0) + { + s->rwstate=SSL_WRITING; + num1=BIO_flush(s->wbio); + if (num1 <= 0) { ret= -1; goto end; } + s->rwstate=SSL_NOTHING; + } + + /* flushed and now remove buffering */ + s->wbio=BIO_pop(s->wbio); + + s->state=SSL2_ST_GET_CLIENT_FINISHED_A; + BREAK; + + case SSL2_ST_GET_CLIENT_FINISHED_A: + case SSL2_ST_GET_CLIENT_FINISHED_B: + ret=get_client_finished(s); + if (ret <= 0) + goto end; + s->init_num=0; + s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_A; + BREAK; + + case SSL2_ST_SEND_REQUEST_CERTIFICATE_A: + case SSL2_ST_SEND_REQUEST_CERTIFICATE_B: + case SSL2_ST_SEND_REQUEST_CERTIFICATE_C: + case SSL2_ST_SEND_REQUEST_CERTIFICATE_D: + /* don't do a 'request certificate' if we + * don't want to, or we already have one, and + * we only want to do it once. */ + if (!(s->verify_mode & SSL_VERIFY_PEER) || + ((s->session->peer != NULL) && + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE))) + { + s->state=SSL2_ST_SEND_SERVER_FINISHED_A; + break; + } + else + { + ret=request_certificate(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL2_ST_SEND_SERVER_FINISHED_A; + } + BREAK; + + case SSL2_ST_SEND_SERVER_FINISHED_A: + case SSL2_ST_SEND_SERVER_FINISHED_B: + ret=server_finish(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL_ST_OK; + break; + + case SSL_ST_OK: + BUF_MEM_free(s->init_buf); + s->init_buf=NULL; + s->init_num=0; + /* ERR_clear_error();*/ + + ssl_update_cache(s,SSL_SESS_CACHE_SERVER); + + s->ctx->sess_accept_good++; + /* s->server=1; */ + ret=1; + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + + goto end; + BREAK; + + default: + SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_UNKNOWN_STATE); + ret= -1; + goto end; + BREAK; + } + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_ACCEPT_LOOP,1); + s->state=new_state; + } + } +end: + s->in_handshake--; + if (cb != NULL) + cb(s,SSL_CB_ACCEPT_EXIT,ret); + return(ret); + } + +static int get_client_master_key(s) +SSL *s; + { + int export,i,n,keya,ek; + unsigned char *p; + SSL_CIPHER *cp; + EVP_CIPHER *c; + EVP_MD *md; + + p=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A) + { + i=ssl2_read(s,(char *)&(p[s->init_num]),10-s->init_num); + + if (i < (10-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i)); + if (*(p++) != SSL2_MT_CLIENT_MASTER_KEY) + { + if (p[-1] != SSL2_MT_ERROR) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_READ_WRONG_PACKET_TYPE); + } + else + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, + SSL_R_PEER_ERROR); + return(-1); + } + + cp=ssl2_get_cipher_by_char(p); + if (cp == NULL) + { + ssl2_return_error(s,SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, + SSL_R_NO_CIPHER_MATCH); + return(-1); + } + s->session->cipher= cp; + + p+=3; + n2s(p,i); s->s2->tmp.clear=i; + n2s(p,i); s->s2->tmp.enc=i; + n2s(p,i); s->session->key_arg_length=i; + s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B; + s->init_num=0; + } + + /* SSL2_ST_GET_CLIENT_MASTER_KEY_B */ + p=(unsigned char *)s->init_buf->data; + keya=s->session->key_arg_length; + n=s->s2->tmp.clear+s->s2->tmp.enc+keya - s->init_num; + i=ssl2_read(s,(char *)&(p[s->init_num]),n); + if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i)); + + memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]), + (unsigned int)keya); + + if (s->session->cert->key->privatekey == NULL) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY); + return(-1); + } + i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc, + &(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]), + (s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING); + + export=(s->session->cipher->algorithms & SSL_EXP)?1:0; + + if (!ssl_cipher_get_evp(s->session->cipher,&c,&md)) + { + ssl2_return_error(s,SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS); + return(0); + } + + if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) + { + export=1; + ek=8; + } + else + ek=5; + + /* bad decrypt */ +#if 1 + /* If a bad decrypt, continue with protocol but with a + * dud master secret */ + if ((i < 0) || + ((!export && (i != EVP_CIPHER_key_length(c))) + || ( export && ((i != ek) || (s->s2->tmp.clear+i != + EVP_CIPHER_key_length(c)))))) + { + if (export) + i=ek; + else + i=EVP_CIPHER_key_length(c); + RAND_bytes(p,i); + } +#else + if (i < 0) + { + error=1; + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_RSA_DECRYPT); + } + /* incorrect number of key bytes for non export cipher */ + else if ((!export && (i != EVP_CIPHER_key_length(c))) + || ( export && ((i != ek) || (s->s2->tmp.clear+i != + EVP_CIPHER_key_length(c))))) + { + error=1; + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_WRONG_NUMBER_OF_KEY_BITS); + } + if (error) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } +#endif + + if (export) i+=s->s2->tmp.clear; + s->session->master_key_length=i; + memcpy(s->session->master_key,p,(unsigned int)i); + return(1); + } + +static int get_client_hello(s) +SSL *s; + { + int i,n; + unsigned char *p; + STACK *cs; /* a stack of SSL_CIPHERS */ + STACK *cl; /* the ones we want to use */ + int z; + + /* This is a bit of a hack to check for the correct packet + * type the first time round. */ + if (s->state == SSL2_ST_GET_CLIENT_HELLO_A) + { + s->first_packet=1; + s->state=SSL2_ST_GET_CLIENT_HELLO_B; + } + + p=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_GET_CLIENT_HELLO_B) + { + i=ssl2_read(s,(char *)&(p[s->init_num]),9-s->init_num); + if (i < (9-s->init_num)) + return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i)); + + if (*(p++) != SSL2_MT_CLIENT_HELLO) + { + if (p[-1] != SSL2_MT_ERROR) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_READ_WRONG_PACKET_TYPE); + } + else + SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); + return(-1); + } + n2s(p,i); + if (i < s->version) s->version=i; + n2s(p,i); s->s2->tmp.cipher_spec_length=i; + n2s(p,i); s->s2->tmp.session_id_length=i; + n2s(p,i); s->s2->challenge_length=i; + if ( (i < SSL2_MIN_CHALLENGE_LENGTH) || + (i > SSL2_MAX_CHALLENGE_LENGTH)) + { + SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_INVALID_CHALLENGE_LENGTH); + return(-1); + } + s->state=SSL2_ST_GET_CLIENT_HELLO_C; + s->init_num=0; + } + + /* SSL2_ST_GET_CLIENT_HELLO_C */ + p=(unsigned char *)s->init_buf->data; + n=s->s2->tmp.cipher_spec_length+s->s2->challenge_length+ + s->s2->tmp.session_id_length-s->init_num; + i=ssl2_read(s,(char *)&(p[s->init_num]),n); + if (i != n) return(ssl2_part_read(s,SSL_F_GET_CLIENT_HELLO,i)); + + /* get session-id before cipher stuff so we can get out session + * structure if it is cached */ + /* session-id */ + if ((s->s2->tmp.session_id_length != 0) && + (s->s2->tmp.session_id_length != SSL2_SSL_SESSION_ID_LENGTH)) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_BAD_SSL_SESSION_ID_LENGTH); + return(-1); + } + + if (s->s2->tmp.session_id_length == 0) + { + if (!ssl_get_new_session(s,1)) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } + } + else + { + i=ssl_get_prev_session(s,s->s2->tmp.session_id_length, + &(p[s->s2->tmp.cipher_spec_length])); + if (i == 1) + { /* previous session */ + s->hit=1; + } + else if (i == -1) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } + else + { + if (s->cert == NULL) + { + ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE); + SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_NO_CERTIFICATE_SET); + return(-1); + } + + if (!ssl_get_new_session(s,1)) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } + } + } + + if (!s->hit) + { + cs=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.cipher_spec_length, + &s->session->ciphers); + if (cs == NULL) goto mem_err; + + cl=ssl_get_ciphers_by_id(s); + + for (z=0; z<sk_num(cs); z++) + { + if (sk_find(cl,sk_value(cs,z)) < 0) + { + sk_delete(cs,z); + z--; + } + } + + /* s->session->ciphers should now have a list of + * ciphers that are on both the client and server. + * This list is ordered by the order the client sent + * the ciphers. + */ + } + p+=s->s2->tmp.cipher_spec_length; + /* done cipher selection */ + + /* session id extracted already */ + p+=s->s2->tmp.session_id_length; + + /* challenge */ + memcpy(s->s2->challenge,p,(unsigned int)s->s2->challenge_length); + return(1); +mem_err: + SSLerr(SSL_F_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); + return(0); + } + +static int server_hello(s) +SSL *s; + { + unsigned char *p,*d; + int n,hit; + STACK *sk; + + p=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_SEND_SERVER_HELLO_A) + { + d=p+11; + *(p++)=SSL2_MT_SERVER_HELLO; /* type */ + hit=s->hit; + *(p++)=(unsigned char)hit; + if (!hit) + { /* else add cert to session */ + CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); + if (s->session->cert != NULL) + ssl_cert_free(s->session->cert); + s->session->cert=s->cert; + } + else /* We have a session id-cache hit, if the + * session-id has no certificate listed against + * the 'cert' structure, grab the 'old' one + * listed against the SSL connection */ + { + if (s->session->cert == NULL) + { + CRYPTO_add(&s->cert->references,1, + CRYPTO_LOCK_SSL_CERT); + s->session->cert=s->cert; + } + } + + if (s->session->cert == NULL) + { + ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE); + SSLerr(SSL_F_SERVER_HELLO,SSL_R_NO_CERTIFICATE_SPECIFIED); + return(-1); + } + + if (hit) + { + *(p++)=0; /* no certificate type */ + s2n(s->version,p); /* version */ + s2n(0,p); /* cert len */ + s2n(0,p); /* ciphers len */ + } + else + { + /* EAY EAY */ + /* put certificate type */ + *(p++)=SSL2_CT_X509_CERTIFICATE; + s2n(s->version,p); /* version */ + n=i2d_X509(s->cert->key->x509,NULL); + s2n(n,p); /* certificate length */ + i2d_X509(s->cert->key->x509,&d); + n=0; + + /* lets send out the ciphers we like in the + * prefered order */ + sk= s->session->ciphers; + n=ssl_cipher_list_to_bytes(s,s->session->ciphers,d); + d+=n; + s2n(n,p); /* add cipher length */ + } + + /* make and send conn_id */ + s2n(SSL2_CONNECTION_ID_LENGTH,p); /* add conn_id length */ + s->s2->conn_id_length=SSL2_CONNECTION_ID_LENGTH; + RAND_bytes(s->s2->conn_id,(int)s->s2->conn_id_length); + memcpy(d,s->s2->conn_id,SSL2_CONNECTION_ID_LENGTH); + d+=SSL2_CONNECTION_ID_LENGTH; + + s->state=SSL2_ST_SEND_SERVER_HELLO_B; + s->init_num=d-(unsigned char *)s->init_buf->data; + s->init_off=0; + } + /* SSL2_ST_SEND_SERVER_HELLO_B */ + /* If we are using TCP/IP, the performace is bad if we do 2 + * writes without a read between them. This occurs when + * Session-id reuse is used, so I will put in a buffering module + */ + if (s->hit) + { + BIO *buf; + + if (s->bbio == NULL) + { + buf=BIO_new(BIO_f_buffer()); + if (buf == NULL) + { + SSLerr(SSL_F_SERVER_HELLO,ERR_LIB_BUF); + return(-1); + } + s->bbio=buf; + } + else + buf=s->bbio; + + BIO_reset(buf); + s->wbio=BIO_push(buf,s->wbio); + } + + return(ssl2_do_write(s)); + } + +static int get_client_finished(s) +SSL *s; + { + unsigned char *p; + int i; + + p=(unsigned char *)s->init_buf->data; + if (s->state == SSL2_ST_GET_CLIENT_FINISHED_A) + { + i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num); + if (i < 1-s->init_num) + return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i)); + + if (*p != SSL2_MT_CLIENT_FINISHED) + { + if (*p != SSL2_MT_ERROR) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE); + } + else + SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_PEER_ERROR); + return(-1); + } + s->init_num=0; + s->state=SSL2_ST_GET_CLIENT_FINISHED_B; + } + + /* SSL2_ST_GET_CLIENT_FINISHED_B */ + i=ssl2_read(s,(char *)&(p[s->init_num]),s->s2->conn_id_length-s->init_num); + if (i < (int)s->s2->conn_id_length-s->init_num) + { + return(ssl2_part_read(s,SSL_F_GET_CLIENT_FINISHED,i)); + } + if (memcmp(p,s->s2->conn_id,(unsigned int)s->s2->conn_id_length) != 0) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_FINISHED,SSL_R_CONNECTION_ID_IS_DIFFERENT); + return(-1); + } + return(1); + } + +static int server_verify(s) +SSL *s; + { + unsigned char *p; + + if (s->state == SSL2_ST_SEND_SERVER_VERIFY_A) + { + p=(unsigned char *)s->init_buf->data; + *(p++)=SSL2_MT_SERVER_VERIFY; + memcpy(p,s->s2->challenge,(unsigned int)s->s2->challenge_length); + /* p+=s->s2->challenge_length; */ + + s->state=SSL2_ST_SEND_SERVER_VERIFY_B; + s->init_num=s->s2->challenge_length+1; + s->init_off=0; + } + return(ssl2_do_write(s)); + } + +static int server_finish(s) +SSL *s; + { + unsigned char *p; + + if (s->state == SSL2_ST_SEND_SERVER_FINISHED_A) + { + p=(unsigned char *)s->init_buf->data; + *(p++)=SSL2_MT_SERVER_FINISHED; + + memcpy(p,s->session->session_id, + (unsigned int)s->session->session_id_length); + /* p+=s->session->session_id_length; */ + + s->state=SSL2_ST_SEND_SERVER_FINISHED_B; + s->init_num=s->session->session_id_length+1; + s->init_off=0; + } + + /* SSL2_ST_SEND_SERVER_FINISHED_B */ + return(ssl2_do_write(s)); + } + +/* send the request and check the response */ +static int request_certificate(s) +SSL *s; + { + unsigned char *p,*p2,*buf2; + unsigned char *ccd; + int i,j,ctype,ret= -1; + X509 *x509=NULL; + STACK *sk=NULL; + + ccd=s->s2->tmp.ccl; + if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_A) + { + p=(unsigned char *)s->init_buf->data; + *(p++)=SSL2_MT_REQUEST_CERTIFICATE; + *(p++)=SSL2_AT_MD5_WITH_RSA_ENCRYPTION; + RAND_bytes(ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH); + memcpy(p,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH); + + s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_B; + s->init_num=SSL2_MIN_CERT_CHALLENGE_LENGTH+2; + s->init_off=0; + } + + if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_B) + { + i=ssl2_do_write(s); + if (i <= 0) + { + ret=i; + goto end; + } + + s->init_num=0; + s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_C; + } + + if (s->state == SSL2_ST_SEND_REQUEST_CERTIFICATE_C) + { + p=(unsigned char *)s->init_buf->data; + i=ssl2_read(s,(char *)&(p[s->init_num]),6-s->init_num); + if (i < 3) + { + ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i); + goto end; + } + + if ((*p == SSL2_MT_ERROR) && (i >= 3)) + { + n2s(p,i); + if (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + { + ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE); + SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + goto end; + } + ret=1; + goto end; + } + if ((*(p++) != SSL2_MT_CLIENT_CERTIFICATE) || (i < 6)) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_SHORT_READ); + goto end; + } + /* ok we have a response */ + /* certificate type, there is only one right now. */ + ctype= *(p++); + if (ctype != SSL2_AT_MD5_WITH_RSA_ENCRYPTION) + { + ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE); + SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_RESPONSE_ARGUMENT); + goto end; + } + n2s(p,i); s->s2->tmp.clen=i; + n2s(p,i); s->s2->tmp.rlen=i; + s->state=SSL2_ST_SEND_REQUEST_CERTIFICATE_D; + s->init_num=0; + } + + /* SSL2_ST_SEND_REQUEST_CERTIFICATE_D */ + p=(unsigned char *)s->init_buf->data; + j=s->s2->tmp.clen+s->s2->tmp.rlen-s->init_num; + i=ssl2_read(s,(char *)&(p[s->init_num]),j); + if (i < j) + { + ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i); + goto end; + } + + x509=(X509 *)d2i_X509(NULL,&p,(long)s->s2->tmp.clen); + if (x509 == NULL) + { + SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_X509_LIB); + goto msg_end; + } + + if (((sk=sk_new_null()) == NULL) || (!sk_push(sk,(char *)x509))) + { + SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto msg_end; + } + + i=ssl_verify_cert_chain(s,sk); + + if (i) /* we like the packet, now check the chksum */ + { + EVP_MD_CTX ctx; + EVP_PKEY *pkey=NULL; + + EVP_VerifyInit(&ctx,EVP_md5()); + EVP_VerifyUpdate(&ctx,s->s2->key_material, + (unsigned int)s->s2->key_material_length); + EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH); + + i=i2d_X509(s->session->cert->key->x509,NULL); + buf2=(unsigned char *)Malloc((unsigned int)i); + if (buf2 == NULL) + { + SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto msg_end; + } + p2=buf2; + i=i2d_X509(s->session->cert->key->x509,&p2); + EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i); + Free(buf2); + + pkey=X509_get_pubkey(x509); + if (pkey == NULL) goto end; + i=EVP_VerifyFinal(&ctx,p,s->s2->tmp.rlen,pkey); + memset(&ctx,0,sizeof(ctx)); + + if (i) + { + if (s->session->peer != NULL) + X509_free(s->session->peer); + s->session->peer=x509; + CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); + ret=1; + goto end; + } + else + { + SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_BAD_CHECKSUM); + goto msg_end; + } + } + else + { +msg_end: + ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE); + } +end: + if (sk != NULL) sk_free(sk); + if (x509 != NULL) X509_free(x509); + return(ret); + } + +static int ssl_rsa_private_decrypt(c, len, from, to,padding) +CERT *c; +int len; +unsigned char *from; +unsigned char *to; +int padding; + { + RSA *rsa; + int i; + + if ((c == NULL) || (c->key->privatekey == NULL)) + { + SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY); + return(-1); + } + if (c->key->privatekey->type != EVP_PKEY_RSA) + { + SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA); + return(-1); + } + rsa=c->key->privatekey->pkey.rsa; + + /* we have the public key */ + i=RSA_private_decrypt(len,from,to,rsa,padding); + if (i < 0) + SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,ERR_R_RSA_LIB); + return(i); + } + diff --git a/ssl/s3_both.c b/ssl/s3_both.c new file mode 100644 index 0000000000..1d710eef2e --- /dev/null +++ b/ssl/s3_both.c @@ -0,0 +1,444 @@ +/* ssl/s3_both.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "buffer.h" +#include "rand.h" +#include "objects.h" +#include "evp.h" +#include "x509.h" +#include "ssl_locl.h" + +#define BREAK break + +/* SSL3err(SSL_F_SSL3_GET_FINISHED,SSL_R_EXCESSIVE_MESSAGE_SIZE); + */ + +unsigned char ssl3_server_finished_const[4]= + {SSL3_MD_SERVER_FINISHED_CONST}; +unsigned char ssl3_client_finished_const[4]= + {SSL3_MD_CLIENT_FINISHED_CONST}; + +int ssl3_send_finished(s,a,b,sender) +SSL *s; +int a; +int b; +unsigned char *sender; + { + unsigned char *p,*d; + int i; + unsigned long l; + + if (s->state == a) + { + d=(unsigned char *)s->init_buf->data; + p= &(d[4]); + + i=ssl3_final_finish_mac(s,&(s->s3->finish_dgst1),sender,p); + p+=i; + l=i; + i=ssl3_final_finish_mac(s,&(s->s3->finish_dgst2),sender,p); + l+=i; + + *(d++)=SSL3_MT_FINISHED; + l2n3(l,d); + s->init_num=(int)l+4; + s->init_off=0; + + s->state=b; + } + + /* SSL3_ST_SEND_xxxxxx_HELLO_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } + +int ssl3_get_finished(s,a,b,sender) +SSL *s; +int a; +int b; +unsigned char *sender; + { + int al,i,j,ok; + long n; + unsigned char *p; + + /* the mac has already been generated when we received the + * change cipher spec message and is in s->s3->tmp.in_dgst[12] + */ + + n=ssl3_get_message(s, + a, + b, + SSL3_MT_FINISHED, + 64, /* should actually be 36+4 :-) */ + &ok); + + if (!ok) return((int)n); + + /* If this occurs if we has missed a message */ + if (!s->s3->change_cipher_spec) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_GOT_A_FIN_BEFORE_A_CCS); + goto f_err; + } + s->s3->change_cipher_spec=0; + + p=(unsigned char *)s->init_buf->data; + + i=EVP_MD_CTX_size(&(s->s3->finish_dgst1)); + j=EVP_MD_CTX_size(&(s->s3->finish_dgst2)); + + if ((i+j) != n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_BAD_DIGEST_LENGTH); + goto f_err; + } + + if ( (memcmp( p, &(s->s3->tmp.finish_md1[0]),i) != 0) || + (memcmp(&(p[i]),&(s->s3->tmp.finish_md2[0]),j) != 0)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED); + goto f_err; + } + + return(1); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + return(0); + } + +/* for these 2 messages, we need to + * ssl->enc_read_ctx re-init + * ssl->s3->read_sequence zero + * ssl->s3->read_mac_secret re-init + * ssl->session->read_sym_enc assign + * ssl->session->read_compression assign + * ssl->session->read_hash assign + */ +int ssl3_send_change_cipher_spec(s,a,b) +SSL *s; +int a,b; + { + unsigned char *p; + + if (s->state == a) + { + p=(unsigned char *)s->init_buf->data; + *p=SSL3_MT_CCS; + s->init_num=1; + s->init_off=0; + + s->state=b; + } + + /* SSL3_ST_CW_CHANGE_B */ + return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); + } + +unsigned long ssl3_output_cert_chain(s,x) +SSL *s; +X509 *x; + { + unsigned char *p; + int n,i; + unsigned long l=7; + BUF_MEM *buf; + X509_STORE_CTX xs_ctx; + X509_OBJECT obj; + + X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL); + + buf=s->init_buf; + for (;;) + { + n=i2d_X509(x,NULL); + if (!BUF_MEM_grow(buf,(int)(n+l+3))) + { + SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); + return(0); + } + p=(unsigned char *)&(buf->data[l]); + l2n3(n,p); + i2d_X509(x,&p); + l+=n+3; + if (X509_NAME_cmp(X509_get_subject_name(x), + X509_get_issuer_name(x)) == 0) break; + + i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509, + X509_get_issuer_name(x),&obj); + if (i <= 0) break; + x=obj.data.x509; + /* Count is one too high since the X509_STORE_get uped the + * ref count */ + X509_free(x); + } + + X509_STORE_CTX_cleanup(&xs_ctx); + + l-=7; + p=(unsigned char *)&(buf->data[4]); + l2n3(l,p); + l+=3; + p=(unsigned char *)&(buf->data[0]); + *(p++)=SSL3_MT_CERTIFICATE; + l2n3(l,p); + l+=4; + return(l); + } + +long ssl3_get_message(s,st1,stn,mt,max,ok) +SSL *s; +int st1,stn,mt; +long max; +int *ok; + { + unsigned char *p; + unsigned long l; + long n; + int i,al; + + if (s->s3->tmp.reuse_message) + { + s->s3->tmp.reuse_message=0; + if ((mt >= 0) && (s->s3->tmp.message_type != mt)) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + *ok=1; + return((int)s->s3->tmp.message_size); + } + + p=(unsigned char *)s->init_buf->data; + + if (s->state == st1) + { + i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE, + (char *)&(p[s->init_num]), + 4-s->init_num); + if (i < (4-s->init_num)) + { + *ok=0; + return(ssl3_part_read(s,i)); + } + + if ((mt >= 0) && (*p != mt)) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + s->s3->tmp.message_type= *(p++); + + n2l3(p,l); + if (l > (unsigned long)max) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); + goto f_err; + } + if (l && !BUF_MEM_grow(s->init_buf,(int)l)) + { + SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB); + goto err; + } + s->s3->tmp.message_size=l; + s->state=stn; + + s->init_num=0; + } + + /* next state (stn) */ + p=(unsigned char *)s->init_buf->data; + n=s->s3->tmp.message_size; + if (n > 0) + { + i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE, + (char *)&(p[s->init_num]),(int)n); + if (i != (int)n) + { + *ok=0; + return(ssl3_part_read(s,i)); + } + } + *ok=1; + return(n); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + *ok=0; + return(-1); + } + +int ssl_cert_type(x,pkey) +X509 *x; +EVP_PKEY *pkey; + { + EVP_PKEY *pk; + int ret= -1,i,j; + + if (pkey == NULL) + pk=X509_get_pubkey(x); + else + pk=pkey; + if (pk == NULL) goto err; + + i=pk->type; + if (i == EVP_PKEY_RSA) + { + ret=SSL_PKEY_RSA_ENC; + if (x != NULL) + { + j=X509_get_ext_count(x); + /* check to see if this is a signing only certificate */ + /* EAY EAY EAY EAY */ + } + } + else if (i == EVP_PKEY_DSA) + { + ret=SSL_PKEY_DSA_SIGN; + } + else if (i == EVP_PKEY_DH) + { + /* if we just have a key, we needs to be guess */ + + if (x == NULL) + ret=SSL_PKEY_DH_DSA; + else + { + j=X509_get_signature_type(x); + if (j == EVP_PKEY_RSA) + ret=SSL_PKEY_DH_RSA; + else if (j== EVP_PKEY_DSA) + ret=SSL_PKEY_DH_DSA; + else ret= -1; + } + } + else + ret= -1; + +err: + return(ret); + } + +int ssl_verify_alarm_type(type) +int type; + { + int al; + + switch(type) + { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + al=SSL3_AD_BAD_CERTIFICATE; + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + al=SSL3_AD_CERTIFICATE_EXPIRED; + break; + default: + al=SSL3_AD_CERTIFICATE_UNKNOWN; + break; + } + return(al); + } + +int ssl3_setup_buffers(s) +SSL *s; + { + unsigned char *p; + unsigned int extra; + + if (s->s3->rbuf.buf == NULL) + { + if (s->ctx->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) + extra=SSL3_RT_MAX_EXTRA; + else + extra=0; + if ((p=(unsigned char *)Malloc(SSL3_RT_MAX_PACKET_SIZE+extra)) + == NULL) + goto err; + s->s3->rbuf.buf=p; + } + + if (s->s3->wbuf.buf == NULL) + { + if ((p=(unsigned char *)Malloc(SSL3_RT_MAX_PACKET_SIZE)) + == NULL) + goto err; + s->s3->wbuf.buf=p; + } + s->packet= &(s->s3->rbuf.buf[0]); + return(1); +err: + SSLerr(SSL_F_SSL3_SETUP_BUFFERS,ERR_R_MALLOC_FAILURE); + return(0); + } diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c new file mode 100644 index 0000000000..4f551d20e9 --- /dev/null +++ b/ssl/s3_clnt.c @@ -0,0 +1,1642 @@ +/* ssl/s3_clnt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "buffer.h" +#include "rand.h" +#include "objects.h" +#include "evp.h" +#include "ssl_locl.h" + +#define BREAK break +/* SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_SERVER_DONE,ERR_R_MALLOC_FAILURE); +SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_SHORT); + */ + +#ifndef NOPROTO +static int ssl3_client_hello(SSL *s); +static int ssl3_get_server_hello(SSL *s); +static int ssl3_get_certificate_request(SSL *s); +static int ca_dn_cmp(X509_NAME **a,X509_NAME **b); +static int ssl3_get_server_done(SSL *s); +static int ssl3_send_client_verify(SSL *s); +static int ssl3_send_client_certificate(SSL *s); +static int ssl3_send_client_key_exchange(SSL *s); +static int ssl3_get_key_exchange(SSL *s); +static int ssl3_get_server_certificate(SSL *s); +static int ssl3_check_cert_and_algorithm(SSL *s); +#else +static int ssl3_client_hello(); +static int ssl3_get_server_hello(); +static int ssl3_get_certificate_request(); +static int ca_dn_cmp(); +static int ssl3_get_server_done(); +static int ssl3_send_client_verify(); +static int ssl3_send_client_certificate(); +static int ssl3_send_client_key_exchange(); +static int ssl3_get_key_exchange(); +static int ssl3_get_server_certificate(); +static int ssl3_check_cert_and_algorithm(); +#endif + +static SSL_METHOD *ssl3_get_client_method(ver) +int ver; + { + if (ver == 3) + return(SSLv3_client_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv3_client_method() + { + static int init=1; + static SSL_METHOD SSLv3_client_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv3_client_data,(char *)sslv3_base_method(), + sizeof(SSL_METHOD)); + SSLv3_client_data.ssl_connect=ssl3_connect; + SSLv3_client_data.get_ssl_method=ssl3_get_client_method; + } + return(&SSLv3_client_data); + } + +int ssl3_connect(s) +SSL *s; + { + BUF_MEM *buf; + unsigned long Time=time(NULL),l; + long num1; + void (*cb)()=NULL; + int ret= -1; + BIO *bbio,*under; + int new_state,state,skip=0;; + + RAND_seed((unsigned char *)&Time,sizeof(Time)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + + for (;;) + { + state=s->state; + + switch(s->state) + { + case SSL_ST_RENEGOTIATE: + s->new_session=1; + s->state=SSL_ST_CONNECT; + /* break */ + case SSL_ST_BEFORE: + case SSL_ST_CONNECT: + case SSL_ST_BEFORE|SSL_ST_CONNECT: + case SSL_ST_OK|SSL_ST_CONNECT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=3; + s->type=SSL_ST_CONNECT; + + if (s->init_buf == NULL) + { + if ((buf=BUF_MEM_new()) == NULL) + { + ret= -1; + goto end; + } + if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) + { + ret= -1; + goto end; + } + s->init_buf=buf; + } + + if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } + + /* setup buffing BIO */ + if (s->bbio == NULL) + { + bbio=BIO_new(BIO_f_buffer()); + if (bbio == NULL) + { + SSLerr(SSL_F_SSL3_CONNECT,ERR_LIB_BUF); + ret= -1; + goto end; + } + s->bbio=bbio; + } + else + bbio=s->bbio; + + BIO_reset(bbio); + if (!BIO_set_write_buffer_size(bbio,16*1024)) + { + SSLerr(SSL_F_SSL3_CONNECT,ERR_LIB_BUF); + ret= -1; + goto end; + } + + /* don't push the buffering BIO quite yet */ + + ssl3_init_finished_mac(s); + + s->state=SSL3_ST_CW_CLNT_HELLO_A; + s->ctx->sess_connect++; + s->init_num=0; + break; + + case SSL3_ST_CW_CLNT_HELLO_A: + case SSL3_ST_CW_CLNT_HELLO_B: + + s->shutdown=0; + ret=ssl3_client_hello(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_CR_SRVR_HELLO_A; + s->init_num=0; + + /* turn on buffering for the next lot of output */ + s->wbio=BIO_push(s->bbio,s->wbio); + + break; + + case SSL3_ST_CR_SRVR_HELLO_A: + case SSL3_ST_CR_SRVR_HELLO_B: + ret=ssl3_get_server_hello(s); + if (ret <= 0) goto end; + if (s->hit) + s->state=SSL3_ST_CR_FINISHED_A; + else + s->state=SSL3_ST_CR_CERT_A; + s->init_num=0; + break; + + case SSL3_ST_CR_CERT_A: + case SSL3_ST_CR_CERT_B: + /* Check if it is anon DH */ + if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) + { + ret=ssl3_get_server_certificate(s); + if (ret <= 0) goto end; + } + else + skip=1; + s->state=SSL3_ST_CR_KEY_EXCH_A; + s->init_num=0; + break; + + case SSL3_ST_CR_KEY_EXCH_A: + case SSL3_ST_CR_KEY_EXCH_B: + ret=ssl3_get_key_exchange(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_CR_CERT_REQ_A; + s->init_num=0; + + /* at this point we check that we have the + * required stuff from the server */ + if (!ssl3_check_cert_and_algorithm(s)) + { + ret= -1; + goto end; + } + break; + + case SSL3_ST_CR_CERT_REQ_A: + case SSL3_ST_CR_CERT_REQ_B: + ret=ssl3_get_certificate_request(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_CR_SRVR_DONE_A; + s->init_num=0; + break; + + case SSL3_ST_CR_SRVR_DONE_A: + case SSL3_ST_CR_SRVR_DONE_B: + ret=ssl3_get_server_done(s); + if (ret <= 0) goto end; + if (s->s3->tmp.cert_req) + s->state=SSL3_ST_CW_CERT_A; + else + s->state=SSL3_ST_CW_KEY_EXCH_A; + s->init_num=0; + + break; + + case SSL3_ST_CW_CERT_A: + case SSL3_ST_CW_CERT_B: + case SSL3_ST_CW_CERT_C: + ret=ssl3_send_client_certificate(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_CW_KEY_EXCH_A; + s->init_num=0; + break; + + case SSL3_ST_CW_KEY_EXCH_A: + case SSL3_ST_CW_KEY_EXCH_B: + ret=ssl3_send_client_key_exchange(s); + if (ret <= 0) goto end; + l=s->s3->tmp.new_cipher->algorithms; + /* EAY EAY EAY need to check for DH fix cert + * sent back */ + if ((s->s3->tmp.cert_req) && 1) + { + s->state=SSL3_ST_CW_CERT_VRFY_A; + } + else + { + s->state=SSL3_ST_CW_CHANGE_A; + s->s3->change_cipher_spec=0; + } + + s->init_num=0; + break; + + case SSL3_ST_CW_CERT_VRFY_A: + case SSL3_ST_CW_CERT_VRFY_B: + ret=ssl3_send_client_verify(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_CW_CHANGE_A; + s->init_num=0; + s->s3->change_cipher_spec=0; + break; + + case SSL3_ST_CW_CHANGE_A: + case SSL3_ST_CW_CHANGE_B: + ret=ssl3_send_change_cipher_spec(s, + SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B); + if (ret <= 0) goto end; + s->state=SSL3_ST_CW_FINISHED_A; + s->init_num=0; + + s->session->cipher=s->s3->tmp.new_cipher; + if (!ssl3_setup_key_block(s)) + { + ret= -1; + goto end; + } + + if (!ssl3_change_cipher_state(s, + SSL3_CHANGE_CIPHER_CLIENT_WRITE)) + { + ret= -1; + goto end; + } + + break; + + case SSL3_ST_CW_FINISHED_A: + case SSL3_ST_CW_FINISHED_B: + ret=ssl3_send_finished(s, + SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B, + &(ssl3_client_finished_const[0])); + if (ret <= 0) goto end; + s->state=SSL3_ST_CW_FLUSH; + + /* clear flags */ + s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER; + if (s->hit) + { + s->s3->tmp.next_state=SSL_ST_OK; + if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) + { + s->state=SSL_ST_OK; + s->s3->flags|=SSL3_FLAGS_POP_BUFFER; + s->s3->delay_buf_pop_ret=0; + } + } + else + { + s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A; + } + s->init_num=0; + break; + + case SSL3_ST_CR_FINISHED_A: + case SSL3_ST_CR_FINISHED_B: + + ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, + SSL3_ST_CR_FINISHED_B, + &(ssl3_server_finished_const[0])); + if (ret <= 0) goto end; + + if (s->hit) + s->state=SSL3_ST_CW_CHANGE_A; + else + s->state=SSL_ST_OK; + s->init_num=0; + break; + + case SSL3_ST_CW_FLUSH: + /* number of bytes to be flushed */ + num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL); + if (num1 > 0) + { + s->rwstate=SSL_WRITING; + num1=BIO_flush(s->wbio); + if (num1 <= 0) { ret= -1; goto end; } + s->rwstate=SSL_NOTHING; + } + + s->state=s->s3->tmp.next_state; + break; + + case SSL_ST_OK: + /* clean a few things up */ + ssl3_cleanup_key_block(s); + + BUF_MEM_free(s->init_buf); + s->init_buf=NULL; + + if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER)) + { + /* remove buffering */ + under=BIO_pop(s->wbio); + if (under != NULL) + s->wbio=under; + else + abort(); /* ok */ + + BIO_free(s->bbio); + s->bbio=NULL; + } + /* else do it later */ + + s->init_num=0; + s->new_session=0; + + ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); + + ret=1; + /* s->server=0; */ + s->handshake_func=ssl3_connect; + s->ctx->sess_connect_good++; + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + + goto end; + break; + + default: + SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE); + ret= -1; + goto end; + /* break; */ + } + + /* did we do anything */ + if (!s->s3->tmp.reuse_message && !skip) + { + if (s->debug) BIO_flush(s->wbio); + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_CONNECT_LOOP,1); + s->state=new_state; + } + } + skip=0; + } +end: + if (cb != NULL) + cb(s,SSL_CB_CONNECT_EXIT,ret); + s->in_handshake--; + return(ret); + } + + +static int ssl3_client_hello(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p,*d; + int i; + unsigned long Time,l; + + buf=(unsigned char *)s->init_buf->data; + if (s->state == SSL3_ST_CW_CLNT_HELLO_A) + { + if ((s->session == NULL) || + (s->session->ssl_version != s->version)) + { + if (!ssl_get_new_session(s,0)) + goto err; + } + /* else use the pre-loaded session */ + + p=s->s3->client_random; + Time=time(NULL); /* Time */ + l2n(Time,p); + RAND_bytes(&(p[4]),SSL3_RANDOM_SIZE-sizeof(Time)); + + /* Do the message type and length last */ + d=p= &(buf[4]); + + *(p++)=SSL3_VERSION_MAJOR; + *(p++)=SSL3_VERSION_MINOR; + + /* Random stuff */ + memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); + p+=SSL3_RANDOM_SIZE; + + /* Session ID */ + if (s->new_session) + i=0; + else + i=s->session->session_id_length; + *(p++)=i; + if (i != 0) + { + memcpy(p,s->session->session_id,i); + p+=i; + } + + /* Ciphers supported */ + i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2])); + if (i == 0) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); + goto err; + } + s2n(i,p); + p+=i; + + /* hardwire in the NULL compression algorithm. */ + *(p++)=1; + *(p++)=0; + + l=(p-d); + d=buf; + *(d++)=SSL3_MT_CLIENT_HELLO; + l2n3(l,d); + + s->state=SSL3_ST_CW_CLNT_HELLO_B; + /* number of bytes to write */ + s->init_num=p-buf; + s->init_off=0; + } + + /* SSL3_ST_CW_CLNT_HELLO_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +err: + return(-1); + } + +static int ssl3_get_server_hello(s) +SSL *s; + { + STACK *sk; + SSL_CIPHER *c; + unsigned char *p,*d; + int i,al,ok; + unsigned int j; + long n; + + n=ssl3_get_message(s, + SSL3_ST_CR_SRVR_HELLO_A, + SSL3_ST_CR_SRVR_HELLO_B, + SSL3_MT_SERVER_HELLO, + 300, /* ?? */ + &ok); + + if (!ok) return((int)n); + d=p=(unsigned char *)s->init_buf->data; + + if ((p[0] != SSL3_VERSION_MAJOR) && (p[1] != SSL3_VERSION_MINOR)) + { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION); + goto err; + } + p+=2; + + /* load the server hello data */ + /* load the server random */ + memcpy(s->s3->server_random,p,SSL3_RANDOM_SIZE); + p+=SSL3_RANDOM_SIZE; + + /* get the session-id */ + j= *(p++); + + if ((j != 0) && (j != SSL3_SESSION_ID_SIZE)) + { + /* SSLref returns 16 :-( */ + if (j < SSL2_SSL_SESSION_ID_LENGTH) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_SHORT); + goto f_err; + } + } + if (j == 0) + { + s->hit=0; + memset(s->session->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH); + s->session->session_id_length=0; + } + else if ((j == s->session->session_id_length) && + (memcmp(p,s->session->session_id,j) == 0)) + s->hit=1; + else + { + memcpy(s->session->session_id,p,j); + s->session->session_id_length=j; + s->hit=0; + } + p+=j; + c=ssl_get_cipher_by_char(s,p); + if (c == NULL) + { + /* unknown cipher */ + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED); + goto f_err; + } + p+=ssl_put_cipher_by_char(s,NULL,NULL); + + sk=ssl_get_ciphers_by_id(s); + i=sk_find(sk,(char *)c); + if (i < 0) + { + /* we did not say we would use this cipher */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED); + goto f_err; + } + + if (s->hit && (s->session->cipher != c)) + { + if (!(s->ctx->options & + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + goto f_err; + } + } + s->s3->tmp.new_cipher=c; + + /* lets get the compression algorithm */ + j= *(p++); + if (j != 0) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + goto f_err; + } + + if (p != (d+n)) + { + /* wrong packet length */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH); + goto err; + } + + return(1); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + return(-1); + } + +static int ssl3_get_server_certificate(s) +SSL *s; + { + int al,i,ok,ret= -1; + unsigned long n,nc,llen,l; + X509 *x=NULL; + unsigned char *p,*d,*q; + STACK *sk=NULL; + CERT *c; + EVP_PKEY *pkey=NULL; + + n=ssl3_get_message(s, + SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, + -1, +#if defined(MSDOS) && !defined(WIN32) + 1024*30, /* 30k max cert list :-) */ +#else + 1024*100, /* 100k max cert list :-) */ +#endif + &ok); + + if (!ok) return((int)n); + + if (s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) + { + s->s3->tmp.reuse_message=1; + return(1); + } + + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE); + goto f_err; + } + d=p=(unsigned char *)s->init_buf->data; + + if ((sk=sk_new_null()) == NULL) + { + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto err; + } + + n2l3(p,llen); + if (llen+3 != n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_LENGTH_MISMATCH); + goto f_err; + } + for (nc=0; nc<llen; ) + { + n2l3(p,l); + if ((l+nc+3) > llen) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + + q=p; + x=d2i_X509(NULL,&q,l); + if (x == NULL) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB); + goto f_err; + } + if (q != (p+l)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + if (!sk_push(sk,(char *)x)) + { + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto err; + } + x=NULL; + nc+=l+3; + p=q; + } + + i=ssl_verify_cert_chain(s,sk); + if ((s->verify_mode != SSL_VERIFY_NONE) && (!i)) + { + al=ssl_verify_alarm_type(s->verify_result); + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); + goto f_err; + } + + c=ssl_cert_new(); + if (c == NULL) goto err; + + if (s->session->cert) ssl_cert_free(s->session->cert); + s->session->cert=c; + + c->cert_chain=sk; + x=(X509 *)sk_value(sk,0); + sk=NULL; + + pkey=X509_get_pubkey(x); + + if (EVP_PKEY_missing_parameters(pkey)) + { + x=NULL; + al=SSL3_AL_FATAL; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); + goto f_err; + } + + i=ssl_cert_type(x,pkey); + if (i < 0) + { + x=NULL; + al=SSL3_AL_FATAL; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto f_err; + } + + c->cert_type=i; + x->references++; + if (c->pkeys[i].x509 != NULL) + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509=x; + c->key= &(c->pkeys[i]); + + if ((s->session != NULL) && (s->session->peer != NULL)) + X509_free(s->session->peer); + x->references++; + s->session->peer=x; + + x=NULL; + ret=1; + + if (0) + { +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + } +err: + if (x != NULL) X509_free(x); + if (sk != NULL) sk_pop_free(sk,X509_free); + return(ret); + } + +static int ssl3_get_key_exchange(s) +SSL *s; + { +#ifndef NO_RSA + unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2]; +#endif + EVP_MD_CTX md_ctx; + unsigned char *param,*p; + int al,i,j,param_len,ok; + long n,alg; + EVP_PKEY *pkey=NULL; + RSA *rsa=NULL; + DH *dh=NULL; + + n=ssl3_get_message(s, + SSL3_ST_CR_KEY_EXCH_A, + SSL3_ST_CR_KEY_EXCH_B, + -1, + 1024*8, /* ?? */ + &ok); + + if (!ok) return((int)n); + + if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) + { + s->s3->tmp.reuse_message=1; + return(1); + } + + param=p=(unsigned char *)s->init_buf->data; + + if (s->session->cert != NULL) + { +#ifndef NO_RSA + if (s->session->cert->rsa_tmp != NULL) + { + RSA_free(s->session->cert->rsa_tmp); + s->session->cert->rsa_tmp=NULL; + } +#endif +#ifndef NO_DH + if (s->session->cert->dh_tmp) + { + DH_free(s->session->cert->dh_tmp); + s->session->cert->dh_tmp=NULL; + } +#endif + } + else + { + s->session->cert=ssl_cert_new(); + } + + param_len=0; + alg=s->s3->tmp.new_cipher->algorithms; + +#ifndef NO_RSA + if (alg & SSL_kRSA) + { + if ((rsa=RSA_new()) == NULL) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); + goto err; + } + n2s(p,i); + param_len=i+2; + if (param_len > n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH); + goto f_err; + } + if (!(rsa->n=BN_bin2bn(p,i,rsa->n))) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + p+=i; + + n2s(p,i); + param_len+=i+2; + if (param_len > n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH); + goto f_err; + } + if (!(rsa->e=BN_bin2bn(p,i,rsa->e))) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + p+=i; + n-=param_len; + +/* s->session->cert->rsa_tmp=rsa;*/ + /* this should be because we are using an export cipher */ + if (alg & SSL_aRSA) + pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509); + else + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + goto err; + } + s->session->cert->rsa_tmp=rsa; + } + else +#endif +#ifndef NO_DH + if (alg & SSL_kEDH) + { + if ((dh=DH_new()) == NULL) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + n2s(p,i); + param_len=i+2; + if (param_len > n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH); + goto f_err; + } + if (!(dh->p=BN_bin2bn(p,i,NULL))) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + p+=i; + + n2s(p,i); + param_len+=i+2; + if (param_len > n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH); + goto f_err; + } + if (!(dh->g=BN_bin2bn(p,i,NULL))) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + p+=i; + + n2s(p,i); + param_len+=i+2; + if (param_len > n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH); + goto f_err; + } + if (!(dh->pub_key=BN_bin2bn(p,i,NULL))) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + p+=i; + n-=param_len; + +#ifndef NO_RSA + if (alg & SSL_aRSA) + pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509); + else +#endif +#ifndef NO_DSA + if (alg & SSL_aDSS) + pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_DSA_SIGN].x509); +#endif + /* else anonymous DH, so no certificate or pkey. */ + + s->session->cert->dh_tmp=dh; + } + else if ((alg & SSL_kDHr) || (alg & SSL_kDHd)) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); + goto f_err; + } +#endif + + /* p points to the next byte, there are 'n' bytes left */ + + + /* if it was signed, check the signature */ + if (pkey != NULL) + { + n2s(p,i); + n-=2; + j=EVP_PKEY_size(pkey); + + if ((i != n) || (n > j) || (n <= 0)) + { + /* wrong packet length */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH); + goto err; + } + +#ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + int num; + + j=0; + q=md_buf; + for (num=2; num > 0; num--) + { + EVP_DigestInit(&md_ctx,(num == 2)?EVP_md5():EVP_sha1()); + EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); + EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); + EVP_DigestUpdate(&md_ctx,param,param_len); + EVP_DigestFinal(&md_ctx,q,(unsigned int *)&i); + q+=i; + j+=i; + } + i=RSA_public_decrypt((int)n,p,p,pkey->pkey.rsa, + RSA_PKCS1_PADDING); + if (i <= 0) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); + goto f_err; + } + if ((j != i) || (memcmp(p,md_buf,i) != 0)) + { + /* bad signature */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE); + goto f_err; + } + } + else +#endif +#ifndef NO_DSA + if (pkey->type == EVP_PKEY_DSA) + { + /* lets do DSS */ + EVP_VerifyInit(&md_ctx,EVP_dss1()); + EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); + EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); + EVP_VerifyUpdate(&md_ctx,param,param_len); + if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey)) + { + /* bad signature */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE); + goto f_err; + } + } + else +#endif + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + goto err; + } + } + else + { + /* still data left over */ + if (!(alg & SSL_aNULL)) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + goto err; + } + if (n != 0) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE); + goto f_err; + } + } + + return(1); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + return(-1); + } + +static int ssl3_get_certificate_request(s) +SSL *s; + { + int ok,ret=0; + unsigned long n,nc; + unsigned int llen,l,ctype_num,i; + X509_NAME *xn=NULL; + unsigned char *p,*d,*q; + STACK *ca_sk=NULL; + + n=ssl3_get_message(s, + SSL3_ST_CR_CERT_REQ_A, + SSL3_ST_CR_CERT_REQ_B, + -1, +#if defined(MSDOS) && !defined(WIN32) + 1024*30, /* 30k max cert list :-) */ +#else + 1024*100, /* 100k max cert list :-) */ +#endif + &ok); + + if (!ok) return((int)n); + + s->s3->tmp.cert_req=0; + + if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE) + { + s->s3->tmp.reuse_message=1; + return(1); + } + + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_UNEXPECTED_MESSAGE); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE); + goto err; + } + + d=p=(unsigned char *)s->init_buf->data; + + if ((ca_sk=sk_new(ca_dn_cmp)) == NULL) + { + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); + goto err; + } + + /* get the certificate types */ + ctype_num= *(p++); + if (ctype_num > SSL3_CT_NUMBER) + ctype_num=SSL3_CT_NUMBER; + for (i=0; i<ctype_num; i++) + s->s3->tmp.ctype[i]= p[i]; + p+=ctype_num; + + /* get the CA RDNs */ + n2s(p,llen); + if ((llen+ctype_num+2+1) != n) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH); + goto err; + } + + for (nc=0; nc<llen; ) + { + n2s(p,l); + if ((l+nc+2) > llen) + { + if ((s->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG)) + goto cont; /* netscape bugs */ + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_TOO_LONG); + goto err; + } + + q=p; + + if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL) + { + /* If netscape tollerance is on, ignore errors */ + if (s->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG) + goto cont; + else + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB); + goto err; + } + } + + if (q != (p+l)) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH); + goto err; + } + if (!sk_push(ca_sk,(char *)xn)) + { + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); + goto err; + } + + p+=l; + nc+=l+2; + } + + if (0) + { +cont: + ERR_clear_error(); + } + + /* we should setup a certficate to return.... */ + s->s3->tmp.cert_req=1; + s->s3->tmp.ctype_num=ctype_num; + if (s->s3->tmp.ca_names != NULL) + sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + s->s3->tmp.ca_names=ca_sk; + ca_sk=NULL; + + ret=1; +err: + if (ca_sk != NULL) sk_pop_free(ca_sk,X509_NAME_free); + return(ret); + } + +static int ca_dn_cmp(a,b) +X509_NAME **a,**b; + { + return(X509_NAME_cmp(*a,*b)); + } + +static int ssl3_get_server_done(s) +SSL *s; + { + int ok,ret=0; + long n; + + n=ssl3_get_message(s, + SSL3_ST_CR_SRVR_DONE_A, + SSL3_ST_CR_SRVR_DONE_B, + SSL3_MT_SERVER_DONE, + 30, /* should be very small, like 0 :-) */ + &ok); + + if (!ok) return((int)n); + if (n > 0) + { + /* should contain no data */ + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_ILLEGAL_PARAMETER); + SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH); + } + ret=1; + return(ret); + } + +static int ssl3_send_client_key_exchange(s) +SSL *s; + { + unsigned char *p,*d; + int n; + unsigned long l; + EVP_PKEY *pkey=NULL; + + if (s->state == SSL3_ST_CW_KEY_EXCH_A) + { + d=(unsigned char *)s->init_buf->data; + p= &(d[4]); + + l=s->s3->tmp.new_cipher->algorithms; + +#ifndef NO_RSA + if (l & SSL_kRSA) + { + RSA *rsa; + unsigned char tmp_buf[48]; + + if (s->session->cert->rsa_tmp != NULL) + rsa=s->session->cert->rsa_tmp; + else + { + pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509); + if ((pkey == NULL) || + (pkey->type != EVP_PKEY_RSA) || + (pkey->pkey.rsa == NULL)) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + goto err; + } + rsa=pkey->pkey.rsa; + } + + tmp_buf[0]=SSL3_VERSION_MAJOR; + tmp_buf[1]=SSL3_VERSION_MINOR; + RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2); + + s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH; + + n=RSA_public_encrypt(48,tmp_buf,p,rsa, + RSA_PKCS1_PADDING); + if (n <= 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT); + goto err; + } + + s->session->master_key_length= + ssl3_generate_master_secret(s, + s->session->master_key, + tmp_buf,48); + memset(tmp_buf,0,48); + } + else +#endif +#ifndef NO_DH + if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + { + DH *dh_srvr,*dh_clnt; + + if (s->session->cert->dh_tmp != NULL) + dh_srvr=s->session->cert->dh_tmp; + else + { + /* we get them from the cert */ + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); + goto err; + } + + /* generate a new random key */ + if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + if (!DH_generate_key(dh_clnt)) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + + /* use the 'p' output buffer for the DH key, but + * make sure to clear it out afterwards */ + n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt); + if (n <= 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + + /* generate master key from the result */ + s->session->master_key_length= + ssl3_generate_master_secret(s, + s->session->master_key,p,n); + /* clean up */ + memset(p,0,n); + + /* send off the data */ + n=BN_num_bytes(dh_clnt->pub_key); + s2n(n,p); + BN_bn2bin(dh_clnt->pub_key,p); + n+=2; + + DH_free(dh_clnt); + + /* perhaps clean things up a bit EAY EAY EAY EAY*/ + } + else +#endif + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + goto err; + } + + *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; + l2n3(n,d); + + s->state=SSL3_ST_CW_KEY_EXCH_B; + /* number of bytes to write */ + s->init_num=n+4; + s->init_off=0; + } + + /* SSL3_ST_CW_KEY_EXCH_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +err: + return(-1); + } + +static int ssl3_send_client_verify(s) +SSL *s; + { + unsigned char *p,*d; + unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; + EVP_PKEY *pkey; + int i=0,j; + unsigned long n; + + if (s->state == SSL3_ST_CW_CERT_VRFY_A) + { + d=(unsigned char *)s->init_buf->data; + p= &(d[4]); + pkey=s->cert->key->privatekey; + + ssl3_final_finish_mac(s,&(s->s3->finish_dgst2), + NULL,&(data[MD5_DIGEST_LENGTH])); + +#ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + ssl3_final_finish_mac(s,&(s->s3->finish_dgst1), + NULL,&(data[0])); + i=RSA_private_encrypt( + MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, + data,&(p[2]),pkey->pkey.rsa, + RSA_PKCS1_PADDING); + if (i <= 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB); + goto err; + } + s2n(i,p); + n=i+2; + } + else +#endif +#ifndef NO_DSA + if (pkey->type == EVP_PKEY_DSA) + { + if (!DSA_sign(pkey->save_type, + &(data[MD5_DIGEST_LENGTH]), + SHA_DIGEST_LENGTH,&(p[2]), + (unsigned int *)&j,pkey->pkey.dsa)) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB); + goto err; + } + s2n(j,p); + n=j+2; + } + else +#endif + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,SSL_R_INTERNAL_ERROR); + goto err; + } + *(d++)=SSL3_MT_CERTIFICATE_VERIFY; + l2n3(n,d); + + s->init_num=(int)n+4; + s->init_off=0; + } + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +err: + return(-1); + } + +static int ssl3_send_client_certificate(s) +SSL *s; + { + X509 *x509=NULL; + EVP_PKEY *pkey=NULL; + int i; + unsigned long l; + + if (s->state == SSL3_ST_CW_CERT_A) + { + if ((s->cert == NULL) || + (s->cert->key->x509 == NULL) || + (s->cert->key->privatekey == NULL)) + s->state=SSL3_ST_CW_CERT_B; + else + s->state=SSL3_ST_CW_CERT_C; + } + + /* We need to get a client cert */ + if (s->state == SSL3_ST_CW_CERT_B) + { + /* If we get an error, we need to + * ssl->rwstate=SSL_X509_LOOKUP; return(-1); + * We then get retied later */ + i=0; + if (s->ctx->client_cert_cb != NULL) + i=s->ctx->client_cert_cb(s,&(x509),&(pkey)); + if (i < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return(-1); + } + s->rwstate=SSL_NOTHING; + if ((i == 1) && (pkey != NULL) && (x509 != NULL)) + { + s->state=SSL3_ST_CW_CERT_B; + if ( !SSL_use_certificate(s,x509) || + !SSL_use_PrivateKey(s,pkey)) + i=0; + } + else if (i == 1) + { + i=0; + SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + } + + if (x509 != NULL) X509_free(x509); + if (pkey != NULL) EVP_PKEY_free(pkey); + if (i == 0) + { + s->s3->tmp.cert_req=0; + ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_NO_CERTIFICATE); + return(1); + } + + /* Ok, we have a cert */ + s->state=SSL3_ST_CW_CERT_C; + } + + if (s->state == SSL3_ST_CW_CERT_C) + { + s->state=SSL3_ST_CW_CERT_D; + l=ssl3_output_cert_chain(s,s->cert->key->x509); + s->init_num=(int)l; + s->init_off=0; + } + /* SSL3_ST_CW_CERT_D */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } + +#define has_bits(i,m) (((i)&(m)) == (m)) + +static int ssl3_check_cert_and_algorithm(s) +SSL *s; + { + int i,idx; + long algs; + EVP_PKEY *pkey=NULL; + CERT *c; + RSA *rsa; + DH *dh; + + c=s->session->cert; + + if (c == NULL) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_INTERNAL_ERROR); + goto err; + } + + algs=s->s3->tmp.new_cipher->algorithms; + + /* we don't have a certificate */ + if (algs & (SSL_aDH|SSL_aNULL)) + return(1); + + rsa=s->session->cert->rsa_tmp; + dh=s->session->cert->dh_tmp; + + /* This is the passed certificate */ + + idx=c->cert_type; + pkey=X509_get_pubkey(c->pkeys[idx].x509); + i=X509_certificate_type(c->pkeys[idx].x509,pkey); + + + /* Check that we have a certificate if we require one */ + if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT); + goto f_err; + } +#ifndef NO_DSA + else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT); + goto f_err; + } +#endif + + if ((algs & SSL_kRSA) && + !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); + goto f_err; + } +#ifndef NO_DH + else if ((algs & SSL_kEDH) && + !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); + goto f_err; + } + else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); + goto f_err; + } +#ifndef NO_DSA + else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); + goto f_err; + } +#endif +#endif + + if ((algs & SSL_EXP) && !has_bits(i,EVP_PKT_EXP)) + { +#ifndef NO_RSA + if (algs & SSL_kRSA) + { + if ((rsa == NULL) || (RSA_size(rsa) > 512)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY); + goto f_err; + } + } + else +#endif +#ifndef NO_DH + if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + { + if ((dh == NULL) || (DH_size(dh) > 512)) + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY); + goto f_err; + } + } + else +#endif + { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto f_err; + } + } + return(1); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_HANDSHAKE_FAILURE); +err: + return(0); + } + diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c new file mode 100644 index 0000000000..f1cd25e3d3 --- /dev/null +++ b/ssl/s3_enc.c @@ -0,0 +1,481 @@ +/* ssl/s3_enc.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "evp.h" +#include "ssl_locl.h" + +static unsigned char ssl3_pad_1[48]={ + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36 }; + +static unsigned char ssl3_pad_2[48]={ + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c }; + +int ssl3_change_cipher_state(s,which) +SSL *s; +int which; + { + unsigned char *p,*key_block,*mac_secret; + unsigned char exp_key[EVP_MAX_KEY_LENGTH]; + unsigned char exp_iv[EVP_MAX_KEY_LENGTH]; + unsigned char *ms,*key,*iv,*er1,*er2; + EVP_CIPHER_CTX *dd; + EVP_CIPHER *c; + SSL_COMPRESSION *comp; + EVP_MD *m; + MD5_CTX md; + int exp,n,i,j,k; + + exp=(s->s3->tmp.new_cipher->algorithms & SSL_EXPORT)?1:0; + c=s->s3->tmp.new_sym_enc; + m=s->s3->tmp.new_hash; + comp=s->s3->tmp.new_compression; + key_block=s->s3->tmp.key_block; + + if (which & SSL3_CC_READ) + { + if ((s->enc_read_ctx == NULL) && + ((s->enc_read_ctx=(EVP_CIPHER_CTX *) + Malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) + goto err; + dd= s->enc_read_ctx; + s->read_hash=m; + s->read_compression=comp; + memset(&(s->s3->read_sequence[0]),0,8); + mac_secret= &(s->s3->read_mac_secret[0]); + } + else + { + if ((s->enc_write_ctx == NULL) && + ((s->enc_write_ctx=(EVP_CIPHER_CTX *) + Malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) + goto err; + dd= s->enc_write_ctx; + s->write_hash=m; + s->write_compression=comp; + memset(&(s->s3->write_sequence[0]),0,8); + mac_secret= &(s->s3->write_mac_secret[0]); + } + + p=s->s3->tmp.key_block; + i=EVP_MD_size(m); + j=(exp)?5:EVP_CIPHER_key_length(c); + k=EVP_CIPHER_iv_length(c); + if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || + (which == SSL3_CHANGE_CIPHER_SERVER_READ)) + { + ms= &(p[ 0]); n=i+i; + key= &(p[ n]); n+=j+j; + iv= &(p[ n]); n+=k+k; + er1= &(s->s3->client_random[0]); + er2= &(s->s3->server_random[0]); + } + else + { + n=i; + ms= &(p[ n]); n+=i+j; + key= &(p[ n]); n+=j+k; + iv= &(p[ n]); n+=k; + er1= &(s->s3->server_random[0]); + er2= &(s->s3->client_random[0]); + } + + if (n > s->s3->tmp.key_block_length) + { + SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_INTERNAL_ERROR); + goto err2; + } + + memcpy(mac_secret,ms,i); + if (exp) + { + /* In here I set both the read and write key/iv to the + * same value since only the correct one will be used :-). + */ + MD5_Init(&md); + MD5_Update(&md,key,j); + MD5_Update(&md,er1,SSL3_RANDOM_SIZE); + MD5_Update(&md,er2,SSL3_RANDOM_SIZE); + MD5_Final(&(exp_key[0]),&md); + key= &(exp_key[0]); + + MD5_Init(&md); + MD5_Update(&md,er1,SSL3_RANDOM_SIZE); + MD5_Update(&md,er2,SSL3_RANDOM_SIZE); + MD5_Final(&(exp_iv[0]),&md); + iv= &(exp_iv[0]); + } + + s->session->key_arg_length=k; + if (k > 0) + memcpy(&(s->session->key_arg[0]),iv,k); + + EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE)); + memset(&(exp_key[0]),0,sizeof(exp_key)); + memset(&(exp_iv[0]),0,sizeof(exp_iv)); + return(1); +err: + SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); +err2: + return(0); + } + +int ssl3_setup_key_block(s) +SSL *s; + { + unsigned char *p; + EVP_CIPHER *c; + EVP_MD *hash; + int num,exp; + + if (s->s3->tmp.key_block_length != 0) + return(1); + + if (!ssl_cipher_get_evp(s->session->cipher,&c,&hash)) + { + SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return(0); + } + + s->s3->tmp.new_sym_enc=c; + s->s3->tmp.new_hash=hash; + + exp=(s->session->cipher->algorithms & SSL_EXPORT)?1:0; + + num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c); + num*=2; + + ssl3_cleanup_key_block(s); + + if ((p=(unsigned char *)Malloc(num)) == NULL) + goto err; + + s->s3->tmp.key_block_length=num; + s->s3->tmp.key_block=p; + + ssl3_generate_key_block(s,p,num); + + return(1); +err: + SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); + return(0); + } + +void ssl3_cleanup_key_block(s) +SSL *s; + { + if (s->s3->tmp.key_block != NULL) + { + memset(s->s3->tmp.key_block,0, + s->s3->tmp.key_block_length); + Free(s->s3->tmp.key_block); + s->s3->tmp.key_block=NULL; + } + s->s3->tmp.key_block_length=0; + } + +int ssl3_enc(s,send) +SSL *s; +int send; + { + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + unsigned long l; + int bs,i; + EVP_CIPHER *enc; + SSL_COMPRESSION *comp; + + if (send) + { + ds=s->enc_write_ctx; + rec= &(s->s3->wrec); + if (s->enc_write_ctx == NULL) + { enc=NULL; comp=NULL; } + else + { + enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); + comp=s->write_compression; + } + } + else + { + ds=s->enc_read_ctx; + rec= &(s->s3->rrec); + if (s->enc_read_ctx == NULL) + { enc=NULL; comp=NULL; } + else + { + enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); + comp=s->read_compression; + } + } + + if ((s->session == NULL) || (ds == NULL) || + ((enc == NULL) && (comp == NULL))) + { + memcpy(rec->data,rec->input,rec->length); + rec->input=rec->data; + } + else + { + l=rec->length; + bs=EVP_CIPHER_block_size(ds->cipher); + + /* This should be using (bs-1) and bs instead of 7 and 8 */ + if ((bs != 1) && send) + { + i=bs-((int)l%bs); + + /* we need to add 'i-1' padding bytes */ + l+=i; + rec->length+=i; + rec->input[l-1]=(i-1); + } + + EVP_Cipher(ds,rec->data,rec->input,l); + + if ((bs != 1) && !send) + { + i=rec->data[l-1]+1; + if (i > bs) + { + SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_BAD_RECORD_MAC); + return(0); + } + rec->length-=i; + } + } + return(1); + } + +void ssl3_init_finished_mac(s) +SSL *s; + { + EVP_DigestInit(&(s->s3->finish_dgst1),EVP_md5()); + EVP_DigestInit(&(s->s3->finish_dgst2),EVP_sha1()); + } + +void ssl3_finish_mac(s,buf,len) +SSL *s; +unsigned char *buf; +int len; + { + EVP_DigestUpdate(&(s->s3->finish_dgst1),buf,len); + EVP_DigestUpdate(&(s->s3->finish_dgst2),buf,len); + } + +int ssl3_final_finish_mac(s,in_ctx,sender,p) +SSL *s; +EVP_MD_CTX *in_ctx; +unsigned char *sender; +unsigned char *p; + { + unsigned int ret; + int npad,n; + unsigned int i; + unsigned char md_buf[EVP_MAX_MD_SIZE]; + EVP_MD_CTX ctx; + + memcpy(&ctx,in_ctx,sizeof(EVP_MD_CTX)); + + n=EVP_MD_CTX_size(&ctx); + npad=(48/n)*n; + + if (sender != NULL) + EVP_DigestUpdate(&ctx,sender,4); + EVP_DigestUpdate(&ctx,s->session->master_key, + s->session->master_key_length); + EVP_DigestUpdate(&ctx,ssl3_pad_1,npad); + EVP_DigestFinal(&ctx,md_buf,&i); + + EVP_DigestInit(&ctx,EVP_MD_CTX_type(&ctx)); + EVP_DigestUpdate(&ctx,s->session->master_key, + s->session->master_key_length); + EVP_DigestUpdate(&ctx,ssl3_pad_2,npad); + EVP_DigestUpdate(&ctx,md_buf,i); + EVP_DigestFinal(&ctx,p,&ret); + + memset(&ctx,0,sizeof(EVP_MD_CTX)); + + return((int)ret); + } + +int ssl3_mac(ssl,md,send) +SSL *ssl; +unsigned char *md; +int send; + { + SSL3_RECORD *rec; + unsigned char *mac_sec,*seq; + EVP_MD_CTX md_ctx; + EVP_MD *hash; + unsigned char *p,rec_char; + unsigned int md_size; + int npad,i; + + if (send) + { + rec= &(ssl->s3->wrec); + mac_sec= &(ssl->s3->write_mac_secret[0]); + seq= &(ssl->s3->write_sequence[0]); + hash=ssl->write_hash; + } + else + { + rec= &(ssl->s3->rrec); + mac_sec= &(ssl->s3->read_mac_secret[0]); + seq= &(ssl->s3->read_sequence[0]); + hash=ssl->read_hash; + } + + md_size=EVP_MD_size(hash); + npad=(48/md_size)*md_size; + +#ifdef MAC_DEBUG +printf("npad=%d md_size=%d",npad,md_size); +printf("\nmsec="); +for (i=0; i<md_size; i++) printf("%02X ",mac_sec[i]); +printf("\npad1="); +for (i=0; i<npad; i++) printf("%02X ",ssl3_pad_1[i]); +printf("\nseq ="); +for (i=0; i<8; i++) printf("%02X ",seq[i]); +printf("\nreqt=%02X len=%04X\n",rec->type,rec->length); +for (i=0; i<rec->length; i++) printf("%02X",rec->input[i]); +printf("\n"); +#endif + + /* Chop the digest off the end :-) */ + + EVP_DigestInit( &md_ctx,hash); + EVP_DigestUpdate(&md_ctx,mac_sec,md_size); + EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); + EVP_DigestUpdate(&md_ctx,seq,8); + rec_char=rec->type; + EVP_DigestUpdate(&md_ctx,&rec_char,1); + p=md; + s2n(rec->length,p); + EVP_DigestUpdate(&md_ctx,md,2); + EVP_DigestUpdate(&md_ctx,rec->input,rec->length); + EVP_DigestFinal( &md_ctx,md,NULL); + + EVP_DigestInit( &md_ctx,hash); + EVP_DigestUpdate(&md_ctx,mac_sec,md_size); + EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); + EVP_DigestUpdate(&md_ctx,md,md_size); + EVP_DigestFinal( &md_ctx,md,&md_size); + + for (i=7; i>=0; i--) + if (++seq[i]) break; + +#ifdef MAC_DEBUG +printf("md="); +for (i=0; i<md_size; i++) printf("%02X ",md[i]); +printf("\n"); +#endif + + return(md_size); + } + +int ssl3_generate_master_secret(s,out,p,len) +SSL *s; +unsigned char *out; +unsigned char *p; +int len; + { + static unsigned char *salt[3]={ + (unsigned char *)"A", + (unsigned char *)"BB", + (unsigned char *)"CCC", + }; + unsigned char buf[EVP_MAX_MD_SIZE]; + EVP_MD_CTX ctx; + int i,ret=0; + unsigned int n; + + for (i=0; i<3; i++) + { + EVP_DigestInit(&ctx,EVP_sha1()); + EVP_DigestUpdate(&ctx,salt[i],strlen((char *)salt[i])); + EVP_DigestUpdate(&ctx,p,len); + EVP_DigestUpdate(&ctx,&(s->s3->client_random[0]), + SSL3_RANDOM_SIZE); + EVP_DigestUpdate(&ctx,&(s->s3->server_random[0]), + SSL3_RANDOM_SIZE); + EVP_DigestFinal(&ctx,buf,&n); + + EVP_DigestInit(&ctx,EVP_md5()); + EVP_DigestUpdate(&ctx,p,len); + EVP_DigestUpdate(&ctx,buf,n); + EVP_DigestFinal(&ctx,out,&n); + out+=n; + ret+=n; + } + return(ret); + } + diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c new file mode 100644 index 0000000000..b7bac8e10f --- /dev/null +++ b/ssl/s3_lib.c @@ -0,0 +1,915 @@ +/* ssl/s3_lib.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "ssl_locl.h" + +char *ssl3_version_str="SSLv3 part of SSLeay 0.8.1b 29-Jun-1998"; + +#define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER)) + +#ifndef NOPROTO +static long ssl3_default_timeout(void ); +#else +static long ssl3_default_timeout(); +#endif + +SSL_CIPHER ssl3_ciphers[]={ +/* The RSA ciphers */ +/* Cipher 01 */ + { + 1, + SSL3_TXT_RSA_NULL_MD5, + SSL3_CK_RSA_NULL_MD5, + SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 02 */ + { + 1, + SSL3_TXT_RSA_NULL_SHA, + SSL3_CK_RSA_NULL_SHA, + SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, + +/* anon DH */ +/* Cipher 17 */ + { + 1, + SSL3_TXT_ADH_RC4_40_MD5, + SSL3_CK_ADH_RC4_40_MD5, + SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5 |SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 18 */ + { + 1, + SSL3_TXT_ADH_RC4_128_MD5, + SSL3_CK_ADH_RC4_128_MD5, + SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 19 */ + { + 1, + SSL3_TXT_ADH_DES_40_CBC_SHA, + SSL3_CK_ADH_DES_40_CBC_SHA, + SSL_kEDH |SSL_aNULL|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 1A */ + { + 1, + SSL3_TXT_ADH_DES_64_CBC_SHA, + SSL3_CK_ADH_DES_64_CBC_SHA, + SSL_kEDH |SSL_aNULL|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 1B */ + { + 1, + SSL3_TXT_ADH_DES_196_CBC_SHA, + SSL3_CK_ADH_DES_196_CBC_SHA, + SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, + +/* RSA again */ +/* Cipher 03 */ + { + 1, + SSL3_TXT_RSA_RC4_40_MD5, + SSL3_CK_RSA_RC4_40_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5 |SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 04 */ + { + 1, + SSL3_TXT_RSA_RC4_128_MD5, + SSL3_CK_RSA_RC4_128_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 05 */ + { + 1, + SSL3_TXT_RSA_RC4_128_SHA, + SSL3_CK_RSA_RC4_128_SHA, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 06 */ + { + 1, + SSL3_TXT_RSA_RC2_40_MD5, + SSL3_CK_RSA_RC2_40_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC2 |SSL_MD5 |SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 07 */ + { + 1, + SSL3_TXT_RSA_IDEA_128_SHA, + SSL3_CK_RSA_IDEA_128_SHA, + SSL_kRSA|SSL_aRSA|SSL_IDEA |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 08 */ + { + 1, + SSL3_TXT_RSA_DES_40_CBC_SHA, + SSL3_CK_RSA_DES_40_CBC_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 09 */ + { + 1, + SSL3_TXT_RSA_DES_64_CBC_SHA, + SSL3_CK_RSA_DES_64_CBC_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 0A */ + { + 1, + SSL3_TXT_RSA_DES_192_CBC3_SHA, + SSL3_CK_RSA_DES_192_CBC3_SHA, + SSL_kRSA|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, + +/* The DH ciphers */ +/* Cipher 0B */ + { + 0, + SSL3_TXT_DH_DSS_DES_40_CBC_SHA, + SSL3_CK_DH_DSS_DES_40_CBC_SHA, + SSL_kDHd |SSL_aDH|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 0C */ + { + 0, + SSL3_TXT_DH_DSS_DES_64_CBC_SHA, + SSL3_CK_DH_DSS_DES_64_CBC_SHA, + SSL_kDHd |SSL_aDH|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 0D */ + { + 0, + SSL3_TXT_DH_DSS_DES_192_CBC3_SHA, + SSL3_CK_DH_DSS_DES_192_CBC3_SHA, + SSL_kDHd |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 0E */ + { + 0, + SSL3_TXT_DH_RSA_DES_40_CBC_SHA, + SSL3_CK_DH_RSA_DES_40_CBC_SHA, + SSL_kDHr |SSL_aDH|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 0F */ + { + 0, + SSL3_TXT_DH_RSA_DES_64_CBC_SHA, + SSL3_CK_DH_RSA_DES_64_CBC_SHA, + SSL_kDHr |SSL_aDH|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 10 */ + { + 0, + SSL3_TXT_DH_RSA_DES_192_CBC3_SHA, + SSL3_CK_DH_RSA_DES_192_CBC3_SHA, + SSL_kDHr |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, + +/* The Ephemeral DH ciphers */ +/* Cipher 11 */ + { + 1, + SSL3_TXT_EDH_DSS_DES_40_CBC_SHA, + SSL3_CK_EDH_DSS_DES_40_CBC_SHA, + SSL_kEDH|SSL_aDSS|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 12 */ + { + 1, + SSL3_TXT_EDH_DSS_DES_64_CBC_SHA, + SSL3_CK_EDH_DSS_DES_64_CBC_SHA, + SSL_kEDH|SSL_aDSS|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 13 */ + { + 1, + SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA, + SSL3_CK_EDH_DSS_DES_192_CBC3_SHA, + SSL_kEDH|SSL_aDSS|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 14 */ + { + 1, + SSL3_TXT_EDH_RSA_DES_40_CBC_SHA, + SSL3_CK_EDH_RSA_DES_40_CBC_SHA, + SSL_kEDH|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 15 */ + { + 1, + SSL3_TXT_EDH_RSA_DES_64_CBC_SHA, + SSL3_CK_EDH_RSA_DES_64_CBC_SHA, + SSL_kEDH|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + 0, + SSL_ALL_CIPHERS, + }, +/* Cipher 16 */ + { + 1, + SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, + SSL3_CK_EDH_RSA_DES_192_CBC3_SHA, + SSL_kEDH|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + 0, + SSL_ALL_CIPHERS, + }, + +/* Fortezza */ +/* Cipher 1C */ + { + 0, + SSL3_TXT_FZA_DMS_NULL_SHA, + SSL3_CK_FZA_DMS_NULL_SHA, + SSL_kFZA|SSL_aFZA |SSL_eNULL |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, + +/* Cipher 1D */ + { + 0, + SSL3_TXT_FZA_DMS_FZA_SHA, + SSL3_CK_FZA_DMS_FZA_SHA, + SSL_kFZA|SSL_aFZA |SSL_eFZA |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, + +/* Cipher 1E */ + { + 0, + SSL3_TXT_FZA_DMS_RC4_SHA, + SSL3_CK_FZA_DMS_RC4_SHA, + SSL_kFZA|SSL_aFZA |SSL_RC4 |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + 0, + SSL_ALL_CIPHERS, + }, + +/* end of list */ + }; + +static SSL_METHOD SSLv3_data= { + 3, + ssl3_new, + ssl3_clear, + ssl3_free, + ssl_undefined_function, + ssl_undefined_function, + ssl3_read, + ssl3_peek, + ssl3_write, + ssl3_shutdown, + ssl3_renegotiate, + ssl3_ctrl, + ssl3_ctx_ctrl, + ssl3_get_cipher_by_char, + ssl3_put_cipher_by_char, + ssl3_pending, + ssl3_num_ciphers, + ssl3_get_cipher, + ssl_bad_method, + ssl3_default_timeout, + }; + +static long ssl3_default_timeout() + { + /* 2 hours, the 24 hours mentioned in the SSLv3 spec + * is way too long for http, the cache would over fill */ + return(60*60*2); + } + +SSL_METHOD *sslv3_base_method() + { + return(&SSLv3_data); + } + +int ssl3_num_ciphers() + { + return(SSL3_NUM_CIPHERS); + } + +SSL_CIPHER *ssl3_get_cipher(u) +unsigned int u; + { + if (u < SSL3_NUM_CIPHERS) + return(&(ssl3_ciphers[SSL3_NUM_CIPHERS-1-u])); + else + return(NULL); + } + +/* The problem is that it may not be the correct record type */ +int ssl3_pending(s) +SSL *s; + { + return(s->s3->rrec.length); + } + +int ssl3_new(s) +SSL *s; + { + SSL3_CTX *s3; + + if ((s3=(SSL3_CTX *)Malloc(sizeof(SSL3_CTX))) == NULL) goto err; + + s->s3=s3; + s->s3->tmp.ca_names=NULL; + s->s3->tmp.key_block=NULL; + s->s3->rbuf.buf=NULL; + s->s3->wbuf.buf=NULL; + + ssl3_clear(s); + return(1); +err: + return(0); + } + +void ssl3_free(s) +SSL *s; + { + ssl3_cleanup_key_block(s); + if (s->s3->rbuf.buf != NULL) + Free(s->s3->rbuf.buf); + if (s->s3->wbuf.buf != NULL) + Free(s->s3->wbuf.buf); +#ifndef NO_DH + if (s->s3->tmp.dh != NULL) + DH_free(s->s3->tmp.dh); +#endif + if (s->s3->tmp.ca_names != NULL) + sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + memset(s->s3,0,sizeof(SSL3_CTX)); + Free(s->s3); + s->s3=NULL; + } + +void ssl3_clear(s) +SSL *s; + { + unsigned char *rp,*wp; + + ssl3_cleanup_key_block(s); + if (s->s3->tmp.ca_names != NULL) + sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + + rp=s->s3->rbuf.buf; + wp=s->s3->wbuf.buf; + + memset(s->s3,0,sizeof(SSL3_CTX)); + if (rp != NULL) + { + s->packet= &(s->s3->rbuf.buf[0]); + s->s3->rbuf.buf=rp; + s->s3->wbuf.buf=wp; + } + else + s->packet=NULL; + s->packet_length=0; + s->version=3; + } + +long ssl3_ctrl(s,cmd,larg,parg) +SSL *s; +int cmd; +long larg; +char *parg; + { + return(0); + } + +long ssl3_ctx_ctrl(ctx,cmd,larg,parg) +SSL_CTX *ctx; +int cmd; +long larg; +char *parg; + { + CERT *cert; + + cert=ctx->default_cert; + + switch (cmd) + { +#ifndef NO_RSA + case SSL_CTRL_NEED_TMP_RSA: + if ( (cert->rsa_tmp == NULL) && + ((cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) || + (EVP_PKEY_size(cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > (512/8))) + ) + return(1); + else + return(0); + break; + case SSL_CTRL_SET_TMP_RSA: + { + RSA *rsa; + int i; + + rsa=(RSA *)parg; + i=1; + if (rsa == NULL) + i=0; + else + { + if ((rsa=RSAPrivateKey_dup(rsa)) == NULL) + i=0; + } + if (!i) + { + SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_RSA_LIB); + return(0); + } + else + { + if (cert->rsa_tmp != NULL) + RSA_free(cert->rsa_tmp); + cert->rsa_tmp=rsa; + return(1); + } + } + break; + case SSL_CTRL_SET_TMP_RSA_CB: + cert->rsa_tmp_cb=(RSA *(*)())parg; + break; +#endif +#ifndef NO_DH + case SSL_CTRL_SET_TMP_DH: + { + DH *new=NULL,*dh; + + dh=(DH *)parg; + if ( ((new=DHparams_dup(dh)) == NULL) || + (!DH_generate_key(new))) + { + SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB); + if (new != NULL) DH_free(new); + return(0); + } + else + { + if (cert->dh_tmp != NULL) + DH_free(cert->dh_tmp); + cert->dh_tmp=new; + return(1); + } + } + break; + case SSL_CTRL_SET_TMP_DH_CB: + cert->dh_tmp_cb=(DH *(*)())parg; + break; +#endif + default: + return(0); + } + return(1); + } + +/* This function needs to check if the ciphers required are actually + * available */ +SSL_CIPHER *ssl3_get_cipher_by_char(p) +unsigned char *p; + { + static int init=1; + static SSL_CIPHER *sorted[SSL3_NUM_CIPHERS]; + SSL_CIPHER c,*cp= &c,**cpp; + unsigned long id; + int i; + + if (init) + { + init=0; + + for (i=0; i<SSL3_NUM_CIPHERS; i++) + sorted[i]= &(ssl3_ciphers[i]); + + qsort( (char *)sorted, + SSL3_NUM_CIPHERS,sizeof(SSL_CIPHER *), + FP_ICC ssl_cipher_ptr_id_cmp); + } + + id=0x03000000L|((unsigned long)p[0]<<8L)|(unsigned long)p[1]; + c.id=id; + cpp=(SSL_CIPHER **)OBJ_bsearch((char *)&cp, + (char *)sorted, + SSL3_NUM_CIPHERS,sizeof(SSL_CIPHER *), + (int (*)())ssl_cipher_ptr_id_cmp); + if ((cpp == NULL) || !(*cpp)->valid) + return(NULL); + else + return(*cpp); + } + +int ssl3_put_cipher_by_char(c,p) +SSL_CIPHER *c; +unsigned char *p; + { + long l; + + if (p != NULL) + { + l=c->id; + if ((l & 0xff000000) != 0x03000000) return(0); + p[0]=((unsigned char)(l>> 8L))&0xFF; + p[1]=((unsigned char)(l ))&0xFF; + } + return(2); + } + +void ssl3_generate_key_block(s,km,num) +SSL *s; +unsigned char *km; +int num; + { + MD5_CTX m5; + SHA_CTX s1; + unsigned char buf[8],smd[SHA_DIGEST_LENGTH]; + unsigned char c='A'; + int i,j,k; + + k=0; + for (i=0; i<num; i+=MD5_DIGEST_LENGTH) + { + k++; + for (j=0; j<k; j++) + buf[j]=c; + c++; + SHA1_Init( &s1); + SHA1_Update(&s1,buf,k); + SHA1_Update(&s1,s->session->master_key, + s->session->master_key_length); + SHA1_Update(&s1,s->s3->server_random,SSL3_RANDOM_SIZE); + SHA1_Update(&s1,s->s3->client_random,SSL3_RANDOM_SIZE); + SHA1_Final( smd,&s1); + + MD5_Init( &m5); + MD5_Update(&m5,s->session->master_key, + s->session->master_key_length); + MD5_Update(&m5,smd,SHA_DIGEST_LENGTH); + if ((i+MD5_DIGEST_LENGTH) > num) + { + MD5_Final(smd,&m5); + memcpy(km,smd,(num-i)); + } + else + MD5_Final(km,&m5); + + km+=MD5_DIGEST_LENGTH; + } + memset(smd,0,SHA_DIGEST_LENGTH); + } + +int ssl3_part_read(s,i) +SSL *s; +int i; + { + s->rwstate=SSL_READING; + + if (i < 0) + { + return(i); + } + else + { + s->init_num+=i; + return(0); + } + } + +SSL_CIPHER *ssl3_choose_cipher(s,have,pref) +SSL *s; +STACK *have,*pref; + { + SSL_CIPHER *c,*ret=NULL; + int i,j,ok; + CERT *cert; + unsigned long alg,mask,emask; + + /* Lets see which ciphers we can supported */ + if (s->cert != NULL) + cert=s->cert; + else + cert=s->ctx->default_cert; + + ssl_set_cert_masks(cert); + mask=cert->mask; + emask=cert->export_mask; + + sk_set_cmp_func(pref,ssl_cipher_ptr_id_cmp); + + for (i=0; i<sk_num(have); i++) + { + c=(SSL_CIPHER *)sk_value(have,i); + alg=c->algorithms&(SSL_MKEY_MASK|SSL_AUTH_MASK); + if (alg & SSL_EXPORT) + { + ok=((alg & emask) == alg)?1:0; +#ifdef CIPHER_DEBUG + printf("%d:[%08lX:%08lX]%s\n",ok,alg,mask,c->name); +#endif + } + else + { + ok=((alg & mask) == alg)?1:0; +#ifdef CIPHER_DEBUG + printf("%d:[%08lX:%08lX]%s\n",ok,alg,mask,c->name); +#endif + } + + if (!ok) continue; + + j=sk_find(pref,(char *)c); + if (j >= 0) + { + ret=(SSL_CIPHER *)sk_value(pref,j); + break; + } + } + return(ret); + } + +int ssl3_get_req_cert_type(s,p) +SSL *s; +unsigned char *p; + { + int ret=0; + unsigned long alg; + + alg=s->s3->tmp.new_cipher->algorithms; + +#ifndef NO_DH + if (alg & (SSL_kDHr|SSL_kEDH)) + { +#ifndef NO_RSA + p[ret++]=SSL3_CT_RSA_FIXED_DH; +#endif +#ifndef NO_DSA + p[ret++]=SSL3_CT_DSS_FIXED_DH; +#endif + } + if (alg & (SSL_kEDH|SSL_kDHd|SSL_kDHr)) + { +#ifndef NO_RSA + p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH; +#endif +#ifndef NO_DSA + p[ret++]=SSL3_CT_DSS_EPHEMERAL_DH; +#endif + } +#endif /* !NO_DH */ +#ifndef NO_RSA + p[ret++]=SSL3_CT_RSA_SIGN; +#endif +/* p[ret++]=SSL3_CT_DSS_SIGN; */ + return(ret); + } + +int ssl3_shutdown(s) +SSL *s; + { + + /* Don't do anything much if we have not done the handshake or + * we don't want to send messages :-) */ + if ((s->quiet_shutdown) || (s->state == SSL_ST_BEFORE)) + { + s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); + return(1); + } + + if (!(s->shutdown & SSL_SENT_SHUTDOWN)) + { + s->shutdown|=SSL_SENT_SHUTDOWN; +#if 1 + ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_CLOSE_NOTIFY); +#endif + /* our shutdown alert has been sent now, and if it still needs + * to be written, s->s3->alert_dispatch will be true */ + } + else if (s->s3->alert_dispatch) + { + /* resend it if not sent */ +#if 1 + ssl3_dispatch_alert(s); +#endif + } + else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) + { + /* If we are waiting for a close from our peer, we are closed */ + ssl3_read_bytes(s,0,NULL,0); + } + + if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) && + !s->s3->alert_dispatch) + return(1); + else + return(0); + } + +int ssl3_write(s,buf,len) +SSL *s; +const char *buf; +int len; + { + int ret,n; + BIO *under; + +#if 0 + if (s->shutdown & SSL_SEND_SHUTDOWN) + { + s->rwstate=SSL_NOTHING; + return(0); + } +#endif + errno=0; + + /* This is an experimental flag that sends the + * last handshake message in the same packet as the first + * use data - used to see if it helps the TCP protocol during + * session-id reuse */ + /* The second test is because the buffer may have been removed */ + if ((s->s3->flags & SSL3_FLAGS_POP_BUFFER) && (s->wbio == s->bbio)) + { + /* First time through, we write into the buffer */ + if (s->s3->delay_buf_pop_ret == 0) + { + ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA, + (char *)buf,len); + if (ret <= 0) return(ret); + + s->s3->delay_buf_pop_ret=ret; + } + + s->rwstate=SSL_WRITING; + n=BIO_flush(s->wbio); + if (n <= 0) return(n); + s->rwstate=SSL_NOTHING; + + /* We have flushed the buffer */ + under=BIO_pop(s->wbio); + s->wbio=under; + BIO_free(s->bbio); + s->bbio=NULL; + ret=s->s3->delay_buf_pop_ret; + s->s3->delay_buf_pop_ret=0; + + s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER; + } + else + { + ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA, + (char *)buf,len); + if (ret <= 0) return(ret); + } + return(ret); + } + +int ssl3_read(s,buf,len) +SSL *s; +char *buf; +int len; + { + errno=0; + return(ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len)); + } + +int ssl3_peek(s,buf,len) +SSL *s; +char *buf; +int len; + { + SSL3_RECORD *rr; + int n; + + rr= &(s->s3->rrec); + if ((rr->length == 0) || (rr->type != SSL3_RT_APPLICATION_DATA)) + return(0); + + if ((unsigned int)len > rr->length) + n=rr->length; + else + n=len; + memcpy(buf,&(rr->data[rr->off]),(unsigned int)n); + return(n); + } + +int ssl3_renegotiate(s) +SSL *s; + { + if (s->handshake_func == NULL) + return(1); + + if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) + return(0); + + if (!SSL_in_init(s)) + s->state=SSL_ST_RENEGOTIATE; + return(1); + } + diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c new file mode 100644 index 0000000000..4762b21442 --- /dev/null +++ b/ssl/s3_meth.c @@ -0,0 +1,88 @@ +/* ssl/s3_meth.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "ssl_locl.h" + +static SSL_METHOD *ssl3_get_method(ver) +int ver; + { + if (ver == 3) + return(SSLv3_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv3_method() + { + static int init=1; + static SSL_METHOD SSLv3_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv3_data,(char *)sslv3_base_method(), + sizeof(SSL_METHOD)); + SSLv3_data.ssl_connect=ssl3_connect; + SSLv3_data.ssl_accept=ssl3_accept; + SSLv3_data.get_ssl_method=ssl3_get_method; + } + return(&SSLv3_data); + } + diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c new file mode 100644 index 0000000000..3be69ef138 --- /dev/null +++ b/ssl/s3_pkt.c @@ -0,0 +1,963 @@ +/* ssl/s3_pkt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <errno.h> +#define USE_SOCKETS +#include "evp.h" +#include "buffer.h" +#include "ssl_locl.h" + +/* SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_BAD_RECORD_MAC); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_NO_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_BAD_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN); + * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER); + */ + +#ifndef NOPROTO +static int do_ssl3_write(SSL *s, int type, char *buf, unsigned int len); +static int ssl3_write_pending(SSL *s, int type, char *buf, unsigned int len); +static int ssl3_get_record(SSL *s); +static int do_compress(SSL *ssl); +static int do_uncompress(SSL *ssl); +#else +static int do_ssl3_write(); +static int ssl3_write_pending(); +static int ssl3_get_record(); +static int do_compress(); +static int do_uncompress(); +#endif + +static int ssl3_read_n(s,n,max,extend) +SSL *s; +int n; +int max; +int extend; + { + int i,off,newb; + + /* if there is stuff still in the buffer from a previous read, + * and there is more than we want, take some. */ + if (s->s3->rbuf.left >= (int)n) + { + if (extend) + s->packet_length+=n; + else + { + s->packet= &(s->s3->rbuf.buf[s->s3->rbuf.offset]); + s->packet_length=n; + } + s->s3->rbuf.left-=n; + s->s3->rbuf.offset+=n; + return(n); + } + + /* else we need to read more data */ + if (!s->read_ahead) max=n; + if (max > SSL3_RT_MAX_PACKET_SIZE) + max=SSL3_RT_MAX_PACKET_SIZE; + + /* First check if there is some left or we want to extend */ + off=0; + if ( (s->s3->rbuf.left != 0) || + ((s->packet_length != 0) && extend)) + { + newb=s->s3->rbuf.left; + if (extend) + { + /* Copy bytes back to the front of the buffer + * Take the bytes already pointed to by 'packet' + * and take the extra ones on the end. */ + off=s->packet_length; + if (s->packet != s->s3->rbuf.buf) + memcpy(s->s3->rbuf.buf,s->packet,newb+off); + } + else if (s->s3->rbuf.offset != 0) + { /* so the data is not at the start of the buffer */ + memcpy(s->s3->rbuf.buf, + &(s->s3->rbuf.buf[s->s3->rbuf.offset]),newb); + s->s3->rbuf.offset=0; + } + + s->s3->rbuf.left=0; + } + else + newb=0; + + /* So we now have 'newb' bytes at the front of + * s->s3->rbuf.buf and need to read some more in on the end + * We start reading into the buffer at 's->s3->rbuf.offset' + */ + s->packet=s->s3->rbuf.buf; + + while (newb < n) + { + errno=0; + if (s->rbio != NULL) + { + s->rwstate=SSL_READING; + i=BIO_read(s->rbio, + (char *)&(s->s3->rbuf.buf[off+newb]), + max-newb); + } + else + { + SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); + i= -1; + } + + if (i <= 0) + { + s->s3->rbuf.left+=newb; + return(i); + } + newb+=i; + } + + /* record used data read */ + if (newb > n) + { + s->s3->rbuf.offset=n+off; + s->s3->rbuf.left=newb-n; + } + else + { + s->s3->rbuf.offset=0; + s->s3->rbuf.left=0; + } + + if (extend) + s->packet_length+=n; + else + s->packet_length+=n; + return(n); + } + +/* Call this to get a new input record. + * It will return <= 0 if more data is needed, normally due to an error + * or non-blocking IO. + * When it finishes, one packet has been decoded and can be found in + * ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data, - data + * ssl->s3->rrec.length, - number of bytes + */ +static int ssl3_get_record(s) +SSL *s; + { + int ssl_major,ssl_minor,al; + int n,i,ret= -1; + SSL3_BUFFER *rb; + SSL3_RECORD *rr; + SSL_SESSION *sess; + unsigned char *p; + unsigned char md[EVP_MAX_MD_SIZE]; + short version; + unsigned int mac_size; + int clear=0,extra; + + rr= &(s->s3->rrec); + rb= &(s->s3->rbuf); + sess=s->session; + + if (s->ctx->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) + extra=SSL3_RT_MAX_EXTRA; + else + extra=0; + +again: + /* check if we have the header */ + if ( (s->rstate != SSL_ST_READ_BODY) || + (s->packet_length < SSL3_RT_HEADER_LENGTH)) + { + n=ssl3_read_n(s,SSL3_RT_HEADER_LENGTH, + SSL3_RT_MAX_PACKET_SIZE,0); + if (n <= 0) return(n); /* error or non-blocking */ + s->rstate=SSL_ST_READ_BODY; + + p=s->packet; + + /* Pull apart the header into the SSL3_RECORD */ + rr->type= *(p++); + ssl_major= *(p++); + ssl_minor= *(p++); + version=(ssl_major<<8)|ssl_minor; + n2s(p,rr->length); + + /* Lets check version */ + if (s->first_packet) + { + s->first_packet=0; + } + else + { + if ( (ssl_major != SSL3_VERSION_MAJOR) || + (ssl_minor != SSL3_VERSION_MINOR)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); + goto f_err; + } + } + + if (s->version != SSL3_VERSION_MAJOR) + { + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_INTERNAL_ERROR); + goto err; + } + + if (rr->length > + (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG); + goto f_err; + } + + s->rstate=SSL_ST_READ_BODY; + } + + /* get and decode the data */ + if (s->rstate == SSL_ST_READ_BODY) + { + if (rr->length > (s->packet_length-SSL3_RT_HEADER_LENGTH)) + { + i=rr->length; + /*-(s->packet_length-SSL3_RT_HEADER_LENGTH); */ + n=ssl3_read_n(s,i,i,1); + if (n <= 0) return(n); /* error or non-blocking io */ + } + s->rstate=SSL_ST_READ_HEADER; + } + + /* At this point, we have the data in s->packet and there should be + * s->packet_length bytes, we must not 'overrun' this buffer :-) + * One of the following functions will copy the data from the + * s->packet buffer */ + + rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]); + + /* ok, we can now read from 's->packet' data into 'rr' + * rr->input points at rr->length bytes, which + * need to be copied into rr->data by either + * the decryption or by the decompression + * When the data is 'copied' into the rr->data buffer, + * rr->input will be pointed at the new buffer */ + + /* Set the state for the following operations */ + s->rstate=SSL_ST_READ_HEADER; + + /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] + * rr->length bytes of encrypted compressed stuff. */ + + /* check is not needed I belive */ + if (rr->length > (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + goto f_err; + } + + /* decrypt in place in 'rr->input' */ + rr->data=rr->input; + + if (!ssl3_enc(s,0)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + /* r->length is now the compressed data plus mac */ + if ( (sess == NULL) || + (s->enc_read_ctx == NULL) || + (s->read_hash == NULL)) + clear=1; + + if (!clear) + { + mac_size=EVP_MD_size(s->read_hash); + + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); + goto f_err; + } + /* check MAC for rr->input' */ + if (rr->length < mac_size) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + rr->length-=mac_size; + i=ssl3_mac(s,md,0); + if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0) + { + al=SSL3_AD_BAD_RECORD_MAC; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_MAC_DECODE); + ret=SSL_RWERR_BAD_MAC_DECODE; + goto f_err; + } + } + + /* r->length is now just compressed */ + if ((sess != NULL) && (sess->read_compression != NULL)) + { + if (rr->length > + (unsigned int)SSL3_RT_MAX_COMPRESSED_LENGTH+extra) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG); + goto f_err; + } + if (!do_uncompress(s)) + { + al=SSL3_AD_DECOMPRESSION_FAILURE; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION); + goto f_err; + } + } + + if (rr->length > (unsigned int)SSL3_RT_MAX_PLAIN_LENGTH+extra) + { + al=SSL3_AD_DECOMPRESSION_FAILURE; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG); + goto f_err; + } + + rr->off=0; + /* So at this point the following is true + * ssl->s3->rrec.type is the type of record + * ssl->s3->rrec.length == number of bytes in record + * ssl->s3->rrec.off == offset to first valid byte + * ssl->s3->rrec.data == where to take bytes from, increment + * after use :-). + */ + + /* we have pulled in a full packet so zero things */ + s->packet_length=0; + + /* just read a 0 length packet */ + if (rr->length == 0) goto again; + + return(1); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + return(ret); + } + +static int do_uncompress(ssl) +SSL *ssl; + { + return(1); + } + +static int do_compress(ssl) +SSL *ssl; + { + return(1); + } + +/* Call this write a data + * It will return <= 0 if not all data has been sent or non-blocking IO. + */ +int ssl3_write_bytes(s,type,buf,len) +SSL *s; +int type; +char *buf; +int len; + { + unsigned int tot,n,nw; + int i; + + s->rwstate=SSL_NOTHING; + tot=s->s3->wnum; + s->s3->wnum=0; + + if (SSL_in_init(s) && !s->in_handshake) + { + i=s->handshake_func(s); + if (i < 0) return(i); + if (i == 0) + { + SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + } + + n=(len-tot); + for (;;) + { + if (n > SSL3_RT_MAX_PLAIN_LENGTH) + nw=SSL3_RT_MAX_PLAIN_LENGTH; + else + nw=n; + + i=do_ssl3_write(s,type,&(buf[tot]),nw); + if (i <= 0) + { + s->s3->wnum=tot; + return(i); + } + + if (type == SSL3_RT_HANDSHAKE) + ssl3_finish_mac(s,(unsigned char *)&(buf[tot]),i); + + if (i == (int)n) return(tot+i); + + n-=i; + tot+=i; + } + } + +static int do_ssl3_write(s,type,buf,len) +SSL *s; +int type; +char *buf; +unsigned int len; + { + unsigned char *p,*plen; + int i,mac_size,clear=0; + SSL3_RECORD *wr; + SSL3_BUFFER *wb; + SSL_SESSION *sess; + + /* first check is there is a SSL3_RECORD still being written + * out. This will happen with non blocking IO */ + if (s->s3->wbuf.left != 0) + return(ssl3_write_pending(s,type,buf,len)); + + /* If we have an alert to send, lets send it */ + if (s->s3->alert_dispatch) + { + i=ssl3_dispatch_alert(s); + if (i <= 0) + return(i); + /* if it went, fall through and send more stuff */ + } + + if (len <= 0) return(len); + + wr= &(s->s3->wrec); + wb= &(s->s3->wbuf); + sess=s->session; + + if ( (sess == NULL) || + (s->enc_write_ctx == NULL) || + (s->write_hash == NULL)) + clear=1; + + if (clear) + mac_size=0; + else + mac_size=EVP_MD_size(s->write_hash); + + p=wb->buf; + + /* write the header */ + *(p++)=type&0xff; + wr->type=type; + + *(p++)=SSL3_VERSION_MAJOR; + *(p++)=SSL3_VERSION_MINOR; + + /* record where we are to write out packet length */ + plen=p; + p+=2; + + /* lets setup the record stuff. */ + wr->data=p; + wr->length=(int)len; + wr->input=(unsigned char *)buf; + + /* we now 'read' from wr->input, wr->length bytes into + * wr->data */ + + /* first we compress */ + if ((sess != NULL) && (sess->write_compression != NULL)) + { + if (!do_compress(s)) + { + SSLerr(SSL_F_DO_SSL3_WRITE,SSL_R_COMPRESSION_FAILURE); + goto err; + } + } + else + { + memcpy(wr->data,wr->input,wr->length); + wr->input=wr->data; + } + + /* we should still have the output to wr->data and the input + * from wr->input. Length should be wr->length. + * wr->data still points in the wb->buf */ + + if (mac_size != 0) + { + ssl3_mac(s,&(p[wr->length]),1); + wr->length+=mac_size; + wr->input=p; + wr->data=p; + } + + /* ssl3_enc can only have an error on read */ + ssl3_enc(s,1); + + /* record length after mac and block padding */ + s2n(wr->length,plen); + + /* we should now have + * wr->data pointing to the encrypted data, which is + * wr->length long */ + wr->type=type; /* not needed but helps for debugging */ + wr->length+=SSL3_RT_HEADER_LENGTH; + + /* Now lets setup wb */ + wb->left=wr->length; + wb->offset=0; + + s->s3->wpend_tot=len; + s->s3->wpend_buf=buf; + s->s3->wpend_type=type; + s->s3->wpend_ret=len; + + /* we now just need to write the buffer */ + return(ssl3_write_pending(s,type,buf,len)); +err: + return(-1); + } + +/* if s->s3->wbuf.left != 0, we need to call this */ +static int ssl3_write_pending(s,type,buf,len) +SSL *s; +int type; +char *buf; +unsigned int len; + { + int i; + + if ((s->s3->wpend_tot != (int)len) || (s->s3->wpend_buf != buf) + || (s->s3->wpend_type != type)) + { + SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); + return(SSL_RWERR_BAD_WRITE_RETRY); + } + + for (;;) + { + errno=0; + if (s->wbio != NULL) + { + s->rwstate=SSL_WRITING; + i=BIO_write(s->wbio, + (char *)&(s->s3->wbuf.buf[s->s3->wbuf.offset]), + (unsigned int)s->s3->wbuf.left); + } + else + { + SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET); + i= -1; + } + if (i == s->s3->wbuf.left) + { + s->s3->wbuf.left=0; + s->rwstate=SSL_NOTHING; + return(s->s3->wpend_ret); + } + else if (i <= 0) + return(i); + s->s3->wbuf.offset+=i; + s->s3->wbuf.left-=i; + } + } + +int ssl3_read_bytes(s,type,buf,len) +SSL *s; +int type; +char *buf; +int len; + { + int al,i,j,n,ret; + SSL3_RECORD *rr; + unsigned char *sender; + void (*cb)()=NULL; + + if (s->s3->rbuf.buf == NULL) /* Not initalised yet */ + if (!ssl3_setup_buffers(s)) + return(-1); + + if (!s->in_handshake && SSL_in_before(s)) + { + i=s->handshake_func(s); + if (i < 0) return(i); + if (i == 0) + { + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + } +start: + s->rwstate=SSL_NOTHING; + + /* s->s3->rrec.type - is the type of record + * s->s3->rrec.data, - data + * s->s3->rrec.off, - ofset into 'data' for next read + * s->s3->rrec.length, - number of bytes. */ + rr= &(s->s3->rrec); + + /* get new packet */ + if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) + { + ret=ssl3_get_record(s); + if (ret <= 0) return(ret); + } + + /* we now have a packet which can be read and processed */ + + if (s->s3->change_cipher_spec && (rr->type != SSL3_RT_HANDSHAKE)) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); + goto err; + } + + /* If the other end has shutdown, throw anything we read away */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) + { + rr->length=0; + s->rwstate=SSL_NOTHING; + return(0); + } + + /* Check for an incoming 'Client Request' message */ + if ((rr->type == SSL3_RT_HANDSHAKE) && (rr->length == 4) && + (rr->data[0] == SSL3_MT_CLIENT_REQUEST) && + (s->session != NULL) && (s->session->cipher != NULL)) + { + if ((rr->data[1] != 0) || (rr->data[2] != 0) || + (rr->data[3] != 0)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CLIENT_REQUEST); + goto err; + } + + if (SSL_is_init_finished(s) && + !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) + { + ssl3_renegotiate(s); + n=s->handshake_func(s); + if (n < 0) return(n); + if (n == 0) + { + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + } + rr->length=0; +/* ZZZ */ goto start; + } + + /* if it is not the type we want, or we have shutdown and want + * the peer shutdown */ + if ((rr->type != type) || (s->shutdown & SSL_SENT_SHUTDOWN)) + { + if (rr->type == SSL3_RT_ALERT) + { + if ((rr->length != 2) || (rr->off != 0)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_ALERT_RECORD); + goto f_err; + } + + i=rr->data[0]; + n=rr->data[1]; + + /* clear from buffer */ + rr->length=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + if (cb != NULL) + { + j=(i<<8)|n; + cb(s,SSL_CB_READ_ALERT,j); + } + + if (i == 1) + { + s->s3->warn_alert=n; + if (n == SSL3_AD_CLOSE_NOTIFY) + { + s->shutdown|=SSL_RECEIVED_SHUTDOWN; + return(0); + } + } + else if (i == 2) + { + s->rwstate=SSL_NOTHING; + s->s3->fatal_alert=n; + SSLerr(SSL_F_SSL3_READ_BYTES,1000+n); + s->shutdown|=SSL_RECEIVED_SHUTDOWN; + SSL_CTX_remove_session(s->ctx,s->session); + return(0); + } + else + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE); + goto f_err; + } + + rr->length=0; + goto start; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) + { + s->rwstate=SSL_NOTHING; + rr->length=0; + return(0); + } + + if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) + { + if ( (rr->length != 1) || (rr->off != 0) || + (rr->data[0] != SSL3_MT_CCS)) + { + i=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); + goto err; + } + + rr->length=0; + + s->s3->change_cipher_spec=1; + + if (s->state & SSL_ST_ACCEPT) + i=SSL3_CHANGE_CIPHER_SERVER_READ; + else + i=SSL3_CHANGE_CIPHER_CLIENT_READ; + + if (s->s3->tmp.key_block == NULL) + { + s->session->cipher=s->s3->tmp.new_cipher; + if (!ssl3_setup_key_block(s)) + goto err; + } + + if (!ssl3_change_cipher_state(s,i)) + goto err; + + /* we have to record the message digest at + * this point so we can get it before we read + * the finished message */ + sender=(s->state & SSL_ST_CONNECT) + ?&(ssl3_server_finished_const[0]) + :&(ssl3_client_finished_const[0]); + + ssl3_final_finish_mac(s,&(s->s3->finish_dgst1), + sender,&(s->s3->tmp.finish_md1[0])); + ssl3_final_finish_mac(s,&(s->s3->finish_dgst2), + sender,&(s->s3->tmp.finish_md2[0])); + + goto start; + } + + /* else we have a handshake */ + if ((rr->type == SSL3_RT_HANDSHAKE) && + !s->in_handshake) + { + if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && + !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) + { + s->state=SSL_ST_BEFORE; + s->new_session=1; + } + n=s->handshake_func(s); + if (n < 0) return(n); + if (n == 0) + { + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + goto start; + } + + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); + goto f_err; + } + + /* make sure that we are not getting application data when we + * are doing a handshake for the first time */ + if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && + (s->enc_read_ctx == NULL)) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE); + goto f_err; + } + + if (len <= 0) return(len); + + if ((unsigned int)len > rr->length) + n=rr->length; + else + n=len; + + memcpy(buf,&(rr->data[rr->off]),(unsigned int)n); + rr->length-=n; + rr->off+=n; + if (rr->length <= 0) + s->rstate=SSL_ST_READ_HEADER; + + if (type == SSL3_RT_HANDSHAKE) + ssl3_finish_mac(s,(unsigned char *)buf,n); + return(n); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + return(-1); + } + +int ssl3_do_write(s,type) +SSL *s; +int type; + { + int ret; + + ret=ssl3_write_bytes(s,type,(char *) + &(s->init_buf->data[s->init_off]),s->init_num); + if (ret == s->init_num) + return(1); + if (ret < 0) return(-1); + s->init_off+=ret; + s->init_num-=ret; + return(0); + } + +void ssl3_send_alert(s,level,desc) +SSL *s; +int level; +int desc; + { + /* If a fatal one, remove from cache */ + if ((level == 2) && (s->session != NULL)) + SSL_CTX_remove_session(s->ctx,s->session); + + s->s3->alert_dispatch=1; + s->s3->send_alert[0]=level; + s->s3->send_alert[1]=desc; + if (s->s3->wbuf.left == 0) /* data still being written out */ + ssl3_dispatch_alert(s); + /* else data is still being written out, we will get written + * some time in the future */ + } + +int ssl3_dispatch_alert(s) +SSL *s; + { + int i,j; + void (*cb)()=NULL; + + s->s3->alert_dispatch=0; + i=do_ssl3_write(s,SSL3_RT_ALERT,&(s->s3->send_alert[0]),2); + if (i <= 0) + { + s->s3->alert_dispatch=1; + } + else + { + /* If it is important, send it now. If the message + * does not get sent due to non-blocking IO, we will + * not worry too much. */ + if (s->s3->send_alert[0] == SSL3_AL_FATAL) + BIO_flush(s->wbio); + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + if (cb != NULL) + { + j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1]; + cb(s,SSL_CB_WRITE_ALERT,j); + } + } + return(i); + } + diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c new file mode 100644 index 0000000000..ebff57506f --- /dev/null +++ b/ssl/s3_srvr.c @@ -0,0 +1,1629 @@ +/* ssl/s3_srvr.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#define REUSE_CIPHER_BUG + +#include <stdio.h> +#include "buffer.h" +#include "rand.h" +#include "objects.h" +#include "evp.h" +#include "x509.h" +#include "ssl_locl.h" + +#define BREAK break +/* SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_MALLOC_FAILURE); + * SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); + */ + +#ifndef NOPROTO +static int ssl3_get_client_hello(SSL *s); +static int ssl3_send_server_hello(SSL *s); +static int ssl3_send_server_key_exchange(SSL *s); +static int ssl3_send_certificate_request(SSL *s); +static int ssl3_send_server_done(SSL *s); +static int ssl3_get_cert_verify(SSL *s); +static int ssl3_get_client_key_exchange(SSL *s); +static int ssl3_get_client_certificate(SSL *s); +static int ssl3_send_hello_request(SSL *s); + +#else + +static int ssl3_get_client_hello(); +static int ssl3_send_server_hello(); +static int ssl3_send_server_key_exchange(); +static int ssl3_send_certificate_request(); +static int ssl3_send_server_done(); +static int ssl3_get_cert_verify(); +static int ssl3_get_client_key_exchange(); +static int ssl3_get_client_certificate(); +static int ssl3_send_hello_request(); +static SSL_METHOD *ssl3_get_server_method(); + +#endif + +static SSL_METHOD *ssl3_get_server_method(ver) +int ver; + { + if (ver == 3) + return(SSLv3_server_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv3_server_method() + { + static int init=1; + static SSL_METHOD SSLv3_server_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(), + sizeof(SSL_METHOD)); + SSLv3_server_data.ssl_accept=ssl3_accept; + SSLv3_server_data.get_ssl_method=ssl3_get_server_method; + } + return(&SSLv3_server_data); + } + +int ssl3_accept(s) +SSL *s; + { + BUF_MEM *buf; + unsigned long l,Time=time(NULL); + void (*cb)()=NULL; + long num1; + int ret= -1; + CERT *ct; + BIO *bbio,*under; + int new_state,state,skip=0; + + RAND_seed((unsigned char *)&Time,sizeof(Time)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + /* init things to blank */ + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + +#ifdef undef + /* FIX THIS EAY EAY EAY */ + /* we don't actually need a cert, we just need a cert or a DH_tmp */ + if (((s->session == NULL) || (s->session->cert == NULL)) && + (s->cert == NULL)) + { + SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET); + ret= -1; + goto end; + } +#endif + + for (;;) + { + state=s->state; + + switch (s->state) + { + case SSL_ST_RENEGOTIATE: + s->new_session=1; + /* s->state=SSL_ST_ACCEPT; */ + + case SSL_ST_BEFORE: + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + case SSL_ST_OK|SSL_ST_ACCEPT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=3; + s->type=SSL_ST_ACCEPT; + + if (s->init_buf == NULL) + { + if ((buf=BUF_MEM_new()) == NULL) + { + ret= -1; + goto end; + } + if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) + { + ret= -1; + goto end; + } + s->init_buf=buf; + } + + if (!ssl3_setup_buffers(s)) + { + ret= -1; + goto end; + } + + /* Ok, we now need to push on a buffering BIO so that + * the output is sent in a way that TCP likes :-) + */ + if (s->bbio == NULL) + { + bbio=BIO_new(BIO_f_buffer()); + if (bbio == NULL) + { + SSLerr(SSL_F_SSL3_ACCEPT,ERR_LIB_BUF); + ret= -1; + goto end; + } + s->bbio=bbio; + } + else + bbio=s->bbio; + BIO_reset(bbio); + if (!BIO_set_write_buffer_size(bbio,16*1024)) + { + SSLerr(SSL_F_SSL3_ACCEPT,ERR_LIB_BUF); + ret= -1; + goto end; + } + + s->wbio=BIO_push(bbio,s->wbio); + + s->ctx->sess_accept++; + s->init_num=0; + + if (s->state != SSL_ST_RENEGOTIATE) + { + s->state=SSL3_ST_SR_CLNT_HELLO_A; + ssl3_init_finished_mac(s); + } + else + { + s->state=SSL3_ST_SW_HELLO_REQ_A; + } + break; + + case SSL3_ST_SW_HELLO_REQ_A: + case SSL3_ST_SW_HELLO_REQ_B: + + s->shutdown=0; + ret=ssl3_send_hello_request(s); + if (ret <= 0) goto end; + s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; + s->state=SSL3_ST_SW_FLUSH; + s->init_num=0; + + ssl3_init_finished_mac(s); + break; + + case SSL3_ST_SW_HELLO_REQ_C: + /* remove buffering on output */ + under=BIO_pop(s->wbio); + if (under != NULL) + s->wbio=under; + else + abort(); /* ok */ + BIO_free(s->bbio); + s->bbio=NULL; + + s->state=SSL_ST_OK; + ret=1; + goto end; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + case SSL3_ST_SR_CLNT_HELLO_C: + + s->shutdown=0; + ret=ssl3_get_client_hello(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_SW_SRVR_HELLO_A; + s->init_num=0; + break; + + case SSL3_ST_SW_SRVR_HELLO_A: + case SSL3_ST_SW_SRVR_HELLO_B: + ret=ssl3_send_server_hello(s); + if (ret <= 0) goto end; + + if (s->hit) + s->state=SSL3_ST_SW_CHANGE_A; + else + s->state=SSL3_ST_SW_CERT_A; + s->init_num=0; + break; + + case SSL3_ST_SW_CERT_A: + case SSL3_ST_SW_CERT_B: + /* Check if it is anon DH */ + if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) + { + ret=ssl3_send_server_certificate(s); + if (ret <= 0) goto end; + } + else + skip=1; + s->state=SSL3_ST_SW_KEY_EXCH_A; + s->init_num=0; + break; + + case SSL3_ST_SW_KEY_EXCH_A: + case SSL3_ST_SW_KEY_EXCH_B: + l=s->s3->tmp.new_cipher->algorithms; + if (s->session->cert == NULL) + { + if (s->cert != NULL) + { + CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); + s->session->cert=s->cert; + } + else + { + CRYPTO_add(&s->ctx->default_cert->references,1,CRYPTO_LOCK_SSL_CERT); + s->session->cert=s->ctx->default_cert; + } + } + ct=s->session->cert; + + /* clear this, it may get reset by + * send_server_key_exchange */ + if (s->ctx->options & SSL_OP_EPHEMERAL_RSA) + s->s3->tmp.use_rsa_tmp=1; + else + s->s3->tmp.use_rsa_tmp=0; + + /* only send if a DH key exchange, fortezza or + * RSA but we have a sign only certificate */ + if ( s->s3->tmp.use_rsa_tmp || + (l & (SSL_DH|SSL_kFZA)) || + ((l & SSL_kRSA) && + ((ct->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)|| + ((l & SSL_EXPORT) && + (EVP_PKEY_size(ct->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > 512) + ) + ) + ) + ) + { + ret=ssl3_send_server_key_exchange(s); + if (ret <= 0) goto end; + } + else + skip=1; + + s->state=SSL3_ST_SW_CERT_REQ_A; + s->init_num=0; + break; + + case SSL3_ST_SW_CERT_REQ_A: + case SSL3_ST_SW_CERT_REQ_B: + if (!(s->verify_mode & SSL_VERIFY_PEER) || + ((s->session->peer != NULL) && + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE))) + { + /* no cert request */ + skip=1; + s->state=SSL3_ST_SW_SRVR_DONE_A; + } + else + { + ret=ssl3_send_certificate_request(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_SW_SRVR_DONE_A; + s->init_num=0; + } + break; + + case SSL3_ST_SW_SRVR_DONE_A: + case SSL3_ST_SW_SRVR_DONE_B: + ret=ssl3_send_server_done(s); + if (ret <= 0) goto end; + s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; + s->state=SSL3_ST_SW_FLUSH; + s->init_num=0; + break; + + case SSL3_ST_SW_FLUSH: + /* number of bytes to be flushed */ + num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL); + if (num1 > 0) + { + s->rwstate=SSL_WRITING; + num1=BIO_flush(s->wbio); + if (num1 <= 0) { ret= -1; goto end; } + s->rwstate=SSL_NOTHING; + } + + s->state=s->s3->tmp.next_state; + break; + + case SSL3_ST_SR_CERT_A: + case SSL3_ST_SR_CERT_B: + /* could be sent for a DH cert, even if we + * have not asked for it :-) */ + ret=ssl3_get_client_certificate(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL3_ST_SR_KEY_EXCH_A; + break; + + case SSL3_ST_SR_KEY_EXCH_A: + case SSL3_ST_SR_KEY_EXCH_B: + ret=ssl3_get_client_key_exchange(s); + if (ret <= 0) goto end; + s->state=SSL3_ST_SR_CERT_VRFY_A; + s->init_num=0; + + /* We need to get hashes here so if there is + * a client cert, it can be verified */ + ssl3_final_finish_mac(s,&(s->s3->finish_dgst1), + NULL,&(s->s3->tmp.finish_md1[0])); + ssl3_final_finish_mac(s,&(s->s3->finish_dgst2), + NULL,&(s->s3->tmp.finish_md2[0])); + + break; + + case SSL3_ST_SR_CERT_VRFY_A: + case SSL3_ST_SR_CERT_VRFY_B: + + /* we should decide if we expected this one */ + ret=ssl3_get_cert_verify(s); + if (ret <= 0) goto end; + + s->state=SSL3_ST_SR_FINISHED_A; + s->init_num=0; + break; + + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_SR_FINISHED_B: + ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, + SSL3_ST_SR_FINISHED_B, + &(ssl3_client_finished_const[0])); + if (ret <= 0) goto end; + if (s->hit) + s->state=SSL_ST_OK; + else + s->state=SSL3_ST_SW_CHANGE_A; + s->init_num=0; + break; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_SW_CHANGE_B: + + s->session->cipher=s->s3->tmp.new_cipher; + if (!ssl3_setup_key_block(s)) { ret= -1; goto end; } + + ret=ssl3_send_change_cipher_spec(s, + SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); + + if (ret <= 0) goto end; + s->state=SSL3_ST_SW_FINISHED_A; + s->init_num=0; + + if (!ssl3_change_cipher_state(s, + SSL3_CHANGE_CIPHER_SERVER_WRITE)) + { + ret= -1; + goto end; + } + + break; + + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_SW_FINISHED_B: + ret=ssl3_send_finished(s, + SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, + &(ssl3_server_finished_const[0])); + if (ret <= 0) goto end; + s->state=SSL3_ST_SW_FLUSH; + if (s->hit) + s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; + else + s->s3->tmp.next_state=SSL_ST_OK; + s->init_num=0; + break; + + case SSL_ST_OK: + /* clean a few things up */ + ssl3_cleanup_key_block(s); + + BUF_MEM_free(s->init_buf); + s->init_buf=NULL; + + /* remove buffering on output */ + under=BIO_pop(s->wbio); + if (under != NULL) + s->wbio=under; + else + abort(); /* ok */ + BIO_free(s->bbio); + s->bbio=NULL; + + s->new_session=0; + s->init_num=0; + + ssl_update_cache(s,SSL_SESS_CACHE_SERVER); + + s->ctx->sess_accept_good++; + /* s->server=1; */ + s->handshake_func=ssl3_accept; + ret=1; + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + + goto end; + break; + + default: + SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE); + ret= -1; + goto end; + break; + } + + if (!s->s3->tmp.reuse_message && !skip) + { + if (s->debug) BIO_flush(s->wbio); + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_ACCEPT_LOOP,1); + s->state=new_state; + } + } + skip=0; + } +end: + /* BIO_flush(s->wbio); */ + + if (cb != NULL) + cb(s,SSL_CB_ACCEPT_EXIT,ret); + s->in_handshake--; + return(ret); + } + +static int ssl3_send_hello_request(s) +SSL *s; + { + unsigned char *p; + + if (s->state == SSL3_ST_SW_HELLO_REQ_A) + { + p=(unsigned char *)s->init_buf->data; + *(p++)=SSL3_MT_CLIENT_REQUEST; + *(p++)=0; + *(p++)=0; + *(p++)=0; + + s->state=SSL3_ST_SW_HELLO_REQ_B; + /* number of bytes to write */ + s->init_num=4; + s->init_off=0; + } + + /* SSL3_ST_SW_HELLO_REQ_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } + +static int ssl3_get_client_hello(s) +SSL *s; + { + int i,j,ok,al,ret= -1; + long n; + unsigned long id; + unsigned char *p,*d; + SSL_CIPHER *c; + STACK *ciphers=NULL; + + if (s->state == SSL3_ST_SR_CLNT_HELLO_A) + { + s->first_packet=1; + s->state=SSL3_ST_SR_CLNT_HELLO_B; + } + n=ssl3_get_message(s, + SSL3_ST_SR_CLNT_HELLO_B, + SSL3_ST_SR_CLNT_HELLO_C, + SSL3_MT_CLIENT_HELLO, + SSL3_RT_MAX_PLAIN_LENGTH, + &ok); + + if (!ok) return((int)n); + d=p=(unsigned char *)s->init_buf->data; + + if (p[0] != SSL3_VERSION_MAJOR) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_WRONG_SSL_VERSION); + goto err; + } + p+=2; + + /* load the client random */ + memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE); + p+=SSL3_RANDOM_SIZE; + + /* get the session-id */ + j= *(p++); + + s->hit=0; + if (j == 0) + { + if (!ssl_get_new_session(s,1)) + goto err; + } + else + { + i=ssl_get_prev_session(s,j,p); + if (i == 1) + { /* previous session */ + s->hit=1; + } + else + { + if (!ssl_get_new_session(s,1)) + goto err; + } + } + + p+=j; + n2s(p,i); + if ((i == 0) && (j != 0)) + { + /* we need a cipher if we are not resuming a session */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } + if ((i+p) > (d+n)) + { + /* not enough data */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); + goto f_err; + } + if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers)) + == NULL)) + { + goto err; + } + p+=i; + + /* If it is a hit, check that the cipher is in the list */ + if ((s->hit) && (i > 0)) + { + j=0; + id=s->session->cipher->id; + + for (i=0; i<sk_num(ciphers); i++) + { + c=(SSL_CIPHER *)sk_value(ciphers,i); + if (c->id == id) + { + j=1; + break; + } + } + if (j == 0) + { + if ((s->ctx->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_num(ciphers) == 1)) + { + /* Very bad for multi-threading.... */ + s->session->cipher= + (SSL_CIPHER *)sk_value(ciphers,0); + } + else + { + /* we need to have the cipher in the cipher + * list if we are asked to reuse it */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING); + goto f_err; + } + } + } + + /* compression */ + i= *(p++); + for (j=0; j<i; j++) + if (p[j] == 0) break; + + p+=i; + if (j >= i) + { + /* no compress */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED); + goto f_err; + } + + if (p > (d+n)) + { + /* wrong number of bytes, + * there could be more to follow */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); + goto f_err; + } + + /* do nothing with compression */ + + /* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must + * pick a cipher */ + + if (!s->hit) + { + if (s->session->ciphers != NULL) + sk_free(s->session->ciphers); + s->session->ciphers=ciphers; + if (ciphers == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED); + goto f_err; + } + ciphers=NULL; + c=ssl3_choose_cipher(s,s->session->ciphers, + ssl_get_ciphers_by_id(s)); + + if (c == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); + goto f_err; + } + s->s3->tmp.new_cipher=c; + } + else + { + /* Session-id reuse */ +#ifdef REUSE_CIPHER_BUG + STACK *sk; + SSL_CIPHER *nc=NULL; + SSL_CIPHER *ec=NULL; + + if (s->ctx->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) + { + sk=s->session->ciphers; + for (i=0; i<sk_num(sk); i++) + { + c=(SSL_CIPHER *)sk_value(sk,i); + if (c->algorithms & SSL_eNULL) + nc=c; + if (c->algorithms & SSL_EXP) + ec=c; + } + if (nc != NULL) + s->s3->tmp.new_cipher=nc; + else if (ec != NULL) + s->s3->tmp.new_cipher=ec; + else + s->s3->tmp.new_cipher=s->session->cipher; + } + else +#endif + s->s3->tmp.new_cipher=s->session->cipher; + } + + /* we now have the following setup. + * client_random + * cipher_list - our prefered list of ciphers + * ciphers - the clients prefered list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - sesson reuse flag + * s->tmp.new_cipher - the new cipher to use. + */ + + ret=1; + if (0) + { +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + } +err: + if (ciphers != NULL) sk_free(ciphers); + return(ret); + } + +static int ssl3_send_server_hello(s) +SSL *s; + { + unsigned char *buf; + unsigned char *p,*d; + int i,sl; + unsigned long l,Time; + + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) + { + buf=(unsigned char *)s->init_buf->data; + p=s->s3->server_random; + Time=time(NULL); /* Time */ + l2n(Time,p); + RAND_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); + /* Do the message type and length last */ + d=p= &(buf[4]); + + *(p++)=SSL3_VERSION_MAJOR; + *(p++)=SSL3_VERSION_MINOR; + + /* Random stuff */ + memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); + p+=SSL3_RANDOM_SIZE; + + /* now in theory we have 3 options to sending back the + * session id. If it is a re-use, we send back the + * old session-id, if it is a new session, we send + * back the new session-id or we send back a 0 length + * session-id if we want it to be single use. + * Currently I will not implement the '0' length session-id + */ + + sl=s->session->session_id_length; + *(p++)=sl; + memcpy(p,s->session->session_id,sl); + p+=sl; + + /* put the cipher */ + i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p); + p+=i; + + /* put the compression method */ + *(p++)=0; + + /* do the header */ + l=(p-d); + d=buf; + *(d++)=SSL3_MT_SERVER_HELLO; + l2n3(l,d); + + s->state=SSL3_ST_CW_CLNT_HELLO_B; + /* number of bytes to write */ + s->init_num=p-buf; + s->init_off=0; + } + + /* SSL3_ST_CW_CLNT_HELLO_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } + +static int ssl3_send_server_done(s) +SSL *s; + { + unsigned char *p; + + if (s->state == SSL3_ST_SW_SRVR_DONE_A) + { + p=(unsigned char *)s->init_buf->data; + + /* do the header */ + *(p++)=SSL3_MT_SERVER_DONE; + *(p++)=0; + *(p++)=0; + *(p++)=0; + + s->state=SSL3_ST_SW_SRVR_DONE_B; + /* number of bytes to write */ + s->init_num=4; + s->init_off=0; + } + + /* SSL3_ST_CW_CLNT_HELLO_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } + +static int ssl3_send_server_key_exchange(s) +SSL *s; + { +#ifndef NO_RSA + unsigned char *q; + int j,num; + RSA *rsa; + unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; +#endif +#ifndef NO_DH + DH *dh,*dhp; +#endif + EVP_PKEY *pkey; + unsigned char *p,*d; + int al,i; + unsigned long type; + int n; + CERT *cert; + BIGNUM *r[4]; + int nr[4],kn; + BUF_MEM *buf; + EVP_MD_CTX md_ctx; + + if (s->state == SSL3_ST_SW_KEY_EXCH_A) + { + type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK; + cert=s->session->cert; + + buf=s->init_buf; + + r[0]=r[1]=r[2]=r[3]=NULL; + n=0; +#ifndef NO_RSA + if (type & SSL_kRSA) + { + rsa=cert->rsa_tmp; + if ((rsa == NULL) && (s->ctx->default_cert->rsa_tmp_cb != NULL)) + { + rsa=s->ctx->default_cert->rsa_tmp_cb(s, + (s->s3->tmp.new_cipher->algorithms| + SSL_NOT_EXP)?0:1); + CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + cert->rsa_tmp=rsa; + } + if (rsa == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY); + goto f_err; + } + r[0]=rsa->n; + r[1]=rsa->e; + s->s3->tmp.use_rsa_tmp=1; + } + else +#endif +#ifndef NO_DH + if (type & SSL_kEDH) + { + dhp=cert->dh_tmp; + if ((dhp == NULL) && (cert->dh_tmp_cb != NULL)) + dhp=cert->dh_tmp_cb(s, + (s->s3->tmp.new_cipher->algorithms| + SSL_NOT_EXP)?0:1); + if (dhp == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); + goto f_err; + } + if ((dh=DHparams_dup(dhp)) == NULL) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + + s->s3->tmp.dh=dh; + if (((dhp->pub_key == NULL) || + (dhp->priv_key == NULL) || + (s->ctx->options & SSL_OP_SINGLE_DH_USE)) && + (!DH_generate_key(dh))) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + else + { + dh->pub_key=BN_dup(dhp->pub_key); + dh->priv_key=BN_dup(dhp->priv_key); + if ((dh->pub_key == NULL) || + (dh->priv_key == NULL)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + } + r[0]=dh->p; + r[1]=dh->g; + r[2]=dh->pub_key; + } + else +#endif + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto f_err; + } + for (i=0; r[i] != NULL; i++) + { + nr[i]=BN_num_bytes(r[i]); + n+=2+nr[i]; + } + + if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) + { + if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) + == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + goto f_err; + } + kn=EVP_PKEY_size(pkey); + } + else + { + pkey=NULL; + kn=0; + } + + if (!BUF_MEM_grow(buf,n+4+kn)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); + goto err; + } + d=(unsigned char *)s->init_buf->data; + p= &(d[4]); + + for (i=0; r[i] != NULL; i++) + { + s2n(nr[i],p); + BN_bn2bin(r[i],p); + p+=nr[i]; + } + + /* not anonymous */ + if (pkey != NULL) + { + /* n is the length of the params, they start at &(d[4]) + * and p points to the space at the end. */ +#ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + q=md_buf; + j=0; + for (num=2; num > 0; num--) + { + EVP_DigestInit(&md_ctx,(num == 2)?EVP_md5():EVP_sha1()); + EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); + EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); + EVP_DigestUpdate(&md_ctx,&(d[4]),n); + EVP_DigestFinal(&md_ctx,q, + (unsigned int *)&i); + q+=i; + j+=i; + } + i=RSA_private_encrypt(j,md_buf,&(p[2]), + pkey->pkey.rsa,RSA_PKCS1_PADDING); + if (i <= 0) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); + goto err; + } + s2n(i,p); + n+=i+2; + } + else +#endif +#if !defined(NO_DSA) + if (pkey->type == EVP_PKEY_DSA) + { + /* lets do DSS */ + EVP_SignInit(&md_ctx,EVP_dss1()); + EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); + EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); + EVP_SignUpdate(&md_ctx,&(d[4]),n); + if (!EVP_SignFinal(&md_ctx,&(p[2]), + (unsigned int *)&i,pkey)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA); + goto err; + } + s2n(i,p); + n+=i+2; + } + else +#endif + { + /* Is this error check actually needed? */ + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE); + goto f_err; + } + } + + *(d++)=SSL3_MT_SERVER_KEY_EXCHANGE; + l2n3(n,d); + + /* we should now have things packed up, so lets send + * it off */ + s->init_num=n+4; + s->init_off=0; + } + + /* SSL3_ST_SW_KEY_EXCH_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + return(-1); + } + +static int ssl3_send_certificate_request(s) +SSL *s; + { + unsigned char *p,*d; + int i,j,nl,off,n; + STACK *sk=NULL; + X509_NAME *name; + BUF_MEM *buf; + + if (s->state == SSL3_ST_SW_CERT_REQ_A) + { + buf=s->init_buf; + + d=p=(unsigned char *)&(buf->data[4]); + + /* get the list of acceptable cert types */ + p++; + n=ssl3_get_req_cert_type(s,p); + d[0]=n; + p+=n; + n++; + + off=n; + p+=2; + n+=2; + + sk=SSL_get_client_CA_list(s); + nl=0; + if (sk != NULL) + { + for (i=0; i<sk_num(sk); i++) + { + name=(X509_NAME *)sk_value(sk,i); + j=i2d_X509_NAME(name,NULL); + if (!BUF_MEM_grow(buf,4+n+j+2)) + { + SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB); + goto err; + } + p=(unsigned char *)&(buf->data[4+n]); + if (!(s->ctx->options & SSL_OP_NETSCAPE_CA_DN_BUG)) + { + s2n(j,p); + i2d_X509_NAME(name,&p); + n+=2+j; + nl+=2+j; + } + else + { + d=p; + i2d_X509_NAME(name,&p); + j-=2; s2n(j,d); j+=2; + n+=j; + nl+=j; + } + } + } + /* else no CA names */ + p=(unsigned char *)&(buf->data[4+off]); + s2n(nl,p); + + d=(unsigned char *)buf->data; + *(d++)=SSL3_MT_CERTIFICATE_REQUEST; + l2n3(n,d); + + /* we should now have things packed up, so lets send + * it off */ + + s->init_num=n+4; + s->init_off=0; + } + + /* SSL3_ST_SW_CERT_REQ_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +err: + return(-1); + } + +static int ssl3_get_client_key_exchange(s) +SSL *s; + { + int i,al,ok; + long n; + unsigned long l; + unsigned char *p; + RSA *rsa=NULL; + BIGNUM *pub=NULL; + EVP_PKEY *pkey=NULL; + DH *dh_srvr; + + n=ssl3_get_message(s, + SSL3_ST_SR_KEY_EXCH_A, + SSL3_ST_SR_KEY_EXCH_B, + SSL3_MT_CLIENT_KEY_EXCHANGE, + 400, /* ???? */ + &ok); + + if (!ok) return((int)n); + p=(unsigned char *)s->init_buf->data; + + l=s->s3->tmp.new_cipher->algorithms; + +#ifndef NO_RSA + if (l & SSL_kRSA) + { + /* FIX THIS UP EAY EAY EAY EAY */ + if (s->s3->tmp.use_rsa_tmp) + { + if ((s->session->cert != NULL) && + (s->session->cert->rsa_tmp != NULL)) + rsa=s->session->cert->rsa_tmp; + else if ((s->ctx->default_cert != NULL) && + (s->ctx->default_cert->rsa_tmp != NULL)) + rsa=s->ctx->default_cert->rsa_tmp; + /* Don't do a callback because rsa_tmp should + * be sent already */ + if (rsa == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY); + goto f_err; + + } + } + else + { + pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; + if ( (pkey == NULL) || + (pkey->type != EVP_PKEY_RSA) || + (pkey->pkey.rsa == NULL)) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + rsa=pkey->pkey.rsa; + } + + i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); +#if 1 + /* If a bad decrypt, use a dud master key */ + if ((i != SSL_MAX_MASTER_KEY_LENGTH) || + (p[0] != 3) || + (p[1] != 0)) + { + p[0]=3; + p[1]=0; + RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2); + i=SSL_MAX_MASTER_KEY_LENGTH; + } +#else + if (i != SSL_MAX_MASTER_KEY_LENGTH) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); + goto f_err; + } + + if ((p[0] != (s->version>>8)) || (p[1] != (s->version & 0xff))) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + goto f_err; + } +#endif + + s->session->master_key_length= + ssl3_generate_master_secret(s, + s->session->master_key, + p,i); + memset(p,0,i); + } + else +#endif +#ifndef NO_DH + if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + { + + n2s(p,i); + if (n != i+2) + { + if (!(s->ctx->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + goto err; + } + else + { + p-=2; + i=(int)n; + } + } + + if (n == 0L) /* the parameters are in the cert */ + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS); + goto f_err; + } + else + { + if (s->s3->tmp.dh == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); + goto f_err; + } + else + dh_srvr=s->s3->tmp.dh; + } + + pub=BN_bin2bn(p,i,NULL); + if (pub == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB); + goto err; + } + i=DH_compute_key(p,pub,dh_srvr); + + if (i <= 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); + goto err; + } + + DH_free(s->s3->tmp.dh); + s->s3->tmp.dh=NULL; + + BN_clear_free(pub); + pub=NULL; + s->session->master_key_length= + ssl3_generate_master_secret(s, + s->session->master_key,p,i); + } + else +#endif + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNKNOWN_CIPHER_TYPE); + goto f_err; + } + + return(1); +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: + return(-1); + } + +static int ssl3_get_cert_verify(s) +SSL *s; + { + EVP_PKEY *pkey=NULL; + unsigned char *p; + int al,ok,ret=0; + long n; + int type=0,i,j; + X509 *peer; + + n=ssl3_get_message(s, + SSL3_ST_SR_CERT_VRFY_A, + SSL3_ST_SR_CERT_VRFY_B, + -1, + 512, /* 512? */ + &ok); + + if (!ok) return((int)n); + + if (s->session->peer != NULL) + { + peer=s->session->peer; + pkey=X509_get_pubkey(peer); + type=X509_certificate_type(peer,pkey); + } + else + { + peer=NULL; + pkey=NULL; + } + + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY) + { + s->s3->tmp.reuse_message=1; + if ((peer != NULL) && (type | EVP_PKT_SIGN)) + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE); + al=SSL3_AD_UNEXPECTED_MESSAGE; + goto f_err; + } + ret=1; + goto end; + } + + if (peer == NULL) + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED); + al=SSL3_AD_UNEXPECTED_MESSAGE; + goto f_err; + } + + if (!(type & EVP_PKT_SIGN)) + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE); + al=SSL3_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + if (s->s3->change_cipher_spec) + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY); + al=SSL3_AD_UNEXPECTED_MESSAGE; + goto f_err; + } + + /* we now have a signature that we need to verify */ + p=(unsigned char *)s->init_buf->data; + n2s(p,i); + n-=2; + if (i > n) + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH); + al=SSL3_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + j=EVP_PKEY_size(pkey); + if ((i > j) || (n > j) || (n <= 0)) + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE); + al=SSL3_AD_ILLEGAL_PARAMETER; + goto f_err; + } + +#ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + i=RSA_public_decrypt(i,p,p,pkey->pkey.rsa,RSA_PKCS1_PADDING); + if (i < 0) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT); + goto f_err; + } + if ((i != (MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH)) || + memcmp(&(s->s3->tmp.finish_md1[0]), + p,MD5_DIGEST_LENGTH) || + memcmp(&(s->s3->tmp.finish_md2[0]), + &(p[MD5_DIGEST_LENGTH]),SHA_DIGEST_LENGTH)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE); + goto f_err; + } + } + else +#endif +#ifndef NO_DSA + if (pkey->type == EVP_PKEY_DSA) + { + j=DSA_verify(pkey->save_type,s->s3->tmp.finish_md2, + SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa); + if (j <= 0) + { + /* bad signature */ + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE); + goto f_err; + } + } + else +#endif + { + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_INTERNAL_ERROR); + al=SSL3_AD_UNSUPPORTED_CERTIFICATE; + goto f_err; + } + + + ret=1; + if (0) + { +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + } +end: + return(ret); + } + +static int ssl3_get_client_certificate(s) +SSL *s; + { + int i,ok,al,ret= -1; + X509 *x=NULL; + unsigned long l,nc,llen,n; + unsigned char *p,*d,*q; + STACK *sk=NULL; + + n=ssl3_get_message(s, + SSL3_ST_SR_CERT_A, + SSL3_ST_SR_CERT_B, + -1, +#if defined(MSDOS) && !defined(WIN32) + 1024*30, /* 30k max cert list :-) */ +#else + 1024*100, /* 100k max cert list :-) */ +#endif + &ok); + + if (!ok) return((int)n); + + if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) + { + if ( (s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al=SSL3_AD_NO_CERTIFICATE; + goto f_err; + } + s->s3->tmp.reuse_message=1; + return(1); + } + + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) + { + al=SSL3_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE); + goto f_err; + } + d=p=(unsigned char *)s->init_buf->data; + + if ((sk=sk_new_null()) == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto err; + } + + n2l3(p,llen); + if (llen+3 != n) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH); + goto f_err; + } + for (nc=0; nc<llen; ) + { + n2l3(p,l); + if ((l+nc+3) > llen) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + + q=p; + x=d2i_X509(NULL,&p,l); + if (x == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB); + goto err; + } + if (p != (q+l)) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + if (!sk_push(sk,(char *)x)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); + goto err; + } + x=NULL; + nc+=l+3; + } + + if (sk_num(sk) <= 0) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_PASSED); + goto f_err; + } + i=ssl_verify_cert_chain(s,sk); + if (!i) + { + al=ssl_verify_alarm_type(s->verify_result); + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED); + goto f_err; + } + + /* This should not be needed */ + if (s->session->peer != NULL) + X509_free(s->session->peer); + + s->session->peer=(X509 *)sk_shift(sk); + + ret=1; + if (0) + { +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + } +err: + if (x != NULL) X509_free(x); + if (sk != NULL) sk_pop_free(sk,X509_free); + return(ret); + } + +int ssl3_send_server_certificate(s) +SSL *s; + { + unsigned long l; + X509 *x; + + if (s->state == SSL3_ST_SW_CERT_A) + { + x=ssl_get_server_send_cert(s); + if (x == NULL) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,SSL_R_INTERNAL_ERROR); + return(0); + } + + l=ssl3_output_cert_chain(s,x); + s->state=SSL3_ST_SW_CERT_B; + s->init_num=(int)l; + s->init_off=0; + } + + /* SSL3_ST_SW_CERT_B */ + return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + } diff --git a/ssl/ssl.c b/ssl/ssl.c new file mode 100644 index 0000000000..fcc29b0e45 --- /dev/null +++ b/ssl/ssl.c @@ -0,0 +1,162 @@ +/* ssl/ssl.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define USE_SOCKETS +#include "../e_os.h" + +#include "buffer.h" +#include "stack.h" +#include "lhash.h" + +#include "bio.h" +#include "err.h" + +#include "bn.h" + +#include "rand.h" +#include "conf.h" +#include "txt_db.h" + +#include "err.h" +#include "evp.h" + +#include "x509.h" +#include "pkcs7.h" +#include "pem.h" +#include "asn1.h" +#include "objects.h" + +#include "ssl_locl.h" + +#if !(BUILD_SSLV23) && !defined(BUILD_SSLV2) && !defined(BUILD_SSLV3) && !defined(BUILD_SSL_COMMON) && !defined(BUILD_SSL_BIO) && !defined(BUILD_SSL_OPTIONAL) +#define BUILD_SSLV23 +#define BUILD_SSLV2 +#define BUILD_SSLV3 +#define BUILD_SSL_COMMON +#define BUILD_SSL_BIO +#define BUILD_SSL_OPTIONAL +#endif + +#ifdef NO_RSA +#undef BUILD_SSLV2 +#undef BUILD_SSLV23 +#endif + +#ifdef NO_SSL2 +#undef BUILD_SSLV2 +#undef BUILD_SSLV23 +#endif + +#ifdef NO_SSL3 +#undef BUILD_SSL3 +#undef BUILD_SSLV23 +#endif + +#ifdef BUILD_SSLV23 +#include "s23_clnt.c" +#include "s23_srvr.c" +#include "s23_pkt.c" +#include "s23_lib.c" +#include "s23_meth.c" +#endif + +#ifdef BUILD_SSLV2 +#include "s2_clnt.c" +#include "s2_srvr.c" +#include "s2_pkt.c" +#include "s2_enc.c" +#include "s2_lib.c" +#include "s2_meth.c" +#endif + +#ifdef BUILD_SSLV3 +#include "s3_clnt.c" +#include "s3_both.c" +#include "s3_srvr.c" +#include "s3_pkt.c" +#include "s3_enc.c" +#include "s3_lib.c" +#include "s3_meth.c" +#endif + +#ifdef BUILD_SSL_COMMON +#include "ssl_lib.c" +#include "ssl_algs.c" +#include "ssl_cert.c" +#include "ssl_ciph.c" +#include "ssl_sess.c" +#include "ssl_rsa.c" +#endif + +/* Extra things */ +#ifdef BUILD_SSL_BIO +#include "bio_ssl.c" +#endif + +#ifdef BUILD_SSL_OPTIONAL +#include "ssl_asn1.c" +#include "ssl_txt.c" +#include "ssl_stat.c" +#include "ssl_err.c" +#include "ssl_err2.c" +#endif + diff --git a/ssl/ssl.err b/ssl/ssl.err new file mode 100644 index 0000000000..f3bc5d37ab --- /dev/null +++ b/ssl/ssl.err @@ -0,0 +1,272 @@ +/* Error codes for the SSL functions. */ + +/* Function codes. */ +#define SSL_F_CLIENT_CERTIFICATE 100 +#define SSL_F_CLIENT_HELLO 101 +#define SSL_F_CLIENT_MASTER_KEY 102 +#define SSL_F_D2I_SSL_SESSION 103 +#define SSL_F_DO_SSL3_WRITE 104 +#define SSL_F_GET_CLIENT_FINISHED 105 +#define SSL_F_GET_CLIENT_HELLO 106 +#define SSL_F_GET_CLIENT_MASTER_KEY 107 +#define SSL_F_GET_SERVER_FINISHED 108 +#define SSL_F_GET_SERVER_HELLO 109 +#define SSL_F_GET_SERVER_VERIFY 110 +#define SSL_F_I2D_SSL_SESSION 111 +#define SSL_F_READ_N 112 +#define SSL_F_REQUEST_CERTIFICATE 113 +#define SSL_F_SERVER_HELLO 114 +#define SSL_F_SSL23_ACCEPT 115 +#define SSL_F_SSL23_CLIENT_HELLO 116 +#define SSL_F_SSL23_CONNECT 117 +#define SSL_F_SSL23_GET_CLIENT_HELLO 118 +#define SSL_F_SSL23_GET_SERVER_HELLO 119 +#define SSL_F_SSL23_READ 120 +#define SSL_F_SSL23_WRITE 121 +#define SSL_F_SSL2_ACCEPT 122 +#define SSL_F_SSL2_CONNECT 123 +#define SSL_F_SSL2_ENC_INIT 124 +#define SSL_F_SSL2_READ 125 +#define SSL_F_SSL2_SET_CERTIFICATE 126 +#define SSL_F_SSL2_WRITE 127 +#define SSL_F_SSL3_ACCEPT 128 +#define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 +#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +#define SSL_F_SSL3_CLIENT_HELLO 131 +#define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTX_CTRL 133 +#define SSL_F_SSL3_ENC 134 +#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 +#define SSL_F_SSL3_GET_CERT_VERIFY 136 +#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137 +#define SSL_F_SSL3_GET_CLIENT_HELLO 138 +#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE 139 +#define SSL_F_SSL3_GET_FINISHED 140 +#define SSL_F_SSL3_GET_KEY_EXCHANGE 141 +#define SSL_F_SSL3_GET_MESSAGE 142 +#define SSL_F_SSL3_GET_RECORD 143 +#define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144 +#define SSL_F_SSL3_GET_SERVER_DONE 145 +#define SSL_F_SSL3_GET_SERVER_HELLO 146 +#define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +#define SSL_F_SSL3_READ_BYTES 148 +#define SSL_F_SSL3_READ_N 149 +#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150 +#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE 151 +#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152 +#define SSL_F_SSL3_SEND_CLIENT_VERIFY 153 +#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154 +#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155 +#define SSL_F_SSL3_SETUP_BUFFERS 156 +#define SSL_F_SSL3_SETUP_KEY_BLOCK 157 +#define SSL_F_SSL3_WRITE_BYTES 158 +#define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_BAD_METHOD 160 +#define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_NEW 162 +#define SSL_F_SSL_CHECK_PRIVATE_KEY 163 +#define SSL_F_SSL_CREATE_CIPHER_LIST 164 +#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 165 +#define SSL_F_SSL_CTX_NEW 166 +#define SSL_F_SSL_CTX_SET_SSL_VERSION 167 +#define SSL_F_SSL_CTX_USE_CERTIFICATE 168 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 169 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 170 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY 171 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 172 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 173 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 174 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 175 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 176 +#define SSL_F_SSL_DO_HANDSHAKE 177 +#define SSL_F_SSL_GET_NEW_SESSION 178 +#define SSL_F_SSL_GET_SERVER_SEND_CERT 179 +#define SSL_F_SSL_GET_SIGN_PKEY 180 +#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 181 +#define SSL_F_SSL_NEW 182 +#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 183 +#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 184 +#define SSL_F_SSL_SESSION_NEW 185 +#define SSL_F_SSL_SESSION_PRINT_FP 186 +#define SSL_F_SSL_SET_FD 187 +#define SSL_F_SSL_SET_PKEY 188 +#define SSL_F_SSL_SET_RFD 189 +#define SSL_F_SSL_SET_SESSION 190 +#define SSL_F_SSL_SET_WFD 191 +#define SSL_F_SSL_UNDEFINED_FUNCTION 192 +#define SSL_F_SSL_USE_CERTIFICATE 193 +#define SSL_F_SSL_USE_CERTIFICATE_ASN1 194 +#define SSL_F_SSL_USE_CERTIFICATE_FILE 195 +#define SSL_F_SSL_USE_PRIVATEKEY 196 +#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 197 +#define SSL_F_SSL_USE_PRIVATEKEY_FILE 198 +#define SSL_F_SSL_USE_RSAPRIVATEKEY 199 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 200 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 201 +#define SSL_F_SSL_WRITE 202 +#define SSL_F_WRITE_PENDING 203 + +/* Reason codes. */ +#define SSL_R_APP_DATA_IN_HANDSHAKE 100 +#define SSL_R_BAD_ALERT_RECORD 101 +#define SSL_R_BAD_AUTHENTICATION_TYPE 102 +#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +#define SSL_R_BAD_CHECKSUM 104 +#define SSL_R_BAD_CLIENT_REQUEST 105 +#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 +#define SSL_R_BAD_DECOMPRESSION 107 +#define SSL_R_BAD_DH_G_LENGTH 108 +#define SSL_R_BAD_DH_PUB_KEY_LENGTH 109 +#define SSL_R_BAD_DH_P_LENGTH 110 +#define SSL_R_BAD_DIGEST_LENGTH 111 +#define SSL_R_BAD_DSA_SIGNATURE 112 +#define SSL_R_BAD_MAC_DECODE 113 +#define SSL_R_BAD_MESSAGE_TYPE 114 +#define SSL_R_BAD_PACKET_LENGTH 115 +#define SSL_R_BAD_RESPONSE_ARGUMENT 116 +#define SSL_R_BAD_RSA_DECRYPT 117 +#define SSL_R_BAD_RSA_ENCRYPT 118 +#define SSL_R_BAD_RSA_E_LENGTH 119 +#define SSL_R_BAD_RSA_MODULUS_LENGTH 120 +#define SSL_R_BAD_RSA_SIGNATURE 121 +#define SSL_R_BAD_SIGNATURE 122 +#define SSL_R_BAD_SSL_FILETYPE 123 +#define SSL_R_BAD_SSL_SESSION_ID_LENGTH 124 +#define SSL_R_BAD_STATE 125 +#define SSL_R_BAD_WRITE_RETRY 126 +#define SSL_R_BIO_NOT_SET 127 +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 128 +#define SSL_R_BN_LIB 129 +#define SSL_R_CA_DN_LENGTH_MISMATCH 130 +#define SSL_R_CA_DN_TOO_LONG 131 +#define SSL_R_CCS_RECEIVED_EARLY 132 +#define SSL_R_CERTIFICATE_VERIFY_FAILED 133 +#define SSL_R_CERT_LENGTH_MISMATCH 134 +#define SSL_R_CHALLENGE_IS_DIFFERENT 135 +#define SSL_R_CIPHER_CODE_WRONG_LENGTH 136 +#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 137 +#define SSL_R_CIPHER_TABLE_SRC_ERROR 138 +#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 139 +#define SSL_R_COMPRESSION_FAILURE 140 +#define SSL_R_CONNECTION_ID_IS_DIFFERENT 141 +#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 142 +#define SSL_R_DATA_LENGTH_TOO_LONG 143 +#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 144 +#define SSL_R_DIGEST_CHECK_FAILED 145 +#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 146 +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 147 +#define SSL_R_EXCESSIVE_MESSAGE_SIZE 148 +#define SSL_R_EXTRA_DATA_IN_MESSAGE 149 +#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 150 +#define SSL_R_INTERNAL_ERROR 151 +#define SSL_R_INVALID_CHALLENGE_LENGTH 152 +#define SSL_R_LENGTH_MISMATCH 153 +#define SSL_R_LENGTH_TOO_SHORT 154 +#define SSL_R_LIBRARY_HAS_NO_CIPHERS 155 +#define SSL_R_MISSING_DH_DSA_CERT 156 +#define SSL_R_MISSING_DH_KEY 157 +#define SSL_R_MISSING_DH_RSA_CERT 158 +#define SSL_R_MISSING_DSA_SIGNING_CERT 159 +#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 160 +#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 161 +#define SSL_R_MISSING_RSA_CERTIFICATE 162 +#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 163 +#define SSL_R_MISSING_RSA_SIGNING_CERT 164 +#define SSL_R_MISSING_TMP_DH_KEY 165 +#define SSL_R_MISSING_TMP_RSA_KEY 166 +#define SSL_R_MISSING_TMP_RSA_PKEY 167 +#define SSL_R_MISSING_VERIFY_MESSAGE 168 +#define SSL_R_NON_SSLV2_INITIAL_PACKET 169 +#define SSL_R_NO_CERTIFICATES_PASSED 170 +#define SSL_R_NO_CERTIFICATE_ASSIGNED 171 +#define SSL_R_NO_CERTIFICATE_RETURNED 172 +#define SSL_R_NO_CERTIFICATE_SET 173 +#define SSL_R_NO_CERTIFICATE_SPECIFIED 174 +#define SSL_R_NO_CIPHERS_AVAILABLE 175 +#define SSL_R_NO_CIPHERS_PASSED 176 +#define SSL_R_NO_CIPHERS_SPECIFIED 177 +#define SSL_R_NO_CIPHER_LIST 178 +#define SSL_R_NO_CIPHER_MATCH 179 +#define SSL_R_NO_CLIENT_CERT_RECEIVED 180 +#define SSL_R_NO_COMPRESSION_SPECIFIED 181 +#define SSL_R_NO_PRIVATEKEY 182 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 183 +#define SSL_R_NO_PUBLICKEY 184 +#define SSL_R_NO_SHARED_CIPHER 185 +#define SSL_R_NULL_SSL_CTX 186 +#define SSL_R_NULL_SSL_METHOD_PASSED 187 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 188 +#define SSL_R_PACKET_LENGTH_TOO_LONG 189 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 190 +#define SSL_R_PEER_ERROR 191 +#define SSL_R_PEER_ERROR_CERTIFICATE 192 +#define SSL_R_PEER_ERROR_NO_CERTIFICATE 193 +#define SSL_R_PEER_ERROR_NO_CIPHER 194 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 195 +#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 196 +#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 197 +#define SSL_R_PROTOCOL_IS_SHUTDOWN 198 +#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 199 +#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 200 +#define SSL_R_PUBLIC_KEY_NOT_RSA 201 +#define SSL_R_READ_BIO_NOT_SET 202 +#define SSL_R_READ_WRONG_PACKET_TYPE 203 +#define SSL_R_RECORD_LENGTH_MISMATCH 204 +#define SSL_R_RECORD_TOO_LARGE 205 +#define SSL_R_REQUIRED_CIPHER_MISSING 206 +#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 207 +#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 208 +#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 209 +#define SSL_R_SHORT_READ 210 +#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 211 +#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 212 +#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE 213 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE 214 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER 215 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 216 +#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE 217 +#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 218 +#define SSL_R_SSL_HANDSHAKE_FAILURE 219 +#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 220 +#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 221 +#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 222 +#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 223 +#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 224 +#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 225 +#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 226 +#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 227 +#define SSL_R_UNEXPECTED_MESSAGE 228 +#define SSL_R_UNEXPECTED_RECORD 229 +#define SSL_R_UNKNOWN_ALERT_TYPE 230 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 231 +#define SSL_R_UNKNOWN_CIPHER_RETURNED 232 +#define SSL_R_UNKNOWN_CIPHER_TYPE 233 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 234 +#define SSL_R_UNKNOWN_PKEY_TYPE 235 +#define SSL_R_UNKNOWN_PROTOCOL 236 +#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 237 +#define SSL_R_UNKNOWN_SSL_VERSION 238 +#define SSL_R_UNKNOWN_STATE 239 +#define SSL_R_UNSUPPORTED_CIPHER 240 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 241 +#define SSL_R_UNSUPPORTED_SSL_VERSION 242 +#define SSL_R_WRITE_BIO_NOT_SET 243 +#define SSL_R_WRONG_CIPHER_RETURNED 244 +#define SSL_R_WRONG_MESSAGE_TYPE 245 +#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 246 +#define SSL_R_WRONG_SIGNATURE_LENGTH 247 +#define SSL_R_WRONG_SIGNATURE_SIZE 248 +#define SSL_R_WRONG_SSL_VERSION 249 +#define SSL_R_WRONG_VERSION_NUMBER 250 +#define SSL_R_X509_LIB 251 diff --git a/ssl/ssl.h b/ssl/ssl.h new file mode 100644 index 0000000000..594295d5e0 --- /dev/null +++ b/ssl/ssl.h @@ -0,0 +1,1290 @@ +/* ssl/ssl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL_H +#define HEADER_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* SSLeay version number for ASN.1 encoding of the session information */ +/* Version 0 - initial version + * Version 1 - added the optional peer certificate + */ +#define SSL_SESSION_ASN1_VERSION 0x0001 + +/* text strings for the ciphers */ +#define SSL_TXT_NULL_WITH_MD5 SSL2_TXT_NULL_WITH_MD5 +#define SSL_TXT_RC4_128_WITH_MD5 SSL2_TXT_RC4_128_WITH_MD5 +#define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 +#define SSL_TXT_RC2_128_CBC_WITH_MD5 SSL2_TXT_RC2_128_CBC_WITH_MD5 +#define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 +#define SSL_TXT_IDEA_128_CBC_WITH_MD5 SSL2_TXT_IDEA_128_CBC_WITH_MD5 +#define SSL_TXT_DES_64_CBC_WITH_MD5 SSL2_TXT_DES_64_CBC_WITH_MD5 +#define SSL_TXT_DES_64_CBC_WITH_SHA SSL2_TXT_DES_64_CBC_WITH_SHA +#define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 +#define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA + +#define SSL_MAX_SSL_SESSION_ID_LENGTH 32 + +#define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) +#define SSL_MAX_KEY_ARG_LENGTH 8 +#define SSL_MAX_MASTER_KEY_LENGTH 48 + +/* These are used to specify which ciphers to use and not to use */ +#define SSL_TXT_LOW "LOW" +#define SSL_TXT_MEDIUM "MEDIUM" +#define SSL_TXT_HIGH "HIGH" +#define SSL_TXT_kFZA "kFZA" +#define SSL_TXT_aFZA "aFZA" +#define SSL_TXT_eFZA "eFZA" +#define SSL_TXT_FZA "FZA" + +#define SSL_TXT_aNULL "aNULL" +#define SSL_TXT_eNULL "eNULL" +#define SSL_TXT_NULL "NULL" + +#define SSL_TXT_kRSA "kRSA" +#define SSL_TXT_kDHr "kDHr" +#define SSL_TXT_kDHd "kDHd" +#define SSL_TXT_kEDH "kEDH" +#define SSL_TXT_aRSA "aRSA" +#define SSL_TXT_aDSS "aDSS" +#define SSL_TXT_aDH "aDH" +#define SSL_TXT_DSS "DSS" +#define SSL_TXT_DH "DH" +#define SSL_TXT_EDH "EDH" +#define SSL_TXT_ADH "ADH" +#define SSL_TXT_RSA "RSA" +#define SSL_TXT_DES "DES" +#define SSL_TXT_3DES "3DES" +#define SSL_TXT_RC4 "RC4" +#define SSL_TXT_RC2 "RC2" +#define SSL_TXT_IDEA "IDEA" +#define SSL_TXT_MD5 "MD5" +#define SSL_TXT_SHA0 "SHA0" +#define SSL_TXT_SHA1 "SHA1" +#define SSL_TXT_SHA "SHA" +#define SSL_TXT_EXP "EXP" +#define SSL_TXT_EXPORT "EXPORT" +#define SSL_TXT_SSLV2 "SSLv2" +#define SSL_TXT_SSLV3 "SSLv3" +#define SSL_TXT_ALL "ALL" + +/* 'DEFAULT' at the start of the cipher list insert the following string + * in addition to this being the default cipher string */ +#ifndef NO_RSA +#define SSL_DEFAULT_CIPHER_LIST "!ADH:RC4+RSA:HIGH:MEDIUM:LOW:EXP:+SSLv2:+EXP" +#else +#define SSL_ALLOW_ADH +#define SSL_DEFAULT_CIPHER_LIST "HIGH:MEDIUM:LOW:ADH+3DES:ADH+RC4:ADH+DES:+EXP" +#endif + +#define SSL_SENT_SHUTDOWN 1 +#define SSL_RECEIVED_SHUTDOWN 2 +#define SSL_CTX_set_quiet_shutdown(ctx,y) ((ctx)->quiet_shutdown=(y)); +#define SSL_CTX_get_quiet_shutdown(ctx) ((ctx)->quiet_shutdown); +#define SSL_set_quiet_shutdown(s,y) ((s)->quiet_shutdown=(y)); +#define SSL_get_quiet_shutdown(s) ((s)->quiet_shutdown); +#define SSL_set_shutdown(s,mode) ((s)->shutdown=(mode)) +#define SSL_get_shutdown(s) ((s)->shutdown) +#define SSL_version(s) ((s)->version) + +#include "buffer.h" +#include "bio.h" +#include "x509.h" + +#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 +#define SSL_FILETYPE_PEM X509_FILETYPE_PEM + +typedef struct ssl_st *ssl_crock_st; + +/* used to hold info on the particular ciphers used */ +typedef struct ssl_cipher_st + { + int valid; + char *name; /* text name */ + unsigned long id; /* id, 4 bytes, first is version */ + unsigned long algorithms; /* what ciphers are used */ + unsigned long algorithm2; /* Extra flags */ + unsigned long mask; /* used for matching */ + } SSL_CIPHER; + +/* Used to hold functions for SSLv2 or SSLv3 functions */ +typedef struct ssl_method_st + { + int version; + int (*ssl_new)(); + void (*ssl_clear)(); + void (*ssl_free)(); + int (*ssl_accept)(); + int (*ssl_connect)(); + int (*ssl_read)(); + int (*ssl_peek)(); + int (*ssl_write)(); + int (*ssl_shutdown)(); + int (*ssl_renegotiate)(); + long (*ssl_ctrl)(); + long (*ssl_ctx_ctrl)(); + SSL_CIPHER *(*get_cipher_by_char)(); + int (*put_cipher_by_char)(); + int (*ssl_pending)(); + int (*num_ciphers)(); + SSL_CIPHER *(*get_cipher)(); + struct ssl_method_st *(*get_ssl_method)(); + long (*get_timeout)(); + } SSL_METHOD; + +typedef struct ssl_compression_st + { + char *stuff; + } SSL_COMPRESSION; + +/* Lets make this into an ASN.1 type structure as follows + * SSL_SESSION_ID ::= SEQUENCE { + * version INTEGER, -- structure version number + * SSLversion INTEGER, -- SSL version number + * Cipher OCTET_STRING, -- the 3 byte cipher ID + * Session_ID OCTET_STRING, -- the Session ID + * Master_key OCTET_STRING, -- the master key + * Key_Arg [ 0 ] IMPLICIT OCTET_STRING, -- the optional Key argument + * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time + * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds + * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate + * } + * Look in ssl/ssl_asn1.c for more details + * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). + */ +typedef struct ssl_session_st + { + int ssl_version; /* what ssl version session info is + * being kept in here? */ + + /* only really used in SSLv2 */ + unsigned int key_arg_length; + unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH]; + int master_key_length; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + /* session_id - valid? */ + unsigned int session_id_length; + unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + + int not_resumable; + + /* The cert is the certificate used to establish this connection */ + struct cert_st /* CERT */ *cert; + + /* This is the cert for the other end. On servers, it will be + * the same as cert->x509 */ + X509 *peer; + + int references; + long timeout; + long time; + + SSL_COMPRESSION *read_compression; + SSL_COMPRESSION *write_compression; + + SSL_CIPHER *cipher; + unsigned long cipher_id; /* when ASN.1 loaded, this + * needs to be used to load + * the 'cipher' structure */ + + STACK /* SSL_CIPHER */ *ciphers; /* shared ciphers? */ + + char *app_data; /* application specific data */ + } SSL_SESSION; + +#define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L +#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L +#define SSL_OP_NETSCAPE_CA_DN_BUG 0x00000004L +#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L +#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L +#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L +#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L +#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L + +/* If set, only use tmp_dh parameters once */ +#define SSL_OP_SINGLE_DH_USE 0x00100000L +/* Set to also use the tmp_rsa key when doing RSA operations. */ +#define SSL_OP_EPHEMERAL_RSA 0x00200000L + +#define SSL_OP_NON_EXPORT_FIRST 0x40000000L +#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x80000000L +#define SSL_OP_ALL 0x000FFFFFL + +#define SSL_CTX_set_options(ctx,op) ((ctx)->options|=(op)) + +/* Normally you will only use these if your application wants to use + * the certificate store in other places, perhaps PKCS7 */ +#define SSL_CTX_get_cert_store(ctx) ((ctx)->cert_store) +#define SSL_CTX_set_cert_store(ctx,cs) \ + (X509_STORE_free((ctx)->cert_store),(ctx)->cert_store=(cs)) + + +typedef struct ssl_ctx_st + { + SSL_METHOD *method; + unsigned long options; + + STACK /* SSL_CIPHER */ *cipher_list; + /* same as above but sorted for lookup */ + STACK /* SSL_CIPHER */ *cipher_list_by_id; + + struct x509_store_st /* X509_STORE */ *cert_store; + struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSION's */ + + /* This can have one of 2 values, ored together, + * SSL_SESS_CACHE_CLIENT, + * SSL_SESS_CACHE_SERVER, + * Default is SSL_SESSION_CACHE_SERVER, which means only + * SSL_accept which cache SSL_SESSIONS. */ + int session_cache_mode; + + /* If timeout is not 0, it is the default timeout value set + * when SSL_new() is called. This has been put in to make + * life easier to set things up */ + long session_timeout; + + /* If this callback is not null, it will be called each + * time a session id is added to the cache. If this function + * returns 1, it means that the callback will do a + * SSL_SESSION_free() when it has finished using it. Otherwise, + * on 0, it means the callback has finished with it. + * If remove_session_cb is not null, it will be called when + * a session-id is removed from the cache. Again, a return + * of 0 mens that SSLeay should not SSL_SESSION_free() since + * the application is doing something with it. */ +#ifndef NOPROTO + int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess); + void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess); + SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, + unsigned char *data,int len,int *copy); +#else + int (*new_session_cb)(); + void (*remove_session_cb)(); + SSL_SESSION *(*get_session_cb)(); +#endif + + int sess_connect; /* SSL new (expensive) connection - started */ + int sess_connect_good; /* SSL new (expensive) connection - finished */ + int sess_accept; /* SSL new (expensive) accept - started */ + int sess_accept_good; /* SSL new (expensive) accept - finished */ + int sess_miss; /* session lookup misses */ + int sess_timeout; /* session reuse attempt on timeouted session */ + int sess_hit; /* session reuse actually done */ + int sess_cb_hit; /* session-id that was not in the cache was + * passed back via the callback. This + * indicates that the application is supplying + * session-id's from other processes - + * spooky :-) */ + + int references; + + void (*info_callback)(); + + /* if defined, these override the X509_verify_cert() calls */ + int (*app_verify_callback)(); + char *app_verify_arg; + + /* default values to use in SSL structures */ + struct cert_st /* CERT */ *default_cert; + int default_read_ahead; + int default_verify_mode; + int (*default_verify_callback)(); + + /* Default password callback. */ + int (*default_passwd_callback)(); + + /* get client cert callback */ + int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */); + + /* what we put in client requests */ + STACK *client_CA; + + int quiet_shutdown; + + char *app_data; + } SSL_CTX; + +#define SSL_SESS_CACHE_OFF 0x00 +#define SSL_SESS_CACHE_CLIENT 0x01 +#define SSL_SESS_CACHE_SERVER 0x02 +#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER) +#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x80 + +#define SSL_session_reused(s) ((s)->hit) + +#define SSL_CTX_sessions(ctx) ((ctx)->sessions) +/* You will need to include lhash.h to access the following #define */ +#define SSL_CTX_sess_number(ctx) ((ctx)->sessions->num_items) +#define SSL_CTX_sess_connect(ctx) ((ctx)->sess_connect) +#define SSL_CTX_sess_connect_good(ctx) ((ctx)->sess_connect_good) +#define SSL_CTX_sess_accept(ctx) ((ctx)->sess_accept) +#define SSL_CTX_sess_accept_good(ctx) ((ctx)->sess_accept_good) +#define SSL_CTX_sess_hits(ctx) ((ctx)->sess_hit) +#define SSL_CTX_sess_cb_hits(ctx) ((ctx)->sess_cb_hit) +#define SSL_CTX_sess_misses(ctx) ((ctx)->sess_miss) +#define SSL_CTX_sess_timeouts(ctx) ((ctx)->sess_timeout) + +#define SSL_CTX_sess_set_new_cb(ctx,cb) ((ctx)->new_session_cb=(cb)) +#define SSL_CTX_sess_get_new_cb(ctx) ((ctx)->new_session_cb) +#define SSL_CTX_sess_set_remove_cb(ctx,cb) ((ctx)->remove_session_cb=(cb)) +#define SSL_CTX_sess_get_remove_cb(ctx) ((ctx)->remove_session_cb) +#define SSL_CTX_sess_set_get_cb(ctx,cb) ((ctx)->get_session_cb=(cb)) +#define SSL_CTX_sess_get_get_cb(ctx) ((ctx)->get_session_cb) +#define SSL_CTX_set_session_cache_mode(ctx,m) ((ctx)->session_cache_mode=(m)) +#define SSL_CTX_get_session_cache_mode(ctx) ((ctx)->session_cache_mode) +#define SSL_CTX_set_timeout(ctx,t) ((ctx)->session_timeout=(t)) +#define SSL_CTX_get_timeout(ctx) ((ctx)->session_timeout) + +#define SSL_CTX_set_info_callback(ctx,cb) ((ctx)->info_callback=(cb)) +#define SSL_CTX_get_info_callback(ctx) ((ctx)->info_callback) +#define SSL_CTX_set_default_read_ahead(ctx,m) (((ctx)->default_read_ahead)=(m)) + +#define SSL_CTX_set_client_cert_cb(ctx,cb) ((ctx)->client_cert_cb=(cb)) +#define SSL_CTX_get_client_cert_cb(ctx) ((ctx)->client_cert_cb) + +#define SSL_NOTHING 1 +#define SSL_WRITING 2 +#define SSL_READING 3 +#define SSL_X509_LOOKUP 4 + +/* These will only be used when doing non-blocking IO */ +#define SSL_want(s) ((s)->rwstate) +#define SSL_want_nothing(s) ((s)->rwstate == SSL_NOTHING) +#define SSL_want_read(s) ((s)->rwstate == SSL_READING) +#define SSL_want_write(s) ((s)->rwstate == SSL_WRITING) +#define SSL_want_x509_lookup(s) ((s)->rwstate == SSL_X509_LOOKUP) + +typedef struct ssl_st + { + /* procol version + * 2 for SSLv2 + * 3 for SSLv3 + * -3 for SSLv3 but accept SSLv2 */ + int version; + int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */ + + SSL_METHOD *method; /* SSLv3 */ + + /* There are 2 BIO's even though they are normally both the + * same. This is so data can be read and written to different + * handlers */ + +#ifdef HEADER_BIO_H + BIO *rbio; /* used by SSL_read */ + BIO *wbio; /* used by SSL_write */ + BIO *bbio; /* used during session-id reuse to concatinate + * messages */ +#else + char *rbio; /* used by SSL_read */ + char *wbio; /* used by SSL_write */ + char *bbio; +#endif + /* This holds a variable that indicates what we were doing + * when a 0 or -1 is returned. This is needed for + * non-blocking IO so we know what request needs re-doing when + * in SSL_accept or SSL_connect */ + int rwstate; + + /* true when we are actually in SSL_accept() or SSL_connect() */ + int in_handshake; + int (*handshake_func)(); + +/* int server;*/ /* are we the server side? */ + + int new_session;/* 1 if we are to use a new session */ + int quiet_shutdown;/* don't send shutdown packets */ + int shutdown; /* we have shut things down, 0x01 sent, 0x02 + * for received */ + int state; /* where we are */ + int rstate; /* where we are when reading */ + + BUF_MEM *init_buf; /* buffer used during init */ + int init_num; /* amount read/written */ + int init_off; /* amount read/written */ + + /* used internally to point at a raw packet */ + unsigned char *packet; + unsigned int packet_length; + + struct ssl2_ctx_st *s2; /* SSLv2 variables */ + struct ssl3_ctx_st *s3; /* SSLv3 variables */ + + int read_ahead; /* Read as many input bytes as possible */ + int hit; /* reusing a previous session */ + + /* crypto */ + STACK /* SSL_CIPHER */ *cipher_list; + STACK /* SSL_CIPHER */ *cipher_list_by_id; + + /* These are the ones being used, the ones is SSL_SESSION are + * the ones to be 'copied' into these ones */ + + EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ + EVP_MD *read_hash; /* used for mac generation */ + SSL_COMPRESSION *read_compression; /* compression */ + + EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + EVP_MD *write_hash; /* used for mac generation */ + SSL_COMPRESSION *write_compression; /* compression */ + + /* session info */ + + /* client cert? */ + /* This is used to hold the server certificate used */ + struct cert_st /* CERT */ *cert; + + /* This can also be in the session once a session is established */ + SSL_SESSION *session; + + /* Used in SSL2 and SSL3 */ + int verify_mode; /* 0 don't care about verify failure. + * 1 fail if verify fails */ + int (*verify_callback)(); /* fail if callback returns 0 */ + void (*info_callback)(); /* optional informational callback */ + + int error; /* error bytes to be written */ + int error_code; /* actual code */ + + SSL_CTX *ctx; + /* set this flag to 1 and a sleep(1) is put into all SSL_read() + * and SSL_write() calls, good for nbio debuging :-) */ + int debug; + + /* extra application data */ + int verify_result; + char *app_data; + + /* for server side, keep the list of CA_dn we can use */ + STACK /* X509_NAME */ *client_CA; + + int first_packet; + } SSL; + +#include "ssl2.h" +#include "ssl3.h" +#include "ssl23.h" + +/* application stuff */ +#define SSL_set_verify_result(s,arg) ((s)->verify_result=(long)arg) +#define SSL_get_verify_result(s) ((s)->verify_result) +#define SSL_set_app_data(s,arg) ((s)->app_data=(char *)arg) +#define SSL_get_app_data(s) ((s)->app_data) + +#define SSL_SESSION_set_app_data(s,arg) ((s)->app_data=(char *)arg) +#define SSL_SESSION_get_app_data(s) ((s)->app_data) + +#define SSL_CTX_set_app_data(ctx,arg) ((ctx)->app_data=(char *)arg) +#define SSL_CTX_get_app_data(ctx) ((ctx)->app_data) + +/* The following are the possible values for ssl->state are are + * used to indicate where we are upto in the SSL connection establishment. + * The macros that follow are about the only things you should need to use + * and even then, only when using non-blocking IO. + * It can also be useful to work out where you were when the connection + * failed */ + +#define SSL_state(a) ((a)->state) +#define SSL_ST_CONNECT 0x1000 +#define SSL_ST_ACCEPT 0x2000 +#define SSL_ST_MASK 0x0FFF +#define SSL_ST_INIT (SSL_ST_CONNECT|SSL_ST_ACCEPT) +#define SSL_ST_BEFORE 0x4000 +#define SSL_ST_OK 0x03 +#define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT) + +/* SSL info callback functions */ +#define SSL_set_info_callback(ssl,cb) ((ssl)->info_callback=(cb)) +#define SSL_get_info_callback(ssl) ((ssl)->info_callback) + +#define SSL_CB_LOOP 0x01 +#define SSL_CB_EXIT 0x02 +#define SSL_CB_READ 0x04 +#define SSL_CB_WRITE 0x08 +#define SSL_CB_ALERT 0x4000 /* used in callback */ +#define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ) +#define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE) +#define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP) +#define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT) +#define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP) +#define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT) +#define SSL_CB_HANDSHAKE_START 0x10 +#define SSL_CB_HANDSHAKE_DONE 0x20 + +/* Is the SSL_connection established? */ +#define SSL_is_init_finished(a) ((a)->state == SSL_ST_OK) +#define SSL_in_init(a) ((a)->state&SSL_ST_INIT) +#define SSL_in_before(a) ((a)->state&SSL_ST_BEFORE) +#define SSL_in_connect_init(a) ((a)->state&SSL_ST_CONNECT) +#define SSL_in_accept_init(a) ((a)->state&SSL_ST_ACCEPT) + +/* The following 2 states are kept in ssl->rstate when reads fail, + * you should not need these */ +#define SSL_ST_READ_HEADER 0xF0 +#define SSL_ST_READ_BODY 0xF1 +#define SSL_ST_READ_DONE 0xF2 + +/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options + * are 'ored' with SSL_VERIFY_PEER if they are desired */ +#define SSL_VERIFY_NONE 0x00 +#define SSL_VERIFY_PEER 0x01 +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +#define SSL_VERIFY_CLIENT_ONCE 0x04 + +#define SSL_RWERR_BAD_WRITE_RETRY (-2) +#define SSL_RWERR_BAD_MAC_DECODE (-3) +#define SSL_RWERR_INTERNAL_ERROR (-4) /* should not get this one */ +#define SSL_RWERR_WRONG_RECORD_TYPE (-5) /* used internally */ + +#define SSL_CTX_set_default_verify_paths(ctx) \ + X509_STORE_set_default_paths((ctx)->cert_store) +#define SSL_CTX_load_verify_locations(ctx,CAfile,CApath) \ + X509_STORE_load_locations((ctx)->cert_store,\ + (CAfile),(CApath)) + +#define SSL_get_session(s) ((s)->session) +#define SSL_get_SSL_CTX(s) ((s)->ctx) + +/* this is for backward compatablility */ +#if 0 /* NEW_SSLEAY */ +#define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c) +#define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n) +#define SSL_add_session(a,b) SSL_CTX_add_session((a),(b)) +#define SSL_remove_session(a,b) SSL_CTX_remove_session((a),(b)) +#define SSL_flush_sessions(a,b) SSL_CTX_flush_sessions((a),(b)) +#endif +/* More backward compatablity */ +#define SSL_get_cipher(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +#define SSL_get_cipher_bits(s,np) \ + SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +#define SSL_get_cipher_version(s) \ + SSL_CIPHER_get_version(SSL_get_current_cipher(s)) +#define SSL_get_cipher_name(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) + +/* VMS linker has a 31 char name limit */ +#define SSL_CTX_set_cert_verify_callback(a,b,c) \ + SSL_CTX_set_cert_verify_cb((a),(b),(c)) + +#if 1 /*SSLEAY_MACROS*/ +#define d2i_SSL_SESSION_bio(bp,s_id) (SSL_SESSION *)ASN1_d2i_bio( \ + (char *(*)())SSL_SESSION_new,(char *(*)())d2i_SSL_SESSION, \ + (bp),(unsigned char **)(s_id)) +#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio(i2d_SSL_SESSION, \ + bp,(unsigned char *)s_id) +#define PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb) +#define PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb) +#define PEM_write_SSL_SESSION(fp,x) \ + PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \ + PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL) +#define PEM_write_bio_SSL_SESSION(bp,x) \ + PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \ + PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL) +#endif + +#define SSL_ERROR_NONE 0 +#define SSL_ERROR_SSL 1 +#define SSL_ERROR_WANT_READ 2 +#define SSL_ERROR_WANT_WRITE 3 +#define SSL_ERROR_WANT_X509_LOOKUP 4 +#define SSL_ERROR_SYSCALL 5 /* look at errno */ +#define SSL_ERROR_ZERO_RETURN 6 +#define SSL_ERROR_WANT_CONNECT 7 + +#define SSL_CTRL_NEED_TMP_RSA 1 +#define SSL_CTRL_SET_TMP_RSA 2 +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_SET_TMP_RSA_CB 4 +#define SSL_CTRL_SET_TMP_DH_CB 5 + +#define SSL_CTX_need_tmp_RSA(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL) +#define SSL_CTX_set_tmp_rsa(ctx,rsa) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +#define SSL_CTX_set_tmp_dh(ctx,dh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh) + +/* For the next 2, the callbacks are + * RSA *tmp_rsa_cb(int export) + * DH *tmp_dh_cb(int export) + */ +#define SSL_CTX_set_tmp_rsa_callback(ctx,cb) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb) +#define SSL_CTX_set_tmp_dh_callback(ctx,dh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)cb) + +#ifndef NOPROTO + +#ifdef HEADER_BIO_H +BIO_METHOD *BIO_f_ssl(void); +BIO *BIO_new_ssl(SSL_CTX *ctx,int client); +int BIO_ssl_copy_session_id(BIO *to,BIO *from); +void BIO_ssl_shutdown(BIO *ssl_bio); + +#endif + +int SSL_CTX_set_cipher_list(SSL_CTX *,char *str); +SSL_CTX *SSL_CTX_new(SSL_METHOD *meth); +void SSL_CTX_free(SSL_CTX *); +void SSL_clear(SSL *s); +void SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm); + +SSL_CIPHER *SSL_get_current_cipher(SSL *s); +int SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits); +char * SSL_CIPHER_get_version(SSL_CIPHER *c); +char * SSL_CIPHER_get_name(SSL_CIPHER *c); + +int SSL_get_fd(SSL *s); +char * SSL_get_cipher_list(SSL *s,int n); +char * SSL_get_shared_ciphers(SSL *s, char *buf, int len); +int SSL_get_read_ahead(SSL * s); +int SSL_pending(SSL *s); +#ifndef NO_SOCK +int SSL_set_fd(SSL *s, int fd); +int SSL_set_rfd(SSL *s, int fd); +int SSL_set_wfd(SSL *s, int fd); +#endif +#ifdef HEADER_BIO_H +void SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio); +BIO * SSL_get_rbio(SSL *s); +BIO * SSL_get_wbio(SSL *s); +#endif +int SSL_set_cipher_list(SSL *s, char *str); +void SSL_set_read_ahead(SSL *s, int yes); +int SSL_get_verify_mode(SSL *s); +int (*SSL_get_verify_callback(SSL *s))(); +void SSL_set_verify(SSL *s, int mode, int (*callback) ()); +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); +int SSL_use_RSAPrivateKey_file(SSL *ssl, char *file, int type); +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, unsigned char *d, long len); +int SSL_use_PrivateKey_file(SSL *ssl, char *file, int type); +int SSL_use_certificate(SSL *ssl, X509 *x); +int SSL_use_certificate_ASN1(SSL *ssl, int len, unsigned char *d); +int SSL_use_certificate_file(SSL *ssl, char *file, int type); +void ERR_load_SSL_strings(void ); +void SSL_load_error_strings(void ); +char * SSL_state_string(SSL *s); +char * SSL_rstate_string(SSL *s); +char * SSL_state_string_long(SSL *s); +char * SSL_rstate_string_long(SSL *s); +long SSL_get_time(SSL_SESSION *s); +long SSL_set_time(SSL_SESSION *s, long t); +long SSL_get_timeout(SSL_SESSION *s); +long SSL_set_timeout(SSL_SESSION *s, long t); +void SSL_copy_session_id(SSL *to,SSL *from); + +SSL_SESSION *SSL_SESSION_new(void); +#ifndef WIN16 +int SSL_SESSION_print_fp(FILE *fp,SSL_SESSION *ses); +#endif +#ifdef HEADER_BIO_H +int SSL_SESSION_print(BIO *fp,SSL_SESSION *ses); +#endif +void SSL_SESSION_free(SSL_SESSION *ses); +int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp); +int SSL_set_session(SSL *to, SSL_SESSION *session); +int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c); +int SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,unsigned char **pp,long length); + +#ifdef HEADER_X509_H +X509 * SSL_get_peer_certificate(SSL *s); +#endif + +STACK * SSL_get_peer_cert_chain(SSL *s); + +int SSL_CTX_get_verify_mode(SSL_CTX *ctx); +int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))(); +void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*callback)()); +void SSL_CTX_set_cert_verify_cb(SSL_CTX *ctx, int (*cb)(),char *arg); +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type); +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx, + unsigned char *d, long len); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type); +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,int (*cb)()); + +int SSL_CTX_check_private_key(SSL_CTX *ctx); +int SSL_check_private_key(SSL *ctx); + +SSL * SSL_new(SSL_CTX *ctx); +void SSL_clear(SSL *s); +void SSL_free(SSL *ssl); +int SSL_accept(SSL *ssl); +int SSL_connect(SSL *ssl); +int SSL_read(SSL *ssl,char *buf,int num); +int SSL_peek(SSL *ssl,char *buf,int num); +int SSL_write(SSL *ssl,char *buf,int num); +long SSL_ctrl(SSL *ssl,int cmd, long larg, char *parg); +long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, char *parg); + +int SSL_get_error(SSL *s,int ret_code); +char * SSL_get_version(SSL *s); + +/* This sets the 'default' SSL version that SSL_new() will create */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth); + +SSL_METHOD *SSLv2_method(void); /* sslv2 */ +SSL_METHOD *SSLv2_server_method(void); /* sslv2 */ +SSL_METHOD *SSLv2_client_method(void); /* sslv2 */ + +SSL_METHOD *SSLv3_method(void); /* sslv3 */ +SSL_METHOD *SSLv3_server_method(void); /* sslv3 */ +SSL_METHOD *SSLv3_client_method(void); /* sslv3 */ + +SSL_METHOD *SSLv23_method(void); /* sslv3 but can rollback to v2 */ +SSL_METHOD *SSLv23_server_method(void); /* sslv3 but can rollback to v2 */ +SSL_METHOD *SSLv23_client_method(void); /* sslv3 but can rollback to v2 */ + +STACK *SSL_get_ciphers(SSL *s); + +int SSL_do_handshake(SSL *s); +int SSL_renegotiate(SSL *s); +int SSL_shutdown(SSL *s); + +SSL_METHOD *SSL_get_ssl_method(SSL *s); +int SSL_set_ssl_method(SSL *s,SSL_METHOD *method); +char *SSL_alert_type_string_long(int value); +char *SSL_alert_type_string(int value); +char *SSL_alert_desc_string_long(int value); +char *SSL_alert_desc_string(int value); + +STACK *SSL_load_client_CA_file(char *file); +void SSL_set_client_CA_list(SSL *s, STACK *list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK *list); +STACK *SSL_get_client_CA_list(SSL *s); +STACK *SSL_CTX_get_client_CA_list(SSL_CTX *s); +int SSL_add_client_CA(SSL *ssl,X509 *x); +int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x); + +void SSL_set_connect_state(SSL *s); +void SSL_set_accept_state(SSL *s); + +long SSL_get_default_timeout(SSL *s); + +void SSLeay_add_ssl_algorithms(void ); + +char *SSL_CIPHER_description(SSL_CIPHER *,char *buf,int size); +STACK *SSL_dup_CA_list(STACK *sk); + +SSL *SSL_dup(SSL *ssl); + +X509 *SSL_get_certificate(SSL *ssl); +/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl); + +#else + +BIO_METHOD *BIO_f_ssl(); +BIO *BIO_new_ssl(); +int BIO_ssl_copy_session_id(); +void BIO_ssl_shutdown(); + +int SSL_CTX_set_cipher_list(); +SSL_CTX *SSL_CTX_new(); +void SSL_CTX_free(); +void SSL_clear(); +void SSL_CTX_flush_sessions(); + +SSL_CIPHER *SSL_get_current_cipher(); +int SSL_CIPHER_get_bits(); +char * SSL_CIPHER_get_version(); +char * SSL_CIPHER_get_name(); + +int SSL_get_fd(); +char * SSL_get_cipher_list(); +char * SSL_get_shared_ciphers(); +int SSL_get_read_ahead(); +int SSL_pending(); +#ifndef NO_SOCK +int SSL_set_fd(); +int SSL_set_rfd(); +int SSL_set_wfd(); +#endif +#ifdef HEADER_BIO_H +void SSL_set_bio(); +BIO * SSL_get_rbio(); +BIO * SSL_get_wbio(); +#endif +int SSL_set_cipher_list(); +void SSL_set_read_ahead(); +int SSL_get_verify_mode(); + +void SSL_set_verify(); +int SSL_use_RSAPrivateKey(); +int SSL_use_RSAPrivateKey_ASN1(); +int SSL_use_RSAPrivateKey_file(); +int SSL_use_PrivateKey(); +int SSL_use_PrivateKey_ASN1(); +int SSL_use_PrivateKey_file(); +int SSL_use_certificate(); +int SSL_use_certificate_ASN1(); +int SSL_use_certificate_file(); +void ERR_load_SSL_strings(); +void SSL_load_error_strings(); +char * SSL_state_string(); +char * SSL_rstate_string(); +char * SSL_state_string_long(); +char * SSL_rstate_string_long(); +long SSL_get_time(); +long SSL_set_time(); +long SSL_get_timeout(); +long SSL_set_timeout(); +void SSL_copy_session_id(); + +SSL_SESSION *SSL_SESSION_new(); +#ifndef WIN16 +int SSL_SESSION_print_fp(); +#endif +#ifdef HEADER_BIO_H +int SSL_SESSION_print(); +#endif +void SSL_SESSION_free(); +int i2d_SSL_SESSION(); +int SSL_set_session(); +int SSL_CTX_add_session(); +int SSL_CTX_remove_session(); +SSL_SESSION *d2i_SSL_SESSION(); + +#ifdef HEADER_X509_H +X509 * SSL_get_peer_certificate(); +#endif + +STACK * SSL_get_peer_cert_chain(); + +int SSL_CTX_get_verify_mode(); +int (*SSL_CTX_get_verify_callback())(); +void SSL_CTX_set_verify(); +void SSL_CTX_set_cert_verify_cb(); +int SSL_CTX_use_RSAPrivateKey(); +int SSL_CTX_use_RSAPrivateKey_ASN1(); +int SSL_CTX_use_RSAPrivateKey_file(); +int SSL_CTX_use_PrivateKey(); +int SSL_CTX_use_PrivateKey_ASN1(); +int SSL_CTX_use_PrivateKey_file(); +int SSL_CTX_use_certificate(); +int SSL_CTX_use_certificate_ASN1(); +int SSL_CTX_use_certificate_file(); + +void SSL_CTX_set_default_passwd_cb(); + +int SSL_CTX_check_private_key(); +int SSL_check_private_key(); + +SSL * SSL_new(); +void SSL_clear(); +void SSL_free(); +int SSL_accept(); +int SSL_connect(); +int SSL_read(); +int SSL_peek(); +int SSL_write(); +long SSL_ctrl(); +long SSL_CTX_ctrl(); + +int SSL_get_error(); +char * SSL_get_version(); + +int SSL_CTX_set_ssl_version(); + +SSL_METHOD *SSLv2_method(); +SSL_METHOD *SSLv2_server_method(); +SSL_METHOD *SSLv2_client_method(); + +SSL_METHOD *SSLv3_method(); +SSL_METHOD *SSLv3_server_method(); +SSL_METHOD *SSLv3_client_method(); + +SSL_METHOD *SSLv23_method(); +SSL_METHOD *SSLv23_server_method(); +SSL_METHOD *SSLv23_client_method(); + +STACK *SSL_get_ciphers(); + +int SSL_do_handshake(); +int SSL_renegotiate(); +int SSL_shutdown(); + +SSL_METHOD *SSL_get_ssl_method(); +int SSL_set_ssl_method(); +char *SSL_alert_type_string_long(); +char *SSL_alert_type_string(); +char *SSL_alert_desc_string_long(); +char *SSL_alert_desc_string(); + +STACK *SSL_load_client_CA_file(); +void SSL_set_client_CA_list(); +void SSL_CTX_set_client_CA_list(); +STACK *SSL_get_client_CA_list(); +STACK *SSL_CTX_get_client_CA_list(); +int SSL_add_client_CA(); +int SSL_CTX_add_client_CA(); + +void SSL_set_connect_state(); +void SSL_set_accept_state(); + +long SSL_get_default_timeout(); + +void SSLeay_add_ssl_algorithms(); + +char *SSL_CIPHER_description(); +STACK *SSL_dup_CA_list(); + +SSL *SSL_dup(); + +X509 *SSL_get_certificate(); +/* EVP * */ struct evp_pkey_st *SSL_get_privatekey(); + +#ifdef this_is_for_mk1mf_pl +EVP *SSL_get_privatekey(); +#endif + +#endif + +/* BEGIN ERROR CODES */ +/* Error codes for the SSL functions. */ + +/* Function codes. */ +#define SSL_F_CLIENT_CERTIFICATE 100 +#define SSL_F_CLIENT_HELLO 101 +#define SSL_F_CLIENT_MASTER_KEY 102 +#define SSL_F_D2I_SSL_SESSION 103 +#define SSL_F_DO_SSL3_WRITE 104 +#define SSL_F_GET_CLIENT_FINISHED 105 +#define SSL_F_GET_CLIENT_HELLO 106 +#define SSL_F_GET_CLIENT_MASTER_KEY 107 +#define SSL_F_GET_SERVER_FINISHED 108 +#define SSL_F_GET_SERVER_HELLO 109 +#define SSL_F_GET_SERVER_VERIFY 110 +#define SSL_F_I2D_SSL_SESSION 111 +#define SSL_F_READ_N 112 +#define SSL_F_REQUEST_CERTIFICATE 113 +#define SSL_F_SERVER_HELLO 114 +#define SSL_F_SSL23_ACCEPT 115 +#define SSL_F_SSL23_CLIENT_HELLO 116 +#define SSL_F_SSL23_CONNECT 117 +#define SSL_F_SSL23_GET_CLIENT_HELLO 118 +#define SSL_F_SSL23_GET_SERVER_HELLO 119 +#define SSL_F_SSL23_READ 120 +#define SSL_F_SSL23_WRITE 121 +#define SSL_F_SSL2_ACCEPT 122 +#define SSL_F_SSL2_CONNECT 123 +#define SSL_F_SSL2_ENC_INIT 124 +#define SSL_F_SSL2_READ 125 +#define SSL_F_SSL2_SET_CERTIFICATE 126 +#define SSL_F_SSL2_WRITE 127 +#define SSL_F_SSL3_ACCEPT 128 +#define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 +#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +#define SSL_F_SSL3_CLIENT_HELLO 131 +#define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTX_CTRL 133 +#define SSL_F_SSL3_ENC 134 +#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 +#define SSL_F_SSL3_GET_CERT_VERIFY 136 +#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137 +#define SSL_F_SSL3_GET_CLIENT_HELLO 138 +#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE 139 +#define SSL_F_SSL3_GET_FINISHED 140 +#define SSL_F_SSL3_GET_KEY_EXCHANGE 141 +#define SSL_F_SSL3_GET_MESSAGE 142 +#define SSL_F_SSL3_GET_RECORD 143 +#define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144 +#define SSL_F_SSL3_GET_SERVER_DONE 145 +#define SSL_F_SSL3_GET_SERVER_HELLO 146 +#define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +#define SSL_F_SSL3_READ_BYTES 148 +#define SSL_F_SSL3_READ_N 149 +#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150 +#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE 151 +#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152 +#define SSL_F_SSL3_SEND_CLIENT_VERIFY 153 +#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154 +#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155 +#define SSL_F_SSL3_SETUP_BUFFERS 156 +#define SSL_F_SSL3_SETUP_KEY_BLOCK 157 +#define SSL_F_SSL3_WRITE_BYTES 158 +#define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_BAD_METHOD 160 +#define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_NEW 162 +#define SSL_F_SSL_CHECK_PRIVATE_KEY 163 +#define SSL_F_SSL_CREATE_CIPHER_LIST 164 +#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 165 +#define SSL_F_SSL_CTX_NEW 166 +#define SSL_F_SSL_CTX_SET_SSL_VERSION 167 +#define SSL_F_SSL_CTX_USE_CERTIFICATE 168 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 169 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 170 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY 171 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 172 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 173 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 174 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 175 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 176 +#define SSL_F_SSL_DO_HANDSHAKE 177 +#define SSL_F_SSL_GET_NEW_SESSION 178 +#define SSL_F_SSL_GET_SERVER_SEND_CERT 179 +#define SSL_F_SSL_GET_SIGN_PKEY 180 +#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 181 +#define SSL_F_SSL_NEW 182 +#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 183 +#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 184 +#define SSL_F_SSL_SESSION_NEW 185 +#define SSL_F_SSL_SESSION_PRINT_FP 186 +#define SSL_F_SSL_SET_FD 187 +#define SSL_F_SSL_SET_PKEY 188 +#define SSL_F_SSL_SET_RFD 189 +#define SSL_F_SSL_SET_SESSION 190 +#define SSL_F_SSL_SET_WFD 191 +#define SSL_F_SSL_UNDEFINED_FUNCTION 192 +#define SSL_F_SSL_USE_CERTIFICATE 193 +#define SSL_F_SSL_USE_CERTIFICATE_ASN1 194 +#define SSL_F_SSL_USE_CERTIFICATE_FILE 195 +#define SSL_F_SSL_USE_PRIVATEKEY 196 +#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 197 +#define SSL_F_SSL_USE_PRIVATEKEY_FILE 198 +#define SSL_F_SSL_USE_RSAPRIVATEKEY 199 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 200 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 201 +#define SSL_F_SSL_WRITE 202 +#define SSL_F_WRITE_PENDING 203 + +/* Reason codes. */ +#define SSL_R_APP_DATA_IN_HANDSHAKE 100 +#define SSL_R_BAD_ALERT_RECORD 101 +#define SSL_R_BAD_AUTHENTICATION_TYPE 102 +#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +#define SSL_R_BAD_CHECKSUM 104 +#define SSL_R_BAD_CLIENT_REQUEST 105 +#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 +#define SSL_R_BAD_DECOMPRESSION 107 +#define SSL_R_BAD_DH_G_LENGTH 108 +#define SSL_R_BAD_DH_PUB_KEY_LENGTH 109 +#define SSL_R_BAD_DH_P_LENGTH 110 +#define SSL_R_BAD_DIGEST_LENGTH 111 +#define SSL_R_BAD_DSA_SIGNATURE 112 +#define SSL_R_BAD_MAC_DECODE 113 +#define SSL_R_BAD_MESSAGE_TYPE 114 +#define SSL_R_BAD_PACKET_LENGTH 115 +#define SSL_R_BAD_RESPONSE_ARGUMENT 116 +#define SSL_R_BAD_RSA_DECRYPT 117 +#define SSL_R_BAD_RSA_ENCRYPT 118 +#define SSL_R_BAD_RSA_E_LENGTH 119 +#define SSL_R_BAD_RSA_MODULUS_LENGTH 120 +#define SSL_R_BAD_RSA_SIGNATURE 121 +#define SSL_R_BAD_SIGNATURE 122 +#define SSL_R_BAD_SSL_FILETYPE 123 +#define SSL_R_BAD_SSL_SESSION_ID_LENGTH 124 +#define SSL_R_BAD_STATE 125 +#define SSL_R_BAD_WRITE_RETRY 126 +#define SSL_R_BIO_NOT_SET 127 +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 128 +#define SSL_R_BN_LIB 129 +#define SSL_R_CA_DN_LENGTH_MISMATCH 130 +#define SSL_R_CA_DN_TOO_LONG 131 +#define SSL_R_CCS_RECEIVED_EARLY 132 +#define SSL_R_CERTIFICATE_VERIFY_FAILED 133 +#define SSL_R_CERT_LENGTH_MISMATCH 134 +#define SSL_R_CHALLENGE_IS_DIFFERENT 135 +#define SSL_R_CIPHER_CODE_WRONG_LENGTH 136 +#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 137 +#define SSL_R_CIPHER_TABLE_SRC_ERROR 138 +#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 139 +#define SSL_R_COMPRESSION_FAILURE 140 +#define SSL_R_CONNECTION_ID_IS_DIFFERENT 141 +#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 142 +#define SSL_R_DATA_LENGTH_TOO_LONG 143 +#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 144 +#define SSL_R_DIGEST_CHECK_FAILED 145 +#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 146 +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 147 +#define SSL_R_EXCESSIVE_MESSAGE_SIZE 148 +#define SSL_R_EXTRA_DATA_IN_MESSAGE 149 +#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 150 +#define SSL_R_INTERNAL_ERROR 151 +#define SSL_R_INVALID_CHALLENGE_LENGTH 152 +#define SSL_R_LENGTH_MISMATCH 153 +#define SSL_R_LENGTH_TOO_SHORT 154 +#define SSL_R_LIBRARY_HAS_NO_CIPHERS 155 +#define SSL_R_MISSING_DH_DSA_CERT 156 +#define SSL_R_MISSING_DH_KEY 157 +#define SSL_R_MISSING_DH_RSA_CERT 158 +#define SSL_R_MISSING_DSA_SIGNING_CERT 159 +#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 160 +#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 161 +#define SSL_R_MISSING_RSA_CERTIFICATE 162 +#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 163 +#define SSL_R_MISSING_RSA_SIGNING_CERT 164 +#define SSL_R_MISSING_TMP_DH_KEY 165 +#define SSL_R_MISSING_TMP_RSA_KEY 166 +#define SSL_R_MISSING_TMP_RSA_PKEY 167 +#define SSL_R_MISSING_VERIFY_MESSAGE 168 +#define SSL_R_NON_SSLV2_INITIAL_PACKET 169 +#define SSL_R_NO_CERTIFICATES_PASSED 170 +#define SSL_R_NO_CERTIFICATE_ASSIGNED 171 +#define SSL_R_NO_CERTIFICATE_RETURNED 172 +#define SSL_R_NO_CERTIFICATE_SET 173 +#define SSL_R_NO_CERTIFICATE_SPECIFIED 174 +#define SSL_R_NO_CIPHERS_AVAILABLE 175 +#define SSL_R_NO_CIPHERS_PASSED 176 +#define SSL_R_NO_CIPHERS_SPECIFIED 177 +#define SSL_R_NO_CIPHER_LIST 178 +#define SSL_R_NO_CIPHER_MATCH 179 +#define SSL_R_NO_CLIENT_CERT_RECEIVED 180 +#define SSL_R_NO_COMPRESSION_SPECIFIED 181 +#define SSL_R_NO_PRIVATEKEY 182 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 183 +#define SSL_R_NO_PUBLICKEY 184 +#define SSL_R_NO_SHARED_CIPHER 185 +#define SSL_R_NULL_SSL_CTX 186 +#define SSL_R_NULL_SSL_METHOD_PASSED 187 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 188 +#define SSL_R_PACKET_LENGTH_TOO_LONG 189 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 190 +#define SSL_R_PEER_ERROR 191 +#define SSL_R_PEER_ERROR_CERTIFICATE 192 +#define SSL_R_PEER_ERROR_NO_CERTIFICATE 193 +#define SSL_R_PEER_ERROR_NO_CIPHER 194 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 195 +#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 196 +#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 197 +#define SSL_R_PROTOCOL_IS_SHUTDOWN 198 +#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 199 +#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 200 +#define SSL_R_PUBLIC_KEY_NOT_RSA 201 +#define SSL_R_READ_BIO_NOT_SET 202 +#define SSL_R_READ_WRONG_PACKET_TYPE 203 +#define SSL_R_RECORD_LENGTH_MISMATCH 204 +#define SSL_R_RECORD_TOO_LARGE 205 +#define SSL_R_REQUIRED_CIPHER_MISSING 206 +#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 207 +#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 208 +#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 209 +#define SSL_R_SHORT_READ 210 +#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 211 +#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 212 +#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE 213 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE 214 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER 215 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 216 +#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE 217 +#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 218 +#define SSL_R_SSL_HANDSHAKE_FAILURE 219 +#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 220 +#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 221 +#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 222 +#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 223 +#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 224 +#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 225 +#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 226 +#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 227 +#define SSL_R_UNEXPECTED_MESSAGE 228 +#define SSL_R_UNEXPECTED_RECORD 229 +#define SSL_R_UNKNOWN_ALERT_TYPE 230 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 231 +#define SSL_R_UNKNOWN_CIPHER_RETURNED 232 +#define SSL_R_UNKNOWN_CIPHER_TYPE 233 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 234 +#define SSL_R_UNKNOWN_PKEY_TYPE 235 +#define SSL_R_UNKNOWN_PROTOCOL 236 +#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 237 +#define SSL_R_UNKNOWN_SSL_VERSION 238 +#define SSL_R_UNKNOWN_STATE 239 +#define SSL_R_UNSUPPORTED_CIPHER 240 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 241 +#define SSL_R_UNSUPPORTED_SSL_VERSION 242 +#define SSL_R_WRITE_BIO_NOT_SET 243 +#define SSL_R_WRONG_CIPHER_RETURNED 244 +#define SSL_R_WRONG_MESSAGE_TYPE 245 +#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 246 +#define SSL_R_WRONG_SIGNATURE_LENGTH 247 +#define SSL_R_WRONG_SIGNATURE_SIZE 248 +#define SSL_R_WRONG_SSL_VERSION 249 +#define SSL_R_WRONG_VERSION_NUMBER 250 +#define SSL_R_X509_LIB 251 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssl/ssl2.h b/ssl/ssl2.h new file mode 100644 index 0000000000..db353f5841 --- /dev/null +++ b/ssl/ssl2.h @@ -0,0 +1,263 @@ +/* ssl/ssl2.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL2_H +#define HEADER_SSL2_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Protocol Version Codes */ +#define SSL2_CLIENT_VERSION 0x0002 +#define SSL2_SERVER_VERSION 0x0002 + +/* Protocol Message Codes */ +#define SSL2_MT_ERROR 0 +#define SSL2_MT_CLIENT_HELLO 1 +#define SSL2_MT_CLIENT_MASTER_KEY 2 +#define SSL2_MT_CLIENT_FINISHED 3 +#define SSL2_MT_SERVER_HELLO 4 +#define SSL2_MT_SERVER_VERIFY 5 +#define SSL2_MT_SERVER_FINISHED 6 +#define SSL2_MT_REQUEST_CERTIFICATE 7 +#define SSL2_MT_CLIENT_CERTIFICATE 8 + +/* Error Message Codes */ +#define SSL2_PE_UNDEFINED_ERROR 0x0000 +#define SSL2_PE_NO_CIPHER 0x0001 +#define SSL2_PE_NO_CERTIFICATE 0x0002 +#define SSL2_PE_BAD_CERTIFICATE 0x0004 +#define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006 + +/* Cipher Kind Values */ +#define SSL2_CK_NULL_WITH_MD5 0x02000000 /* v3 */ +#define SSL2_CK_RC4_128_WITH_MD5 0x02010080 +#define SSL2_CK_RC4_128_EXPORT40_WITH_MD5 0x02020080 +#define SSL2_CK_RC2_128_CBC_WITH_MD5 0x02030080 +#define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x02040080 +#define SSL2_CK_IDEA_128_CBC_WITH_MD5 0x02050080 +#define SSL2_CK_DES_64_CBC_WITH_MD5 0x02060040 +#define SSL2_CK_DES_64_CBC_WITH_SHA 0x02060140 /* v3 */ +#define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 0x020700c0 +#define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA 0x020701c0 /* v3 */ +#define SSL2_CK_RC4_64_WITH_MD5 0x02080080 /* MS hack */ + +#define SSL2_CK_DES_64_CFB64_WITH_MD5_1 0x02ff0800 /* SSLeay */ +#define SSL2_CK_NULL 0x02ff0810 /* SSLeay */ + +#define SSL2_TXT_DES_64_CFB64_WITH_MD5_1 "DES-CFB-M1" +#define SSL2_TXT_NULL_WITH_MD5 "NULL-MD5" +#define SSL2_TXT_RC4_128_WITH_MD5 "RC4-MD5" +#define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 "EXP-RC4-MD5" +#define SSL2_TXT_RC2_128_CBC_WITH_MD5 "RC2-CBC-MD5" +#define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 "EXP-RC2-CBC-MD5" +#define SSL2_TXT_IDEA_128_CBC_WITH_MD5 "IDEA-CBC-MD5" +#define SSL2_TXT_DES_64_CBC_WITH_MD5 "DES-CBC-MD5" +#define SSL2_TXT_DES_64_CBC_WITH_SHA "DES-CBC-SHA" +#define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 "DES-CBC3-MD5" +#define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA "DES-CBC3-SHA" +#define SSL2_TXT_RC4_64_WITH_MD5 "RC4-64-MD5" + +#define SSL2_TXT_NULL "NULL" + +/* Flags for the SSL_CIPHER.algorithm2 field */ +#define SSL2_CF_5_BYTE_ENC 0x01 +#define SSL2_CF_8_BYTE_ENC 0x02 + +/* Certificate Type Codes */ +#define SSL2_CT_X509_CERTIFICATE 0x01 + +/* Authentication Type Code */ +#define SSL2_AT_MD5_WITH_RSA_ENCRYPTION 0x01 + +#define SSL2_MAX_SSL_SESSION_ID_LENGTH 32 + +/* Upper/Lower Bounds */ +#define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS 256 +#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER (unsigned int)32767 +#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383 /**/ + +#define SSL2_CHALLENGE_LENGTH 16 +/*#define SSL2_CHALLENGE_LENGTH 32 */ +#define SSL2_MIN_CHALLENGE_LENGTH 16 +#define SSL2_MAX_CHALLENGE_LENGTH 32 +#define SSL2_CONNECTION_ID_LENGTH 16 +#define SSL2_MAX_CONNECTION_ID_LENGTH 16 +#define SSL2_SSL_SESSION_ID_LENGTH 16 +#define SSL2_MAX_CERT_CHALLENGE_LENGTH 32 +#define SSL2_MIN_CERT_CHALLENGE_LENGTH 16 +#define SSL2_MAX_KEY_MATERIAL_LENGTH 24 + +#ifndef HEADER_SSL_LOCL_H +#define CERT char +#endif + +typedef struct ssl2_ctx_st + { + int first_packet; /* enable first packet checking in server */ + int three_byte_header; + int clear_text; /* clear text */ + int escape; /* not used in SSLv2 */ + int ssl2_rollback; /* used if SSLv23 rolled back to SSLv2 */ + + /* non-blocking io info, used to make sure the same + * args were passwd */ + unsigned int wnum; /* number of bytes sent so far */ + int wpend_tot; + char *wpend_buf; + + int wpend_off; /* offset to data to write */ + int wpend_len; /* number of bytes passwd to write */ + int wpend_ret; /* number of bytes to return to caller */ + + /* buffer raw data */ + int rbuf_left; + int rbuf_offs; + unsigned char *rbuf; + unsigned char *wbuf; + + unsigned char *write_ptr;/* used to point to the start due to + * 2/3 byte header. */ + + unsigned int padding; + unsigned int rlength; /* passed to ssl2_enc */ + int ract_data_length; /* Set when things are encrypted. */ + unsigned int wlength; /* passed to ssl2_enc */ + int wact_data_length; /* Set when things are decrypted. */ + unsigned char *ract_data; + unsigned char *wact_data; + unsigned char *mac_data; + unsigned char *pad_data; + + unsigned char *read_key; + unsigned char *write_key; + + /* Stuff specifically to do with this SSL session */ + unsigned int challenge_length; + unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH]; + unsigned int conn_id_length; + unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH]; + unsigned int key_material_length; + unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH*2]; + + unsigned long read_sequence; + unsigned long write_sequence; + + struct { + unsigned int conn_id_length; + unsigned int cert_type; + unsigned int cert_length; + int csl; + int clear; + unsigned int enc; + unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH]; + int cipher_spec_length; + unsigned int session_id_length; + unsigned int clen; + unsigned int rlen; + } tmp; + } SSL2_CTX; + +/* SSLv2 */ +/* client */ +#define SSL2_ST_SEND_CLIENT_HELLO_A (0x10|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_HELLO_B (0x11|SSL_ST_CONNECT) +#define SSL2_ST_GET_SERVER_HELLO_A (0x20|SSL_ST_CONNECT) +#define SSL2_ST_GET_SERVER_HELLO_B (0x21|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_MASTER_KEY_A (0x30|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_MASTER_KEY_B (0x31|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_FINISHED_A (0x40|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_FINISHED_B (0x41|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_CERTIFICATE_A (0x50|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_CERTIFICATE_B (0x51|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_CERTIFICATE_C (0x52|SSL_ST_CONNECT) +#define SSL2_ST_SEND_CLIENT_CERTIFICATE_D (0x53|SSL_ST_CONNECT) +#define SSL2_ST_GET_SERVER_VERIFY_A (0x60|SSL_ST_CONNECT) +#define SSL2_ST_GET_SERVER_VERIFY_B (0x61|SSL_ST_CONNECT) +#define SSL2_ST_GET_SERVER_FINISHED_A (0x70|SSL_ST_CONNECT) +#define SSL2_ST_GET_SERVER_FINISHED_B (0x71|SSL_ST_CONNECT) +#define SSL2_ST_CLIENT_START_ENCRYPTION (0x80|SSL_ST_CONNECT) +#define SSL2_ST_X509_GET_CLIENT_CERTIFICATE (0x90|SSL_ST_CONNECT) +/* server */ +#define SSL2_ST_GET_CLIENT_HELLO_A (0x10|SSL_ST_ACCEPT) +#define SSL2_ST_GET_CLIENT_HELLO_B (0x11|SSL_ST_ACCEPT) +#define SSL2_ST_GET_CLIENT_HELLO_C (0x12|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_HELLO_A (0x20|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_HELLO_B (0x21|SSL_ST_ACCEPT) +#define SSL2_ST_GET_CLIENT_MASTER_KEY_A (0x30|SSL_ST_ACCEPT) +#define SSL2_ST_GET_CLIENT_MASTER_KEY_B (0x31|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_VERIFY_A (0x40|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_VERIFY_B (0x41|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_VERIFY_C (0x42|SSL_ST_ACCEPT) +#define SSL2_ST_GET_CLIENT_FINISHED_A (0x50|SSL_ST_ACCEPT) +#define SSL2_ST_GET_CLIENT_FINISHED_B (0x51|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_FINISHED_A (0x60|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_SERVER_FINISHED_B (0x61|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_REQUEST_CERTIFICATE_A (0x70|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_REQUEST_CERTIFICATE_B (0x71|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_REQUEST_CERTIFICATE_C (0x72|SSL_ST_ACCEPT) +#define SSL2_ST_SEND_REQUEST_CERTIFICATE_D (0x73|SSL_ST_ACCEPT) +#define SSL2_ST_SERVER_START_ENCRYPTION (0x80|SSL_ST_ACCEPT) +#define SSL2_ST_X509_GET_SERVER_CERTIFICATE (0x90|SSL_ST_ACCEPT) + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssl/ssl23.h b/ssl/ssl23.h new file mode 100644 index 0000000000..6e6f26bbb3 --- /dev/null +++ b/ssl/ssl23.h @@ -0,0 +1,83 @@ +/* ssl/ssl23.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL23_H +#define HEADER_SSL23_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*client */ +/* write to server */ +#define SSL23_ST_CW_CLNT_HELLO_A (0x210|SSL_ST_CONNECT) +#define SSL23_ST_CW_CLNT_HELLO_B (0x211|SSL_ST_CONNECT) +/* read from server */ +#define SSL23_ST_CR_SRVR_HELLO_A (0x220|SSL_ST_CONNECT) +#define SSL23_ST_CR_SRVR_HELLO_B (0x221|SSL_ST_CONNECT) + +/* server */ +/* read from client */ +#define SSL23_ST_SR_CLNT_HELLO_A (0x210|SSL_ST_ACCEPT) +#define SSL23_ST_SR_CLNT_HELLO_B (0x211|SSL_ST_ACCEPT) + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssl/ssl3.h b/ssl/ssl3.h new file mode 100644 index 0000000000..9675ec2d7d --- /dev/null +++ b/ssl/ssl3.h @@ -0,0 +1,417 @@ +/* ssl/ssl3.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL3_H +#define HEADER_SSL3_H + +#include "buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SSL3_CK_RSA_NULL_MD5 0x03000001 +#define SSL3_CK_RSA_NULL_SHA 0x03000002 +#define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +#define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +#define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +#define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +#define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +#define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +#define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +#define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +#define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +#define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +#define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +#define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011 +#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012 +#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013 +#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014 +#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015 +#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016 + +#define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +#define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +#define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +#define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +#define SSL3_CK_ADH_DES_196_CBC_SHA 0x0300001B + +#define SSL3_CK_FZA_DMS_NULL_SHA 0x0300001C +#define SSL3_CK_FZA_DMS_FZA_SHA 0x0300001D +#define SSL3_CK_FZA_DMS_RC4_SHA 0x0300001E + +#define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +#define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +#define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +#define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +#define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-MD5" +#define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC" +#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +#define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +#define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_196_CBC_SHA "ADH-DES-CBC3-SHA" + +#define SSL3_TXT_FZA_DMS_NULL_SHA "FZA-NULL-SHA" +#define SSL3_TXT_FZA_DMS_FZA_SHA "FZA-FZA-CBC-SHA" +#define SSL3_TXT_FZA_DMS_RC4_SHA "FZA-RC4-SHA" + +#define SSL3_SSL_SESSION_ID_LENGTH 32 +#define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +#define SSL3_MASTER_SECRET_SIZE 48 +#define SSL3_RANDOM_SIZE 32 +#define SSL3_SESSION_ID_SIZE 32 +#define SSL3_RT_HEADER_LENGTH 5 + +/* Due to MS stuffing up, this can change.... */ +#if defined(WIN16) || (defined(MSDOS) && !defined(WIN32)) +#define SSL3_RT_MAX_EXTRA (14000) +#else +#define SSL3_RT_MAX_EXTRA (16384) +#endif + +#define SSL3_RT_MAX_PLAIN_LENGTH 16384 +#define SSL3_RT_MAX_COMPRESSED_LENGTH (1024+SSL3_RT_MAX_PLAIN_LENGTH) +#define SSL3_RT_MAX_ENCRYPTED_LENGTH (1024+SSL3_RT_MAX_COMPRESSED_LENGTH) +#define SSL3_RT_MAX_PACKET_SIZE (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) +#define SSL3_RT_MAX_DATA_SIZE (1024*1024) + +/* the states that a SSL3_RECORD can be in + * For SSL_read it goes + * rbuf->ENCODED -> read + * ENCODED -> we need to decode everything - call decode_record + */ + +#define SSL3_RS_BLANK 1 +#define SSL3_RS_DATA + +#define SSL3_RS_ENCODED 2 +#define SSL3_RS_READ_MORE 3 +#define SSL3_RS_WRITE_MORE +#define SSL3_RS_PLAIN 3 +#define SSL3_RS_PART_READ 4 +#define SSL3_RS_PART_WRITE 5 + +#define SSL3_MD_CLIENT_FINISHED_CONST 0x43,0x4C,0x4E,0x54 +#define SSL3_MD_SERVER_FINISHED_CONST 0x53,0x52,0x56,0x52 + +#define SSL3_VERSION 0x0300 +#define SSL3_VERSION_MAJOR 0x03 +#define SSL3_VERSION_MINOR 0x00 + +#define SSL3_RT_CHANGE_CIPHER_SPEC 20 +#define SSL3_RT_ALERT 21 +#define SSL3_RT_HANDSHAKE 22 +#define SSL3_RT_APPLICATION_DATA 23 + +#define SSL3_AL_WARNING 1 +#define SSL3_AL_FATAL 2 + +#define SSL3_AD_CLOSE_NOTIFY 0 +#define SSL3_AD_UNEXPECTED_MESSAGE 10 /* fatal */ +#define SSL3_AD_BAD_RECORD_MAC 20 /* fatal */ +#define SSL3_AD_DECOMPRESSION_FAILURE 30 /* fatal */ +#define SSL3_AD_HANDSHAKE_FAILURE 40 /* fatal */ +#define SSL3_AD_NO_CERTIFICATE 41 +#define SSL3_AD_BAD_CERTIFICATE 42 +#define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +#define SSL3_AD_CERTIFICATE_REVOKED 44 +#define SSL3_AD_CERTIFICATE_EXPIRED 45 +#define SSL3_AD_CERTIFICATE_UNKNOWN 46 +#define SSL3_AD_ILLEGAL_PARAMETER 47 /* fatal */ + +typedef struct ssl3_record_st + { +/*r */ int type; /* type of record */ +/* */ /*int state;*/ /* any data in it? */ +/*rw*/ unsigned int length; /* How many bytes available */ +/*r */ unsigned int off; /* read/write offset into 'buf' */ +/*rw*/ unsigned char *data; /* pointer to the record data */ +/*rw*/ unsigned char *input; /* where the decode bytes are */ +/*rw*/ unsigned char *comp; /* only used with decompression */ + } SSL3_RECORD; + +typedef struct ssl3_buffer_st + { +/*r */ int total; /* used in non-blocking writes */ +/*r */ int wanted; /* how many more bytes we need */ +/*rw*/ int left; /* how many bytes left */ +/*rw*/ int offset; /* where to 'copy from' */ +/*rw*/ unsigned char *buf; /* SSL3_RT_MAX_PACKET_SIZE bytes */ + } SSL3_BUFFER; + +typedef struct ssl3_compression_st { + int nothing; + } SSL3_COMPRESSION; + +#define SSL3_CT_RSA_SIGN 1 +#define SSL3_CT_DSS_SIGN 2 +#define SSL3_CT_RSA_FIXED_DH 3 +#define SSL3_CT_DSS_FIXED_DH 4 +#define SSL3_CT_RSA_EPHEMERAL_DH 5 +#define SSL3_CT_DSS_EPHEMERAL_DH 6 +#define SSL3_CT_FORTEZZA_DMS 20 +#define SSL3_CT_NUMBER 7 + +#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 +#define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002 +#define SSL3_FLAGS_POP_BUFFER 0x0004 + +typedef struct ssl3_ctx_st + { + long flags; + int delay_buf_pop_ret; + + unsigned char read_sequence[8]; + unsigned char read_mac_secret[EVP_MAX_MD_SIZE]; + unsigned char write_sequence[8]; + unsigned char write_mac_secret[EVP_MAX_MD_SIZE]; + + unsigned char server_random[SSL3_RANDOM_SIZE]; + unsigned char client_random[SSL3_RANDOM_SIZE]; + + SSL3_BUFFER rbuf; /* read IO goes into here */ + SSL3_BUFFER wbuf; /* write IO goes into here */ + SSL3_RECORD rrec; /* each decoded record goes in here */ + SSL3_RECORD wrec; /* goes out from here */ + /* Used by ssl3_read_n to point + * to input data packet */ + + /* partial write - check the numbers match */ + unsigned int wnum; /* number of bytes sent so far */ + int wpend_tot; /* number bytes written */ + int wpend_type; + int wpend_ret; /* number of bytes submitted */ + char *wpend_buf; + + /* used during startup, digest all incoming/outgoing packets */ + EVP_MD_CTX finish_dgst1; + EVP_MD_CTX finish_dgst2; + + /* this is set whenerver we see a change_cipher_spec message + * come in when we are not looking for one */ + int change_cipher_spec; + + int warn_alert; + int fatal_alert; + /* we alow one fatal and one warning alert to be outstanding, + * send close alert via the warning alert */ + int alert_dispatch; + char send_alert[2]; + + struct { + unsigned char finish_md1[EVP_MAX_MD_SIZE]; + unsigned char finish_md2[EVP_MAX_MD_SIZE]; + + unsigned long message_size; + int message_type; + + /* used to hold the new cipher we are going to use */ + SSL_CIPHER *new_cipher; + DH *dh; + + /* used when SSL_ST_FLUSH_DATA is entered */ + int next_state; + + int reuse_message; + + /* used for certificate requests */ + int cert_req; + int ctype_num; + char ctype[SSL3_CT_NUMBER]; + STACK *ca_names; + + int use_rsa_tmp; + + int key_block_length; + unsigned char *key_block; + + EVP_CIPHER *new_sym_enc; + EVP_MD *new_hash; + SSL_COMPRESSION *new_compression; + } tmp; + } SSL3_CTX; + +/* SSLv3 */ +/*client */ +/* extra state */ +#define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT) +/* write to server */ +#define SSL3_ST_CW_CLNT_HELLO_A (0x110|SSL_ST_CONNECT) +#define SSL3_ST_CW_CLNT_HELLO_B (0x111|SSL_ST_CONNECT) +/* read from server */ +#define SSL3_ST_CR_SRVR_HELLO_A (0x120|SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_HELLO_B (0x121|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_A (0x130|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_B (0x131|SSL_ST_CONNECT) +#define SSL3_ST_CR_KEY_EXCH_A (0x140|SSL_ST_CONNECT) +#define SSL3_ST_CR_KEY_EXCH_B (0x141|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_REQ_A (0x150|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_REQ_B (0x151|SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_DONE_A (0x160|SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_DONE_B (0x161|SSL_ST_CONNECT) +/* write to server */ +#define SSL3_ST_CW_CERT_A (0x170|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_B (0x171|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_C (0x172|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_D (0x173|SSL_ST_CONNECT) +#define SSL3_ST_CW_KEY_EXCH_A (0x180|SSL_ST_CONNECT) +#define SSL3_ST_CW_KEY_EXCH_B (0x181|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_A (0x190|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT) +#define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT) +#define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT) +/* read from server */ +#define SSL3_ST_CR_CHANGE_A (0x1C0|SSL_ST_CONNECT) +#define SSL3_ST_CR_CHANGE_B (0x1C1|SSL_ST_CONNECT) +#define SSL3_ST_CR_FINISHED_A (0x1D0|SSL_ST_CONNECT) +#define SSL3_ST_CR_FINISHED_B (0x1D1|SSL_ST_CONNECT) + +/* server */ +/* extra state */ +#define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT) +/* read from client */ +#define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT) +/* write to client */ +#define SSL3_ST_SW_HELLO_REQ_A (0x120|SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_B (0x121|SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_C (0x122|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_HELLO_A (0x130|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_HELLO_B (0x131|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_A (0x140|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_B (0x141|SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_A (0x150|SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_B (0x151|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_REQ_A (0x160|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_REQ_B (0x161|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_DONE_A (0x170|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_DONE_B (0x171|SSL_ST_ACCEPT) +/* read from client */ +#define SSL3_ST_SR_CERT_A (0x180|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_B (0x181|SSL_ST_ACCEPT) +#define SSL3_ST_SR_KEY_EXCH_A (0x190|SSL_ST_ACCEPT) +#define SSL3_ST_SR_KEY_EXCH_B (0x191|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_VRFY_A (0x1A0|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT) +#define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT) +#define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT) +/* write to client */ +#define SSL3_ST_SW_CHANGE_A (0x1D0|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CHANGE_B (0x1D1|SSL_ST_ACCEPT) +#define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT) +#define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT) + +#define SSL3_MT_CLIENT_REQUEST 0 +#define SSL3_MT_CLIENT_HELLO 1 +#define SSL3_MT_SERVER_HELLO 2 +#define SSL3_MT_CERTIFICATE 11 +#define SSL3_MT_SERVER_KEY_EXCHANGE 12 +#define SSL3_MT_CERTIFICATE_REQUEST 13 +#define SSL3_MT_SERVER_DONE 14 +#define SSL3_MT_CERTIFICATE_VERIFY 15 +#define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +#define SSL3_MT_FINISHED 20 + +#define SSL3_MT_CCS 1 + +/* These are used when changing over to a new cipher */ +#define SSL3_CC_READ 0x01 +#define SSL3_CC_WRITE 0x02 +#define SSL3_CC_CLIENT 0x10 +#define SSL3_CC_SERVER 0x20 +#define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE) +#define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ) +#define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ) +#define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE) + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c new file mode 100644 index 0000000000..36b03335bb --- /dev/null +++ b/ssl/ssl_algs.c @@ -0,0 +1,99 @@ +/* ssl/ssl_algs.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "lhash.h" +#include "ssl_locl.h" + +void SSLeay_add_ssl_algorithms() + { +#ifndef NO_DES + EVP_add_cipher(EVP_des_cbc()); + EVP_add_cipher(EVP_des_ede3_cbc()); +#endif +#ifndef NO_IDEA + EVP_add_cipher(EVP_idea_cbc()); +#endif +#ifndef NO_RC4 + EVP_add_cipher(EVP_rc4()); +#endif +#ifndef NO_RC2 + EVP_add_cipher(EVP_rc2_cbc()); +#endif + +#ifndef NO_MD2 + EVP_add_digest(EVP_md2()); +#endif +#ifndef NO_MD5 + EVP_add_digest(EVP_md5()); +#endif +#ifndef NO_SHA1 + EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ +#endif +#if !defined(NO_SHA1) && !defined(NO_DSA) + EVP_add_digest(EVP_dss1()); /* DSA with sha1 */ +#endif + + /* If you want support for phased out ciphers, add the following */ +#if 0 + EVP_add_digest(EVP_sha()); + EVP_add_digest(EVP_dss()); +#endif + } + diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c new file mode 100644 index 0000000000..873497a877 --- /dev/null +++ b/ssl/ssl_asn1.c @@ -0,0 +1,313 @@ +/* ssl/ssl_asn1.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <stdlib.h> +#include "asn1_mac.h" +#include "objects.h" +#include "ssl_locl.h" + +typedef struct ssl_session_asn1_st + { + ASN1_INTEGER version; + ASN1_INTEGER ssl_version; + ASN1_OCTET_STRING cipher; + ASN1_OCTET_STRING master_key; + ASN1_OCTET_STRING session_id; + ASN1_OCTET_STRING key_arg; + ASN1_INTEGER time; + ASN1_INTEGER timeout; + } SSL_SESSION_ASN1; + +/* + * SSLerr(SSL_F_I2D_SSL_SESSION,SSL_R_CIPHER_CODE_WRONG_LENGTH); + * SSLerr(SSL_F_D2I_SSL_SESSION,SSL_R_UNSUPPORTED_CIPHER); + */ + +int i2d_SSL_SESSION(in,pp) +SSL_SESSION *in; +unsigned char **pp; + { +#define LSIZE2 (sizeof(long)*2) + int v1=0,v2=0,v3=0; + unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2]; + unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2]; + long l; + SSL_SESSION_ASN1 a; + M_ASN1_I2D_vars(in); + + if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0))) + return(0); + + /* Note that I cheat in the following 2 assignments. I know + * that if the ASN1_INTERGER passed to ASN1_INTEGER_set + * is > sizeof(long)+1, the buffer will not be re-Malloc()ed. + * This is a bit evil but makes things simple, no dynamic allocation + * to clean up :-) */ + a.version.length=LSIZE2; + a.version.type=V_ASN1_INTEGER; + a.version.data=ibuf1; + ASN1_INTEGER_set(&(a.version),SSL_SESSION_ASN1_VERSION); + + a.ssl_version.length=LSIZE2; + a.ssl_version.type=V_ASN1_INTEGER; + a.ssl_version.data=ibuf2; + ASN1_INTEGER_set(&(a.ssl_version),in->ssl_version); + + a.cipher.type=V_ASN1_OCTET_STRING; + a.cipher.data=buf; + + if (in->cipher == NULL) + l=in->cipher_id; + else + l=in->cipher->id; + if (in->ssl_version == 2) + { + a.cipher.length=3; + buf[0]=((unsigned char)(l>>16L))&0xff; + buf[1]=((unsigned char)(l>> 8L))&0xff; + buf[2]=((unsigned char)(l ))&0xff; + } + else + { + a.cipher.length=2; + buf[0]=((unsigned char)(l>>8L))&0xff; + buf[1]=((unsigned char)(l ))&0xff; + } + + a.master_key.length=in->master_key_length; + a.master_key.type=V_ASN1_OCTET_STRING; + a.master_key.data=in->master_key; + + a.session_id.length=in->session_id_length; + a.session_id.type=V_ASN1_OCTET_STRING; + a.session_id.data=in->session_id; + + a.key_arg.length=in->key_arg_length; + a.key_arg.type=V_ASN1_OCTET_STRING; + a.key_arg.data=in->key_arg; + + if (in->time != 0L) + { + a.time.length=LSIZE2; + a.time.type=V_ASN1_INTEGER; + a.time.data=ibuf3; + ASN1_INTEGER_set(&(a.time),in->time); + } + + if (in->timeout != 0L) + { + a.timeout.length=LSIZE2; + a.timeout.type=V_ASN1_INTEGER; + a.timeout.data=ibuf4; + ASN1_INTEGER_set(&(a.timeout),in->timeout); + } + + M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER); + M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER); + M_ASN1_I2D_len(&(a.cipher), i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_len(&(a.session_id), i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_len(&(a.master_key), i2d_ASN1_OCTET_STRING); + if (in->key_arg_length > 0) + M_ASN1_I2D_len_IMP_opt(&(a.key_arg),i2d_ASN1_OCTET_STRING); + if (in->time != 0L) + M_ASN1_I2D_len_EXP_opt(&(a.time),i2d_ASN1_INTEGER,1,v1); + if (in->timeout != 0L) + M_ASN1_I2D_len_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2); + if (in->peer != NULL) + M_ASN1_I2D_len_EXP_opt(in->peer,i2d_X509,3,v3); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put(&(a.version), i2d_ASN1_INTEGER); + M_ASN1_I2D_put(&(a.ssl_version), i2d_ASN1_INTEGER); + M_ASN1_I2D_put(&(a.cipher), i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_put(&(a.session_id), i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_put(&(a.master_key), i2d_ASN1_OCTET_STRING); + if (in->key_arg_length > 0) + M_ASN1_I2D_put_IMP_opt(&(a.key_arg),i2d_ASN1_OCTET_STRING,0); + if (in->time != 0L) + M_ASN1_I2D_put_EXP_opt(&(a.time),i2d_ASN1_INTEGER,1,v1); + if (in->timeout != 0L) + M_ASN1_I2D_put_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2); + if (in->peer != NULL) + M_ASN1_I2D_put_EXP_opt(in->peer,i2d_X509,3,v3); + + M_ASN1_I2D_finish(); + } + +SSL_SESSION *d2i_SSL_SESSION(a,pp,length) +SSL_SESSION **a; +unsigned char **pp; +long length; + { + int version,ssl_version=0,i; + long id; + ASN1_INTEGER ai,*aip; + ASN1_OCTET_STRING os,*osp; + M_ASN1_D2I_vars(a,SSL_SESSION *,SSL_SESSION_new); + + aip= &ai; + osp= &os; + + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + + ai.data=NULL; ai.length=0; + M_ASN1_D2I_get(aip,d2i_ASN1_INTEGER); + version=(int)ASN1_INTEGER_get(aip); + if (ai.data != NULL) { Free(ai.data); ai.data=NULL; ai.length=0; } + + /* we don't care about the version right now :-) */ + M_ASN1_D2I_get(aip,d2i_ASN1_INTEGER); + ssl_version=(int)ASN1_INTEGER_get(aip); + ret->ssl_version=ssl_version; + if (ai.data != NULL) { Free(ai.data); ai.data=NULL; ai.length=0; } + + os.data=NULL; os.length=0; + M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING); + if (ssl_version == 2) + { + if (os.length != 3) + { + c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH; + goto err; + } + id=0x02000000L| + ((unsigned long)os.data[0]<<16L)| + ((unsigned long)os.data[1]<< 8L)| + (unsigned long)os.data[2]; + } + else if (ssl_version == 3) + { + if (os.length != 2) + { + c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH; + goto err; + } + id=0x03000000L| + ((unsigned long)os.data[0]<<8L)| + (unsigned long)os.data[1]; + } + else + { + SSLerr(SSL_F_D2I_SSL_SESSION,SSL_R_UNKNOWN_SSL_VERSION); + return(NULL); + } + + ret->cipher=NULL; + ret->cipher_id=id; + + M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING); + if (ssl_version == 3) + i=SSL3_MAX_SSL_SESSION_ID_LENGTH; + else /* if (ssl_version == 2) */ + i=SSL2_MAX_SSL_SESSION_ID_LENGTH; + + if (os.length > i) + os.length=i; + + ret->session_id_length=os.length; + memcpy(ret->session_id,os.data,os.length); + + M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING); + if (ret->master_key_length > SSL_MAX_MASTER_KEY_LENGTH) + ret->master_key_length=SSL_MAX_MASTER_KEY_LENGTH; + else + ret->master_key_length=os.length; + memcpy(ret->master_key,os.data,ret->master_key_length); + + os.length=0; + M_ASN1_D2I_get_IMP_opt(osp,d2i_ASN1_OCTET_STRING,0,V_ASN1_OCTET_STRING); + if (os.length > SSL_MAX_KEY_ARG_LENGTH) + ret->key_arg_length=SSL_MAX_KEY_ARG_LENGTH; + else + ret->key_arg_length=os.length; + memcpy(ret->key_arg,os.data,ret->key_arg_length); + if (os.data != NULL) Free(os.data); + + ai.length=0; + M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,1); + if (ai.data != NULL) + { + ret->time=ASN1_INTEGER_get(aip); + Free(ai.data); ai.data=NULL; ai.length=0; + } + else + ret->time=time(NULL); + + ai.length=0; + M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,2); + if (ai.data != NULL) + { + ret->timeout=ASN1_INTEGER_get(aip); + Free(ai.data); ai.data=NULL; ai.length=0; + } + else + ret->timeout=3; + + if (ret->peer != NULL) + { + X509_free(ret->peer); + ret->peer=NULL; + } + M_ASN1_D2I_get_EXP_opt(ret->peer,d2i_X509,3); + + M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION); + } + diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c new file mode 100644 index 0000000000..0c040d9cf3 --- /dev/null +++ b/ssl/ssl_cert.c @@ -0,0 +1,326 @@ +/* ssl/ssl_cert.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "bio.h" +#include "pem.h" +#include "ssl_locl.h" + +CERT *ssl_cert_new() + { + CERT *ret; + + ret=(CERT *)Malloc(sizeof(CERT)); + if (ret == NULL) + { + SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + memset(ret,0,sizeof(CERT)); +/* + ret->valid=0; + ret->mask=0; + ret->export_mask=0; + ret->cert_type=0; + ret->key->x509=NULL; + ret->key->publickey=NULL; + ret->key->privatekey=NULL; */ + + ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]); + ret->references=1; + + return(ret); + } + +void ssl_cert_free(c) +CERT *c; + { + int i; + + i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT); + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"ssl_cert_free, bad reference count\n"); + abort(); /* ok */ + } +#endif + +#ifndef NO_RSA + if (c->rsa_tmp) RSA_free(c->rsa_tmp); +#endif +#ifndef NO_DH + if (c->dh_tmp) DH_free(c->dh_tmp); +#endif + + for (i=0; i<SSL_PKEY_NUM; i++) + { + if (c->pkeys[i].x509 != NULL) + X509_free(c->pkeys[i].x509); + if (c->pkeys[i].privatekey != NULL) + EVP_PKEY_free(c->pkeys[i].privatekey); +#if 0 + if (c->pkeys[i].publickey != NULL) + EVP_PKEY_free(c->pkeys[i].publickey); +#endif + } + if (c->cert_chain != NULL) + sk_pop_free(c->cert_chain,X509_free); + Free(c); + } + +int ssl_set_cert_type(c, type) +CERT *c; +int type; + { + c->cert_type=type; + return(1); + } + +int ssl_verify_cert_chain(s,sk) +SSL *s; +STACK *sk; + { + X509 *x; + int i; + X509_STORE_CTX ctx; + + if ((sk == NULL) || (sk_num(sk) == 0)) + return(0); + + x=(X509 *)sk_value(sk,0); + X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk); + X509_STORE_CTX_set_app_data(&ctx,(char *)s); + + if (s->ctx->app_verify_callback != NULL) + i=s->ctx->app_verify_callback(&ctx); + else + i=X509_verify_cert(&ctx); + + X509_STORE_CTX_cleanup(&ctx); + s->verify_result=ctx.error; + + return(i); + } + +static void set_client_CA_list(ca_list,list) +STACK **ca_list; +STACK *list; + { + if (*ca_list != NULL) + sk_pop_free(*ca_list,X509_NAME_free); + + *ca_list=list; + } + +STACK *SSL_dup_CA_list(sk) +STACK *sk; + { + int i; + STACK *ret; + X509_NAME *name; + + ret=sk_new_null(); + for (i=0; i<sk_num(sk); i++) + { + name=X509_NAME_dup((X509_NAME *)sk_value(sk,i)); + if ((name == NULL) || !sk_push(ret,(char *)name)) + { + sk_pop_free(ret,X509_NAME_free); + return(NULL); + } + } + return(ret); + } + +void SSL_set_client_CA_list(s,list) +SSL *s; +STACK *list; + { + set_client_CA_list(&(s->client_CA),list); + } + +void SSL_CTX_set_client_CA_list(ctx,list) +SSL_CTX *ctx; +STACK *list; + { + set_client_CA_list(&(ctx->client_CA),list); + } + +STACK *SSL_CTX_get_client_CA_list(ctx) +SSL_CTX *ctx; + { + return(ctx->client_CA); + } + +STACK *SSL_get_client_CA_list(s) +SSL *s; + { + if (s->type == SSL_ST_CONNECT) + { /* we are in the client */ + if ((s->version == 3) && (s->s3 != NULL)) + return(s->s3->tmp.ca_names); + else + return(NULL); + } + else + { + if (s->client_CA != NULL) + return(s->client_CA); + else + return(s->ctx->client_CA); + } + } + +static int add_client_CA(sk,x) +STACK **sk; +X509 *x; + { + X509_NAME *name; + + if (x == NULL) return(0); + if ((*sk == NULL) && ((*sk=sk_new_null()) == NULL)) + return(0); + + if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL) + return(0); + + if (!sk_push(*sk,(char *)name)) + { + X509_NAME_free(name); + return(0); + } + return(1); + } + +int SSL_add_client_CA(ssl,x) +SSL *ssl; +X509 *x; + { + return(add_client_CA(&(ssl->client_CA),x)); + } + +int SSL_CTX_add_client_CA(ctx,x) +SSL_CTX *ctx; +X509 *x; + { + return(add_client_CA(&(ctx->client_CA),x)); + } + +static int name_cmp(a,b) +X509_NAME **a,**b; + { + return(X509_NAME_cmp(*a,*b)); + } + +STACK *SSL_load_client_CA_file(file) +char *file; + { + BIO *in; + X509 *x=NULL; + X509_NAME *xn=NULL; + STACK *ret,*sk; + + ret=sk_new(NULL); + sk=sk_new(name_cmp); +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if ((ret == NULL) || (sk == NULL) || (in == NULL)) + { + SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in,file)) + goto err; + + for (;;) + { + if (PEM_read_bio_X509(in,&x,NULL) == NULL) + break; + if ((xn=X509_get_subject_name(x)) == NULL) goto err; + /* check for duplicates */ + xn=X509_NAME_dup(xn); + if (xn == NULL) goto err; + if (sk_find(sk,(char *)xn) >= 0) + X509_NAME_free(xn); + else + { + sk_push(sk,(char *)xn); + sk_push(ret,(char *)xn); + } + } + + if (0) + { +err: + if (ret != NULL) sk_pop_free(ret,X509_NAME_free); + ret=NULL; + } + if (sk != NULL) sk_free(sk); + if (in != NULL) BIO_free(in); + if (x != NULL) X509_free(x); + return(ret); + } + + diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c new file mode 100644 index 0000000000..9fed3ad59a --- /dev/null +++ b/ssl/ssl_ciph.c @@ -0,0 +1,721 @@ +/* ssl/ssl_ciph.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "ssl_locl.h" + +#define SSL_ENC_DES_IDX 0 +#define SSL_ENC_3DES_IDX 1 +#define SSL_ENC_RC4_IDX 2 +#define SSL_ENC_RC2_IDX 3 +#define SSL_ENC_IDEA_IDX 4 +#define SSL_ENC_eFZA_IDX 5 +#define SSL_ENC_NULL_IDX 6 +#define SSL_ENC_NUM_IDX 7 + +static EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={ + NULL,NULL,NULL,NULL,NULL,NULL, + }; + +#define SSL_MD_MD5_IDX 0 +#define SSL_MD_SHA0_IDX 1 +#define SSL_MD_SHA1_IDX 2 +#define SSL_MD_NUM_IDX 3 +static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={ + NULL,NULL,NULL, + }; + +typedef struct cipher_sort_st + { + SSL_CIPHER *cipher; + int pref; + } CIPHER_SORT; + +#define CIPHER_ADD 1 +#define CIPHER_KILL 2 +#define CIPHER_DEL 3 +#define CIPHER_ORDER 4 + +typedef struct cipher_choice_st + { + int type; + unsigned long algorithms; + unsigned long mask; + STACK *order; + } CIPHER_CHOICE; + +static SSL_CIPHER cipher_aliases[]={ + {0,SSL_TXT_ALL, 0,SSL_ALL, 0,SSL_ALL}, /* must be first */ + {0,SSL_TXT_kRSA,0,SSL_kRSA, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_kDHr,0,SSL_kDHr, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_kDHd,0,SSL_kDHd, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_kEDH,0,SSL_kEDH, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_kFZA,0,SSL_kFZA, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_DH, 0,SSL_DH, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_EDH, 0,SSL_EDH, 0,SSL_MKEY_MASK|SSL_AUTH_MASK}, + + {0,SSL_TXT_aRSA,0,SSL_aRSA, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_aDSS,0,SSL_aDSS, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_aFZA,0,SSL_aFZA, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_aNULL,0,SSL_aNULL,0,SSL_AUTH_MASK}, + {0,SSL_TXT_aDH, 0,SSL_aDH, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_DSS, 0,SSL_DSS, 0,SSL_AUTH_MASK}, + + {0,SSL_TXT_DES, 0,SSL_DES, 0,SSL_ENC_MASK}, + {0,SSL_TXT_3DES,0,SSL_3DES, 0,SSL_ENC_MASK}, + {0,SSL_TXT_RC4, 0,SSL_RC4, 0,SSL_ENC_MASK}, + {0,SSL_TXT_RC2, 0,SSL_RC2, 0,SSL_ENC_MASK}, + {0,SSL_TXT_IDEA,0,SSL_IDEA, 0,SSL_ENC_MASK}, + {0,SSL_TXT_eNULL,0,SSL_eNULL,0,SSL_ENC_MASK}, + {0,SSL_TXT_eFZA,0,SSL_eFZA, 0,SSL_ENC_MASK}, + + {0,SSL_TXT_MD5, 0,SSL_MD5, 0,SSL_MAC_MASK}, + {0,SSL_TXT_SHA0,0,SSL_SHA0, 0,SSL_MAC_MASK}, + {0,SSL_TXT_SHA1,0,SSL_SHA1, 0,SSL_MAC_MASK}, + {0,SSL_TXT_SHA, 0,SSL_SHA, 0,SSL_MAC_MASK}, + + {0,SSL_TXT_NULL,0,SSL_NULL, 0,SSL_ENC_MASK}, + {0,SSL_TXT_RSA, 0,SSL_RSA, 0,SSL_AUTH_MASK|SSL_MKEY_MASK}, + {0,SSL_TXT_ADH, 0,SSL_ADH, 0,SSL_AUTH_MASK|SSL_MKEY_MASK}, + {0,SSL_TXT_FZA, 0,SSL_FZA, 0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK}, + + {0,SSL_TXT_EXP, 0,SSL_EXP, 0,SSL_EXP_MASK}, + {0,SSL_TXT_EXPORT,0,SSL_EXPORT,0,SSL_EXP_MASK}, + {0,SSL_TXT_SSLV2,0,SSL_SSLV2,0,SSL_SSL_MASK}, + {0,SSL_TXT_SSLV3,0,SSL_SSLV3,0,SSL_SSL_MASK}, + {0,SSL_TXT_LOW, 0,SSL_LOW,0,SSL_STRONG_MASK}, + {0,SSL_TXT_MEDIUM,0,SSL_MEDIUM,0,SSL_STRONG_MASK}, + {0,SSL_TXT_HIGH, 0,SSL_HIGH,0,SSL_STRONG_MASK}, + }; + +static int init_ciphers=1; +static void load_ciphers(); + +static int cmp_by_name(a,b) +SSL_CIPHER **a,**b; + { + return(strcmp((*a)->name,(*b)->name)); + } + +static void load_ciphers() + { + init_ciphers=0; + ssl_cipher_methods[SSL_ENC_DES_IDX]= + EVP_get_cipherbyname(SN_des_cbc); + ssl_cipher_methods[SSL_ENC_3DES_IDX]= + EVP_get_cipherbyname(SN_des_ede3_cbc); + ssl_cipher_methods[SSL_ENC_RC4_IDX]= + EVP_get_cipherbyname(SN_rc4); + ssl_cipher_methods[SSL_ENC_RC2_IDX]= + EVP_get_cipherbyname(SN_rc2_cbc); + ssl_cipher_methods[SSL_ENC_IDEA_IDX]= + EVP_get_cipherbyname(SN_idea_cbc); + + ssl_digest_methods[SSL_MD_MD5_IDX]= + EVP_get_digestbyname(SN_md5); + ssl_digest_methods[SSL_MD_SHA0_IDX]= + EVP_get_digestbyname(SN_sha); + ssl_digest_methods[SSL_MD_SHA1_IDX]= + EVP_get_digestbyname(SN_sha1); + } + +int ssl_cipher_get_evp(c,enc,md) +SSL_CIPHER *c; +EVP_CIPHER **enc; +EVP_MD **md; + { + int i; + + if (c == NULL) return(0); + + switch (c->algorithms & SSL_ENC_MASK) + { + case SSL_DES: + i=SSL_ENC_DES_IDX; + break; + case SSL_3DES: + i=SSL_ENC_3DES_IDX; + break; + case SSL_RC4: + i=SSL_ENC_RC4_IDX; + break; + case SSL_RC2: + i=SSL_ENC_RC2_IDX; + break; + case SSL_IDEA: + i=SSL_ENC_IDEA_IDX; + break; + case SSL_eNULL: + i=SSL_ENC_NULL_IDX; + break; + break; + default: + i= -1; + break; + } + + if ((i < 0) || (i > SSL_ENC_NUM_IDX)) + *enc=NULL; + else + { + if (i == SSL_ENC_NULL_IDX) + *enc=EVP_enc_null(); + else + *enc=ssl_cipher_methods[i]; + } + + switch (c->algorithms & SSL_MAC_MASK) + { + case SSL_MD5: + i=SSL_MD_MD5_IDX; + break; + case SSL_SHA0: + i=SSL_MD_SHA0_IDX; + break; + case SSL_SHA1: + i=SSL_MD_SHA1_IDX; + break; + default: + i= -1; + break; + } + if ((i < 0) || (i > SSL_MD_NUM_IDX)) + *md=NULL; + else + *md=ssl_digest_methods[i]; + + if ((*enc != NULL) && (*md != NULL)) + return(1); + else + return(0); + } + +STACK *ssl_create_cipher_list(ssl_method,cipher_list,cipher_list_by_id,str) +SSL_METHOD *ssl_method; +STACK **cipher_list,**cipher_list_by_id; +char *str; + { + SSL_CIPHER *c; + char *l; + STACK *ret=NULL,*ok=NULL; +#define CL_BUF 40 + char buf[CL_BUF]; + char *tmp_str=NULL; + unsigned long mask,algorithms,ma; + char *start; + int i,j,k,num=0,ch,multi; + unsigned long al; + STACK *ca_list=NULL; + STACK *c_list=NULL; + int old_x,old_y,current_x,num_x; + CIPHER_CHOICE *ops=NULL; + SSL_CIPHER c_tmp,*cp; + + if (str == NULL) return(NULL); + + if (strncmp(str,"DEFAULT",7) == 0) + { + i=strlen(str)+2+strlen(SSL_DEFAULT_CIPHER_LIST); + if ((tmp_str=Malloc(i)) == NULL) + { + SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); + goto err; + } + strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST); + strcat(tmp_str,&(str[7])); + str=tmp_str; + } + if (init_ciphers) load_ciphers(); + + num=ssl_method->num_ciphers(); + + if ((ret=(STACK *)sk_new(NULL)) == NULL) goto err; + if ((c_list=(STACK *)sk_new(NULL)) == NULL) goto err; + if ((ca_list=(STACK *)sk_new(cmp_by_name)) == NULL) goto err; + + mask =SSL_kFZA; +#ifdef NO_RSA + mask|=SSL_aRSA|SSL_kRSA; +#endif +#ifdef NO_DSA + mask|=SSL_aDSS; +#endif +#ifdef NO_DH + mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH; +#endif + +#ifndef SSL_ALLOW_ENULL + mask|=SSL_eNULL; +#endif + + mask|=(ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL)?SSL_DES :0; + mask|=(ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL)?SSL_3DES:0; + mask|=(ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL)?SSL_RC4 :0; + mask|=(ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL)?SSL_RC2 :0; + mask|=(ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL)?SSL_IDEA:0; + mask|=(ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL)?SSL_eFZA:0; + + mask|=(ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL)?SSL_MD5 :0; + mask|=(ssl_digest_methods[SSL_MD_SHA0_IDX] == NULL)?SSL_SHA0:0; + mask|=(ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL)?SSL_SHA1:0; + + /* Get the initial list of ciphers */ + for (i=0; i<num; i++) + { + c=ssl_method->get_cipher((unsigned int)i); + /* drop those that use any of that is not available */ + if ((c != NULL) && c->valid && !(c->algorithms & mask)) + { + if (!sk_push(c_list,(char *)c)) goto err; + if (!sk_push(ca_list,(char *)c)) goto err; + } + } + + /* special case */ + cipher_aliases[0].algorithms= ~mask; + + /* get the aliases */ + k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER); + for (j=0; j<k; j++) + { + al=cipher_aliases[j].algorithms; + /* Drop those that are not relevent */ + if ((al & mask) == al) continue; + if (!sk_push(ca_list,(char *)&(cipher_aliases[j]))) goto err; + } + + /* ca_list now holds a 'stack' of SSL_CIPHERS, some real, some + * 'aliases' */ + + /* how many parameters are there? */ + num=1; + for (l=str; *l; l++) + if (*l == ':') num++; + ops=(CIPHER_CHOICE *)Malloc(sizeof(CIPHER_CHOICE)*num); + if (ops == NULL) goto err; + memset(ops,0,sizeof(CIPHER_CHOICE)*num); + for (i=0; i<num; i++) + if ((ops[i].order=sk_new_null()) == NULL) goto err; + + /* we now parse the input string and create our operations */ + l=str; + i=0; + current_x=0; + + for (;;) + { + ch= *l; + if (ch == '-') + { j=CIPHER_DEL; l++; } + else if (ch == '+') + { j=CIPHER_ORDER; l++; } + else if (ch == '!') + { j=CIPHER_KILL; l++; } + else + { j=CIPHER_ADD; } + + if (*l == ':') + { + l++; + continue; + } + ops[current_x].type=j; + ops[current_x].algorithms=0; + ops[current_x].mask=0; + + start=l; + for (;;) + { + ch= *l; + i=0; + while ( ((ch >= 'A') && (ch <= 'Z')) || + ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || + (ch == '-')) + { + buf[i]=ch; + ch= *(++l); + i++; + if (i >= (CL_BUF-2)) break; + } + buf[i]='\0'; + if (ch != '\0') l++; + + /* check for multi-part specification */ + multi=(ch == '+')?1:0; + + c_tmp.name=buf; + j=sk_find(ca_list,(char *)&c_tmp); + if (j < 0) + { + if (ch == '\0') + break; + else + continue; + } + + cp=(SSL_CIPHER *)sk_value(ca_list,j); + ops[current_x].algorithms|=cp->algorithms; + /* We add the SSL_SSL_MASK so we can match the + * SSLv2 and SSLv3 versions of RC4-MD5 */ + ops[current_x].mask|=cp->mask; + if (!multi) break; + } + current_x++; + if (ch == '\0') break; + } + + num_x=current_x; + current_x=0; + +#ifdef CIPHER_DEBUG + printf("<--->\n"); +#endif + + for (i=0; i<sk_num(c_list); i++) + { + old_x= -1; + old_y= -1; + cp=(SSL_CIPHER *)sk_value(c_list,i); +#ifdef CIPHER_DEBUG + printf("[%s]\n",cp->name); +#endif + for (j=0; j<num_x; j++) + { + algorithms=ops[j].algorithms; + ma=ops[j].mask & cp->algorithms; +#ifdef CIPHER_DEBUG + printf(" %s %08lX&%08lX==0 || %08lX != %08lX \n", + cp->name,ops[j].mask,cp->algorithms,ma,algorithms); +#endif + if ((ma == 0) || ((ma & algorithms) != ma)) + { + continue; + } + k=ops[j].type; +#ifdef CIPHER_DEBUG + printf(">>%s\n",cp->name); +#endif + + /* add the cipher if it has not been added yet. */ + if (k == CIPHER_ADD) + { + if (old_x < 0) + { + old_x=j; + old_y=sk_num(ops[j].order); + sk_push(ops[j].order,(char *)cp); + } + } + /* Move the added cipher to this location */ + else if (k == CIPHER_ORDER) + { + if (old_x >= 0) + { + sk_value(ops[old_x].order,old_y)=NULL; + old_y=sk_num(ops[j].order); + sk_push(ops[j].order,(char *)cp); + old_x=j; + } + } + /* Remove added cipher */ + else if ((k == CIPHER_DEL) || (k == CIPHER_KILL)) + { + if (old_x >= 0) + { + sk_value(ops[old_x].order,old_y)=NULL; + old_x= -1; + } + if (k == CIPHER_KILL) + break; + } + } + } + + for (i=0; i<num_x; i++) + { + for (j=0; j<sk_num(ops[i].order); j++) + { + cp=(SSL_CIPHER *)sk_value(ops[i].order,j); + if (cp != NULL) + { + sk_push(ret,(char *)cp); +#ifdef CIPHER_DEBUG + printf("<%s>\n",cp->name); +#endif + } + } + } + + if (cipher_list != NULL) + { + if (*cipher_list != NULL) + sk_free(*cipher_list); + *cipher_list=ret; + } + + if (cipher_list_by_id != NULL) + { + if (*cipher_list_by_id != NULL) + sk_free(*cipher_list_by_id); + *cipher_list_by_id=sk_dup(ret); + } + + if ( (cipher_list_by_id == NULL) || + (*cipher_list_by_id == NULL) || + (cipher_list == NULL) || + (*cipher_list == NULL)) + goto err; + sk_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp); + + ok=ret; + ret=NULL; +err: + if (tmp_str) Free(tmp_str); + if (ops != NULL) + { + for (i=0; i<num; i++) + if (ops[i].order != NULL) + sk_free(ops[i].order); + Free(ops); + } + if (ret != NULL) sk_free(ret); + if (c_list != NULL) sk_free(c_list); + if (ca_list != NULL) sk_free(ca_list); + return(ok); + } + +char *SSL_CIPHER_description(cipher,buf,len) +SSL_CIPHER *cipher; +char *buf; +int len; + { + int export; + char *ver,*exp; + char *kx,*au,*enc,*mac; + unsigned long alg,alg2; + static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n"; + + alg=cipher->algorithms; + alg2=cipher->algorithm2; + + export=(alg&SSL_EXP)?1:0; + exp=(export)?" export":""; + + if (alg & SSL_SSLV2) + ver="SSLv2"; + else if (alg & SSL_SSLV3) + ver="SSLv3"; + else + ver="unknown"; + + switch (alg&SSL_MKEY_MASK) + { + case SSL_kRSA: + kx=(export)?"RSA(512)":"RSA"; + break; + case SSL_kDHr: + kx="DH/RSA"; + break; + case SSL_kDHd: + kx="DH/DSS"; + break; + case SSL_kFZA: + kx="Fortezza"; + break; + case SSL_kEDH: + kx=(export)?"DH(512)":"DH"; + break; + default: + kx="unknown"; + } + + switch (alg&SSL_AUTH_MASK) + { + case SSL_aRSA: + au="RSA"; + break; + case SSL_aDSS: + au="DSS"; + break; + case SSL_aDH: + au="DH"; + break; + case SSL_aFZA: + case SSL_aNULL: + au="None"; + break; + default: + au="unknown"; + break; + } + + switch (alg&SSL_ENC_MASK) + { + case SSL_DES: + enc=export?"DES(40)":"DES(56)"; + break; + case SSL_3DES: + enc="3DES(168)"; + break; + case SSL_RC4: + enc=export?"RC4(40)":((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)"); + break; + case SSL_RC2: + enc=export?"RC2(40)":"RC2(128)"; + break; + case SSL_IDEA: + enc="IDEA(128)"; + break; + case SSL_eFZA: + enc="Fortezza"; + break; + case SSL_eNULL: + enc="None"; + break; + default: + enc="unknown"; + break; + } + + switch (alg&SSL_MAC_MASK) + { + case SSL_MD5: + mac="MD5"; + break; + case SSL_SHA0: + mac="SHA0"; + break; + case SSL_SHA1: + mac="SHA1"; + break; + default: + mac="unknown"; + break; + } + + if (buf == NULL) + { + buf=Malloc(128); + if (buf == NULL) return("Malloc Error"); + } + else if (len < 128) + return("Buffer too small"); + + sprintf(buf,format,cipher->name,ver,kx,au,enc,mac,exp); + return(buf); + } + +char *SSL_CIPHER_get_version(c) +SSL_CIPHER *c; + { + int i; + + i=(int)(c->id>>24L); + if (i == 3) + return("SSLv3"); + else if (i == 2) + return("SSLv2"); + else + return("unknown"); + } + +/* return the actual cipher being used */ +char *SSL_CIPHER_get_name(c) +SSL_CIPHER *c; + { + if (c != NULL) + return(c->name); + return("(NONE)"); + } + +/* number of bits for symetric cipher */ +int SSL_CIPHER_get_bits(c,alg_bits) +SSL_CIPHER *c; +int *alg_bits; + { + int ret=0,a=0; + EVP_CIPHER *enc; + EVP_MD *md; + + if (c != NULL) + { + if (!ssl_cipher_get_evp(c,&enc,&md)) + return(0); + + a=EVP_CIPHER_key_length(enc)*8; + + if (c->algorithms & SSL_EXP) + { + ret=40; + } + else + { + if (c->algorithm2 & SSL2_CF_8_BYTE_ENC) + ret=64; + else + ret=a; + } + } + + if (alg_bits != NULL) *alg_bits=a; + + return(ret); + } + diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c new file mode 100644 index 0000000000..18a1a22a82 --- /dev/null +++ b/ssl/ssl_err.c @@ -0,0 +1,350 @@ +/* lib/ssl/ssl_err.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +#include <stdio.h> +#include "err.h" +#include "ssl.h" + +/* BEGIN ERROR CODES */ +static ERR_STRING_DATA SSL_str_functs[]= + { +{ERR_PACK(0,SSL_F_CLIENT_CERTIFICATE,0), "CLIENT_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_CLIENT_HELLO,0), "CLIENT_HELLO"}, +{ERR_PACK(0,SSL_F_CLIENT_MASTER_KEY,0), "CLIENT_MASTER_KEY"}, +{ERR_PACK(0,SSL_F_D2I_SSL_SESSION,0), "d2i_SSL_SESSION"}, +{ERR_PACK(0,SSL_F_DO_SSL3_WRITE,0), "DO_SSL3_WRITE"}, +{ERR_PACK(0,SSL_F_GET_CLIENT_FINISHED,0), "GET_CLIENT_FINISHED"}, +{ERR_PACK(0,SSL_F_GET_CLIENT_HELLO,0), "GET_CLIENT_HELLO"}, +{ERR_PACK(0,SSL_F_GET_CLIENT_MASTER_KEY,0), "GET_CLIENT_MASTER_KEY"}, +{ERR_PACK(0,SSL_F_GET_SERVER_FINISHED,0), "GET_SERVER_FINISHED"}, +{ERR_PACK(0,SSL_F_GET_SERVER_HELLO,0), "GET_SERVER_HELLO"}, +{ERR_PACK(0,SSL_F_GET_SERVER_VERIFY,0), "GET_SERVER_VERIFY"}, +{ERR_PACK(0,SSL_F_I2D_SSL_SESSION,0), "i2d_SSL_SESSION"}, +{ERR_PACK(0,SSL_F_READ_N,0), "READ_N"}, +{ERR_PACK(0,SSL_F_REQUEST_CERTIFICATE,0), "REQUEST_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SERVER_HELLO,0), "SERVER_HELLO"}, +{ERR_PACK(0,SSL_F_SSL23_ACCEPT,0), "SSL23_ACCEPT"}, +{ERR_PACK(0,SSL_F_SSL23_CLIENT_HELLO,0), "SSL23_CLIENT_HELLO"}, +{ERR_PACK(0,SSL_F_SSL23_CONNECT,0), "SSL23_CONNECT"}, +{ERR_PACK(0,SSL_F_SSL23_GET_CLIENT_HELLO,0), "SSL23_GET_CLIENT_HELLO"}, +{ERR_PACK(0,SSL_F_SSL23_GET_SERVER_HELLO,0), "SSL23_GET_SERVER_HELLO"}, +{ERR_PACK(0,SSL_F_SSL23_READ,0), "SSL23_READ"}, +{ERR_PACK(0,SSL_F_SSL23_WRITE,0), "SSL23_WRITE"}, +{ERR_PACK(0,SSL_F_SSL2_ACCEPT,0), "SSL2_ACCEPT"}, +{ERR_PACK(0,SSL_F_SSL2_CONNECT,0), "SSL2_CONNECT"}, +{ERR_PACK(0,SSL_F_SSL2_ENC_INIT,0), "SSL2_ENC_INIT"}, +{ERR_PACK(0,SSL_F_SSL2_READ,0), "SSL2_READ"}, +{ERR_PACK(0,SSL_F_SSL2_SET_CERTIFICATE,0), "SSL2_SET_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SSL2_WRITE,0), "SSL2_WRITE"}, +{ERR_PACK(0,SSL_F_SSL3_ACCEPT,0), "SSL3_ACCEPT"}, +{ERR_PACK(0,SSL_F_SSL3_CHANGE_CIPHER_STATE,0), "SSL3_CHANGE_CIPHER_STATE"}, +{ERR_PACK(0,SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,0), "SSL3_CHECK_CERT_AND_ALGORITHM"}, +{ERR_PACK(0,SSL_F_SSL3_CLIENT_HELLO,0), "SSL3_CLIENT_HELLO"}, +{ERR_PACK(0,SSL_F_SSL3_CONNECT,0), "SSL3_CONNECT"}, +{ERR_PACK(0,SSL_F_SSL3_CTX_CTRL,0), "SSL3_CTX_CTRL"}, +{ERR_PACK(0,SSL_F_SSL3_ENC,0), "SSL3_ENC"}, +{ERR_PACK(0,SSL_F_SSL3_GET_CERTIFICATE_REQUEST,0), "SSL3_GET_CERTIFICATE_REQUEST"}, +{ERR_PACK(0,SSL_F_SSL3_GET_CERT_VERIFY,0), "SSL3_GET_CERT_VERIFY"}, +{ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_CERTIFICATE,0), "SSL3_GET_CLIENT_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_HELLO,0), "SSL3_GET_CLIENT_HELLO"}, +{ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,0), "SSL3_GET_CLIENT_KEY_EXCHANGE"}, +{ERR_PACK(0,SSL_F_SSL3_GET_FINISHED,0), "SSL3_GET_FINISHED"}, +{ERR_PACK(0,SSL_F_SSL3_GET_KEY_EXCHANGE,0), "SSL3_GET_KEY_EXCHANGE"}, +{ERR_PACK(0,SSL_F_SSL3_GET_MESSAGE,0), "SSL3_GET_MESSAGE"}, +{ERR_PACK(0,SSL_F_SSL3_GET_RECORD,0), "SSL3_GET_RECORD"}, +{ERR_PACK(0,SSL_F_SSL3_GET_SERVER_CERTIFICATE,0), "SSL3_GET_SERVER_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SSL3_GET_SERVER_DONE,0), "SSL3_GET_SERVER_DONE"}, +{ERR_PACK(0,SSL_F_SSL3_GET_SERVER_HELLO,0), "SSL3_GET_SERVER_HELLO"}, +{ERR_PACK(0,SSL_F_SSL3_OUTPUT_CERT_CHAIN,0), "SSL3_OUTPUT_CERT_CHAIN"}, +{ERR_PACK(0,SSL_F_SSL3_READ_BYTES,0), "SSL3_READ_BYTES"}, +{ERR_PACK(0,SSL_F_SSL3_READ_N,0), "SSL3_READ_N"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,0), "SSL3_SEND_CERTIFICATE_REQUEST"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,0), "SSL3_SEND_CLIENT_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,0), "SSL3_SEND_CLIENT_KEY_EXCHANGE"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_VERIFY,0), "SSL3_SEND_CLIENT_VERIFY"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_CERTIFICATE,0), "SSL3_SEND_SERVER_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,0), "SSL3_SEND_SERVER_KEY_EXCHANGE"}, +{ERR_PACK(0,SSL_F_SSL3_SETUP_BUFFERS,0), "SSL3_SETUP_BUFFERS"}, +{ERR_PACK(0,SSL_F_SSL3_SETUP_KEY_BLOCK,0), "SSL3_SETUP_KEY_BLOCK"}, +{ERR_PACK(0,SSL_F_SSL3_WRITE_BYTES,0), "SSL3_WRITE_BYTES"}, +{ERR_PACK(0,SSL_F_SSL3_WRITE_PENDING,0), "SSL3_WRITE_PENDING"}, +{ERR_PACK(0,SSL_F_SSL_BAD_METHOD,0), "SSL_BAD_METHOD"}, +{ERR_PACK(0,SSL_F_SSL_BYTES_TO_CIPHER_LIST,0), "SSL_BYTES_TO_CIPHER_LIST"}, +{ERR_PACK(0,SSL_F_SSL_CERT_NEW,0), "SSL_CERT_NEW"}, +{ERR_PACK(0,SSL_F_SSL_CHECK_PRIVATE_KEY,0), "SSL_check_private_key"}, +{ERR_PACK(0,SSL_F_SSL_CREATE_CIPHER_LIST,0), "SSL_CREATE_CIPHER_LIST"}, +{ERR_PACK(0,SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,0), "SSL_CTX_check_private_key"}, +{ERR_PACK(0,SSL_F_SSL_CTX_NEW,0), "SSL_CTX_new"}, +{ERR_PACK(0,SSL_F_SSL_CTX_SET_SSL_VERSION,0), "SSL_CTX_set_ssl_version"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE,0), "SSL_CTX_use_certificate"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,0), "SSL_CTX_use_certificate_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,0), "SSL_CTX_use_certificate_file"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY,0), "SSL_CTX_use_PrivateKey"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,0), "SSL_CTX_use_PrivateKey_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,0), "SSL_CTX_use_PrivateKey_file"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,0), "SSL_CTX_use_RSAPrivateKey"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1,0), "SSL_CTX_use_RSAPrivateKey_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,0), "SSL_CTX_use_RSAPrivateKey_file"}, +{ERR_PACK(0,SSL_F_SSL_DO_HANDSHAKE,0), "SSL_do_handshake"}, +{ERR_PACK(0,SSL_F_SSL_GET_NEW_SESSION,0), "SSL_GET_NEW_SESSION"}, +{ERR_PACK(0,SSL_F_SSL_GET_SERVER_SEND_CERT,0), "SSL_GET_SERVER_SEND_CERT"}, +{ERR_PACK(0,SSL_F_SSL_GET_SIGN_PKEY,0), "SSL_GET_SIGN_PKEY"}, +{ERR_PACK(0,SSL_F_SSL_LOAD_CLIENT_CA_FILE,0), "SSL_load_client_CA_file"}, +{ERR_PACK(0,SSL_F_SSL_NEW,0), "SSL_new"}, +{ERR_PACK(0,SSL_F_SSL_RSA_PRIVATE_DECRYPT,0), "SSL_RSA_PRIVATE_DECRYPT"}, +{ERR_PACK(0,SSL_F_SSL_RSA_PUBLIC_ENCRYPT,0), "SSL_RSA_PUBLIC_ENCRYPT"}, +{ERR_PACK(0,SSL_F_SSL_SESSION_NEW,0), "SSL_SESSION_new"}, +{ERR_PACK(0,SSL_F_SSL_SESSION_PRINT_FP,0), "SSL_SESSION_print_fp"}, +{ERR_PACK(0,SSL_F_SSL_SET_FD,0), "SSL_set_fd"}, +{ERR_PACK(0,SSL_F_SSL_SET_PKEY,0), "SSL_SET_PKEY"}, +{ERR_PACK(0,SSL_F_SSL_SET_RFD,0), "SSL_set_rfd"}, +{ERR_PACK(0,SSL_F_SSL_SET_SESSION,0), "SSL_set_session"}, +{ERR_PACK(0,SSL_F_SSL_SET_WFD,0), "SSL_set_wfd"}, +{ERR_PACK(0,SSL_F_SSL_UNDEFINED_FUNCTION,0), "SSL_UNDEFINED_FUNCTION"}, +{ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE,0), "SSL_use_certificate"}, +{ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE_ASN1,0), "SSL_use_certificate_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE_FILE,0), "SSL_use_certificate_file"}, +{ERR_PACK(0,SSL_F_SSL_USE_PRIVATEKEY,0), "SSL_use_PrivateKey"}, +{ERR_PACK(0,SSL_F_SSL_USE_PRIVATEKEY_ASN1,0), "SSL_use_PrivateKey_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_USE_PRIVATEKEY_FILE,0), "SSL_use_PrivateKey_file"}, +{ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY,0), "SSL_use_RSAPrivateKey"}, +{ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1,0), "SSL_use_RSAPrivateKey_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,0), "SSL_use_RSAPrivateKey_file"}, +{ERR_PACK(0,SSL_F_SSL_WRITE,0), "SSL_write"}, +{ERR_PACK(0,SSL_F_WRITE_PENDING,0), "WRITE_PENDING"}, +{0,NULL}, + }; + +static ERR_STRING_DATA SSL_str_reasons[]= + { +{SSL_R_APP_DATA_IN_HANDSHAKE ,"app data in handshake"}, +{SSL_R_BAD_ALERT_RECORD ,"bad alert record"}, +{SSL_R_BAD_AUTHENTICATION_TYPE ,"bad authentication type"}, +{SSL_R_BAD_CHANGE_CIPHER_SPEC ,"bad change cipher spec"}, +{SSL_R_BAD_CHECKSUM ,"bad checksum"}, +{SSL_R_BAD_CLIENT_REQUEST ,"bad client request"}, +{SSL_R_BAD_DATA_RETURNED_BY_CALLBACK ,"bad data returned by callback"}, +{SSL_R_BAD_DECOMPRESSION ,"bad decompression"}, +{SSL_R_BAD_DH_G_LENGTH ,"bad dh g length"}, +{SSL_R_BAD_DH_PUB_KEY_LENGTH ,"bad dh pub key length"}, +{SSL_R_BAD_DH_P_LENGTH ,"bad dh p length"}, +{SSL_R_BAD_DIGEST_LENGTH ,"bad digest length"}, +{SSL_R_BAD_DSA_SIGNATURE ,"bad dsa signature"}, +{SSL_R_BAD_MAC_DECODE ,"bad mac decode"}, +{SSL_R_BAD_MESSAGE_TYPE ,"bad message type"}, +{SSL_R_BAD_PACKET_LENGTH ,"bad packet length"}, +{SSL_R_BAD_RESPONSE_ARGUMENT ,"bad response argument"}, +{SSL_R_BAD_RSA_DECRYPT ,"bad rsa decrypt"}, +{SSL_R_BAD_RSA_ENCRYPT ,"bad rsa encrypt"}, +{SSL_R_BAD_RSA_E_LENGTH ,"bad rsa e length"}, +{SSL_R_BAD_RSA_MODULUS_LENGTH ,"bad rsa modulus length"}, +{SSL_R_BAD_RSA_SIGNATURE ,"bad rsa signature"}, +{SSL_R_BAD_SIGNATURE ,"bad signature"}, +{SSL_R_BAD_SSL_FILETYPE ,"bad ssl filetype"}, +{SSL_R_BAD_SSL_SESSION_ID_LENGTH ,"bad ssl session id length"}, +{SSL_R_BAD_STATE ,"bad state"}, +{SSL_R_BAD_WRITE_RETRY ,"bad write retry"}, +{SSL_R_BIO_NOT_SET ,"bio not set"}, +{SSL_R_BLOCK_CIPHER_PAD_IS_WRONG ,"block cipher pad is wrong"}, +{SSL_R_BN_LIB ,"bn lib"}, +{SSL_R_CA_DN_LENGTH_MISMATCH ,"ca dn length mismatch"}, +{SSL_R_CA_DN_TOO_LONG ,"ca dn too long"}, +{SSL_R_CCS_RECEIVED_EARLY ,"ccs received early"}, +{SSL_R_CERTIFICATE_VERIFY_FAILED ,"certificate verify failed"}, +{SSL_R_CERT_LENGTH_MISMATCH ,"cert length mismatch"}, +{SSL_R_CHALLENGE_IS_DIFFERENT ,"challenge is different"}, +{SSL_R_CIPHER_CODE_WRONG_LENGTH ,"cipher code wrong length"}, +{SSL_R_CIPHER_OR_HASH_UNAVAILABLE ,"cipher or hash unavailable"}, +{SSL_R_CIPHER_TABLE_SRC_ERROR ,"cipher table src error"}, +{SSL_R_COMPRESSED_LENGTH_TOO_LONG ,"compressed length too long"}, +{SSL_R_COMPRESSION_FAILURE ,"compression failure"}, +{SSL_R_CONNECTION_ID_IS_DIFFERENT ,"connection id is different"}, +{SSL_R_DATA_BETWEEN_CCS_AND_FINISHED ,"data between ccs and finished"}, +{SSL_R_DATA_LENGTH_TOO_LONG ,"data length too long"}, +{SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG ,"dh public value length is wrong"}, +{SSL_R_DIGEST_CHECK_FAILED ,"digest check failed"}, +{SSL_R_ENCRYPTED_LENGTH_TOO_LONG ,"encrypted length too long"}, +{SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST ,"error in received cipher list"}, +{SSL_R_EXCESSIVE_MESSAGE_SIZE ,"excessive message size"}, +{SSL_R_EXTRA_DATA_IN_MESSAGE ,"extra data in message"}, +{SSL_R_GOT_A_FIN_BEFORE_A_CCS ,"got a fin before a ccs"}, +{SSL_R_INTERNAL_ERROR ,"internal error"}, +{SSL_R_INVALID_CHALLENGE_LENGTH ,"invalid challenge length"}, +{SSL_R_LENGTH_MISMATCH ,"length mismatch"}, +{SSL_R_LENGTH_TOO_SHORT ,"length too short"}, +{SSL_R_LIBRARY_HAS_NO_CIPHERS ,"library has no ciphers"}, +{SSL_R_MISSING_DH_DSA_CERT ,"missing dh dsa cert"}, +{SSL_R_MISSING_DH_KEY ,"missing dh key"}, +{SSL_R_MISSING_DH_RSA_CERT ,"missing dh rsa cert"}, +{SSL_R_MISSING_DSA_SIGNING_CERT ,"missing dsa signing cert"}, +{SSL_R_MISSING_EXPORT_TMP_DH_KEY ,"missing export tmp dh key"}, +{SSL_R_MISSING_EXPORT_TMP_RSA_KEY ,"missing export tmp rsa key"}, +{SSL_R_MISSING_RSA_CERTIFICATE ,"missing rsa certificate"}, +{SSL_R_MISSING_RSA_ENCRYPTING_CERT ,"missing rsa encrypting cert"}, +{SSL_R_MISSING_RSA_SIGNING_CERT ,"missing rsa signing cert"}, +{SSL_R_MISSING_TMP_DH_KEY ,"missing tmp dh key"}, +{SSL_R_MISSING_TMP_RSA_KEY ,"missing tmp rsa key"}, +{SSL_R_MISSING_TMP_RSA_PKEY ,"missing tmp rsa pkey"}, +{SSL_R_MISSING_VERIFY_MESSAGE ,"missing verify message"}, +{SSL_R_NON_SSLV2_INITIAL_PACKET ,"non sslv2 initial packet"}, +{SSL_R_NO_CERTIFICATES_PASSED ,"no certificates passed"}, +{SSL_R_NO_CERTIFICATE_ASSIGNED ,"no certificate assigned"}, +{SSL_R_NO_CERTIFICATE_RETURNED ,"no certificate returned"}, +{SSL_R_NO_CERTIFICATE_SET ,"no certificate set"}, +{SSL_R_NO_CERTIFICATE_SPECIFIED ,"no certificate specified"}, +{SSL_R_NO_CIPHERS_AVAILABLE ,"no ciphers available"}, +{SSL_R_NO_CIPHERS_PASSED ,"no ciphers passed"}, +{SSL_R_NO_CIPHERS_SPECIFIED ,"no ciphers specified"}, +{SSL_R_NO_CIPHER_LIST ,"no cipher list"}, +{SSL_R_NO_CIPHER_MATCH ,"no cipher match"}, +{SSL_R_NO_CLIENT_CERT_RECEIVED ,"no client cert received"}, +{SSL_R_NO_COMPRESSION_SPECIFIED ,"no compression specified"}, +{SSL_R_NO_PRIVATEKEY ,"no privatekey"}, +{SSL_R_NO_PRIVATE_KEY_ASSIGNED ,"no private key assigned"}, +{SSL_R_NO_PUBLICKEY ,"no publickey"}, +{SSL_R_NO_SHARED_CIPHER ,"no shared cipher"}, +{SSL_R_NULL_SSL_CTX ,"null ssl ctx"}, +{SSL_R_NULL_SSL_METHOD_PASSED ,"null ssl method passed"}, +{SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED ,"old session cipher not returned"}, +{SSL_R_PACKET_LENGTH_TOO_LONG ,"packet length too long"}, +{SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE ,"peer did not return a certificate"}, +{SSL_R_PEER_ERROR ,"peer error"}, +{SSL_R_PEER_ERROR_CERTIFICATE ,"peer error certificate"}, +{SSL_R_PEER_ERROR_NO_CERTIFICATE ,"peer error no certificate"}, +{SSL_R_PEER_ERROR_NO_CIPHER ,"peer error no cipher"}, +{SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE,"peer error unsupported certificate type"}, +{SSL_R_PRE_MAC_LENGTH_TOO_LONG ,"pre mac length too long"}, +{SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS ,"problems mapping cipher functions"}, +{SSL_R_PROTOCOL_IS_SHUTDOWN ,"protocol is shutdown"}, +{SSL_R_PUBLIC_KEY_ENCRYPT_ERROR ,"public key encrypt error"}, +{SSL_R_PUBLIC_KEY_IS_NOT_RSA ,"public key is not rsa"}, +{SSL_R_PUBLIC_KEY_NOT_RSA ,"public key not rsa"}, +{SSL_R_READ_BIO_NOT_SET ,"read bio not set"}, +{SSL_R_READ_WRONG_PACKET_TYPE ,"read wrong packet type"}, +{SSL_R_RECORD_LENGTH_MISMATCH ,"record length mismatch"}, +{SSL_R_RECORD_TOO_LARGE ,"record too large"}, +{SSL_R_REQUIRED_CIPHER_MISSING ,"required cipher missing"}, +{SSL_R_REUSE_CERT_LENGTH_NOT_ZERO ,"reuse cert length not zero"}, +{SSL_R_REUSE_CERT_TYPE_NOT_ZERO ,"reuse cert type not zero"}, +{SSL_R_REUSE_CIPHER_LIST_NOT_ZERO ,"reuse cipher list not zero"}, +{SSL_R_SHORT_READ ,"short read"}, +{SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE,"signature for non signing certificate"}, +{SSL_R_SSL3_SESSION_ID_TOO_SHORT ,"ssl3 session id too short"}, +{SSL_R_SSLV3_ALERT_BAD_CERTIFICATE ,"sslv3 alert bad certificate"}, +{SSL_R_SSLV3_ALERT_BAD_RECORD_MAC ,"sslv3 alert bad record mac"}, +{SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED ,"sslv3 alert certificate expired"}, +{SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED ,"sslv3 alert certificate revoked"}, +{SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN ,"sslv3 alert certificate unknown"}, +{SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE ,"sslv3 alert decompression failure"}, +{SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE ,"sslv3 alert handshake failure"}, +{SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER ,"sslv3 alert illegal parameter"}, +{SSL_R_SSLV3_ALERT_NO_CERTIFICATE ,"sslv3 alert no certificate"}, +{SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE,"sslv3 alert peer error certificate"}, +{SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE,"sslv3 alert peer error no certificate"}, +{SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER ,"sslv3 alert peer error no cipher"}, +{SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE,"sslv3 alert peer error unsupported certificate type"}, +{SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE ,"sslv3 alert unexpected message"}, +{SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE,"sslv3 alert unknown remote error type"}, +{SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE,"sslv3 alert unsupported certificate"}, +{SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION,"ssl ctx has no default ssl version"}, +{SSL_R_SSL_HANDSHAKE_FAILURE ,"ssl handshake failure"}, +{SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS ,"ssl library has no ciphers"}, +{SSL_R_SSL_SESSION_ID_IS_DIFFERENT ,"ssl session id is different"}, +{SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER ,"tried to use unsupported cipher"}, +{SSL_R_UNABLE_TO_DECODE_DH_CERTS ,"unable to decode dh certs"}, +{SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY ,"unable to extract public key"}, +{SSL_R_UNABLE_TO_FIND_DH_PARAMETERS ,"unable to find dh parameters"}, +{SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS,"unable to find public key parameters"}, +{SSL_R_UNABLE_TO_FIND_SSL_METHOD ,"unable to find ssl method"}, +{SSL_R_UNEXPECTED_MESSAGE ,"unexpected message"}, +{SSL_R_UNEXPECTED_RECORD ,"unexpected record"}, +{SSL_R_UNKNOWN_ALERT_TYPE ,"unknown alert type"}, +{SSL_R_UNKNOWN_CERTIFICATE_TYPE ,"unknown certificate type"}, +{SSL_R_UNKNOWN_CIPHER_RETURNED ,"unknown cipher returned"}, +{SSL_R_UNKNOWN_CIPHER_TYPE ,"unknown cipher type"}, +{SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE ,"unknown key exchange type"}, +{SSL_R_UNKNOWN_PKEY_TYPE ,"unknown pkey type"}, +{SSL_R_UNKNOWN_PROTOCOL ,"unknown protocol"}, +{SSL_R_UNKNOWN_REMOTE_ERROR_TYPE ,"unknown remote error type"}, +{SSL_R_UNKNOWN_SSL_VERSION ,"unknown ssl version"}, +{SSL_R_UNKNOWN_STATE ,"unknown state"}, +{SSL_R_UNSUPPORTED_CIPHER ,"unsupported cipher"}, +{SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM ,"unsupported compression algorithm"}, +{SSL_R_UNSUPPORTED_SSL_VERSION ,"unsupported ssl version"}, +{SSL_R_WRITE_BIO_NOT_SET ,"write bio not set"}, +{SSL_R_WRONG_CIPHER_RETURNED ,"wrong cipher returned"}, +{SSL_R_WRONG_MESSAGE_TYPE ,"wrong message type"}, +{SSL_R_WRONG_NUMBER_OF_KEY_BITS ,"wrong number of key bits"}, +{SSL_R_WRONG_SIGNATURE_LENGTH ,"wrong signature length"}, +{SSL_R_WRONG_SIGNATURE_SIZE ,"wrong signature size"}, +{SSL_R_WRONG_SSL_VERSION ,"wrong ssl version"}, +{SSL_R_WRONG_VERSION_NUMBER ,"wrong version number"}, +{SSL_R_X509_LIB ,"x509 lib"}, +{0,NULL}, + }; + +void ERR_load_SSL_strings() + { + static int init=1; + + if (init) + { + init=0; + ERR_load_strings(ERR_LIB_SSL,SSL_str_functs); + ERR_load_strings(ERR_LIB_SSL,SSL_str_reasons); + } + } diff --git a/ssl/ssl_err2.c b/ssl/ssl_err2.c new file mode 100644 index 0000000000..a159fbb7cd --- /dev/null +++ b/ssl/ssl_err2.c @@ -0,0 +1,70 @@ +/* ssl/ssl_err2.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "err.h" +#include "ssl.h" + +void SSL_load_error_strings() + { +#ifndef NO_ERR + ERR_load_crypto_strings(); + ERR_load_SSL_strings(); +#endif + } + diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c new file mode 100644 index 0000000000..be091b1e75 --- /dev/null +++ b/ssl/ssl_lib.c @@ -0,0 +1,1433 @@ +/* ssl/ssl_lib.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "objects.h" +#include "lhash.h" +#include "ssl_locl.h" + +#ifndef NOPROTO +static unsigned long conn_hash(SSL_SESSION *a); +#else +static unsigned long conn_hash(); +#endif + +char *SSL_version_str="SSLeay 0.8.1b 29-Jun-1998"; + +void SSL_clear(s) +SSL *s; + { + int state; + + if (s->method == NULL) return; + + s->error=0; + s->hit=0; + + /* This is set if we are doing dynamic renegotiation so keep + * the old cipher. It is sort of a SSL_clear_lite :-) */ + if (s->new_session) return; + + state=s->state; /* Keep to check if we throw away the session-id */ + s->type=0; + + s->version=s->method->version; + s->rwstate=SSL_NOTHING; + s->state=SSL_ST_BEFORE; + s->rstate=SSL_ST_READ_HEADER; + s->read_ahead=s->ctx->default_read_ahead; + +/* s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); */ + + if (s->init_buf != NULL) + { + BUF_MEM_free(s->init_buf); + s->init_buf=NULL; + } + + ssl_clear_cipher_ctx(s); + + if (ssl_clear_bad_session(s)) + { + SSL_SESSION_free(s->session); + s->session=NULL; + } + + s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); + s->first_packet=0; + + s->method->ssl_clear(s); + } + +/* Used to change an SSL_CTXs default SSL method type */ +int SSL_CTX_set_ssl_version(ctx,meth) +SSL_CTX *ctx; +SSL_METHOD *meth; + { + STACK *sk; + + ctx->method=meth; + + sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list), + &(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST); + if ((sk == NULL) || (sk_num(sk) <= 0)) + { + SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); + return(0); + } + return(1); + } + +SSL *SSL_new(ctx) +SSL_CTX *ctx; + { + SSL *s; + + if (ctx == NULL) + { + SSLerr(SSL_F_SSL_NEW,SSL_R_NULL_SSL_CTX); + return(NULL); + } + if (ctx->method == NULL) + { + SSLerr(SSL_F_SSL_NEW,SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); + return(NULL); + } + + s=(SSL *)Malloc(sizeof(SSL)); + if (s == NULL) goto err; + memset(s,0,sizeof(SSL)); + + if (ctx->default_cert != NULL) + { + CRYPTO_add(&ctx->default_cert->references,1, + CRYPTO_LOCK_SSL_CERT); + s->cert=ctx->default_cert; + } + else + s->cert=NULL; + s->verify_mode=ctx->default_verify_mode; + s->verify_callback=ctx->default_verify_callback; + CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); + s->ctx=ctx; + + s->verify_result=X509_V_OK; + + s->method=ctx->method; + + if (!s->method->ssl_new(s)) + { + SSL_CTX_free(ctx); + Free(s); + goto err; + } + + s->quiet_shutdown=ctx->quiet_shutdown; + SSL_clear(s); + return(s); +err: + SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + +void SSL_free(s) +SSL *s; + { + if (s->bbio != NULL) + { + /* If the buffering BIO is in place, pop it off */ + if (s->bbio == s->wbio) + { + s->wbio=BIO_pop(s->wbio); + } + BIO_free(s->bbio); + } + if (s->rbio != NULL) + BIO_free_all(s->rbio); + if ((s->wbio != NULL) && (s->wbio != s->rbio)) + BIO_free_all(s->wbio); + + if (s->init_buf != NULL) BUF_MEM_free(s->init_buf); + + /* add extra stuff */ + if (s->cipher_list != NULL) sk_free(s->cipher_list); + if (s->cipher_list_by_id != NULL) sk_free(s->cipher_list_by_id); + + /* Make the next call work :-) */ + if (s->session != NULL) + { + ssl_clear_bad_session(s); + SSL_SESSION_free(s->session); + } + + ssl_clear_cipher_ctx(s); + + if (s->cert != NULL) ssl_cert_free(s->cert); + /* Free up if allocated */ + + if (s->ctx) SSL_CTX_free(s->ctx); + + if (s->client_CA != NULL) + sk_pop_free(s->client_CA,X509_NAME_free); + + if (s->method != NULL) s->method->ssl_free(s); + + Free((char *)s); + } + +void SSL_set_bio(s, rbio,wbio) +SSL *s; +BIO *rbio; +BIO *wbio; + { + /* If the output buffering BIO is still in place, remove it + */ + if (s->bbio != NULL) + { + if (s->wbio == s->bbio) + { + s->wbio=s->wbio->next_bio; + s->bbio->next_bio=NULL; + } + } + if ((s->rbio != NULL) && (s->rbio != rbio)) + BIO_free_all(s->rbio); + if ((s->wbio != NULL) && (s->wbio != wbio) && (s->rbio != s->wbio)) + BIO_free_all(s->wbio); + s->rbio=rbio; + s->wbio=wbio; + } + +BIO *SSL_get_rbio(s) +SSL *s; + { return(s->rbio); } + +BIO *SSL_get_wbio(s) +SSL *s; + { return(s->wbio); } + +int SSL_get_fd(s) +SSL *s; + { + int ret= -1; + BIO *b,*r; + + b=SSL_get_rbio(s); + r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR); + if (r != NULL) + BIO_get_fd(r,&ret); + return(ret); + } + +#ifndef NO_SOCK +int SSL_set_fd(s, fd) +SSL *s; +int fd; + { + int ret=0; + BIO *bio=NULL; + + bio=BIO_new(BIO_s_socket()); + + if (bio == NULL) + { + SSLerr(SSL_F_SSL_SET_FD,ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio,fd,BIO_NOCLOSE); + SSL_set_bio(s,bio,bio); + ret=1; +err: + return(ret); + } + +int SSL_set_wfd(s, fd) +SSL *s; +int fd; + { + int ret=0; + BIO *bio=NULL; + + bio=BIO_new(BIO_s_socket()); + + if (bio == NULL) + { SSLerr(SSL_F_SSL_SET_WFD,ERR_R_BUF_LIB); goto err; } + BIO_set_fd(bio,fd,BIO_NOCLOSE); + SSL_set_bio(s,SSL_get_rbio(s),bio); + ret=1; +err: + return(ret); + } + +int SSL_set_rfd(s, fd) +SSL *s; +int fd; + { + int ret=0; + BIO *bio=NULL; + + bio=BIO_new(BIO_s_socket()); + + if (bio == NULL) + { + SSLerr(SSL_F_SSL_SET_RFD,ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio,fd,BIO_NOCLOSE); + SSL_set_bio(s,bio,SSL_get_wbio(s)); + ret=1; +err: + return(ret); + } +#endif + +int SSL_get_verify_mode(s) +SSL *s; + { + return(s->verify_mode); + } + +int (*SSL_get_verify_callback(s))() +SSL *s; + { + return(s->verify_callback); + } + +int SSL_CTX_get_verify_mode(ctx) +SSL_CTX *ctx; + { + return(ctx->default_verify_mode); + } + +int (*SSL_CTX_get_verify_callback(ctx))() +SSL_CTX *ctx; + { + return(ctx->default_verify_callback); + } + +void SSL_set_verify(s, mode, callback) +SSL *s; +int mode; +int (*callback)(); + { + s->verify_mode=mode; + if (callback != NULL) + s->verify_callback=callback; + } + +void SSL_set_read_ahead(s, yes) +SSL *s; +int yes; + { + s->read_ahead=yes; + } + +int SSL_get_read_ahead(s) +SSL *s; + { + return(s->read_ahead); + } + +int SSL_pending(s) +SSL *s; + { + return(s->method->ssl_pending(s)); + } + +X509 *SSL_get_peer_certificate(s) +SSL *s; + { + X509 *r; + + if ((s == NULL) || (s->session == NULL)) + r=NULL; + else + r=s->session->peer; + + if (r == NULL) return(r); + + CRYPTO_add(&r->references,1,CRYPTO_LOCK_X509); + + return(r); + } + +STACK *SSL_get_peer_cert_chain(s) +SSL *s; + { + STACK *r; + + if ((s == NULL) || (s->session == NULL) || (s->session->cert == NULL)) + r=NULL; + else + r=s->session->cert->cert_chain; + + return(r); + } + +/* Now in theory, since the calling process own 't' it should be safe to + * modify. We need to be able to read f without being hassled */ +void SSL_copy_session_id(t,f) +SSL *t,*f; + { + CERT *tmp; + + /* Do we need to to SSL locking? */ + SSL_set_session(t,SSL_get_session(f)); + + /* what if we are setup as SSLv2 but want to talk SSLv3 or + * vice-versa */ + if (t->method != f->method) + { + t->method->ssl_free(t); /* cleanup current */ + t->method=f->method; /* change method */ + t->method->ssl_new(t); /* setup new */ + } + + tmp=t->cert; + if (f->cert != NULL) + { + CRYPTO_add(&f->cert->references,1,CRYPTO_LOCK_SSL_CERT); + t->cert=f->cert; + } + else + t->cert=NULL; + if (tmp != NULL) ssl_cert_free(tmp); + } + +int SSL_CTX_check_private_key(ctx) +SSL_CTX *ctx; + { + if ( (ctx == NULL) || + (ctx->default_cert == NULL) || + (ctx->default_cert->key->x509 == NULL)) + { + SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); + return(0); + } + if (ctx->default_cert->key->privatekey == NULL) + { + SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return(0); + } + return(X509_check_private_key(ctx->default_cert->key->x509, ctx->default_cert->key->privatekey)); + } + +int SSL_check_private_key(ssl) +SSL *ssl; + { + if (ssl == NULL) + { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if (ssl->cert == NULL) + return(SSL_CTX_check_private_key(ssl->ctx)); + if (ssl->cert->key->x509 == NULL) + { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); + return(0); + } + if (ssl->cert->key->privatekey == NULL) + { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return(0); + } + return(X509_check_private_key(ssl->cert->key->x509, + ssl->cert->key->privatekey)); + } + +int SSL_accept(s) +SSL *s; + { + return(s->method->ssl_accept(s)); + } + +int SSL_connect(s) +SSL *s; + { + return(s->method->ssl_connect(s)); + } + +long SSL_get_default_timeout(s) +SSL *s; + { + return(s->method->get_timeout()); + } + +int SSL_read(s,buf,num) +SSL *s; +char *buf; +int num; + { + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) + { + s->rwstate=SSL_NOTHING; + return(0); + } + return(s->method->ssl_read(s,buf,num)); + } + +int SSL_peek(s,buf,num) +SSL *s; +char *buf; +int num; + { + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) + { + return(0); + } + return(s->method->ssl_peek(s,buf,num)); + } + +int SSL_write(s,buf,num) +SSL *s; +char *buf; +int num; + { + if (s->shutdown & SSL_SENT_SHUTDOWN) + { + s->rwstate=SSL_NOTHING; + SSLerr(SSL_F_SSL_WRITE,SSL_R_PROTOCOL_IS_SHUTDOWN); + return(-1); + } + return(s->method->ssl_write(s,buf,num)); + } + +int SSL_shutdown(s) +SSL *s; + { + if ((s != NULL) && !SSL_in_init(s)) + return(s->method->ssl_shutdown(s)); + else + return(1); + } + +int SSL_renegotiate(s) +SSL *s; + { + return(s->method->ssl_renegotiate(s)); + } + +long SSL_ctrl(s,cmd,larg,parg) +SSL *s; +int cmd; +long larg; +char *parg; + { + return(s->method->ssl_ctrl(s,cmd,larg,parg)); + } + +long SSL_CTX_ctrl(ctx,cmd,larg,parg) +SSL_CTX *ctx; +int cmd; +long larg; +char *parg; + { + return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); + } + +int ssl_cipher_id_cmp(a,b) +SSL_CIPHER *a,*b; + { + long l; + + l=a->id-b->id; + if (l == 0L) + return(0); + else + return((l > 0)?1:-1); + } + +int ssl_cipher_ptr_id_cmp(ap,bp) +SSL_CIPHER **ap,**bp; + { + long l; + + l=(*ap)->id-(*bp)->id; + if (l == 0L) + return(0); + else + return((l > 0)?1:-1); + } + +/* return a STACK of the ciphers available for the SSL and in order of + * preference */ +STACK *SSL_get_ciphers(s) +SSL *s; + { + if ((s != NULL) && (s->cipher_list != NULL)) + { + return(s->cipher_list); + } + else if ((s != NULL) && (s->ctx != NULL) && + (s->ctx->cipher_list != NULL)) + { + return(s->ctx->cipher_list); + } + return(NULL); + } + +/* return a STACK of the ciphers available for the SSL and in order of + * algorithm id */ +STACK *ssl_get_ciphers_by_id(s) +SSL *s; + { + if ((s != NULL) && (s->cipher_list_by_id != NULL)) + { + return(s->cipher_list_by_id); + } + else if ((s != NULL) && (s->ctx != NULL) && + (s->ctx->cipher_list_by_id != NULL)) + { + return(s->ctx->cipher_list_by_id); + } + return(NULL); + } + +/* The old interface to get the same thing as SSL_get_ciphers() */ +char *SSL_get_cipher_list(s,n) +SSL *s; +int n; + { + SSL_CIPHER *c; + STACK *sk; + + if (s == NULL) return(NULL); + sk=SSL_get_ciphers(s); + if ((sk == NULL) || (sk_num(sk) <= n)) + return(NULL); + c=(SSL_CIPHER *)sk_value(sk,n); + if (c == NULL) return(NULL); + return(c->name); + } + +/* specify the ciphers to be used by defaut by the SSL_CTX */ +int SSL_CTX_set_cipher_list(ctx,str) +SSL_CTX *ctx; +char *str; + { + STACK *sk; + + sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, + &ctx->cipher_list_by_id,str); +/* XXXX */ + return((sk == NULL)?0:1); + } + +/* specify the ciphers to be used by the SSL */ +int SSL_set_cipher_list(s, str) +SSL *s; +char *str; + { + STACK *sk; + + sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, + &s->cipher_list_by_id,str); +/* XXXX */ + return((sk == NULL)?0:1); + } + +/* works well for SSLv2, not so good for SSLv3 */ +char *SSL_get_shared_ciphers(s,buf,len) +SSL *s; +char *buf; +int len; + { + char *p,*cp; + STACK *sk; + SSL_CIPHER *c; + int i; + + if ((s->session == NULL) || (s->session->ciphers == NULL) || + (len < 2)) + return(NULL); + + p=buf; + sk=s->session->ciphers; + len--; + for (i=0; i<sk_num(sk); i++) + { + c=(SSL_CIPHER *)sk_value(sk,i); + for (cp=c->name; *cp; ) + { + if (--len == 0) + { + *p='\0'; + return(buf); + } + else + *(p++)= *(cp++); + } + *(p++)=':'; + } + p[-1]='\0'; + return(buf); + } + +int ssl_cipher_list_to_bytes(s,sk,p) +SSL *s; +STACK *sk; +unsigned char *p; + { + int i,j=0; + SSL_CIPHER *c; + unsigned char *q; + + if (sk == NULL) return(0); + q=p; + + for (i=0; i<sk_num(sk); i++) + { + c=(SSL_CIPHER *)sk_value(sk,i); + j=ssl_put_cipher_by_char(s,c,p); + p+=j; + } + return(p-q); + } + +STACK *ssl_bytes_to_cipher_list(s,p,num,skp) +SSL *s; +unsigned char *p; +int num; +STACK **skp; + { + SSL_CIPHER *c; + STACK *sk; + int i,n; + + n=ssl_put_cipher_by_char(s,NULL,NULL); + if ((num%n) != 0) + { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + return(NULL); + } + if ((skp == NULL) || (*skp == NULL)) + sk=sk_new(NULL); /* change perhaps later */ + else + { + sk= *skp; + sk_zero(sk); + } + + for (i=0; i<num; i+=n) + { + c=ssl_get_cipher_by_char(s,p); + p+=n; + if (c != NULL) + { + if (!sk_push(sk,(char *)c)) + { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,ERR_R_MALLOC_FAILURE); + goto err; + } + } + } + + if (skp != NULL) + *skp=sk; + return(sk); +err: + if ((skp == NULL) || (*skp == NULL)) + sk_free(sk); + return(NULL); + } + +static unsigned long conn_hash(a) +SSL_SESSION *a; + { + unsigned long l; + + l= (a->session_id[0] )|(a->session_id[1]<< 8L)| + (a->session_id[1]<<16L)|(a->session_id[2]<<24L); + return(l); + } + +static int session_cmp(a, b) +SSL_SESSION *a; +SSL_SESSION *b; + { + int i; + + i=a->session_id_length - b->session_id_length; + if (i == 0) + return(memcmp(a->session_id,b->session_id, + a->session_id_length)); + else return(1); + } + +SSL_CTX *SSL_CTX_new(meth) +SSL_METHOD *meth; + { + SSL_CTX *ret; + + if (meth == NULL) + { + SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED); + return(NULL); + } + ret=(SSL_CTX *)Malloc(sizeof(SSL_CTX)); + if (ret == NULL) + goto err; + + memset(ret,0,sizeof(SSL_CTX)); + + ret->method=meth; + + ret->cert_store=NULL; + ret->session_cache_mode=SSL_SESS_CACHE_SERVER; + + /* We take the system default */ + ret->session_timeout=meth->get_timeout(); + + ret->new_session_cb=NULL; + ret->remove_session_cb=NULL; + ret->get_session_cb=NULL; + + ret->sess_connect=0; + ret->sess_connect_good=0; + ret->sess_accept=0; + ret->sess_accept_good=0; + ret->sess_miss=0; + ret->sess_timeout=0; + ret->sess_hit=0; + ret->sess_cb_hit=0; + + ret->references=1; + ret->quiet_shutdown=0; + +/* ret->cipher=NULL;*/ +/* ret->s2->challenge=NULL; + ret->master_key=NULL; + ret->key_arg=NULL; + ret->s2->conn_id=NULL; */ + + ret->info_callback=NULL; + + ret->app_verify_callback=NULL; + ret->app_verify_arg=NULL; + + ret->default_read_ahead=0; + ret->default_verify_mode=SSL_VERIFY_NONE; + ret->default_verify_callback=NULL; + if ((ret->default_cert=ssl_cert_new()) == NULL) + goto err; + + ret->default_passwd_callback=NULL; + ret->client_cert_cb=NULL; + + ret->sessions=lh_new(conn_hash,session_cmp); + if (ret->sessions == NULL) goto err; + ret->cert_store=X509_STORE_new(); + if (ret->cert_store == NULL) goto err; + + ssl_create_cipher_list(ret->method, + &ret->cipher_list,&ret->cipher_list_by_id, + SSL_DEFAULT_CIPHER_LIST); + if ((ret->cipher_list == NULL) || (sk_num(ret->cipher_list) <= 0)) + { + SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS); + goto err2; + } + + if ((ret->client_CA=sk_new_null()) == NULL) + goto err; + + return(ret); +err: + SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE); +err2: + if (ret != NULL) SSL_CTX_free(ret); + return(NULL); + } + +void SSL_CTX_free(a) +SSL_CTX *a; + { + int i; + + if (a == NULL) return; + + i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX); + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"SSL_CTX_free, bad reference count\n"); + abort(); /* ok */ + } +#endif + + if (a->sessions != NULL) + { + SSL_CTX_flush_sessions(a,0); + lh_free(a->sessions); + } + if (a->cert_store != NULL) + X509_STORE_free(a->cert_store); + if (a->cipher_list != NULL) + sk_free(a->cipher_list); + if (a->cipher_list_by_id != NULL) + sk_free(a->cipher_list_by_id); + if (a->default_cert != NULL) + ssl_cert_free(a->default_cert); + if (a->client_CA != NULL) + sk_pop_free(a->client_CA,X509_NAME_free); + Free((char *)a); + } + +void SSL_CTX_set_default_passwd_cb(ctx,cb) +SSL_CTX *ctx; +int (*cb)(); + { + ctx->default_passwd_callback=cb; + } + +void SSL_CTX_set_cert_verify_cb(ctx,cb,arg) +SSL_CTX *ctx; +int (*cb)(); +char *arg; + { + ctx->app_verify_callback=cb; + ctx->app_verify_arg=arg; + } + +void SSL_CTX_set_verify(ctx,mode,cb) +SSL_CTX *ctx; +int mode; +int (*cb)(); + { + ctx->default_verify_mode=mode; + ctx->default_verify_callback=cb; + /* This needs cleaning up EAY EAY EAY */ + X509_STORE_set_verify_cb_func(ctx->cert_store,cb); + } + +void ssl_set_cert_masks(c) +CERT *c; + { + CERT_PKEY *cpk; + int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign; + int rsa_enc_export,dh_rsa_export,dh_dsa_export; + int rsa_tmp_export,dh_tmp_export; + unsigned long mask,emask; + + if ((c == NULL) || (c->valid)) return; + +#ifndef NO_RSA + rsa_tmp=((c->rsa_tmp != NULL) || (c->rsa_tmp_cb != NULL))?1:0; + rsa_tmp_export=((c->rsa_tmp_cb != NULL) || + (rsa_tmp && (RSA_size(c->rsa_tmp)*8 <= 512)))?1:0; +#else + rsa_tmp=rsa_tmp_export=0; +#endif +#ifndef NO_DH + dh_tmp=((c->dh_tmp != NULL) || (c->dh_tmp_cb != NULL))?1:0; + dh_tmp_export=((c->dh_tmp_cb != NULL) || + (dh_tmp && (DH_size(c->dh_tmp)*8 <= 512)))?1:0; +#else + dh_tmp=dh_tmp_export=0; +#endif + + cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); + rsa_enc= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + rsa_enc_export=(rsa_enc && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0; + cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]); + rsa_sign=((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); + dsa_sign=((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); + dh_rsa= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + dh_rsa_export=(dh_rsa && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0; + cpk= &(c->pkeys[SSL_PKEY_DH_DSA]); +/* FIX THIS EAY EAY EAY */ + dh_dsa= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + dh_dsa_export=(dh_dsa && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0; + + mask=0; + emask=0; + +#ifdef CIPHER_DEBUG + printf("rt=%d dht=%d re=%d rs=%d ds=%d dhr=%d dhd=%d\n", + rsa_tmp,dh_tmp, + rsa_enc,rsa_sign,dsa_sign,dh_rsa,dh_dsa); +#endif + + if (rsa_enc || (rsa_tmp && rsa_sign)) + mask|=SSL_kRSA; + if (rsa_enc_export || (rsa_tmp_export && rsa_sign)) + emask|=SSL_kRSA; + +#if 0 + /* The match needs to be both kEDH and aRSA or aDSA, so don't worry */ + if ( (dh_tmp || dh_rsa || dh_dsa) && + (rsa_enc || rsa_sign || dsa_sign)) + mask|=SSL_kEDH; + if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) && + (rsa_enc || rsa_sign || dsa_sign)) + emask|=SSL_kEDH; +#endif + + if (dh_tmp_export) + emask|=SSL_kEDH; + + if (dh_tmp) + mask|=SSL_kEDH; + + if (dh_rsa) mask|=SSL_kDHr; + if (dh_rsa_export) emask|=SSL_kDHr; + + if (dh_dsa) mask|=SSL_kDHd; + if (dh_dsa_export) emask|=SSL_kDHd; + + if (rsa_enc || rsa_sign) + { + mask|=SSL_aRSA; + emask|=SSL_aRSA; + } + + if (dsa_sign) + { + mask|=SSL_aDSS; + emask|=SSL_aDSS; + } + +#ifdef SSL_ALLOW_ADH + mask|=SSL_aNULL; + emask|=SSL_aNULL; +#endif + + c->mask=mask; + c->export_mask=emask; + c->valid=1; + } + +/* THIS NEEDS CLEANING UP */ +X509 *ssl_get_server_send_cert(s) +SSL *s; + { + unsigned long alg,mask,kalg; + CERT *c; + int i,export; + + c=s->cert; + ssl_set_cert_masks(c); + alg=s->s3->tmp.new_cipher->algorithms; + export=(alg & SSL_EXPORT)?1:0; + mask=(export)?c->export_mask:c->mask; + kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK); + + if (kalg & SSL_kDHr) + i=SSL_PKEY_DH_RSA; + else if (kalg & SSL_kDHd) + i=SSL_PKEY_DH_DSA; + else if (kalg & SSL_aDSS) + i=SSL_PKEY_DSA_SIGN; + else if (kalg & SSL_aRSA) + { + if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) + i=SSL_PKEY_RSA_SIGN; + else + i=SSL_PKEY_RSA_ENC; + } + else /* if (kalg & SSL_aNULL) */ + { + SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,SSL_R_INTERNAL_ERROR); + return(NULL); + } + if (c->pkeys[i].x509 == NULL) return(NULL); + return(c->pkeys[i].x509); + } + +EVP_PKEY *ssl_get_sign_pkey(s,cipher) +SSL *s; +SSL_CIPHER *cipher; + { + unsigned long alg; + CERT *c; + + alg=cipher->algorithms; + c=s->cert; + + if ((alg & SSL_aDSS) && + (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) + return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey); + else if (alg & SSL_aRSA) + { + if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) + return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey); + else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) + return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey); + else + return(NULL); + } + else /* if (alg & SSL_aNULL) */ + { + SSLerr(SSL_F_SSL_GET_SIGN_PKEY,SSL_R_INTERNAL_ERROR); + return(NULL); + } + } + +void ssl_update_cache(s,mode) +SSL *s; +int mode; + { + if ((s->ctx->session_cache_mode & mode) + && (!s->hit) + && SSL_CTX_add_session(s->ctx,s->session) + && (s->ctx->new_session_cb != NULL)) + { + CRYPTO_add(&s->session->references,1, + CRYPTO_LOCK_SSL_SESSION); + if (!s->ctx->new_session_cb(s,s->session)) + SSL_SESSION_free(s->session); + } + + /* auto flush every 255 connections */ + if ((!(s->ctx->session_cache_mode & + SSL_SESS_CACHE_NO_AUTO_CLEAR)) && + ((s->ctx->sess_connect_good & 0xff) == 0)) + SSL_CTX_flush_sessions(s->ctx,time(NULL)); + } + +SSL_METHOD *SSL_get_ssl_method(s) +SSL *s; + { + return(s->method); + } + +int SSL_set_ssl_method(s,meth) +SSL *s; +SSL_METHOD *meth; + { + int conn= -1; + int ret=1; + + if (s->method != meth) + { + if (s->handshake_func != NULL) + conn=(s->handshake_func == s->method->ssl_connect); + + if (s->method->version == meth->version) + s->method=meth; + else + { + s->method->ssl_free(s); + s->method=meth; + ret=s->method->ssl_new(s); + } + + if (conn == 1) + s->handshake_func=meth->ssl_connect; + else if (conn == 0) + s->handshake_func=meth->ssl_accept; + } + return(ret); + } + +int SSL_get_error(s,i) +SSL *s; +int i; + { + int reason; + BIO *bio; + + if (i > 0) return(SSL_ERROR_NONE); + + if (ERR_peek_error() != 0) + return(SSL_ERROR_SSL); + + if ((i < 0) && SSL_want_read(s)) + { + bio=SSL_get_rbio(s); + if (BIO_should_read(bio)) + return(SSL_ERROR_WANT_READ); + else if (BIO_should_write(bio)) + return(SSL_ERROR_WANT_WRITE); + else if (BIO_should_io_special(bio)) + { + reason=BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) + return(SSL_ERROR_WANT_CONNECT); + else + return(SSL_ERROR_SYSCALL); /* unknown */ + } + } + + if ((i < 0) && SSL_want_write(s)) + { + bio=SSL_get_wbio(s); + if (BIO_should_write(bio)) + return(SSL_ERROR_WANT_WRITE); + else if (BIO_should_read(bio)) + return(SSL_ERROR_WANT_READ); + else if (BIO_should_io_special(bio)) + { + reason=BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) + return(SSL_ERROR_WANT_CONNECT); + else + return(SSL_ERROR_SYSCALL); + } + } + if ((i < 0) && SSL_want_x509_lookup(s)) + { + return(SSL_ERROR_WANT_X509_LOOKUP); + } + + if (i == 0) + { + if (s->version == 2) + { + /* assume it is the socket being closed */ + return(SSL_ERROR_ZERO_RETURN); + } + else + { + if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && + (s->s3->warn_alert == SSL3_AD_CLOSE_NOTIFY)) + return(SSL_ERROR_ZERO_RETURN); + } + } + return(SSL_ERROR_SYSCALL); + } + +int SSL_do_handshake(s) +SSL *s; + { + if (s->handshake_func == NULL) + { + SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_INTERNAL_ERROR); + return(-1); + } + if (SSL_in_init(s) || SSL_in_before(s)) + return(s->handshake_func(s)); + else + return(1); + } + +/* For the next 2 functions, SSL_clear() sets shutdown and so + * one of these calls will reset it */ +void SSL_set_accept_state(s) +SSL *s; + { + s->shutdown=0; + s->state=SSL_ST_ACCEPT|SSL_ST_BEFORE; + s->handshake_func=s->method->ssl_accept; + /* clear the current cipher */ + ssl_clear_cipher_ctx(s); + } + +void SSL_set_connect_state(s) +SSL *s; + { + s->shutdown=0; + s->state=SSL_ST_CONNECT|SSL_ST_BEFORE; + s->handshake_func=s->method->ssl_connect; + /* clear the current cipher */ + ssl_clear_cipher_ctx(s); + } + +int ssl_undefined_function(s) +SSL *s; + { + SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return(0); + } + +SSL_METHOD *ssl_bad_method(ver) +int ver; + { + SSLerr(SSL_F_SSL_BAD_METHOD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return(NULL); + } + +char *SSL_get_version(s) +SSL *s; + { + if (s->version == 3) + return("SSLv3"); + else if (s->version == 2) + return("SSLv2"); + else + return("unknown"); + } + +SSL *SSL_dup(s) +SSL *s; + { + STACK *sk; + X509_NAME *xn; + SSL *ret; + int i; + + if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL) return(NULL); + + /* This copies version, session-id, SSL_METHOD and 'cert' */ + SSL_copy_session_id(ret,s); + + SSL_set_read_ahead(ret,SSL_get_read_ahead(s)); + SSL_set_verify(ret,SSL_get_verify_mode(s), + SSL_get_verify_callback(s)); + + SSL_set_info_callback(ret,SSL_get_info_callback(s)); + + ret->debug=s->debug; + + /* copy app data, a little dangerous perhaps */ + SSL_set_app_data(ret,SSL_get_app_data(s)); + + /* setup rbio, and wbio */ + if (s->rbio != NULL) + { + if (!BIO_dup_state(s->rbio,(char *)&ret->rbio)) + goto err; + } + if (s->wbio != NULL) + { + if (s->wbio != s->rbio) + { + if (!BIO_dup_state(s->wbio,(char *)&ret->rbio)) + goto err; + } + else + ret->wbio=ret->rbio; + } + + /* dup the cipher_list and cipher_list_by_id stacks */ + if (s->cipher_list != NULL) + { + if ((ret->cipher_list=sk_dup(s->cipher_list)) == NULL) + goto err; + } + if (s->cipher_list_by_id != NULL) + if ((ret->cipher_list_by_id=sk_dup(s->cipher_list_by_id)) + == NULL) + goto err; + + /* Dup the client_CA list */ + if (s->client_CA != NULL) + { + if ((sk=sk_dup(s->client_CA)) == NULL) goto err; + ret->client_CA=sk; + for (i=0; i<sk_num(sk); i++) + { + xn=(X509_NAME *)sk_value(sk,i); + if ((sk_value(sk,i)=(char *)X509_NAME_dup(xn)) == NULL) + { + X509_NAME_free(xn); + goto err; + } + } + } + + ret->shutdown=s->shutdown; + ret->state=s->state; + ret->handshake_func=s->handshake_func; + + if (0) + { +err: + if (ret != NULL) SSL_free(ret); + ret=NULL; + } + return(ret); + } + +void ssl_clear_cipher_ctx(s) +SSL *s; + { + if (s->enc_read_ctx != NULL) + { + EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); + Free(s->enc_read_ctx); + s->enc_read_ctx=NULL; + } + if (s->enc_write_ctx != NULL) + { + EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); + Free(s->enc_write_ctx); + s->enc_write_ctx=NULL; + } + } + +X509 *SSL_get_certificate(s) +SSL *s; + { + if (s->cert != NULL) + return(s->cert->key->x509); + else + return(NULL); + } + +EVP_PKEY *SSL_get_privatekey(s) +SSL *s; + { + if (s->cert != NULL) + return(s->cert->key->privatekey); + else + return(NULL); + } + +SSL_CIPHER *SSL_get_current_cipher(s) +SSL *s; + { + if ((s->session != NULL) && (s->session->cipher != NULL)) + return(s->session->cipher); + return(NULL); + } + diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h new file mode 100644 index 0000000000..ef3a70e93e --- /dev/null +++ b/ssl/ssl_locl.h @@ -0,0 +1,520 @@ +/* ssl/ssl_locl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL_LOCL_H +#define HEADER_SSL_LOCL_H +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <errno.h> + +#ifdef FLAT_INC +#include "e_os.h" +#else +#include "../e_os.h" +#endif + +#include "buffer.h" +#include "bio.h" +#include "crypto.h" +#include "evp.h" +#include "stack.h" +#include "x509.h" +#include "err.h" +#include "ssl.h" + + +#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))) + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +#define n2s(c,s) (s =((unsigned int)(*((c)++)))<< 8, \ + s|=((unsigned int)(*((c)++)))) +#define s2n(s,c) (*((c)++)=(unsigned char)(((s)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((s) )&0xff)) + +#define n2l3(c,l) (l =((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))) + +#define l2n3(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* LOCAL STUFF */ + +#define SSL_DECRYPT 0 +#define SSL_ENCRYPT 1 + +#define TWO_BYTE_BIT 0x80 +#define SEC_ESC_BIT 0x40 +#define TWO_BYTE_MASK 0x7fff +#define THREE_BYTE_MASK 0x3fff + +#define INC32(a) ((a)=((a)+1)&0xffffffffL) +#define DEC32(a) ((a)=((a)-1)&0xffffffffL) +#define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */ + +#define SSL_MKEY_MASK 0x0000001FL +#define SSL_kRSA 0x00000001L /* RSA key exchange */ +#define SSL_kDHr 0x00000002L /* DH cert RSA CA cert */ +#define SSL_kDHd 0x00000004L /* DH cert DSA CA cert */ +#define SSL_kFZA 0x00000008L +#define SSL_kEDH 0x00000010L /* tmp DH key no DH cert */ +#define SSL_EDH (SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL)) + +#define SSL_AUTH_MASK 0x000003e0L +#define SSL_aRSA 0x00000020L /* Authenticate with RSA */ +#define SSL_aDSS 0x00000040L /* Authenticate with DSS */ +#define SSL_DSS SSL_aDSS +#define SSL_aFZA 0x00000080L +#define SSL_aNULL 0x00000100L /* no Authenticate, ADH */ +#define SSL_aDH 0x00000200L /* no Authenticate, ADH */ + +#define SSL_NULL (SSL_eNULL) +#define SSL_ADH (SSL_kEDH|SSL_aNULL) +#define SSL_RSA (SSL_kRSA|SSL_aRSA) +#define SSL_DH (SSL_kDHr|SSL_kDHd|SSL_kEDH) +#define SSL_FZA (SSL_aFZA|SSL_kFZA|SSL_eFZA) + +#define SSL_ENC_MASK 0x0001Fc00L +#define SSL_DES 0x00000400L +#define SSL_3DES 0x00000800L +#define SSL_RC4 0x00001000L +#define SSL_RC2 0x00002000L +#define SSL_IDEA 0x00004000L +#define SSL_eFZA 0x00008000L +#define SSL_eNULL 0x00010000L + +#define SSL_MAC_MASK 0x000e0000L +#define SSL_MD5 0x00020000L +#define SSL_SHA0 0x00040000L +#define SSL_SHA1 0x00080000L +#define SSL_SHA (SSL_SHA0|SSL_SHA1) + +#define SSL_EXP_MASK 0x00300000L +#define SSL_EXP 0x00100000L +#define SSL_NOT_EXP 0x00200000L +#define SSL_EXPORT SSL_EXP + +#define SSL_SSL_MASK 0x00c00000L +#define SSL_SSLV2 0x00400000L +#define SSL_SSLV3 0x00800000L + +#define SSL_STRONG_MASK 0x07000000L +#define SSL_LOW 0x01000000L +#define SSL_MEDIUM 0x02000000L +#define SSL_HIGH 0x04000000L + +/* we have used 0fffffff - 4 bits left to go */ +#define SSL_ALL 0xffffffffL +#define SSL_ALL_CIPHERS (SSL_MKEY_MASK|SSL_AUTH_MASK|SSL_ENC_MASK|\ + SSL_MAC_MASK|SSL_EXP_MASK) + +/* Mostly for SSLv3 */ +#define SSL_PKEY_RSA_ENC 0 +#define SSL_PKEY_RSA_SIGN 1 +#define SSL_PKEY_DSA_SIGN 2 +#define SSL_PKEY_DH_RSA 3 +#define SSL_PKEY_DH_DSA 4 +#define SSL_PKEY_NUM 5 + +/* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) | + * <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN) + * SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN) + * SSL_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN + * SSL_aRSA <- RSA_ENC | RSA_SIGN + * SSL_aDSS <- DSA_SIGN + */ + +/* +#define CERT_INVALID 0 +#define CERT_PUBLIC_KEY 1 +#define CERT_PRIVATE_KEY 2 +*/ + +typedef struct cert_pkey_st + { + X509 *x509; +/* EVP_PKEY *publickey; *//* when extracted */ + EVP_PKEY *privatekey; + } CERT_PKEY; + +typedef struct cert_st + { + int cert_type; + +#ifdef undef + X509 *x509; + EVP_PKEY *publickey; /* when extracted */ + EVP_PKEY *privatekey; + + pkeys[SSL_PKEY_RSA_ENC].x509 +/* pkeys[SSL_PKEY_RSA_ENC].publickey */ + pkeys[SSL_PKEY_RSA_ENC].privatekey +#endif + + /* Current active set */ + CERT_PKEY *key; + + /* The following masks are for the key and auth + * algorithms that are supported by the certs below */ + int valid; + unsigned long mask; + unsigned long export_mask; + + RSA *rsa_tmp; + DH *dh_tmp; + RSA *(*rsa_tmp_cb)(); + DH *(*dh_tmp_cb)(); + CERT_PKEY pkeys[SSL_PKEY_NUM]; + + STACK *cert_chain; + + int references; + } CERT; + +/*#define MAC_DEBUG */ + +/*#define ERR_DEBUG */ +/*#define ABORT_DEBUG */ +/*#define PKT_DEBUG 1 */ +/*#define DES_DEBUG */ +/*#define DES_OFB_DEBUG */ +/*#define SSL_DEBUG */ +/*#define RSA_DEBUG */ +/*#define IDEA_DEBUG */ + +#ifndef NOPROTO +#define FP_ICC (int (*)(const void *,const void *)) +#else +#define FP_ICC +#endif + +#define ssl_put_cipher_by_char(ssl,ciph,ptr) \ + ((ssl)->method->put_cipher_by_char((ciph),(ptr))) +#define ssl_get_cipher_by_char(ssl,ptr) \ + ((ssl)->method->get_cipher_by_char(ptr)) + +extern unsigned char ssl3_client_finished_const[4]; +extern unsigned char ssl3_server_finished_const[4]; + +extern SSL_CIPHER ssl2_ciphers[]; +extern SSL_CIPHER ssl3_ciphers[]; + +#ifndef NOPROTO + +SSL_METHOD *ssl_bad_method(int ver); +SSL_METHOD *sslv2_base_method(void); +SSL_METHOD *sslv23_base_method(void); +SSL_METHOD *sslv3_base_method(void); + +void ssl_clear_cipher_ctx(SSL *s); +int ssl_clear_bad_session(SSL *s); +CERT *ssl_cert_new(void); +void ssl_cert_free(CERT *c); +int ssl_set_cert_type(CERT *c, int type); +int ssl_get_new_session(SSL *s, int session); +int ssl_get_prev_session(SSL *s, int len, unsigned char *session); +int ssl_cipher_id_cmp(SSL_CIPHER *a,SSL_CIPHER *b); +int ssl_cipher_ptr_id_cmp(SSL_CIPHER **ap,SSL_CIPHER **bp); +STACK *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,STACK **skp); +int ssl_cipher_list_to_bytes(SSL *s,STACK *sk,unsigned char *p); +STACK *ssl_create_cipher_list(SSL_METHOD *meth,STACK **pref, + STACK **sorted,char *str); +void ssl_update_cache(SSL *s, int mode); +int ssl_cipher_get_evp(SSL_CIPHER *c, EVP_CIPHER **enc, EVP_MD **md); +int ssl_verify_cert_chain(SSL *s,STACK *sk); +int ssl_undefined_function(SSL *s); +X509 *ssl_get_server_send_cert(SSL *); +EVP_PKEY *ssl_get_sign_pkey(SSL *,SSL_CIPHER *); +int ssl_cert_type(X509 *x,EVP_PKEY *pkey); +void ssl_set_cert_masks(CERT *c); +STACK *ssl_get_ciphers_by_id(SSL *s); +int ssl_verify_alarm_type(int type); + +int ssl2_enc_init(SSL *s, int client); +void ssl2_generate_key_material(SSL *s); +void ssl2_enc(SSL *s,int send_data); +void ssl2_mac(SSL *s,unsigned char *mac,int send_data); +SSL_CIPHER *ssl2_get_cipher_by_char(unsigned char *p); +int ssl2_put_cipher_by_char(SSL_CIPHER *c,unsigned char *p); +int ssl2_part_read(SSL *s, unsigned long f, int i); +int ssl2_do_write(SSL *s); +int ssl2_set_certificate(SSL *s, int type, int len, unsigned char *data); +void ssl2_return_error(SSL *s,int reason); +void ssl2_write_error(SSL *s); +int ssl2_num_ciphers(void); +SSL_CIPHER *ssl2_get_cipher(unsigned int u); +int ssl2_new(SSL *s); +void ssl2_free(SSL *s); +int ssl2_accept(SSL *s); +int ssl2_connect(SSL *s); +int ssl2_read(SSL *s, char *buf, int len); +int ssl2_peek(SSL *s, char *buf, int len); +int ssl2_write(SSL *s, const char *buf, int len); +int ssl2_shutdown(SSL *s); +void ssl2_clear(SSL *s); +long ssl2_ctrl(SSL *s,int cmd, long larg, char *parg); +long ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, char *parg); +int ssl2_pending(SSL *s); + +SSL_CIPHER *ssl3_get_cipher_by_char(unsigned char *p); +int ssl3_put_cipher_by_char(SSL_CIPHER *c,unsigned char *p); +void ssl3_init_finished_mac(SSL *s); +int ssl3_send_server_certificate(SSL *s); +int ssl3_get_finished(SSL *s,int state_a,int state_b,unsigned char *sender); +int ssl3_setup_key_block(SSL *s); +int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b); +int ssl3_change_cipher_state(SSL *s,int which); +void ssl3_cleanup_key_block(SSL *s); +int ssl3_do_write(SSL *s,int type); +void ssl3_send_alert(SSL *s,int level, int desc); +int ssl3_generate_master_secret(SSL *s, unsigned char *out, + unsigned char *p, int len); +int ssl3_get_req_cert_type(SSL *s,unsigned char *p); +long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); +int ssl3_send_finished(SSL *s, int a, int b, unsigned char *sender); +int ssl3_num_ciphers(void); +SSL_CIPHER *ssl3_get_cipher(unsigned int u); +int ssl3_renegotiate(SSL *ssl); +int ssl3_dispatch_alert(SSL *s); +int ssl3_read_bytes(SSL *s, int type, char *buf, int len); +void ssl3_generate_key_block(SSL *s, unsigned char *km, int num); +int ssl3_part_read(SSL *s, int i); +int ssl3_write_bytes(SSL *s, int type, char *buf, int len); +int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *in_ctx, + unsigned char *sender, unsigned char *p); +void ssl3_finish_mac(SSL *s, unsigned char *buf, int len); +int ssl3_enc(SSL *s, int send_data); +int ssl3_mac(SSL *ssl, unsigned char *md, int send_data); +unsigned long ssl3_output_cert_chain(SSL *s, X509 *x); +SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK *have,STACK *pref); +int ssl3_setup_buffers(SSL *s); +int ssl3_new(SSL *s); +void ssl3_free(SSL *s); +int ssl3_accept(SSL *s); +int ssl3_connect(SSL *s); +int ssl3_read(SSL *s, char *buf, int len); +int ssl3_peek(SSL *s,char *buf, int len); +int ssl3_write(SSL *s, const char *buf, int len); +int ssl3_shutdown(SSL *s); +void ssl3_clear(SSL *s); +long ssl3_ctrl(SSL *s,int cmd, long larg, char *parg); +long ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, char *parg); +int ssl3_pending(SSL *s); + +int ssl23_accept(SSL *s); +int ssl23_connect(SSL *s); +int ssl23_read_bytes(SSL *s, int n); +int ssl23_write_bytes(SSL *s); + +#else + +SSL_METHOD *ssl_bad_method(); +SSL_METHOD *sslv2_base_method(); +SSL_METHOD *sslv23_base_method(); +SSL_METHOD *sslv3_base_method(); + +void ssl_clear_cipher_ctx(); +int ssl_clear_bad_session(); +CERT *ssl_cert_new(); +void ssl_cert_free(); +int ssl_set_cert_type(); +int ssl_get_new_session(); +int ssl_get_prev_session(); +int ssl_cipher_id_cmp(); +int ssl_cipher_ptr_id_cmp(); +STACK *ssl_bytes_to_cipher_list(); +int ssl_cipher_list_to_bytes(); +STACK *ssl_create_cipher_list(); +void ssl_update_cache(); +int ssl_session_get_ciphers(); +int ssl_verify_cert_chain(); +int ssl_undefined_function(); +X509 *ssl_get_server_send_cert(); +EVP_PKEY *ssl_get_sign_pkey(); +int ssl_cert_type(); +void ssl_set_cert_masks(); +STACK *ssl_get_ciphers_by_id(); +int ssl_verify_alarm_type(); + +int ssl2_enc_init(); +void ssl2_generate_key_material(); +void ssl2_enc(); +void ssl2_mac(); +SSL_CIPHER *ssl2_get_cipher_by_char(); +int ssl2_put_cipher_by_char(); +int ssl2_part_read(); +int ssl2_do_write(); +int ssl2_set_certificate(); +void ssl2_return_error(); +void ssl2_write_error(); +int ssl2_num_ciphers(); +SSL_CIPHER *ssl2_get_cipher(); +int ssl2_new(); +void ssl2_free(); +int ssl2_accept(); +int ssl2_connect(); +int ssl2_read(); +int ssl2_peek(); +int ssl2_write(); +int ssl2_shutdown(); +void ssl2_clear(); +long ssl2_ctrl(); +long ssl2_ctx_ctrl(); +int ssl2_pending(); + +SSL_CIPHER *ssl3_get_cipher_by_char(); +int ssl3_put_cipher_by_char(); +void ssl3_init_finished_mac(); +int ssl3_send_server_certificate(); +int ssl3_get_finished(); +int ssl3_setup_key_block(); +int ssl3_send_change_cipher_spec(); +int ssl3_change_cipher_state(); +void ssl3_cleanup_key_block(); +int ssl3_do_write(); +void ssl3_send_alert(); +int ssl3_generate_master_secret(); +int ssl3_get_req_cert_type(); +long ssl3_get_message(); +int ssl3_send_finished(); +int ssl3_num_ciphers(); +SSL_CIPHER *ssl3_get_cipher(); +int ssl3_renegotiate(); +int ssl3_dispatch_alert(); +int ssl3_read_bytes(); +void ssl3_generate_key_block(); +int ssl3_part_read(); +int ssl3_write_bytes(); +int ssl3_final_finish_mac(); +void ssl3_finish_mac(); +int ssl3_enc(); +int ssl3_mac(); +unsigned long ssl3_output_cert_chain(); +SSL_CIPHER *ssl3_choose_cipher(); +int ssl3_setup_buffers(); +int ssl3_new(); +void ssl3_free(); +int ssl3_accept(); +int ssl3_connect(); +int ssl3_read(); +int ssl3_peek(); +int ssl3_write(); +int ssl3_shutdown(); +void ssl3_clear(); +long ssl3_ctrl(); +long ssl3_ctx_ctrl(); +int ssl3_pending(); + +int ssl23_accept(); +int ssl23_connect(); +int ssl23_read_bytes(); +int ssl23_write_bytes(); + +#endif + +#endif diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c new file mode 100644 index 0000000000..3a7b8d3c36 --- /dev/null +++ b/ssl/ssl_rsa.c @@ -0,0 +1,840 @@ +/* ssl/ssl_rsa.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "bio.h" +#include "objects.h" +#include "evp.h" +#include "x509.h" +#include "pem.h" +#include "ssl_locl.h" + +#ifndef NOPROTO +static int ssl_set_cert(CERT *c, X509 *x509); +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); +#else +static int ssl_set_cert(); +static int ssl_set_pkey(); +#endif + +int SSL_use_certificate(ssl, x) +SSL *ssl; +X509 *x; + { + CERT *c; + + if (x == NULL) + { + SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert)) + { + c=ssl_cert_new(); + if (c == NULL) + { + SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); + return(0); + } + if (ssl->cert != NULL) ssl_cert_free(ssl->cert); + ssl->cert=c; + } + c=ssl->cert; + + return(ssl_set_cert(c,x)); + } + +int SSL_use_certificate_file(ssl, file, type) +SSL *ssl; +char *file; +int type; + { + int j; + BIO *in; + int ret=0; + X509 *x=NULL; + +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if (in == NULL) + { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SYSerr(SYS_F_FOPEN,errno); + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) + { + j=ERR_R_ASN1_LIB; + x=d2i_X509_bio(in,NULL); + } + else if (type == SSL_FILETYPE_PEM) + { + j=ERR_R_PEM_LIB; + x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback); + } + else + { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) + { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,j); + goto end; + } + + ret=SSL_use_certificate(ssl,x); +end: + if (x != NULL) X509_free(x); + if (in != NULL) BIO_free(in); + return(ret); + } + +int SSL_use_certificate_ASN1(ssl, len, d) +SSL *ssl; +int len; +unsigned char *d; + { + X509 *x; + int ret; + + x=d2i_X509(NULL,&d,(long)len); + if (x == NULL) + { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1,ERR_R_ASN1_LIB); + return(0); + } + + ret=SSL_use_certificate(ssl,x); + X509_free(x); + return(ret); + } + +#ifndef NO_RSA +int SSL_use_RSAPrivateKey(ssl, rsa) +SSL *ssl; +RSA *rsa; + { + CERT *c; + EVP_PKEY *pkey; + int ret; + + if (rsa == NULL) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + + if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert)) + { + c=ssl_cert_new(); + if (c == NULL) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); + } + if (ssl->cert != NULL) ssl_cert_free(ssl->cert); + ssl->cert=c; + } + c=ssl->cert; + if ((pkey=EVP_PKEY_new()) == NULL) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); + return(0); + } + + CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + EVP_PKEY_assign_RSA(pkey,rsa); + + ret=ssl_set_pkey(c,pkey); + EVP_PKEY_free(pkey); + return(ret); + } +#endif + +static int ssl_set_pkey(c,pkey) +CERT *c; +EVP_PKEY *pkey; + { + int i,ok=0,bad=0; + + i=ssl_cert_type(NULL,pkey); + if (i < 0) + { + SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return(0); + } + + if (c->pkeys[i].x509 != NULL) + { + if (!X509_check_private_key(c->pkeys[i].x509,pkey)) + { + if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA)) + { + i=(i == SSL_PKEY_DH_RSA)? + SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA; + + if (c->pkeys[i].x509 == NULL) + ok=1; + else + { + if (!X509_check_private_key( + c->pkeys[i].x509,pkey)) + bad=1; + else + ok=1; + } + } + else + bad=1; + } + else + ok=1; + } + else + ok=1; + + if (bad) + { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509=NULL; + return(0); + } + + if (c->pkeys[i].privatekey != NULL) + EVP_PKEY_free(c->pkeys[i].privatekey); + CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); + c->pkeys[i].privatekey=pkey; + c->key= &(c->pkeys[i]); + + c->valid=0; + return(1); + } + +#ifndef NO_RSA +int SSL_use_RSAPrivateKey_file(ssl, file, type) +SSL *ssl; +char *file; +int type; + { + int j,ret=0; + BIO *in; + RSA *rsa=NULL; + +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if (in == NULL) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SYSerr(SYS_F_FOPEN,errno); + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) + { + j=ERR_R_ASN1_LIB; + rsa=d2i_RSAPrivateKey_bio(in,NULL); + } + else if (type == SSL_FILETYPE_PEM) + { + j=ERR_R_PEM_LIB; + rsa=PEM_read_bio_RSAPrivateKey(in,NULL, + ssl->ctx->default_passwd_callback); + } + else + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (rsa == NULL) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,j); + goto end; + } + ret=SSL_use_RSAPrivateKey(ssl,rsa); + RSA_free(rsa); +end: + if (in != NULL) BIO_free(in); + return(ret); + } + +int SSL_use_RSAPrivateKey_ASN1(ssl,d,len) +SSL *ssl; +unsigned char *d; +long len; + { + int ret; + unsigned char *p; + RSA *rsa; + + p=d; + if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1,ERR_R_ASN1_LIB); + return(0); + } + + ret=SSL_use_RSAPrivateKey(ssl,rsa); + RSA_free(rsa); + return(ret); + } +#endif /* !NO_RSA */ + +int SSL_use_PrivateKey(ssl, pkey) +SSL *ssl; +EVP_PKEY *pkey; + { + CERT *c; + int ret; + + if (pkey == NULL) + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + + if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert)) + { + c=ssl_cert_new(); + if (c == NULL) + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); + } + if (ssl->cert != NULL) ssl_cert_free(ssl->cert); + ssl->cert=c; + } + c=ssl->cert; + + ret=ssl_set_pkey(c,pkey); + return(ret); + } + +int SSL_use_PrivateKey_file(ssl, file, type) +SSL *ssl; +char *file; +int type; + { + int j,ret=0; + BIO *in; + EVP_PKEY *pkey=NULL; + +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if (in == NULL) + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SYSerr(SYS_F_FOPEN,errno); + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) + { + j=ERR_R_PEM_LIB; + pkey=PEM_read_bio_PrivateKey(in,NULL, + ssl->ctx->default_passwd_callback); + } + else + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,j); + goto end; + } + ret=SSL_use_PrivateKey(ssl,pkey); + EVP_PKEY_free(pkey); +end: + if (in != NULL) BIO_free(in); + return(ret); + } + +int SSL_use_PrivateKey_ASN1(type,ssl,d,len) +int type; +SSL *ssl; +unsigned char *d; +long len; + { + int ret; + unsigned char *p; + EVP_PKEY *pkey; + + p=d; + if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL) + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1,ERR_R_ASN1_LIB); + return(0); + } + + ret=SSL_use_PrivateKey(ssl,pkey); + EVP_PKEY_free(pkey); + return(ret); + } + +int SSL_CTX_use_certificate(ctx, x) +SSL_CTX *ctx; +X509 *x; + { + CERT *c; + + if (x == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + + if (ctx->default_cert == NULL) + { + c=ssl_cert_new(); + if (c == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); + return(0); + } + ctx->default_cert=c; + } + c=ctx->default_cert; + + return(ssl_set_cert(c,x)); + } + +static int ssl_set_cert(c,x) +CERT *c; +X509 *x; + { + EVP_PKEY *pkey; + int i,ok=0,bad=0; + + pkey=X509_get_pubkey(x); + if (pkey == NULL) + { + SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_X509_LIB); + return(0); + } + + i=ssl_cert_type(x,pkey); + if (i < 0) + { + SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return(0); + } + + if (c->pkeys[i].privatekey != NULL) + { + if (!X509_check_private_key(x,c->pkeys[i].privatekey)) + { + if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA)) + { + i=(i == SSL_PKEY_DH_RSA)? + SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA; + + if (c->pkeys[i].privatekey == NULL) + ok=1; + else + { + if (!X509_check_private_key(x, + c->pkeys[i].privatekey)) + bad=1; + else + ok=1; + } + } + else + bad=1; + } + else + ok=1; + } + else + ok=1; + + if (bad) + { + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey=NULL; + } + + if (c->pkeys[i].x509 != NULL) + X509_free(c->pkeys[i].x509); + CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); + c->pkeys[i].x509=x; + c->key= &(c->pkeys[i]); + + c->valid=0; + return(1); + } + +int SSL_CTX_use_certificate_file(ctx, file, type) +SSL_CTX *ctx; +char *file; +int type; + { + int j; + BIO *in; + int ret=0; + X509 *x=NULL; + +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if (in == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SYSerr(SYS_F_FOPEN,errno); + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) + { + j=ERR_R_ASN1_LIB; + x=d2i_X509_bio(in,NULL); + } + else if (type == SSL_FILETYPE_PEM) + { + j=ERR_R_PEM_LIB; + x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback); + } + else + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,j); + goto end; + } + + ret=SSL_CTX_use_certificate(ctx,x); +end: + if (x != NULL) X509_free(x); + if (in != NULL) BIO_free(in); + return(ret); + } + +int SSL_CTX_use_certificate_ASN1(ctx, len, d) +SSL_CTX *ctx; +int len; +unsigned char *d; + { + X509 *x; + int ret; + + x=d2i_X509(NULL,&d,(long)len); + if (x == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,ERR_R_ASN1_LIB); + return(0); + } + + ret=SSL_CTX_use_certificate(ctx,x); + X509_free(x); + return(ret); + } + +#ifndef NO_RSA +int SSL_CTX_use_RSAPrivateKey(ctx, rsa) +SSL_CTX *ctx; +RSA *rsa; + { + int ret; + CERT *c; + EVP_PKEY *pkey; + + if (rsa == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if (ctx->default_cert == NULL) + { + c=ssl_cert_new(); + if (c == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); + } + ctx->default_cert=c; + } + c=ctx->default_cert; + + if ((pkey=EVP_PKEY_new()) == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); + return(0); + } + + CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + EVP_PKEY_assign_RSA(pkey,rsa); + + ret=ssl_set_pkey(c,pkey); + EVP_PKEY_free(pkey); + return(ret); + } + +int SSL_CTX_use_RSAPrivateKey_file(ctx, file, type) +SSL_CTX *ctx; +char *file; +int type; + { + int j,ret=0; + BIO *in; + RSA *rsa=NULL; + +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if (in == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SYSerr(SYS_F_FOPEN,errno); + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) + { + j=ERR_R_ASN1_LIB; + rsa=d2i_RSAPrivateKey_bio(in,NULL); + } + else if (type == SSL_FILETYPE_PEM) + { + j=ERR_R_PEM_LIB; + rsa=PEM_read_bio_RSAPrivateKey(in,NULL, + ctx->default_passwd_callback); + } + else + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (rsa == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,j); + goto end; + } + ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa); + RSA_free(rsa); +end: + if (in != NULL) BIO_free(in); + return(ret); + } + +int SSL_CTX_use_RSAPrivateKey_ASN1(ctx,d,len) +SSL_CTX *ctx; +unsigned char *d; +long len; + { + int ret; + unsigned char *p; + RSA *rsa; + + p=d; + if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1,ERR_R_ASN1_LIB); + return(0); + } + + ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa); + RSA_free(rsa); + return(ret); + } +#endif /* !NO_RSA */ + +int SSL_CTX_use_PrivateKey(ctx, pkey) +SSL_CTX *ctx; +EVP_PKEY *pkey; + { + CERT *c; + + if (pkey == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + + if (ctx->default_cert == NULL) + { + c=ssl_cert_new(); + if (c == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); + } + ctx->default_cert=c; + } + c=ctx->default_cert; + + return(ssl_set_pkey(c,pkey)); + } + +int SSL_CTX_use_PrivateKey_file(ctx, file, type) +SSL_CTX *ctx; +char *file; +int type; + { + int j,ret=0; + BIO *in; + EVP_PKEY *pkey=NULL; + +#ifdef WIN16 + in=BIO_new(BIO_s_file_internal_w16()); +#else + in=BIO_new(BIO_s_file()); +#endif + if (in == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SYSerr(SYS_F_FOPEN,errno); + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) + { + j=ERR_R_PEM_LIB; + pkey=PEM_read_bio_PrivateKey(in,NULL, + ctx->default_passwd_callback); + } + else + { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,j); + goto end; + } + ret=SSL_CTX_use_PrivateKey(ctx,pkey); + EVP_PKEY_free(pkey); +end: + if (in != NULL) BIO_free(in); + return(ret); + } + +int SSL_CTX_use_PrivateKey_ASN1(type,ctx,d,len) +int type; +SSL_CTX *ctx; +unsigned char *d; +long len; + { + int ret; + unsigned char *p; + EVP_PKEY *pkey; + + p=d; + if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,ERR_R_ASN1_LIB); + return(0); + } + + ret=SSL_CTX_use_PrivateKey(ctx,pkey); + EVP_PKEY_free(pkey); + return(ret); + } + + diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c new file mode 100644 index 0000000000..af65c65dac --- /dev/null +++ b/ssl/ssl_sess.c @@ -0,0 +1,425 @@ +/* ssl/ssl_sess.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "lhash.h" +#include "rand.h" +#include "ssl_locl.h" + +SSL_SESSION *SSL_SESSION_new() + { + SSL_SESSION *ss; + + ss=(SSL_SESSION *)Malloc(sizeof(SSL_SESSION)); + if (ss == NULL) + { + SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE); + return(0); + } + memset(ss,0,sizeof(SSL_SESSION)); + + ss->references=1; + ss->timeout=60*5+4; /* 5 minute timeout by default */ + ss->time=time(NULL); + return(ss); + } + +int ssl_get_new_session(s, session) +SSL *s; +int session; + { + SSL_SESSION *ss=NULL; + + if ((ss=SSL_SESSION_new()) == NULL) return(0); + + /* If the context has a default timeout, use it */ + if (s->ctx->session_timeout != 0) + ss->timeout=SSL_get_default_timeout(s); + + if (s->session != NULL) + { + SSL_SESSION_free(s->session); + s->session=NULL; + } + + if (session) + { + if (s->version == SSL2_CLIENT_VERSION) + { + ss->ssl_version=2; + ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; + } + else if (s->version == SSL3_VERSION_MAJOR) + { + ss->ssl_version=3; + ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; + } + else + { + SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION); + SSL_SESSION_free(ss); + return(0); + } + + for (;;) + { + SSL_SESSION *r; + + RAND_bytes(ss->session_id,ss->session_id_length); + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions, + (char *)ss); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + if (r == NULL) break; + /* else - woops a session_id match */ + } + } + else + { + ss->session_id_length=0; + } + + s->session=ss; + ss->ssl_version=s->version; + + return(1); + } + +int ssl_get_prev_session(s, len, session) +SSL *s; +int len; +unsigned char *session; + { + SSL_SESSION *ret,data; + + /* conn_init();*/ + data.ssl_version=s->version; + data.session_id_length=len; + if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) + return(0); + memcpy(data.session_id,session,len);; + + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + + if (ret == NULL) + { + int copy=1; + + s->ctx->sess_miss++; + ret=NULL; + if ((s->ctx->get_session_cb != NULL) && + ((ret=s->ctx->get_session_cb(s,session,len,©)) + != NULL)) + { + s->ctx->sess_cb_hit++; + + /* The following should not return 1, otherwise, + * things are very strange */ + SSL_CTX_add_session(s->ctx,ret); + /* auto free it */ + if (!copy) + SSL_SESSION_free(ret); + } + if (ret == NULL) return(0); + } + + if (ret->cipher == NULL) + { + char buf[5],*p; + unsigned long l; + + p=buf; + l=ret->cipher_id; + l2n(l,p); + if (ret->ssl_version == 3) + ret->cipher=ssl_get_cipher_by_char(s,&(buf[2])); + else + ret->cipher=ssl_get_cipher_by_char(s,&(buf[1])); + if (ret->cipher == NULL) + return(0); + } + + /* If a thread got the session, then 'swaped', and another got + * it and then due to a time-out decided to 'Free' it we could + * be in trouble. So I'll increment it now, then double decrement + * later - am I speaking rubbish?. */ + CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); + + if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */ + { + s->ctx->sess_timeout++; + /* remove it from the cache */ + SSL_CTX_remove_session(s->ctx,ret); + SSL_SESSION_free(ret); /* again to actually Free it */ + return(0); + } + + s->ctx->sess_hit++; + + /* ret->time=time(NULL); */ /* rezero timeout? */ + /* again, just leave the session + * if it is the same session, we have just incremented and + * then decremented the reference count :-) */ + if (s->session != NULL) + SSL_SESSION_free(s->session); + s->session=ret; + return(1); + } + +int SSL_CTX_add_session(ctx,c) +SSL_CTX *ctx; +SSL_SESSION *c; + { + SSL_SESSION *s; + + /* conn_init(); */ + CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); + + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + + /* If the same session if is being 're-added', Free the old + * one when the last person stops using it. + * This will also work if it is alread in the cache. + * The references will go up and then down :-) */ + if (s != NULL) + { + SSL_SESSION_free(s); + return(0); + } + else + return(1); + } + +int SSL_CTX_remove_session(ctx,c) +SSL_CTX *ctx; +SSL_SESSION *c; + { + SSL_SESSION *r; + int ret=0; + + if ((c->session_id_length != 0) && (c != NULL)) + { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c); + if (r != NULL) ret=1; + + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + + if (ret) + { + r->not_resumable=1; + if (ctx->remove_session_cb != NULL) + ctx->remove_session_cb(ctx,c); + SSL_SESSION_free(r); + } + } + else + ret=0; + return(ret); + } + +void SSL_SESSION_free(ss) +SSL_SESSION *ss; + { + int i; + + i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"SSL_SESSION_free, bad reference count\n"); + abort(); /* ok */ + } +#endif + + memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); + memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); + memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH); + if (ss->cert != NULL) ssl_cert_free(ss->cert); + if (ss->peer != NULL) X509_free(ss->peer); + if (ss->ciphers != NULL) sk_free(ss->ciphers); + memset(ss,0,sizeof(*ss)); + Free(ss); + } + +int SSL_set_session(s, session) +SSL *s; +SSL_SESSION *session; + { + int ret=0; + SSL_METHOD *meth; + + if (session != NULL) + { + meth=s->ctx->method->get_ssl_method(session->ssl_version); + if (meth == NULL) + meth=s->method->get_ssl_method(session->ssl_version); + if (meth == NULL) + { + SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD); + return(0); + } + + if (meth != s->method) + { + if (!SSL_set_ssl_method(s,meth)) + return(0); + session->timeout=SSL_get_default_timeout(s); + } + + /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ + CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); + if (s->session != NULL) + SSL_SESSION_free(s->session); + s->session=session; + /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/ + ret=1; + } + return(ret); + } + +long SSL_set_timeout(s,t) +SSL_SESSION *s; +long t; + { + if (s == NULL) return(0); + s->timeout=t; + return(1); + } + +long SSL_get_timeout(s) +SSL_SESSION *s; + { + if (s == NULL) return(0); + return(s->timeout); + } + +long SSL_get_time(s) +SSL_SESSION *s; + { + if (s == NULL) return(0); + return(s->time); + } + +long SSL_set_time(s,t) +SSL_SESSION *s; +long t; + { + if (s == NULL) return(0); + s->time=t; + return(t); + } + +typedef struct timeout_param_st + { + SSL_CTX *ctx; + long time; + LHASH *cache; + } TIMEOUT_PARAM; + +static void timeout(s,p) +SSL_SESSION *s; +TIMEOUT_PARAM *p; + { + if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */ + { + lh_delete(p->cache,(char *)s); + s->not_resumable=1; + if (p->ctx->remove_session_cb != NULL) + p->ctx->remove_session_cb(p->ctx,s); + SSL_SESSION_free(s); + } + } + +void SSL_CTX_flush_sessions(s,t) +SSL_CTX *s; +long t; + { + unsigned long i; + TIMEOUT_PARAM tp; + + tp.ctx=s; + tp.cache=SSL_CTX_sessions(s); + if (tp.cache == NULL) return; + tp.time=t; + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + i=tp.cache->down_load; + tp.cache->down_load=0; + lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp); + tp.cache->down_load=i; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } + +int ssl_clear_bad_session(s) +SSL *s; + { + if ( (s->session != NULL) && + !(s->shutdown & SSL_SENT_SHUTDOWN) && + !(SSL_in_init(s) || SSL_in_before(s))) + { + SSL_CTX_remove_session(s->ctx,s->session); + return(1); + } + else + return(0); + } diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c new file mode 100644 index 0000000000..328ccc94ff --- /dev/null +++ b/ssl/ssl_stat.c @@ -0,0 +1,457 @@ +/* ssl/ssl_stat.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "ssl_locl.h" + +char *SSL_state_string_long(s) +SSL *s; + { + char *str; + + switch (s->state) + { +case SSL_ST_BEFORE: str="before SSL initalisation"; break; +case SSL_ST_ACCEPT: str="before accept initalisation"; break; +case SSL_ST_CONNECT: str="before connect initalisation"; break; +case SSL_ST_OK: str="SSL negotiation finished successfully"; break; +case SSL_ST_RENEGOTIATE: str="SSL renegotiate ciphers"; break; +case SSL_ST_BEFORE|SSL_ST_CONNECT: str="before/connect initalisation"; break; +case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initalisation"; break; +case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initalisation"; break; +case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initalisation"; break; +#ifndef NO_SSL2 +case SSL2_ST_CLIENT_START_ENCRYPTION: str="SSLv2 client start encryption"; break; +case SSL2_ST_SERVER_START_ENCRYPTION: str="SSLv2 server start encryption"; break; +case SSL2_ST_SEND_CLIENT_HELLO_A: str="SSLv2 write client hello A"; break; +case SSL2_ST_SEND_CLIENT_HELLO_B: str="SSLv2 write client hello B"; break; +case SSL2_ST_GET_SERVER_HELLO_A: str="SSLv2 read server hello A"; break; +case SSL2_ST_GET_SERVER_HELLO_B: str="SSLv2 read server hello B"; break; +case SSL2_ST_SEND_CLIENT_MASTER_KEY_A: str="SSLv2 write client master key A"; break; +case SSL2_ST_SEND_CLIENT_MASTER_KEY_B: str="SSLv2 write client master key B"; break; +case SSL2_ST_SEND_CLIENT_FINISHED_A: str="SSLv2 write client finished A"; break; +case SSL2_ST_SEND_CLIENT_FINISHED_B: str="SSLv2 write client finished B"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_A: str="SSLv2 write client certificate A"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_B: str="SSLv2 write client certificate B"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_C: str="SSLv2 write client certificate C"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_D: str="SSLv2 write client certificate D"; break; +case SSL2_ST_GET_SERVER_VERIFY_A: str="SSLv2 read server verify A"; break; +case SSL2_ST_GET_SERVER_VERIFY_B: str="SSLv2 read server verify B"; break; +case SSL2_ST_GET_SERVER_FINISHED_A: str="SSLv2 read server finished A"; break; +case SSL2_ST_GET_SERVER_FINISHED_B: str="SSLv2 read server finished B"; break; +case SSL2_ST_GET_CLIENT_HELLO_A: str="SSLv2 read client hello A"; break; +case SSL2_ST_GET_CLIENT_HELLO_B: str="SSLv2 read client hello B"; break; +case SSL2_ST_GET_CLIENT_HELLO_C: str="SSLv2 read client hello C"; break; +case SSL2_ST_SEND_SERVER_HELLO_A: str="SSLv2 write server hello A"; break; +case SSL2_ST_SEND_SERVER_HELLO_B: str="SSLv2 write server hello B"; break; +case SSL2_ST_GET_CLIENT_MASTER_KEY_A: str="SSLv2 read client master key A"; break; +case SSL2_ST_GET_CLIENT_MASTER_KEY_B: str="SSLv2 read client master key B"; break; +case SSL2_ST_SEND_SERVER_VERIFY_A: str="SSLv2 write server verify A"; break; +case SSL2_ST_SEND_SERVER_VERIFY_B: str="SSLv2 write server verify B"; break; +case SSL2_ST_SEND_SERVER_VERIFY_C: str="SSLv2 write server verify C"; break; +case SSL2_ST_GET_CLIENT_FINISHED_A: str="SSLv2 read client finished A"; break; +case SSL2_ST_GET_CLIENT_FINISHED_B: str="SSLv2 read client finished B"; break; +case SSL2_ST_SEND_SERVER_FINISHED_A: str="SSLv2 write server finished A"; break; +case SSL2_ST_SEND_SERVER_FINISHED_B: str="SSLv2 write server finished B"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_A: str="SSLv2 write request certificate A"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_B: str="SSLv2 write request certificate B"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_C: str="SSLv2 write request certificate C"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_D: str="SSLv2 write request certificate D"; break; +case SSL2_ST_X509_GET_SERVER_CERTIFICATE: str="SSLv2 X509 read server certificate"; break; +case SSL2_ST_X509_GET_CLIENT_CERTIFICATE: str="SSLv2 X509 read client certificate"; break; +#endif + +#ifndef NO_SSL3 +/* SSLv3 additions */ +case SSL3_ST_CW_CLNT_HELLO_A: str="SSLv3 write client hello A"; break; +case SSL3_ST_CW_CLNT_HELLO_B: str="SSLv3 write client hello B"; break; +case SSL3_ST_CR_SRVR_HELLO_A: str="SSLv3 read server hello A"; break; +case SSL3_ST_CR_SRVR_HELLO_B: str="SSLv3 read server hello B"; break; +case SSL3_ST_CR_CERT_A: str="SSLv3 read server certificate A"; break; +case SSL3_ST_CR_CERT_B: str="SSLv3 read server certificate B"; break; +case SSL3_ST_CR_KEY_EXCH_A: str="SSLv3 read server key exchange A"; break; +case SSL3_ST_CR_KEY_EXCH_B: str="SSLv3 read server key exchange B"; break; +case SSL3_ST_CR_CERT_REQ_A: str="SSLv3 read server certificate request A"; break; +case SSL3_ST_CR_CERT_REQ_B: str="SSLv3 read server certificate request B"; break; +case SSL3_ST_CR_SRVR_DONE_A: str="SSLv3 read server done A"; break; +case SSL3_ST_CR_SRVR_DONE_B: str="SSLv3 read server done B"; break; +case SSL3_ST_CW_CERT_A: str="SSLv3 write client certificate A"; break; +case SSL3_ST_CW_CERT_B: str="SSLv3 write client certificate B"; break; +case SSL3_ST_CW_KEY_EXCH_A: str="SSLv3 write client key exchange A"; break; +case SSL3_ST_CW_KEY_EXCH_B: str="SSLv3 write client key exchange B"; break; +case SSL3_ST_CW_CERT_VRFY_A: str="SSLv3 write certificate verify A"; break; +case SSL3_ST_CW_CERT_VRFY_B: str="SSLv3 write certificate verify A"; break; + +case SSL3_ST_CW_CHANGE_A: +case SSL3_ST_SW_CHANGE_A: str="SSLv3 write change cipher spec A"; break; +case SSL3_ST_CW_CHANGE_B: +case SSL3_ST_SW_CHANGE_B: str="SSLv3 write change cipher spec B"; break; +case SSL3_ST_CW_FINISHED_A: +case SSL3_ST_SW_FINISHED_A: str="SSLv3 write finished A"; break; +case SSL3_ST_CW_FINISHED_B: +case SSL3_ST_SW_FINISHED_B: str="SSLv3 write finished A"; break; +case SSL3_ST_CR_CHANGE_A: +case SSL3_ST_SR_CHANGE_A: str="SSLv3 read change cipher spec A"; break; +case SSL3_ST_CR_CHANGE_B: +case SSL3_ST_SR_CHANGE_B: str="SSLv3 read change cipher spec B"; break; +case SSL3_ST_CR_FINISHED_A: +case SSL3_ST_SR_FINISHED_A: str="SSLv3 read finished A"; break; +case SSL3_ST_CR_FINISHED_B: +case SSL3_ST_SR_FINISHED_B: str="SSLv3 read finished B"; break; + +case SSL3_ST_CW_FLUSH: +case SSL3_ST_SW_FLUSH: str="SSLv3 flush data"; break; + +case SSL3_ST_SR_CLNT_HELLO_A: str="SSLv3 read client hello A"; break; +case SSL3_ST_SR_CLNT_HELLO_B: str="SSLv3 read client hello B"; break; +case SSL3_ST_SR_CLNT_HELLO_C: str="SSLv3 read client hello C"; break; +case SSL3_ST_SW_HELLO_REQ_A: str="SSLv3 write hello request A"; break; +case SSL3_ST_SW_HELLO_REQ_B: str="SSLv3 write hello request B"; break; +case SSL3_ST_SW_HELLO_REQ_C: str="SSLv3 write hello request C"; break; +case SSL3_ST_SW_SRVR_HELLO_A: str="SSLv3 write server hello A"; break; +case SSL3_ST_SW_SRVR_HELLO_B: str="SSLv3 write server hello B"; break; +case SSL3_ST_SW_CERT_A: str="SSLv3 write certificate A"; break; +case SSL3_ST_SW_CERT_B: str="SSLv3 write certificate B"; break; +case SSL3_ST_SW_KEY_EXCH_A: str="SSLv3 write key exchange A"; break; +case SSL3_ST_SW_KEY_EXCH_B: str="SSLv3 write key exchange B"; break; +case SSL3_ST_SW_CERT_REQ_A: str="SSLv3 write certificate request A"; break; +case SSL3_ST_SW_CERT_REQ_B: str="SSLv3 write certificate request B"; break; +case SSL3_ST_SW_SRVR_DONE_A: str="SSLv3 write server done A"; break; +case SSL3_ST_SW_SRVR_DONE_B: str="SSLv3 write server done B"; break; +case SSL3_ST_SR_CERT_A: str="SSLv3 read client certificate A"; break; +case SSL3_ST_SR_CERT_B: str="SSLv3 read client certificate B"; break; +case SSL3_ST_SR_KEY_EXCH_A: str="SSLv3 read client key exchange A"; break; +case SSL3_ST_SR_KEY_EXCH_B: str="SSLv3 read client key exchange B"; break; +case SSL3_ST_SR_CERT_VRFY_A: str="SSLv3 read certificate verify A"; break; +case SSL3_ST_SR_CERT_VRFY_B: str="SSLv3 read certificate verify B"; break; +#endif + +#if !defined(NO_SSL2) && !defined(NO_SSL3) +/* SSLv2/v3 compatablitity states */ +/* client */ +case SSL23_ST_CW_CLNT_HELLO_A: str="SSLv2/v3 write client hello A"; break; +case SSL23_ST_CW_CLNT_HELLO_B: str="SSLv2/v3 write client hello B"; break; +case SSL23_ST_CR_SRVR_HELLO_A: str="SSLv2/v3 read server hello A"; break; +case SSL23_ST_CR_SRVR_HELLO_B: str="SSLv2/v3 read server hello B"; break; +/* server */ +case SSL23_ST_SR_CLNT_HELLO_A: str="SSLv2/v3 read client hello A"; break; +case SSL23_ST_SR_CLNT_HELLO_B: str="SSLv2/v3 read client hello B"; break; +#endif + +default: str="unknown state"; break; + } + return(str); + } + +char *SSL_rstate_string_long(s) +SSL *s; + { + char *str; + + switch (s->rstate) + { + case SSL_ST_READ_HEADER: str="read header"; break; + case SSL_ST_READ_BODY: str="read body"; break; + default: str="unknown"; break; + } + return(str); + } + +char *SSL_state_string(s) +SSL *s; + { + char *str; + + switch (s->state) + { +case SSL_ST_BEFORE: str="PINIT "; break; +case SSL_ST_ACCEPT: str="AINIT "; break; +case SSL_ST_CONNECT: str="CINIT "; break; +case SSL_ST_OK: str="SSLOK "; break; +#ifndef NO_SSL2 +case SSL2_ST_CLIENT_START_ENCRYPTION: str="2CSENC"; break; +case SSL2_ST_SERVER_START_ENCRYPTION: str="2SSENC"; break; +case SSL2_ST_SEND_CLIENT_HELLO_A: str="2SCH_A"; break; +case SSL2_ST_SEND_CLIENT_HELLO_B: str="2SCH_B"; break; +case SSL2_ST_GET_SERVER_HELLO_A: str="2GSH_A"; break; +case SSL2_ST_GET_SERVER_HELLO_B: str="2GSH_B"; break; +case SSL2_ST_SEND_CLIENT_MASTER_KEY_A: str="2SCMKA"; break; +case SSL2_ST_SEND_CLIENT_MASTER_KEY_B: str="2SCMKB"; break; +case SSL2_ST_SEND_CLIENT_FINISHED_A: str="2SCF_A"; break; +case SSL2_ST_SEND_CLIENT_FINISHED_B: str="2SCF_B"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_A: str="2SCC_A"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_B: str="2SCC_B"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_C: str="2SCC_C"; break; +case SSL2_ST_SEND_CLIENT_CERTIFICATE_D: str="2SCC_D"; break; +case SSL2_ST_GET_SERVER_VERIFY_A: str="2GSV_A"; break; +case SSL2_ST_GET_SERVER_VERIFY_B: str="2GSV_B"; break; +case SSL2_ST_GET_SERVER_FINISHED_A: str="2GSF_A"; break; +case SSL2_ST_GET_SERVER_FINISHED_B: str="2GSF_B"; break; +case SSL2_ST_GET_CLIENT_HELLO_A: str="2GCH_A"; break; +case SSL2_ST_GET_CLIENT_HELLO_B: str="2GCH_B"; break; +case SSL2_ST_GET_CLIENT_HELLO_C: str="2GCH_C"; break; +case SSL2_ST_SEND_SERVER_HELLO_A: str="2SSH_A"; break; +case SSL2_ST_SEND_SERVER_HELLO_B: str="2SSH_B"; break; +case SSL2_ST_GET_CLIENT_MASTER_KEY_A: str="2GCMKA"; break; +case SSL2_ST_GET_CLIENT_MASTER_KEY_B: str="2GCMKA"; break; +case SSL2_ST_SEND_SERVER_VERIFY_A: str="2SSV_A"; break; +case SSL2_ST_SEND_SERVER_VERIFY_B: str="2SSV_B"; break; +case SSL2_ST_SEND_SERVER_VERIFY_C: str="2SSV_C"; break; +case SSL2_ST_GET_CLIENT_FINISHED_A: str="2GCF_A"; break; +case SSL2_ST_GET_CLIENT_FINISHED_B: str="2GCF_B"; break; +case SSL2_ST_SEND_SERVER_FINISHED_A: str="2SSF_A"; break; +case SSL2_ST_SEND_SERVER_FINISHED_B: str="2SSF_B"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_A: str="2SRC_A"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_B: str="2SRC_B"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_C: str="2SRC_C"; break; +case SSL2_ST_SEND_REQUEST_CERTIFICATE_D: str="2SRC_D"; break; +case SSL2_ST_X509_GET_SERVER_CERTIFICATE: str="2X9GSC"; break; +case SSL2_ST_X509_GET_CLIENT_CERTIFICATE: str="2X9GCC"; break; +#endif + +#ifndef NO_SSL3 +/* SSLv3 additions */ +case SSL3_ST_SW_FLUSH: +case SSL3_ST_CW_FLUSH: str="3FLUSH"; break; +case SSL3_ST_CW_CLNT_HELLO_A: str="3WCH_A"; break; +case SSL3_ST_CW_CLNT_HELLO_B: str="3WCH_B"; break; +case SSL3_ST_CR_SRVR_HELLO_A: str="3RSH_A"; break; +case SSL3_ST_CR_SRVR_HELLO_B: str="3RSH_B"; break; +case SSL3_ST_CR_CERT_A: str="3RSC_A"; break; +case SSL3_ST_CR_CERT_B: str="3RSC_B"; break; +case SSL3_ST_CR_KEY_EXCH_A: str="3RSKEA"; break; +case SSL3_ST_CR_KEY_EXCH_B: str="3RSKEB"; break; +case SSL3_ST_CR_CERT_REQ_A: str="3RCR_A"; break; +case SSL3_ST_CR_CERT_REQ_B: str="3RCR_B"; break; +case SSL3_ST_CR_SRVR_DONE_A: str="3RSD_A"; break; +case SSL3_ST_CR_SRVR_DONE_B: str="3RSD_B"; break; +case SSL3_ST_CW_CERT_A: str="3WCC_A"; break; +case SSL3_ST_CW_CERT_B: str="3WCC_B"; break; +case SSL3_ST_CW_KEY_EXCH_A: str="3WCKEA"; break; +case SSL3_ST_CW_KEY_EXCH_B: str="3WCKEB"; break; +case SSL3_ST_CW_CERT_VRFY_A: str="3WCV_A"; break; +case SSL3_ST_CW_CERT_VRFY_B: str="3WCV_B"; break; + +case SSL3_ST_SW_CHANGE_A: +case SSL3_ST_CW_CHANGE_A: str="3WCCSA"; break; +case SSL3_ST_SW_CHANGE_B: +case SSL3_ST_CW_CHANGE_B: str="3WCCSB"; break; +case SSL3_ST_SW_FINISHED_A: +case SSL3_ST_CW_FINISHED_A: str="3WFINA"; break; +case SSL3_ST_SW_FINISHED_B: +case SSL3_ST_CW_FINISHED_B: str="3WFINB"; break; +case SSL3_ST_SR_CHANGE_A: +case SSL3_ST_CR_CHANGE_A: str="3RCCSA"; break; +case SSL3_ST_SR_CHANGE_B: +case SSL3_ST_CR_CHANGE_B: str="3RCCSB"; break; +case SSL3_ST_SR_FINISHED_A: +case SSL3_ST_CR_FINISHED_A: str="3RFINA"; break; +case SSL3_ST_SR_FINISHED_B: +case SSL3_ST_CR_FINISHED_B: str="3RFINB"; break; + +case SSL3_ST_SW_HELLO_REQ_A: str="3WHR_A"; break; +case SSL3_ST_SW_HELLO_REQ_B: str="3WHR_B"; break; +case SSL3_ST_SW_HELLO_REQ_C: str="3WHR_C"; break; +case SSL3_ST_SR_CLNT_HELLO_A: str="3RCH_A"; break; +case SSL3_ST_SR_CLNT_HELLO_B: str="3RCH_B"; break; +case SSL3_ST_SR_CLNT_HELLO_C: str="3RCH_C"; break; +case SSL3_ST_SW_SRVR_HELLO_A: str="3WSH_A"; break; +case SSL3_ST_SW_SRVR_HELLO_B: str="3WSH_B"; break; +case SSL3_ST_SW_CERT_A: str="3WSC_A"; break; +case SSL3_ST_SW_CERT_B: str="3WSC_B"; break; +case SSL3_ST_SW_KEY_EXCH_A: str="3WSKEA"; break; +case SSL3_ST_SW_KEY_EXCH_B: str="3WSKEB"; break; +case SSL3_ST_SW_CERT_REQ_A: str="3WCR_A"; break; +case SSL3_ST_SW_CERT_REQ_B: str="3WCR_B"; break; +case SSL3_ST_SW_SRVR_DONE_A: str="3WSD_A"; break; +case SSL3_ST_SW_SRVR_DONE_B: str="3WSD_B"; break; +case SSL3_ST_SR_CERT_A: str="3RCC_A"; break; +case SSL3_ST_SR_CERT_B: str="3RCC_B"; break; +case SSL3_ST_SR_KEY_EXCH_A: str="3RCKEA"; break; +case SSL3_ST_SR_KEY_EXCH_B: str="3RCKEB"; break; +case SSL3_ST_SR_CERT_VRFY_A: str="3RCV_A"; break; +case SSL3_ST_SR_CERT_VRFY_B: str="3RCV_B"; break; +#endif + +#if !defined(NO_SSL2) && !defined(NO_SSL3) +/* SSLv2/v3 compatablitity states */ +/* client */ +case SSL23_ST_CW_CLNT_HELLO_A: str="23WCHA"; break; +case SSL23_ST_CW_CLNT_HELLO_B: str="23WCHB"; break; +case SSL23_ST_CR_SRVR_HELLO_A: str="23RSHA"; break; +case SSL23_ST_CR_SRVR_HELLO_B: str="23RSHA"; break; +/* server */ +case SSL23_ST_SR_CLNT_HELLO_A: str="23RCHA"; break; +case SSL23_ST_SR_CLNT_HELLO_B: str="23RCHB"; break; +#endif + +default: str="UNKWN "; break; + } + return(str); + } + +char *SSL_alert_type_string_long(value) +int value; + { + value>>=8; + if (value == SSL3_AL_WARNING) + return("warning"); + else if (value == SSL3_AL_FATAL) + return("fatal"); + else + return("unknown"); + } + +char *SSL_alert_type_string(value) +int value; + { + value>>=8; + if (value == SSL3_AL_WARNING) + return("W"); + else if (value == SSL3_AL_FATAL) + return("F"); + else + return("U"); + } + +char *SSL_alert_desc_string(value) +int value; + { + char *str; + + switch (value & 0xff) + { + case SSL3_AD_CLOSE_NOTIFY: str="CN"; break; + case SSL3_AD_UNEXPECTED_MESSAGE: str="UM"; break; + case SSL3_AD_BAD_RECORD_MAC: str="BM"; break; + case SSL3_AD_DECOMPRESSION_FAILURE: str="DF"; break; + case SSL3_AD_HANDSHAKE_FAILURE: str="HF"; break; + case SSL3_AD_NO_CERTIFICATE: str="NC"; break; + case SSL3_AD_BAD_CERTIFICATE: str="BC"; break; + case SSL3_AD_UNSUPPORTED_CERTIFICATE: str="UC"; break; + case SSL3_AD_CERTIFICATE_REVOKED: str="CR"; break; + case SSL3_AD_CERTIFICATE_EXPIRED: str="CE"; break; + case SSL3_AD_CERTIFICATE_UNKNOWN: str="CU"; break; + case SSL3_AD_ILLEGAL_PARAMETER: str="IP"; break; + default: str="UK"; break; + } + return(str); + } + +char *SSL_alert_desc_string_long(value) +int value; + { + char *str; + + switch (value & 0xff) + { + case SSL3_AD_CLOSE_NOTIFY: + str="close notify"; + break; + case SSL3_AD_UNEXPECTED_MESSAGE: + str="unexected_message"; + break; + case SSL3_AD_BAD_RECORD_MAC: + str="bad record mac"; + break; + case SSL3_AD_DECOMPRESSION_FAILURE: + str="decompression failure"; + break; + case SSL3_AD_HANDSHAKE_FAILURE: + str="handshake failure"; + break; + case SSL3_AD_NO_CERTIFICATE: + str="no certificate"; + break; + case SSL3_AD_BAD_CERTIFICATE: + str="bad certificate"; + break; + case SSL3_AD_UNSUPPORTED_CERTIFICATE: + str="unsupported certificate"; + break; + case SSL3_AD_CERTIFICATE_REVOKED: + str="certificate revoked"; + break; + case SSL3_AD_CERTIFICATE_EXPIRED: + str="certificate expired"; + break; + case SSL3_AD_CERTIFICATE_UNKNOWN: + str="certifcate unknown"; + break; + case SSL3_AD_ILLEGAL_PARAMETER: + str="illegal parameter"; + break; + default: str="unknown"; break; + } + return(str); + } + +char *SSL_rstate_string(s) +SSL *s; + { + char *str; + + switch (s->rstate) + { + case SSL_ST_READ_HEADER:str="RH"; break; + case SSL_ST_READ_BODY: str="RB"; break; + case SSL_ST_READ_DONE: str="RD"; break; + default: str="unknown"; break; + } + return(str); + } diff --git a/ssl/ssl_task.c b/ssl/ssl_task.c new file mode 100644 index 0000000000..c27ce913e7 --- /dev/null +++ b/ssl/ssl_task.c @@ -0,0 +1,359 @@ +/* ssl/ssl_task.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* VMS */ +/* + * DECnet object for servicing SSL. We accept the inbound and speak a + * simple protocol for multiplexing the 2 data streams (application and + * ssl data) over this logical link. + * + * Logical names: + * SSL_CIPHER Defines a list of cipher specifications the server + * will support in order of preference. + * SSL_SERVER_CERTIFICATE + * Points to PEM (privacy enhanced mail) file that + * contains the server certificate and private password. + * SYS$NET Logical created by netserver.exe as hook for completing + * DECnet logical link. + * + * Each NSP message sent over the DECnet link has the following structure: + * struct rpc_msg { + * char channel; + * char function; + * short length; + * char data[MAX_DATA]; + * } msg; + * + * The channel field designates the virtual data stream this message applies + * to and is one of: + * A - Application data (payload). + * R - Remote client connection that initiated the SSL connection. Encrypted + * data is sent over this connection. + * G - General data, reserved for future use. + * + * The data streams are half-duplex read/write and have following functions: + * G - Get, requests that up to msg.length bytes of data be returned. The + * data is returned in the next 'C' function response that matches the + * requesting channel. + * P - Put, requests that the first msg.length bytes of msg.data be appended + * to the designated stream. + * C - Confirms a get or put. Every get and put will get a confirm response, + * you cannot initiate another function on a channel until the previous + * operation has been confirmed. + * + * The 2 channels may interleave their operations, for example: + * Server msg Client msg + * A, Get, 4092 ----> + * <---- R, get, 4092 + * R, Confirm, {hello} ----> + * <---- R, put, {srv hello} + * R, Confirm, 0 ----> + * . (SSL handshake completed) + * . (read first app data). + * <---- A, confirm, {http data} + * A, Put, {http data} ----> + * <---- A, confirm, 0 + * + * The length field is not permitted to be larger that 4092 bytes. + * + * Author: Dave Jones + * Date: 22-JUL-1996 + */ +#include <stdlib.h> +#include <stdio.h> +#include <iodef.h> /* VMS IO$_ definitions */ +#include <descrip.h> /* VMS string descriptors */ +extern int SYS$QIOW(), SYS$ASSIGN(); +int LIB$INIT_TIMER(), LIB$SHOW_TIMER(); + +#include <string.h> /* from ssltest.c */ +#include <errno.h> +#include "buffer.h" +#include "../e_os.h" +#include "x509.h" +#include "ssl.h" +#include "err.h" + +int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth, + int error); +BIO *bio_err=NULL; +BIO *bio_stdout=NULL; +BIO_METHOD *BIO_s_rtcp(); + +static char *cipher=NULL; +int verbose=1; +#ifdef FIONBIO +static int s_nbio=0; +#endif +#define TEST_SERVER_CERT "SSL_SERVER_CERTIFICATE" +/*************************************************************************/ +struct rpc_msg { /* Should have member alignment inhibited */ + char channel; /* 'A'-app data. 'R'-remote client 'G'-global */ + char function; /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ + unsigned short int length; /* Amount of data returned or max to return */ + char data[4092]; /* variable data */ +}; +#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) + +static $DESCRIPTOR(sysnet, "SYS$NET"); +typedef unsigned short io_channel; + +struct io_status { + unsigned short status; + unsigned short count; + unsigned long stsval; +}; +int doit(io_channel chan, SSL_CTX *s_ctx ); +/*****************************************************************************/ +/* Decnet I/O routines. + */ +static int get ( io_channel chan, char *buffer, int maxlen, int *length ) +{ + int status; + struct io_status iosb; + status = SYS$QIOW ( 0, chan, IO$_READVBLK, &iosb, 0, 0, + buffer, maxlen, 0, 0, 0, 0 ); + if ( (status&1) == 1 ) status = iosb.status; + if ( (status&1) == 1 ) *length = iosb.count; + return status; +} + +static int put ( io_channel chan, char *buffer, int length ) +{ + int status; + struct io_status iosb; + status = SYS$QIOW ( 0, chan, IO$_WRITEVBLK, &iosb, 0, 0, + buffer, length, 0, 0, 0, 0 ); + if ( (status&1) == 1 ) status = iosb.status; + return status; +} +/***************************************************************************/ +/* Handle operations on the 'G' channel. + */ +static int general_request ( io_channel chan, struct rpc_msg *msg, int length ) +{ + return 48; +} +/***************************************************************************/ +int main ( int argc, char **argv ) +{ + int status, length; + io_channel chan; + struct rpc_msg msg; + + char *CApath=NULL,*CAfile=NULL; + int badop=0; + int ret=1; + int client_auth=0; + int server_auth=0; + SSL_CTX *s_ctx=NULL; + /* + * Confirm logical link with initiating client. + */ + LIB$INIT_TIMER(); + status = SYS$ASSIGN ( &sysnet, &chan, 0, 0, 0 ); + printf("status of assign to SYS$NET: %d\n", status ); + /* + * Initialize standard out and error files. + */ + if (bio_err == NULL) + if ((bio_err=BIO_new(BIO_s_file())) != NULL) + BIO_set_fp(bio_err,stderr,BIO_NOCLOSE); + if (bio_stdout == NULL) + if ((bio_stdout=BIO_new(BIO_s_file())) != NULL) + BIO_set_fp(bio_stdout,stdout,BIO_NOCLOSE); + /* + * get the preferred cipher list and other initialization + */ + if (cipher == NULL) cipher=getenv("SSL_CIPHER"); + printf("cipher list: %s\n", cipher ? cipher : "{undefined}" ); + + SSL_load_error_strings(); + + s_ctx=SSL_CTX_new(SSLv2()); + + if (s_ctx == NULL) goto end; + + SSL_CTX_use_certificate_file(s_ctx,TEST_SERVER_CERT,SSL_FILETYPE_PEM); + SSL_CTX_use_RSAPrivateKey_file(s_ctx,TEST_SERVER_CERT,SSL_FILETYPE_PEM); + printf("Loaded server certificate: '%s'\n", TEST_SERVER_CERT ); + + /* + * Take commands from client until bad status. + */ + LIB$SHOW_TIMER(); + status = doit ( chan, s_ctx ); + LIB$SHOW_TIMER(); + /* + * do final cleanup and exit. + */ +end: + if (s_ctx != NULL) SSL_CTX_free(s_ctx); + LIB$SHOW_TIMER(); + return 1; +} + +int doit(io_channel chan, SSL_CTX *s_ctx ) +{ + int status, length, link_state; + struct rpc_msg msg; + static char cbuf[200],sbuf[200]; + SSL *s_ssl=NULL; + BIO *c_to_s=NULL; + BIO *s_to_c=NULL; + BIO *c_bio=NULL; + BIO *s_bio=NULL; + int i; + int done=0; + + s_ssl=SSL_new(s_ctx); + if (s_ssl == NULL) goto err; + + c_to_s=BIO_new(BIO_s_rtcp()); + s_to_c=BIO_new(BIO_s_rtcp()); + if ((s_to_c == NULL) || (c_to_s == NULL)) goto err; + BIO_set_fd ( c_to_s, "", chan ); + BIO_set_fd ( s_to_c, "", chan ); + + c_bio=BIO_new(BIO_f_ssl()); + s_bio=BIO_new(BIO_f_ssl()); + if ((c_bio == NULL) || (s_bio == NULL)) goto err; + + SSL_set_accept_state(s_ssl); + SSL_set_bio(s_ssl,c_to_s,s_to_c); + BIO_set_ssl(s_bio,s_ssl,BIO_CLOSE); + + /* We can always do writes */ + printf("Begin doit main loop\n"); + /* + * Link states: 0-idle, 1-read pending, 2-write pending, 3-closed. + */ + for (link_state = 0; link_state < 3; ) { + /* + * Wait for remote end to request data action on A channel. + */ + while ( link_state == 0 ) { + status = get ( chan, (char *) &msg, sizeof(msg), &length ); + if ( (status&1) == 0 ) { + printf("Error in main loop get: %d\n", status ); + link_state = 3; + break; + } + if ( length < RPC_HDR_SIZE ) { + printf("Error in main loop get size: %d\n", length ); + break; + link_state = 3; + } + if ( msg.channel != 'A' ) { + printf("Error in main loop, unexpected channel: %c\n", + msg.channel ); + break; + link_state = 3; + } + if ( msg.function == 'G' ) { + link_state = 1; + } else if ( msg.function == 'P' ) { + link_state = 2; /* write pending */ + } else if ( msg.function == 'X' ) { + link_state = 3; + } else { + link_state = 3; + } + } + if ( link_state == 1 ) { + i = BIO_read ( s_bio, msg.data, msg.length ); + if ( i < 0 ) link_state = 3; + else { + msg.channel = 'A'; + msg.function = 'C'; /* confirm */ + msg.length = i; + status = put ( chan, (char *) &msg, i+RPC_HDR_SIZE ); + if ( (status&1) == 0 ) break; + link_state = 0; + } + } else if ( link_state == 2 ) { + i = BIO_write ( s_bio, msg.data, msg.length ); + if ( i < 0 ) link_state = 3; + else { + msg.channel = 'A'; + msg.function = 'C'; /* confirm */ + msg.length = 0; + status = put ( chan, (char *) &msg, RPC_HDR_SIZE ); + if ( (status&1) == 0 ) break; + link_state = 0; + } + } + } + fprintf(stdout,"DONE\n"); +err: + /* We have to set the BIO's to NULL otherwise they will be + * free()ed twice. Once when th s_ssl is SSL_free()ed and + * again when c_ssl is SSL_free()ed. + * This is a hack required because s_ssl and c_ssl are sharing the same + * BIO structure and SSL_set_bio() and SSL_free() automatically + * BIO_free non NULL entries. + * You should not normally do this or be required to do this */ + s_ssl->rbio=NULL; + s_ssl->wbio=NULL; + + if (c_to_s != NULL) BIO_free(c_to_s); + if (s_to_c != NULL) BIO_free(s_to_c); + if (c_bio != NULL) BIO_free(c_bio); + if (s_bio != NULL) BIO_free(s_bio); + return(0); +} diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c new file mode 100644 index 0000000000..b9cb9ef673 --- /dev/null +++ b/ssl/ssl_txt.c @@ -0,0 +1,133 @@ +/* ssl/ssl_txt.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "buffer.h" +#include "ssl_locl.h" + +#ifndef WIN16 +int SSL_SESSION_print_fp(fp, x) +FILE *fp; +SSL_SESSION *x; + { + BIO *b; + int ret; + + if ((b=BIO_new(BIO_s_file())) == NULL) + { + SSLerr(SSL_F_SSL_SESSION_PRINT_FP,ERR_R_BUF_LIB); + return(0); + } + BIO_set_fp(b,fp,BIO_NOCLOSE); + ret=SSL_SESSION_print(b,x); + BIO_free(b); + return(ret); + } +#endif + +int SSL_SESSION_print(bp,x) +BIO *bp; +SSL_SESSION *x; + { + int i; + char str[128]; + + if (x == NULL) goto err; + if (BIO_puts(bp,"SSL-Session:\n") <= 0) goto err; + sprintf(str," Cipher : %s\n",(x->cipher == NULL)?"unknown":x->cipher->name); + if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_puts(bp," Session-ID: ") <= 0) goto err; + for (i=0; i<(int)x->session_id_length; i++) + { + sprintf(str,"%02X",x->session_id[i]); + if (BIO_puts(bp,str) <= 0) goto err; + } + if (BIO_puts(bp,"\n Master-Key: ") <= 0) goto err; + for (i=0; i<(int)x->master_key_length; i++) + { + sprintf(str,"%02X",x->master_key[i]); + if (BIO_puts(bp,str) <= 0) goto err; + } + if (BIO_puts(bp,"\n Key-Arg : ") <= 0) goto err; + if (x->key_arg_length == 0) + { + if (BIO_puts(bp,"None") <= 0) goto err; + } + else + for (i=0; i<(int)x->key_arg_length; i++) + { + sprintf(str,"%02X",x->key_arg[i]); + if (BIO_puts(bp,str) <= 0) goto err; + } + if (x->time != 0L) + { + sprintf(str,"\n Start Time: %ld",x->time); + if (BIO_puts(bp,str) <= 0) goto err; + } + if (x->timeout != 0L) + { + sprintf(str,"\n Timeout : %ld (sec)",x->timeout); + if (BIO_puts(bp,str) <= 0) goto err; + } + if (BIO_puts(bp,"\n") <= 0) goto err; + + return(1); +err: + return(0); + } + diff --git a/ssl/ssltest.c b/ssl/ssltest.c new file mode 100644 index 0000000000..b8d657f3ba --- /dev/null +++ b/ssl/ssltest.c @@ -0,0 +1,635 @@ +/* ssl/ssltest.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#ifdef WIN16 +#define APPS_WIN16 +#endif +#include "bio.h" +#include "crypto.h" +#include "../e_os.h" +#include "x509.h" +#include "ssl.h" +#include "err.h" + +#ifdef WIN16 +#define APPS_WIN16 +#include "../crypto/bio/bss_file.c" +#endif + +#define TEST_SERVER_CERT "../apps/server.pem" +#define TEST_CLIENT_CERT "../apps/client.pem" + +#ifndef NOPROTO +int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); +static DH *get_dh512(void); +#else +int MS_CALLBACK verify_callback(); +static DH *get_dh512(); +#endif + +BIO *bio_err=NULL; +BIO *bio_stdout=NULL; + +static char *cipher=NULL; +int verbose=0; +#ifdef FIONBIO +static int s_nbio=0; +#endif + + +#ifndef NOPROTO +int doit(SSL_CTX *s_ctx,SSL_CTX *c_ctx); +#else +int doit(); +#endif + +static void sv_usage() + { + fprintf(stderr,"usage: ssltest [args ...]\n"); + fprintf(stderr,"\n"); + fprintf(stderr," -server_auth - check server certificate\n"); + fprintf(stderr," -client_auth - do client authentication\n"); + fprintf(stderr," -v - more output\n"); +#ifndef NO_SSL2 + fprintf(stderr," -ssl2 - use SSLv2\n"); +#endif +#ifndef NO_SSL3 + fprintf(stderr," -ssl3 - use SSLv3\n"); +#endif + fprintf(stderr," -CApath arg - PEM format directory of CA's\n"); + fprintf(stderr," -CAfile arg - PEM format file of CA's\n"); + } + +int main(argc, argv) +int argc; +char *argv[]; + { + char *CApath=NULL,*CAfile=NULL; + int badop=0; + int ssl2=0,ssl3=0,ret=1; + int client_auth=0; + int server_auth=0; + char *server_cert=TEST_SERVER_CERT; + char *client_cert=TEST_CLIENT_CERT; + SSL_CTX *s_ctx=NULL; + SSL_CTX *c_ctx=NULL; + SSL_METHOD *meth=NULL; + DH *dh; + + bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); + bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE); + + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + + argc--; + argv++; + + while (argc >= 1) + { + if (strcmp(*argv,"-server_auth") == 0) + server_auth=1; + else if (strcmp(*argv,"-client_auth") == 0) + client_auth=1; + else if (strcmp(*argv,"-v") == 0) + verbose=1; + else if (strcmp(*argv,"-ssl2") == 0) + ssl2=1; + else if (strcmp(*argv,"-ssl3") == 0) + ssl3=1; + else if (strcmp(*argv,"-cert") == 0) + { + if (--argc < 1) goto bad; + server_cert= *(++argv); + } + else if (strcmp(*argv,"-s_cert") == 0) + { + if (--argc < 1) goto bad; + server_cert= *(++argv); + } + else if (strcmp(*argv,"-c_cert") == 0) + { + if (--argc < 1) goto bad; + client_cert= *(++argv); + } + else if (strcmp(*argv,"-cipher") == 0) + { + if (--argc < 1) goto bad; + cipher= *(++argv); + } + else if (strcmp(*argv,"-CApath") == 0) + { + if (--argc < 1) goto bad; + CApath= *(++argv); + } + else if (strcmp(*argv,"-CAfile") == 0) + { + if (--argc < 1) goto bad; + CAfile= *(++argv); + } + else + { + fprintf(stderr,"unknown option %s\n",*argv); + badop=1; + break; + } + argc--; + argv++; + } + if (badop) + { +bad: + sv_usage(); + goto end; + } + +/* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ + + SSLeay_add_ssl_algorithms(); + SSL_load_error_strings(); + +#if !defined(NO_SSL2) && !defined(NO_SSL3) + if (ssl2) + meth=SSLv2_method(); + else + if (ssl3) + meth=SSLv3_method(); + else + meth=SSLv23_method(); +#else +#ifdef NO_SSL2 + meth=SSLv3_method(); +#else + meth=SSLv2_method(); +#endif +#endif + + c_ctx=SSL_CTX_new(meth); + s_ctx=SSL_CTX_new(meth); + if ((c_ctx == NULL) || (s_ctx == NULL)) + { + ERR_print_errors(bio_err); + goto end; + } + + if (cipher != NULL) + { + SSL_CTX_set_cipher_list(c_ctx,cipher); + SSL_CTX_set_cipher_list(s_ctx,cipher); + } + +#ifndef NO_DH + dh=get_dh512(); + SSL_CTX_set_tmp_dh(s_ctx,dh); + DH_free(dh); +#endif + + if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM)) + { + ERR_print_errors(bio_err); + } + else if (!SSL_CTX_use_PrivateKey_file(s_ctx,server_cert, + SSL_FILETYPE_PEM)) + { + ERR_print_errors(bio_err); + goto end; + } + + if (client_auth) + { + SSL_CTX_use_certificate_file(c_ctx,client_cert, + SSL_FILETYPE_PEM); + SSL_CTX_use_PrivateKey_file(c_ctx,client_cert, + SSL_FILETYPE_PEM); + } + + if ( (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) || + (!SSL_CTX_set_default_verify_paths(s_ctx)) || + (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) || + (!SSL_CTX_set_default_verify_paths(c_ctx))) + { + fprintf(stderr,"SSL_load_verify_locations\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (client_auth) + { + fprintf(stderr,"client authentication\n"); + SSL_CTX_set_verify(s_ctx, + SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + verify_callback); + } + if (server_auth) + { + fprintf(stderr,"server authentication\n"); + SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, + verify_callback); + } + + ret=doit(s_ctx,c_ctx); +end: + if (s_ctx != NULL) SSL_CTX_free(s_ctx); + if (c_ctx != NULL) SSL_CTX_free(c_ctx); + + if (bio_stdout != NULL) BIO_free(bio_stdout); + + ERR_remove_state(0); + EVP_cleanup(); + CRYPTO_mem_leaks(bio_err); + EXIT(ret); + } + +#define W_READ 1 +#define W_WRITE 2 +#define C_DONE 1 +#define S_DONE 2 + +int doit(s_ctx,c_ctx) +SSL_CTX *s_ctx,*c_ctx; + { + static char cbuf[200],sbuf[200]; + int ret=1; + SSL *c_ssl=NULL; + SSL *s_ssl=NULL; + BIO *c_to_s=NULL; + BIO *s_to_c=NULL; + BIO *c_bio=NULL; + BIO *s_bio=NULL; + int c_r,c_w,s_r,s_w; + int c_want,s_want; + int i; + int done=0; + int c_write,s_write; + int do_server=0,do_client=0; + SSL_CIPHER *ciph; + + c_ssl=SSL_new(c_ctx); + s_ssl=SSL_new(s_ctx); + if ((s_ssl == NULL) || (c_ssl == NULL)) + { + ERR_print_errors(bio_err); + goto err; + } + + c_to_s=BIO_new(BIO_s_mem()); + s_to_c=BIO_new(BIO_s_mem()); + if ((s_to_c == NULL) || (c_to_s == NULL)) + { + ERR_print_errors(bio_err); + goto err; + } + + c_bio=BIO_new(BIO_f_ssl()); + s_bio=BIO_new(BIO_f_ssl()); + if ((c_bio == NULL) || (s_bio == NULL)) + { + ERR_print_errors(bio_err); + goto err; + } + + SSL_set_connect_state(c_ssl); + SSL_set_bio(c_ssl,s_to_c,c_to_s); + BIO_set_ssl(c_bio,c_ssl,BIO_CLOSE); + + SSL_set_accept_state(s_ssl); + SSL_set_bio(s_ssl,c_to_s,s_to_c); + BIO_set_ssl(s_bio,s_ssl,BIO_CLOSE); + + c_r=0; s_r=1; + c_w=1; s_w=0; + c_want=W_WRITE; + s_want=0; + c_write=1,s_write=0; + + /* We can always do writes */ + for (;;) + { + do_server=0; + do_client=0; + + i=(int)BIO_pending(s_bio); + if ((i && s_r) || s_w) do_server=1; + + i=(int)BIO_pending(c_bio); + if ((i && c_r) || c_w) do_client=1; + + if (do_server && verbose) + { + if (SSL_in_init(s_ssl)) + printf("server waiting in SSL_accept - %s\n", + SSL_state_string_long(s_ssl)); + else if (s_write) + printf("server:SSL_write()\n"); + else + printf("server:SSL_read()\n"); + } + + if (do_client && verbose) + { + if (SSL_in_init(c_ssl)) + printf("client waiting in SSL_connect - %s\n", + SSL_state_string_long(c_ssl)); + else if (c_write) + printf("client:SSL_write()\n"); + else + printf("client:SSL_read()\n"); + } + + if (!do_client && !do_server) + { + fprintf(stdout,"ERROR IN STARTUP\n"); + ERR_print_errors(bio_err); + break; + } + if (do_client && !(done & C_DONE)) + { + if (c_write) + { + i=BIO_write(c_bio,"hello from client\n",18); + if (i < 0) + { + c_r=0; + c_w=0; + if (BIO_should_retry(c_bio)) + { + if (BIO_should_read(c_bio)) + c_r=1; + if (BIO_should_write(c_bio)) + c_w=1; + } + else + { + fprintf(stderr,"ERROR in CLIENT\n"); + ERR_print_errors(bio_err); + goto err; + } + } + else if (i == 0) + { + fprintf(stderr,"SSL CLIENT STARTUP FAILED\n"); + goto err; + } + else + { + /* ok */ + c_write=0; + } + } + else + { + i=BIO_read(c_bio,cbuf,100); + if (i < 0) + { + c_r=0; + c_w=0; + if (BIO_should_retry(c_bio)) + { + if (BIO_should_read(c_bio)) + c_r=1; + if (BIO_should_write(c_bio)) + c_w=1; + } + else + { + fprintf(stderr,"ERROR in CLIENT\n"); + ERR_print_errors(bio_err); + goto err; + } + } + else if (i == 0) + { + fprintf(stderr,"SSL CLIENT STARTUP FAILED\n"); + goto err; + } + else + { + done|=C_DONE; + fprintf(stdout,"CLIENT:from server:"); + fwrite(cbuf,1,i,stdout); + fflush(stdout); + } + } + } + + if (do_server && !(done & S_DONE)) + { + if (!s_write) + { + i=BIO_read(s_bio,sbuf,100); + if (i < 0) + { + s_r=0; + s_w=0; + if (BIO_should_retry(s_bio)) + { + if (BIO_should_read(s_bio)) + s_r=1; + if (BIO_should_write(s_bio)) + s_w=1; + } + else + { + fprintf(stderr,"ERROR in SERVER\n"); + ERR_print_errors(bio_err); + goto err; + } + } + else if (i == 0) + { + ERR_print_errors(bio_err); + fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_read\n"); + goto err; + } + else + { + s_write=1; + s_w=1; + fprintf(stdout,"SERVER:from client:"); + fwrite(sbuf,1,i,stdout); + fflush(stdout); + } + } + else + { + i=BIO_write(s_bio,"hello from server\n",18); + if (i < 0) + { + s_r=0; + s_w=0; + if (BIO_should_retry(s_bio)) + { + if (BIO_should_read(s_bio)) + s_r=1; + if (BIO_should_write(s_bio)) + s_w=1; + } + else + { + fprintf(stderr,"ERROR in SERVER\n"); + ERR_print_errors(bio_err); + goto err; + } + } + else if (i == 0) + { + ERR_print_errors(bio_err); + fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_write\n"); + goto err; + } + else + { + s_write=0; + s_r=1; + done|=S_DONE; + } + } + } + + if ((done & S_DONE) && (done & C_DONE)) break; + } + + ciph=SSL_get_current_cipher(c_ssl); + fprintf(stdout,"DONE, used %s, %s\n",SSL_CIPHER_get_version(ciph), + SSL_CIPHER_get_name(ciph)); + ret=0; +err: + /* We have to set the BIO's to NULL otherwise they will be + * Free()ed twice. Once when th s_ssl is SSL_free()ed and + * again when c_ssl is SSL_free()ed. + * This is a hack required because s_ssl and c_ssl are sharing the same + * BIO structure and SSL_set_bio() and SSL_free() automatically + * BIO_free non NULL entries. + * You should not normally do this or be required to do this */ + if (s_ssl != NULL) + { + s_ssl->rbio=NULL; + s_ssl->wbio=NULL; + } + if (c_ssl != NULL) + { + c_ssl->rbio=NULL; + c_ssl->wbio=NULL; + } + + if (c_to_s != NULL) BIO_free(c_to_s); + if (s_to_c != NULL) BIO_free(s_to_c); + if (c_bio != NULL) BIO_free(c_bio); + if (s_bio != NULL) BIO_free(s_bio); + return(ret); + } + +int MS_CALLBACK verify_callback(ok, ctx) +int ok; +X509_STORE_CTX *ctx; + { + char *s,buf[256]; + + s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,256); + if (s != NULL) + { + if (ok) + fprintf(stderr,"depth=%d %s\n",ctx->error_depth,buf); + else + fprintf(stderr,"depth=%d error=%d %s\n", + ctx->error_depth,ctx->error,buf); + } + + if (ok == 0) + { + switch (ctx->error) + { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + ok=1; + } + } + + return(ok); + } + +static unsigned char dh512_p[]={ + 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, + 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, + 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, + 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, + 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, + 0x47,0x74,0xE8,0x33, + }; +static unsigned char dh512_g[]={ + 0x02, + }; + +static DH *get_dh512() + { + DH *dh=NULL; + +#ifndef NO_DH + if ((dh=DH_new()) == NULL) return(NULL); + dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); + dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); + if ((dh->p == NULL) || (dh->g == NULL)) + return(NULL); +#endif + return(dh); + } + diff --git a/ssl/zz b/ssl/zz new file mode 100644 index 0000000000..47c570ec80 --- /dev/null +++ b/ssl/zz @@ -0,0 +1,402 @@ +/* ssl/s23_srvr.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "buffer.h" +#include "rand.h" +#include "objects.h" +#include "evp.h" +#include "ssl_locl.h" + +#define BREAK break + +#ifndef NOPROTO +int ssl23_get_client_hello(SSL *s); +#else +int ssl23_get_client_hello(); +#endif + +static SSL_METHOD *ssl23_get_server_method(ver) +int ver; + { + if (ver == 2) + return(SSLv2_server_method()); + else if (ver == 3) + return(SSLv3_server_method()); + else + return(NULL); + } + +SSL_METHOD *SSLv23_server_method() + { + static int init=1; + static SSL_METHOD SSLv23_server_data; + + if (init) + { + init=0; + memcpy((char *)&SSLv23_server_data, + (char *)sslv23_base_method(),sizeof(SSL_METHOD)); + SSLv23_server_data.ssl_accept=ssl23_accept; + SSLv23_server_data.get_ssl_method=ssl23_get_server_method; + } + return(&SSLv23_server_data); + } + +int ssl23_accept(s) +SSL *s; + { + BUF_MEM *buf; + unsigned long Time=time(NULL); + void (*cb)()=NULL; + int ret= -1; + int new_state,state; + + RAND_seed((unsigned char *)&Time,sizeof(Time)); + ERR_clear_error(); + errno=0; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + s->in_handshake++; + + for (;;) + { + state=s->state; + + switch(s->state) + { + case SSL_ST_BEFORE: + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + case SSL_ST_OK|SSL_ST_ACCEPT: + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + + s->version=3; + s->type=SSL_ST_ACCEPT; + + if (s->init_buf == NULL) + { + if ((buf=BUF_MEM_new()) == NULL) + { + ret= -1; + goto end; + } + if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) + { + ret= -1; + goto end; + } + s->init_buf=buf; + } + + ssl3_init_finished_mac(s); + + s->state=SSL23_ST_SR_CLNT_HELLO_A; + s->ctx->sess_accept++; + s->init_num=0; + break; + + case SSL23_ST_SR_CLNT_HELLO_A: + case SSL23_ST_SR_CLNT_HELLO_B: + + s->shutdown=0; + ret=ssl23_get_client_hello(s); + if (ret >= 0) cb=NULL; + goto end; + break; + + default: + SSLerr(SSL_F_SSL23_ACCEPT,SSL_R_UNKNOWN_STATE); + ret= -1; + goto end; + /* break; */ + } + + if ((cb != NULL) && (s->state != state)) + { + new_state=s->state; + s->state=state; + cb(s,SSL_CB_ACCEPT_LOOP,1); + s->state=new_state; + } + } +end: + if (cb != NULL) + cb(s,SSL_CB_ACCEPT_EXIT,ret); + s->in_handshake--; + return(ret); + } + + +int ssl23_get_client_hello(s) +SSL *s; + { + char buf[8]; + unsigned char *p,*d,*dd; + unsigned int i; + unsigned int csl,sil,cl; + int n=0,j; + BIO *bbio; + int type=0; + + /* read the initial header */ + if (s->state == SSL23_ST_SR_CLNT_HELLO_A) + { + if (!ssl3_setup_buffers(s)) goto err; + + n=ssl23_read_bytes(s,7); + if (n != 7) return(n); + + p=s->packet; + + memcpy(buf,p,n); + + if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) + { + /* SSLv2 header */ + if ((p[3] == 0x00) && (p[4] == 0x02)) + { + /* SSLv2 */ + type=1; + } + else if ((p[3] == SSL3_VERSION_MAJOR) && + (p[4] == SSL3_VERSION_MINOR)) + { + /* SSLv3 */ + s->state=SSL23_ST_SR_CLNT_HELLO_B; + } + } + else if ((p[0] == SSL3_RT_HANDSHAKE) && + (p[1] == SSL3_VERSION_MAJOR) && + (p[2] == SSL3_VERSION_MINOR) && + (p[5] == SSL3_MT_CLIENT_HELLO)) + { + /* true SSLv3 */ + type=3; + } + } + + if (s->state == SSL23_ST_SR_CLNT_HELLO_B) + { + /* we have a SSLv3 in a SSLv2 header */ + type=2; + p=s->packet; + n=((p[0]&0x7f)<<8)|p[1]; + if (n > (1024*4)) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); + goto err; + } + + j=ssl23_read_bytes(s,n+2); + if (j <= 0) return(j); + + ssl3_finish_mac(s,&(s->packet[2]),s->packet_length-2); + + p=s->packet; + p+=5; + n2s(p,csl); + n2s(p,sil); + n2s(p,cl); + d=(unsigned char *)s->init_buf->data; + if ((csl+sil+cl+11) != s->packet_length) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } + + *(d++)=SSL3_VERSION_MAJOR; + *(d++)=SSL3_VERSION_MINOR; + + /* lets populate the random area */ + /* get the chalenge_length */ + i=(cl > SSL3_RANDOM_SIZE)?SSL3_RANDOM_SIZE:cl; + memset(d,0,SSL3_RANDOM_SIZE); + memcpy(&(d[SSL3_RANDOM_SIZE-i]),&(p[csl+sil]),i); + d+=SSL3_RANDOM_SIZE; + + /* no session-id reuse */ + *(d++)=0; + + /* ciphers */ + j=0; + dd=d; + d+=2; + for (i=0; i<csl; i+=3) + { + if (p[i] != 0) continue; + *(d++)=p[i+1]; + *(d++)=p[i+2]; + j+=2; + } + s2n(j,dd); + + /* compression */ + *(d++)=1; + *(d++)=0; + + i=(d-(unsigned char *)s->init_buf->data); + + /* get the data reused from the init_buf */ + s->s3->tmp.reuse_message=1; + s->s3->tmp.message_type=SSL3_MT_CLIENT_HELLO; + s->s3->tmp.message_size=i; + } + + if (type == 1) + { + /* we are talking sslv2 */ + /* we need to clean up the SSLv3 setup and put in the + * sslv2 stuff. */ + + if (s->s2 == NULL) + { + if (!ssl2_new(s)) + goto err; + } + else + ssl2_clear(s); + + if (s->s3 != NULL) ssl3_free(s); + + if (!BUF_MEM_grow(s->init_buf, + SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) + { + goto err; + } + + s->state=SSL2_ST_GET_CLIENT_HELLO_A; + if (s->ctx->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) + s->s2->ssl2_rollback=0; + else + s->s2->ssl2_rollback=1; + + /* setup the 5 bytes we have read so we get them from + * the sslv2 buffer */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + s->packet= &(s->s2->rbuf[0]); + memcpy(s->packet,buf,n); + s->s2->rbuf_left=n; + s->s2->rbuf_offs=0; + + s->method=SSLv2_server_method(); + s->handshake_func=s->method->ssl_accept; + } + + if ((type == 2) || (type == 3)) + { + /* we have sslv3 */ + + if (s->bbio == NULL) + { + bbio=BIO_new(BIO_f_buffer()); + if (bbio == NULL) + goto err; + s->bbio=bbio; + } + else + bbio=s->bbio; + BIO_reset(bbio); + if (!BIO_set_write_buffer_size(bbio,16*1024)) + goto err; + s->wbio=BIO_push(bbio,s->wbio); + + /* we are in this state */ + s->state=SSL3_ST_SR_CLNT_HELLO_A; + + if (type == 3) + { + /* put the 'n' bytes we have read into the input buffer + * for SSLv3 */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + s->packet= &(s->s3->rbuf.buf[0]); + memcpy(s->packet,buf,n); + s->s3->rbuf.left=n; + s->s3->rbuf.offset=0; + } + else + { + s->packet_length=0; + s->s3->rbuf.left=0; + s->s3->rbuf.offset=0; + } + + s->method=SSLv3_server_method(); + s->handshake_func=s->method->ssl_accept; + } + + if ((type < 1) || (type > 3)) + { + /* bad, very bad */ + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + s->init_num=0; + return(SSL_accept(s)); +err: + return(-1); + } + |