diff options
Diffstat (limited to 'main/openssl/ssl')
56 files changed, 51097 insertions, 0 deletions
diff --git a/main/openssl/ssl/Android.mk b/main/openssl/ssl/Android.mk new file mode 100644 index 00000000..1319d5e1 --- /dev/null +++ b/main/openssl/ssl/Android.mk @@ -0,0 +1,78 @@ +LOCAL_PATH:= $(call my-dir) + +local_c_includes := \ +	openssl \ +	openssl/include \ +	openssl/crypto + +local_src_files:= \ +	s2_meth.c \ +	s2_srvr.c \ +	s2_clnt.c \ +	s2_lib.c \ +	s2_enc.c \ +	s2_pkt.c \ +	s3_meth.c \ +	s3_srvr.c \ +	s3_clnt.c \ +	s3_lib.c \ +	s3_enc.c \ +	s3_pkt.c \ +	s3_both.c \ +	s23_meth.c \ +	s23_srvr.c \ +	s23_clnt.c \ +	s23_lib.c \ +	s23_pkt.c \ +	t1_meth.c \ +	t1_srvr.c \ +	t1_clnt.c \ +	t1_lib.c \ +	t1_enc.c \ +	t1_reneg.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 \ +	ssl_err.c \ +	kssl.c + +####################################### +# target static library +include $(CLEAR_VARS) +include $(LOCAL_PATH)/../android-config.mk + +ifneq ($(TARGET_ARCH),x86) +LOCAL_NDK_VERSION := 5 +LOCAL_SDK_VERSION := 9 +endif +LOCAL_SRC_FILES += $(local_src_files) +LOCAL_C_INCLUDES += $(local_c_includes) +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE:= libssl_static +include $(BUILD_STATIC_LIBRARY) + +####################################### +# target shared library +include $(CLEAR_VARS) +include $(LOCAL_PATH)/../android-config.mk + +ifneq ($(TARGET_ARCH),x86) +LOCAL_NDK_VERSION := 5 +LOCAL_SDK_VERSION := 9 +endif +LOCAL_SRC_FILES += $(local_src_files) +LOCAL_C_INCLUDES += $(local_c_includes) +LOCAL_SHARED_LIBRARIES += libcrypto +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE:= libssl +include $(BUILD_SHARED_LIBRARY) + + diff --git a/main/openssl/ssl/Makefile b/main/openssl/ssl/Makefile new file mode 100644 index 00000000..2b275faf --- /dev/null +++ b/main/openssl/ssl/Makefile @@ -0,0 +1,975 @@ +# +# OpenSSL/ssl/Makefile +# + +DIR=	ssl +TOP=	.. +CC=	cc +INCLUDES= -I../crypto -I$(TOP) -I../include $(KRB5_INCLUDES) +CFLAG=-g +MAKEFILE=	Makefile +AR=		ar r +# KRB5 stuff +KRB5_INCLUDES= + +CFLAGS= $(INCLUDES) $(CFLAG) + +GENERAL=Makefile README ssl-lib.com install.com +TEST=ssltest.c +APPS= + +LIB=$(TOP)/libssl.a +SHARED_LIB= libssl$(SHLIB_EXT) +LIBSRC=	\ +	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_enc.c s2_pkt.c \ +	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c \ +	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \ +	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c \ +	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  d1_pkt.c \ +	d1_both.c d1_enc.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 ssl_err.c kssl.c t1_reneg.c +LIBOBJ= \ +	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \ +	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \ +	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \ +	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o \ +	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  d1_pkt.o \ +	d1_both.o d1_enc.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 ssl_err.o kssl.o t1_reneg.o + +SRC= $(LIBSRC) + +EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h +HEADER=	$(EXHEADER) ssl_locl.h kssl_lcl.h + +ALL=    $(GENERAL) $(SRC) $(HEADER) + +top: +	(cd ..; $(MAKE) DIRS=$(DIR) all) + +all:	shared + +lib:	$(LIBOBJ) +	$(AR) $(LIB) $(LIBOBJ) +	$(RANLIB) $(LIB) || echo Never mind. +	@touch lib + +shared: lib +	if [ -n "$(SHARED_LIBS)" ]; then \ +		(cd ..; $(MAKE) $(SHARED_LIB)); \ +	fi + +files: +	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO + +links: +	@$(PERL) $(TOP)/util/mklink.pl ../include/openssl $(EXHEADER) +	@$(PERL) $(TOP)/util/mklink.pl ../test $(TEST) +	@$(PERL) $(TOP)/util/mklink.pl ../apps $(APPS) + +install: +	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile... +	@headerlist="$(EXHEADER)"; for i in $$headerlist ; \ +	do  \ +	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \ +	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \ +	done; + +tags: +	ctags $(SRC) + +tests: + +lint: +	lint -DLINT $(INCLUDES) $(SRC)>fluff + +depend: +	@if [ -z "$(THIS)" ]; then \ +	    $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; \ +	else \ +	    $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC); \ +	fi + +dclean: +	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new +	mv -f Makefile.new $(MAKEFILE) + +clean: +	rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +bio_ssl.o: ../include/openssl/asn1.h ../include/openssl/bio.h +bio_ssl.o: ../include/openssl/buffer.h ../include/openssl/comp.h +bio_ssl.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h +bio_ssl.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +bio_ssl.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +bio_ssl.o: ../include/openssl/err.h ../include/openssl/evp.h +bio_ssl.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +bio_ssl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +bio_ssl.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +bio_ssl.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +bio_ssl.o: ../include/openssl/pem.h ../include/openssl/pem2.h +bio_ssl.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +bio_ssl.o: ../include/openssl/safestack.h ../include/openssl/sha.h +bio_ssl.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +bio_ssl.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +bio_ssl.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +bio_ssl.o: ../include/openssl/tls1.h ../include/openssl/x509.h +bio_ssl.o: ../include/openssl/x509_vfy.h bio_ssl.c +d1_both.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_both.o: ../include/openssl/buffer.h ../include/openssl/comp.h +d1_both.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +d1_both.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_both.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_both.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_both.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_both.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_both.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +d1_both.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +d1_both.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +d1_both.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +d1_both.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +d1_both.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +d1_both.o: ../include/openssl/sha.h ../include/openssl/ssl.h +d1_both.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +d1_both.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +d1_both.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +d1_both.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_both.c +d1_both.o: ssl_locl.h +d1_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h +d1_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h +d1_clnt.o: ../include/openssl/dh.h ../include/openssl/dsa.h +d1_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_clnt.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +d1_clnt.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +d1_clnt.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +d1_clnt.o: ../include/openssl/pem.h ../include/openssl/pem2.h +d1_clnt.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +d1_clnt.o: ../include/openssl/rand.h ../include/openssl/rsa.h +d1_clnt.o: ../include/openssl/safestack.h ../include/openssl/sha.h +d1_clnt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +d1_clnt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +d1_clnt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +d1_clnt.o: ../include/openssl/tls1.h ../include/openssl/x509.h +d1_clnt.o: ../include/openssl/x509_vfy.h d1_clnt.c kssl_lcl.h ssl_locl.h +d1_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h +d1_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +d1_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +d1_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +d1_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +d1_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h +d1_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +d1_enc.o: ../include/openssl/rand.h ../include/openssl/rsa.h +d1_enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h +d1_enc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +d1_enc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +d1_enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +d1_enc.o: ../include/openssl/tls1.h ../include/openssl/x509.h +d1_enc.o: ../include/openssl/x509_vfy.h d1_enc.c ssl_locl.h +d1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h +d1_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +d1_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +d1_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +d1_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +d1_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +d1_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +d1_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h +d1_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +d1_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +d1_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +d1_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h +d1_lib.o: ../include/openssl/x509_vfy.h d1_lib.c ssl_locl.h +d1_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h +d1_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +d1_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +d1_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +d1_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +d1_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +d1_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +d1_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h +d1_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +d1_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +d1_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +d1_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h +d1_meth.o: ../include/openssl/x509_vfy.h d1_meth.c ssl_locl.h +d1_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +d1_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +d1_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +d1_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +d1_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +d1_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +d1_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +d1_pkt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +d1_pkt.o: ../include/openssl/sha.h ../include/openssl/ssl.h +d1_pkt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +d1_pkt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +d1_pkt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +d1_pkt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_pkt.c +d1_pkt.o: ssl_locl.h +d1_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +d1_srvr.o: ../include/openssl/bn.h ../include/openssl/buffer.h +d1_srvr.o: ../include/openssl/comp.h ../include/openssl/crypto.h +d1_srvr.o: ../include/openssl/dh.h ../include/openssl/dsa.h +d1_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +d1_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +d1_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +d1_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h +d1_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +d1_srvr.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +d1_srvr.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +d1_srvr.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +d1_srvr.o: ../include/openssl/pem.h ../include/openssl/pem2.h +d1_srvr.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +d1_srvr.o: ../include/openssl/rand.h ../include/openssl/rsa.h +d1_srvr.o: ../include/openssl/safestack.h ../include/openssl/sha.h +d1_srvr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +d1_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +d1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +d1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h +d1_srvr.o: ../include/openssl/x509_vfy.h d1_srvr.c ssl_locl.h +kssl.o: ../include/openssl/asn1.h ../include/openssl/bio.h +kssl.o: ../include/openssl/buffer.h ../include/openssl/comp.h +kssl.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h +kssl.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +kssl.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +kssl.o: ../include/openssl/evp.h ../include/openssl/hmac.h +kssl.o: ../include/openssl/krb5_asn.h ../include/openssl/kssl.h +kssl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +kssl.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +kssl.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +kssl.o: ../include/openssl/pem.h ../include/openssl/pem2.h +kssl.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +kssl.o: ../include/openssl/safestack.h ../include/openssl/sha.h +kssl.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +kssl.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +kssl.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +kssl.o: ../include/openssl/tls1.h ../include/openssl/x509.h +kssl.o: ../include/openssl/x509_vfy.h kssl.c kssl_lcl.h +s23_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s23_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s23_clnt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s23_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s23_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s23_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s23_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s23_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s23_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s23_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s23_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s23_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s23_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s23_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s23_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s23_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s23_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s23_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s23_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_clnt.c +s23_clnt.o: ssl_locl.h +s23_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s23_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s23_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s23_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s23_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s23_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s23_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s23_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s23_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s23_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s23_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s23_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s23_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s23_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s23_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s23_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s23_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s23_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s23_lib.o: ../include/openssl/x509_vfy.h s23_lib.c ssl_locl.h +s23_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s23_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s23_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s23_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s23_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s23_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s23_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s23_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s23_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s23_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s23_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s23_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s23_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s23_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s23_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s23_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s23_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s23_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s23_meth.o: ../include/openssl/x509_vfy.h s23_meth.c ssl_locl.h +s23_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s23_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s23_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s23_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s23_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s23_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s23_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s23_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s23_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s23_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s23_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s23_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s23_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s23_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s23_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s23_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s23_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s23_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s23_pkt.o: ../include/openssl/x509_vfy.h s23_pkt.c ssl_locl.h +s23_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s23_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s23_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s23_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s23_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s23_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s23_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s23_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s23_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s23_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s23_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s23_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s23_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s23_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s23_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s23_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s23_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s23_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s23_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_srvr.c +s23_srvr.o: ssl_locl.h +s2_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s2_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s2_clnt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s2_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s2_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s2_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s2_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s2_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s2_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s2_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s2_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s2_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s2_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s2_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s2_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s2_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s2_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s2_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s2_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_clnt.c +s2_clnt.o: ssl_locl.h +s2_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s2_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s2_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s2_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s2_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s2_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s2_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s2_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s2_enc.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s2_enc.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s2_enc.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s2_enc.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s2_enc.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s2_enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s2_enc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s2_enc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s2_enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s2_enc.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s2_enc.o: ../include/openssl/x509_vfy.h s2_enc.c ssl_locl.h +s2_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s2_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s2_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s2_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s2_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s2_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s2_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s2_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s2_lib.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +s2_lib.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +s2_lib.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +s2_lib.o: ../include/openssl/pem.h ../include/openssl/pem2.h +s2_lib.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +s2_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s2_lib.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s2_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s2_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s2_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s2_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_lib.c +s2_lib.o: ssl_locl.h +s2_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s2_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s2_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s2_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s2_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s2_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s2_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s2_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s2_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s2_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s2_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s2_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s2_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s2_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s2_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s2_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s2_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s2_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s2_meth.o: ../include/openssl/x509_vfy.h s2_meth.c ssl_locl.h +s2_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s2_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s2_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s2_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s2_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s2_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s2_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s2_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s2_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s2_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s2_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s2_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s2_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s2_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s2_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s2_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s2_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s2_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s2_pkt.o: ../include/openssl/x509_vfy.h s2_pkt.c ssl_locl.h +s2_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s2_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s2_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s2_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s2_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s2_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s2_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s2_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s2_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s2_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s2_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s2_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s2_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s2_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s2_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s2_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s2_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s2_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s2_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_srvr.c +s2_srvr.o: ssl_locl.h +s3_both.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_both.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s3_both.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s3_both.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_both.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_both.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s3_both.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s3_both.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s3_both.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s3_both.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s3_both.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s3_both.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s3_both.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s3_both.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s3_both.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s3_both.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s3_both.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s3_both.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s3_both.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_both.c +s3_both.o: ssl_locl.h +s3_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h +s3_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h +s3_clnt.o: ../include/openssl/dh.h ../include/openssl/dsa.h +s3_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h +s3_clnt.o: ../include/openssl/err.h ../include/openssl/evp.h +s3_clnt.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +s3_clnt.o: ../include/openssl/lhash.h ../include/openssl/md5.h +s3_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s3_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s3_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s3_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s3_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s3_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s3_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s3_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s3_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s3_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s3_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h kssl_lcl.h +s3_clnt.o: s3_clnt.c ssl_locl.h +s3_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s3_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s3_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s3_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s3_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s3_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +s3_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +s3_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +s3_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h +s3_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +s3_enc.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s3_enc.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s3_enc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s3_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s3_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s3_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_enc.c +s3_enc.o: ssl_locl.h +s3_lib.o: ../crypto/ec/ec_lcl.h ../e_os.h ../include/openssl/asn1.h +s3_lib.o: ../include/openssl/bio.h ../include/openssl/bn.h +s3_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s3_lib.o: ../include/openssl/crypto.h ../include/openssl/dh.h +s3_lib.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h +s3_lib.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +s3_lib.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +s3_lib.o: ../include/openssl/err.h ../include/openssl/evp.h +s3_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +s3_lib.o: ../include/openssl/lhash.h ../include/openssl/md5.h +s3_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s3_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s3_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s3_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s3_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s3_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s3_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s3_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s3_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s3_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s3_lib.o: ../include/openssl/x509_vfy.h kssl_lcl.h s3_lib.c ssl_locl.h +s3_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s3_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s3_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s3_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s3_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s3_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s3_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s3_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s3_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s3_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s3_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s3_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s3_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s3_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s3_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s3_meth.o: ../include/openssl/x509_vfy.h s3_meth.c ssl_locl.h +s3_pkt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_pkt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s3_pkt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s3_pkt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_pkt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_pkt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s3_pkt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s3_pkt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s3_pkt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s3_pkt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s3_pkt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s3_pkt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s3_pkt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +s3_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s3_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s3_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s3_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s3_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s3_pkt.o: ../include/openssl/x509_vfy.h s3_pkt.c ssl_locl.h +s3_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_srvr.o: ../include/openssl/bn.h ../include/openssl/buffer.h +s3_srvr.o: ../include/openssl/comp.h ../include/openssl/crypto.h +s3_srvr.o: ../include/openssl/dh.h ../include/openssl/dsa.h +s3_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s3_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s3_srvr.o: ../include/openssl/krb5_asn.h ../include/openssl/kssl.h +s3_srvr.o: ../include/openssl/lhash.h ../include/openssl/md5.h +s3_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +s3_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s3_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s3_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s3_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +s3_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s3_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h +s3_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +s3_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s3_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s3_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h kssl_lcl.h +s3_srvr.o: s3_srvr.c ssl_locl.h +ssl_algs.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_algs.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_algs.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +ssl_algs.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_algs.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_algs.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +ssl_algs.o: ../include/openssl/evp.h ../include/openssl/hmac.h +ssl_algs.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +ssl_algs.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +ssl_algs.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_algs.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_algs.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_algs.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +ssl_algs.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_algs.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_algs.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_algs.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_algs.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_algs.o: ../include/openssl/x509_vfy.h ssl_algs.c ssl_locl.h +ssl_asn1.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/asn1_mac.h +ssl_asn1.o: ../include/openssl/bio.h ../include/openssl/buffer.h +ssl_asn1.o: ../include/openssl/comp.h ../include/openssl/crypto.h +ssl_asn1.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h +ssl_asn1.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +ssl_asn1.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +ssl_asn1.o: ../include/openssl/err.h ../include/openssl/evp.h +ssl_asn1.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +ssl_asn1.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +ssl_asn1.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +ssl_asn1.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +ssl_asn1.o: ../include/openssl/pem.h ../include/openssl/pem2.h +ssl_asn1.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +ssl_asn1.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +ssl_asn1.o: ../include/openssl/sha.h ../include/openssl/ssl.h +ssl_asn1.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +ssl_asn1.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +ssl_asn1.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +ssl_asn1.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_asn1.c +ssl_asn1.o: ssl_locl.h +ssl_cert.o: ../crypto/o_dir.h ../e_os.h ../include/openssl/asn1.h +ssl_cert.o: ../include/openssl/bio.h ../include/openssl/bn.h +ssl_cert.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_cert.o: ../include/openssl/conf.h ../include/openssl/crypto.h +ssl_cert.o: ../include/openssl/dh.h ../include/openssl/dsa.h +ssl_cert.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_cert.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_cert.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +ssl_cert.o: ../include/openssl/evp.h ../include/openssl/hmac.h +ssl_cert.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +ssl_cert.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +ssl_cert.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_cert.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_cert.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_cert.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +ssl_cert.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_cert.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_cert.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_cert.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_cert.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_cert.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h +ssl_cert.o: ssl_cert.c ssl_locl.h +ssl_ciph.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_ciph.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_ciph.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +ssl_ciph.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_ciph.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_ciph.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h +ssl_ciph.o: ../include/openssl/err.h ../include/openssl/evp.h +ssl_ciph.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +ssl_ciph.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +ssl_ciph.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +ssl_ciph.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +ssl_ciph.o: ../include/openssl/pem.h ../include/openssl/pem2.h +ssl_ciph.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +ssl_ciph.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +ssl_ciph.o: ../include/openssl/sha.h ../include/openssl/ssl.h +ssl_ciph.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +ssl_ciph.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +ssl_ciph.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +ssl_ciph.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_ciph.c +ssl_ciph.o: ssl_locl.h +ssl_err.o: ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_err.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_err.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h +ssl_err.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +ssl_err.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +ssl_err.o: ../include/openssl/err.h ../include/openssl/evp.h +ssl_err.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +ssl_err.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +ssl_err.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +ssl_err.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +ssl_err.o: ../include/openssl/pem.h ../include/openssl/pem2.h +ssl_err.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +ssl_err.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_err.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_err.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_err.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_err.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_err.o: ../include/openssl/x509_vfy.h ssl_err.c +ssl_err2.o: ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_err2.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_err2.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h +ssl_err2.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +ssl_err2.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +ssl_err2.o: ../include/openssl/err.h ../include/openssl/evp.h +ssl_err2.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +ssl_err2.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +ssl_err2.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +ssl_err2.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +ssl_err2.o: ../include/openssl/pem.h ../include/openssl/pem2.h +ssl_err2.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +ssl_err2.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_err2.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_err2.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_err2.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_err2.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_err2.o: ../include/openssl/x509_vfy.h ssl_err2.c +ssl_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_lib.o: ../include/openssl/conf.h ../include/openssl/crypto.h +ssl_lib.o: ../include/openssl/dh.h ../include/openssl/dsa.h +ssl_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_lib.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h +ssl_lib.o: ../include/openssl/err.h ../include/openssl/evp.h +ssl_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +ssl_lib.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +ssl_lib.o: ../include/openssl/objects.h ../include/openssl/ocsp.h +ssl_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_lib.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +ssl_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +ssl_lib.o: ../include/openssl/sha.h ../include/openssl/ssl.h +ssl_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +ssl_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +ssl_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +ssl_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h +ssl_lib.o: ../include/openssl/x509v3.h kssl_lcl.h ssl_lib.c ssl_locl.h +ssl_rsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_rsa.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_rsa.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +ssl_rsa.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_rsa.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_rsa.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +ssl_rsa.o: ../include/openssl/evp.h ../include/openssl/hmac.h +ssl_rsa.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +ssl_rsa.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +ssl_rsa.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_rsa.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_rsa.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_rsa.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +ssl_rsa.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_rsa.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_rsa.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_rsa.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_rsa.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_rsa.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_rsa.c +ssl_sess.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_sess.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_sess.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +ssl_sess.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_sess.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_sess.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h +ssl_sess.o: ../include/openssl/err.h ../include/openssl/evp.h +ssl_sess.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +ssl_sess.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +ssl_sess.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +ssl_sess.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +ssl_sess.o: ../include/openssl/pem.h ../include/openssl/pem2.h +ssl_sess.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +ssl_sess.o: ../include/openssl/rand.h ../include/openssl/rsa.h +ssl_sess.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_sess.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_sess.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_sess.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_sess.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_sess.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_sess.c +ssl_stat.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_stat.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_stat.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +ssl_stat.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_stat.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_stat.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +ssl_stat.o: ../include/openssl/evp.h ../include/openssl/hmac.h +ssl_stat.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +ssl_stat.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +ssl_stat.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_stat.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_stat.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_stat.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +ssl_stat.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_stat.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_stat.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_stat.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_stat.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_stat.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_stat.c +ssl_txt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_txt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_txt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +ssl_txt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_txt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_txt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +ssl_txt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +ssl_txt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +ssl_txt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +ssl_txt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_txt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_txt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_txt.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +ssl_txt.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_txt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +ssl_txt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +ssl_txt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +ssl_txt.o: ../include/openssl/tls1.h ../include/openssl/x509.h +ssl_txt.o: ../include/openssl/x509_vfy.h ssl_locl.h ssl_txt.c +t1_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_clnt.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_clnt.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +t1_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +t1_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +t1_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h +t1_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +t1_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +t1_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +t1_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h +t1_clnt.o: t1_clnt.c +t1_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +t1_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +t1_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +t1_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h +t1_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +t1_enc.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +t1_enc.o: ../include/openssl/sha.h ../include/openssl/ssl.h +t1_enc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +t1_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +t1_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +t1_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h +t1_enc.o: t1_enc.c +t1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_lib.o: ../include/openssl/conf.h ../include/openssl/crypto.h +t1_lib.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h +t1_lib.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +t1_lib.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +t1_lib.o: ../include/openssl/err.h ../include/openssl/evp.h +t1_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h +t1_lib.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +t1_lib.o: ../include/openssl/objects.h ../include/openssl/ocsp.h +t1_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +t1_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h +t1_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +t1_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +t1_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +t1_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h +t1_lib.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h ssl_locl.h +t1_lib.o: t1_lib.c +t1_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_meth.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_meth.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_meth.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_meth.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_meth.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_meth.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +t1_meth.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_meth.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_meth.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_meth.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +t1_meth.o: ../include/openssl/safestack.h ../include/openssl/sha.h +t1_meth.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +t1_meth.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +t1_meth.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +t1_meth.o: ../include/openssl/tls1.h ../include/openssl/x509.h +t1_meth.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_meth.c +t1_reneg.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_reneg.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_reneg.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_reneg.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_reneg.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_reneg.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_reneg.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_reneg.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_reneg.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +t1_reneg.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_reneg.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_reneg.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_reneg.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +t1_reneg.o: ../include/openssl/safestack.h ../include/openssl/sha.h +t1_reneg.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +t1_reneg.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +t1_reneg.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +t1_reneg.o: ../include/openssl/tls1.h ../include/openssl/x509.h +t1_reneg.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_reneg.c +t1_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +t1_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h +t1_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +t1_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h +t1_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +t1_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +t1_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +t1_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h +t1_srvr.o: t1_srvr.c diff --git a/main/openssl/ssl/bio_ssl.c b/main/openssl/ssl/bio_ssl.c new file mode 100644 index 00000000..eedac8a3 --- /dev/null +++ b/main/openssl/ssl/bio_ssl.c @@ -0,0 +1,603 @@ +/* ssl/bio_ssl.c */ +/* Copyright (C) 1995-1998 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> +#include <openssl/crypto.h> +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/ssl.h> + +static int ssl_write(BIO *h, const char *buf, int num); +static int ssl_read(BIO *h, char *buf, int size); +static int ssl_puts(BIO *h, const char *str); +static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int ssl_new(BIO *h); +static int ssl_free(BIO *data); +static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +typedef struct bio_ssl_st +	{ +	SSL *ssl; /* The ssl handle :-) */ +	/* re-negotiate every time the total number of bytes is this size */ +	int num_renegotiates; +	unsigned long renegotiate_count; +	unsigned long byte_count; +	unsigned long renegotiate_timeout; +	unsigned long last_time; +	} BIO_SSL; + +static BIO_METHOD methods_sslp= +	{ +	BIO_TYPE_SSL,"ssl", +	ssl_write, +	ssl_read, +	ssl_puts, +	NULL, /* ssl_gets, */ +	ssl_ctrl, +	ssl_new, +	ssl_free, +	ssl_callback_ctrl, +	}; + +BIO_METHOD *BIO_f_ssl(void) +	{ +	return(&methods_sslp); +	} + +static int ssl_new(BIO *bi) +	{ +	BIO_SSL *bs; + +	bs=(BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL)); +	if (bs == NULL) +		{ +		BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	memset(bs,0,sizeof(BIO_SSL)); +	bi->init=0; +	bi->ptr=(char *)bs; +	bi->flags=0; +	return(1); +	} + +static int ssl_free(BIO *a) +	{ +	BIO_SSL *bs; + +	if (a == NULL) return(0); +	bs=(BIO_SSL *)a->ptr; +	if (bs->ssl != NULL) SSL_shutdown(bs->ssl); +	if (a->shutdown) +		{ +		if (a->init && (bs->ssl != NULL)) +			SSL_free(bs->ssl); +		a->init=0; +		a->flags=0; +		} +	if (a->ptr != NULL) +		OPENSSL_free(a->ptr); +	return(1); +	} +	 +static int ssl_read(BIO *b, char *out, int outl) +	{ +	int ret=1; +	BIO_SSL *sb; +	SSL *ssl; +	int retry_reason=0; +	int r=0; + +	if (out == NULL) return(0); +	sb=(BIO_SSL *)b->ptr; +	ssl=sb->ssl; + +	BIO_clear_retry_flags(b); + +#if 0 +	if (!SSL_is_init_finished(ssl)) +		{ +/*		ret=SSL_do_handshake(ssl); */ +		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; +		if (sb->renegotiate_count > 0) +			{ +			sb->byte_count+=ret; +			if (sb->byte_count > sb->renegotiate_count) +				{ +				sb->byte_count=0; +				sb->num_renegotiates++; +				SSL_renegotiate(ssl); +				r=1; +				} +			} +		if ((sb->renegotiate_timeout > 0) && (!r)) +			{ +			unsigned long tm; + +			tm=(unsigned long)time(NULL); +			if (tm > sb->last_time+sb->renegotiate_timeout) +				{ +				sb->last_time=tm; +				sb->num_renegotiates++; +				SSL_renegotiate(ssl); +				} +			} + +		break; +	case SSL_ERROR_WANT_READ: +		BIO_set_retry_read(b); +		break; +	case SSL_ERROR_WANT_WRITE: +		BIO_set_retry_write(b); +		break; +	case SSL_ERROR_WANT_X509_LOOKUP: +		BIO_set_retry_special(b); +		retry_reason=BIO_RR_SSL_X509_LOOKUP; +		break; +	case SSL_ERROR_WANT_ACCEPT: +		BIO_set_retry_special(b); +		retry_reason=BIO_RR_ACCEPT; +		break; +	case SSL_ERROR_WANT_CONNECT: +		BIO_set_retry_special(b); +		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; +	return(ret); +	} + +static int ssl_write(BIO *b, const char *out, int outl) +	{ +	int ret,r=0; +	int retry_reason=0; +	SSL *ssl; +	BIO_SSL *bs; + +	if (out == NULL) return(0); +	bs=(BIO_SSL *)b->ptr; +	ssl=bs->ssl; + +	BIO_clear_retry_flags(b); + +/*	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 (bs->renegotiate_count > 0) +			{ +			bs->byte_count+=ret; +			if (bs->byte_count > bs->renegotiate_count) +				{ +				bs->byte_count=0; +				bs->num_renegotiates++; +				SSL_renegotiate(ssl); +				r=1; +				} +			} +		if ((bs->renegotiate_timeout > 0) && (!r)) +			{ +			unsigned long tm; + +			tm=(unsigned long)time(NULL); +			if (tm > bs->last_time+bs->renegotiate_timeout) +				{ +				bs->last_time=tm; +				bs->num_renegotiates++; +				SSL_renegotiate(ssl); +				} +			} +		break; +	case SSL_ERROR_WANT_WRITE: +		BIO_set_retry_write(b); +		break; +	case SSL_ERROR_WANT_READ: +		BIO_set_retry_read(b); +		break; +	case SSL_ERROR_WANT_X509_LOOKUP: +		BIO_set_retry_special(b); +		retry_reason=BIO_RR_SSL_X509_LOOKUP; +		break; +	case SSL_ERROR_WANT_CONNECT: +		BIO_set_retry_special(b); +		retry_reason=BIO_RR_CONNECT; +	case SSL_ERROR_SYSCALL: +	case SSL_ERROR_SSL: +	default: +		break; +		} + +	b->retry_reason=retry_reason; +	return(ret); +	} + +static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) +	{ +	SSL **sslp,*ssl; +	BIO_SSL *bs; +	BIO *dbio,*bio; +	long ret=1; + +	bs=(BIO_SSL *)b->ptr; +	ssl=bs->ssl; +	if ((ssl == NULL)  && (cmd != BIO_C_SET_SSL)) +		return(0); +	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_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_RENEGOTIATE_TIMEOUT: +		ret=bs->renegotiate_timeout; +		if (num < 60) num=5; +		bs->renegotiate_timeout=(unsigned long)num; +		bs->last_time=(unsigned long)time(NULL); +		break; +	case BIO_C_SET_SSL_RENEGOTIATE_BYTES: +		ret=bs->renegotiate_count; +		if ((long)num >=512) +			bs->renegotiate_count=(unsigned long)num; +		break; +	case BIO_C_GET_SSL_NUM_RENEGOTIATES: +		ret=bs->num_renegotiates; +		break; +	case BIO_C_SET_SSL: +		if (ssl != NULL) +			{ +			ssl_free(b); +			if (!ssl_new(b)) +				return 0; +			} +		b->shutdown=(int)num; +		ssl=(SSL *)ptr; +		((BIO_SSL *)b->ptr)->ssl=ssl; +		bio=SSL_get_rbio(ssl); +		if (bio != NULL) +			{ +			if (b->next_bio != NULL) +				BIO_push(bio,b->next_bio); +			b->next_bio=bio; +			CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO); +			} +		b->init=1; +		break; +	case BIO_C_GET_SSL: +		if (ptr != NULL) +			{ +			sslp=(SSL **)ptr; +			*sslp=ssl; +			} +		else +			ret=0; +		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) && (b->next_bio != ssl->rbio)) +			{ +			SSL_set_bio(ssl,b->next_bio,b->next_bio); +			CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO); +			} +		break; +	case BIO_CTRL_POP: +		/* Only detach if we are the BIO explicitly being popped */ +		if (b == ptr) +			{ +			/* Shouldn't happen in practice because the +			 * rbio and wbio are the same when pushed. +			 */ +			if (ssl->rbio != ssl->wbio) +				BIO_free_all(ssl->wbio); +			if (b->next_bio != NULL) +				CRYPTO_add(&b->next_bio->references,-1,CRYPTO_LOCK_BIO); +			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 (((BIO_SSL *)dbio->ptr)->ssl != NULL) +			SSL_free(((BIO_SSL *)dbio->ptr)->ssl); +		((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl); +		((BIO_SSL *)dbio->ptr)->renegotiate_count= +			((BIO_SSL *)b->ptr)->renegotiate_count; +		((BIO_SSL *)dbio->ptr)->byte_count= +			((BIO_SSL *)b->ptr)->byte_count; +		((BIO_SSL *)dbio->ptr)->renegotiate_timeout= +			((BIO_SSL *)b->ptr)->renegotiate_timeout; +		((BIO_SSL *)dbio->ptr)->last_time= +			((BIO_SSL *)b->ptr)->last_time; +		ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL); +		break; +	case BIO_C_GET_FD: +		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); +		break; +	case BIO_CTRL_SET_CALLBACK: +		{ +#if 0 /* FIXME: Should this be used?  -- Richard Levitte */ +		SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		ret = -1; +#else +		ret=0; +#endif +		} +		break; +	case BIO_CTRL_GET_CALLBACK: +		{ +		void (**fptr)(const SSL *xssl,int type,int val); + +		fptr=(void (**)(const SSL *xssl,int type,int val))ptr; +		*fptr=SSL_get_info_callback(ssl); +		} +		break; +	default: +		ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); +		break; +		} +	return(ret); +	} + +static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +	{ +	SSL *ssl; +	BIO_SSL *bs; +	long ret=1; + +	bs=(BIO_SSL *)b->ptr; +	ssl=bs->ssl; +	switch (cmd) +		{ +	case BIO_CTRL_SET_CALLBACK: +		{ +		/* FIXME: setting this via a completely different prototype +		   seems like a crap idea */ +		SSL_set_info_callback(ssl,(void (*)(const SSL *,int,int))fp); +		} +		break; +	default: +		ret=BIO_callback_ctrl(ssl->rbio,cmd,fp); +		break; +		} +	return(ret); +	} + +static int ssl_puts(BIO *bp, const char *str) +	{ +	int n,ret; + +	n=strlen(str); +	ret=BIO_write(bp,str,n); +	return(ret); +	} + +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) +	{ +#ifndef OPENSSL_NO_SOCK +	BIO *ret=NULL,*buf=NULL,*ssl=NULL; + +	if ((buf=BIO_new(BIO_f_buffer())) == NULL) +		return(NULL); +	if ((ssl=BIO_new_ssl_connect(ctx)) == NULL) +		goto err; +	if ((ret=BIO_push(buf,ssl)) == NULL) +		goto err; +	return(ret); +err: +	if (buf != NULL) BIO_free(buf); +	if (ssl != NULL) BIO_free(ssl); +#endif +	return(NULL); +	} + +BIO *BIO_new_ssl_connect(SSL_CTX *ctx) +	{ +	BIO *ret=NULL,*con=NULL,*ssl=NULL; + +	if ((con=BIO_new(BIO_s_connect())) == NULL) +		return(NULL); +	if ((ssl=BIO_new_ssl(ctx,1)) == NULL) +		goto err; +	if ((ret=BIO_push(ssl,con)) == NULL) +		goto err; +	return(ret); +err: +	if (con != NULL) BIO_free(con); +	return(NULL); +	} + +BIO *BIO_new_ssl(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(BIO *t, BIO *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 (	(((BIO_SSL *)t->ptr)->ssl == NULL) ||  +		(((BIO_SSL *)f->ptr)->ssl == NULL)) +		return(0); +	SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl); +	return(1); +	} + +void BIO_ssl_shutdown(BIO *b) +	{ +	SSL *s; + +	while (b != NULL) +		{ +		if (b->method->type == BIO_TYPE_SSL) +			{ +			s=((BIO_SSL *)b->ptr)->ssl; +			SSL_shutdown(s); +			break; +			} +		b=b->next_bio; +		} +	} diff --git a/main/openssl/ssl/d1_both.c b/main/openssl/ssl/d1_both.c new file mode 100644 index 00000000..2180c6d4 --- /dev/null +++ b/main/openssl/ssl/d1_both.c @@ -0,0 +1,1410 @@ +/* ssl/d1_both.c */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 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 <limits.h> +#include <string.h> +#include <stdio.h> +#include "ssl_locl.h" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/x509.h> + +#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) + +#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ +			if ((end) - (start) <= 8) { \ +				long ii; \ +				for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \ +			} else { \ +				long ii; \ +				bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \ +				for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \ +				bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \ +			} } + +#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ +			long ii; \ +			OPENSSL_assert((msg_len) > 0); \ +			is_complete = 1; \ +			if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \ +			if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \ +				if (bitmask[ii] != 0xff) { is_complete = 0; break; } } + +#if 0 +#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \ +			long ii; \ +			printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \ +			printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \ +			printf("\n"); } +#endif + +static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; +static unsigned char bitmask_end_values[]   = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; + +/* XDTLS:  figure out the right values */ +static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; + +static unsigned int dtls1_min_mtu(void); +static unsigned int dtls1_guess_mtu(unsigned int curr_mtu); +static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,  +	unsigned long frag_len); +static unsigned char *dtls1_write_message_header(SSL *s, +	unsigned char *p); +static void dtls1_set_message_header_int(SSL *s, unsigned char mt, +	unsigned long len, unsigned short seq_num, unsigned long frag_off,  +	unsigned long frag_len); +static long dtls1_get_message_fragment(SSL *s, int st1, int stn,  +	long max, int *ok); + +static hm_fragment * +dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) +	{ +	hm_fragment *frag = NULL; +	unsigned char *buf = NULL; +	unsigned char *bitmask = NULL; + +	frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); +	if ( frag == NULL) +		return NULL; + +	if (frag_len) +		{ +		buf = (unsigned char *)OPENSSL_malloc(frag_len); +		if ( buf == NULL) +			{ +			OPENSSL_free(frag); +			return NULL; +			} +		} + +	/* zero length fragment gets zero frag->fragment */ +	frag->fragment = buf; + +	/* Initialize reassembly bitmask if necessary */ +	if (reassembly) +		{ +		bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len)); +		if (bitmask == NULL) +			{ +			if (buf != NULL) OPENSSL_free(buf); +			OPENSSL_free(frag); +			return NULL; +			} +		memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len)); +		} + +	frag->reassembly = bitmask; + +	return frag; +	} + +static void +dtls1_hm_fragment_free(hm_fragment *frag) +	{ +	if (frag->fragment) OPENSSL_free(frag->fragment); +	if (frag->reassembly) OPENSSL_free(frag->reassembly); +	OPENSSL_free(frag); +	} + +/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ +int dtls1_do_write(SSL *s, int type) +	{ +	int ret; +	int curr_mtu; +	unsigned int len, frag_off, mac_size, blocksize; + +	/* AHA!  Figure out the MTU, and stick to the right size */ +	if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) +		{ +		s->d1->mtu =  +			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + +		/* I've seen the kernel return bogus numbers when it doesn't know +		 * (initial write), so just make sure we have a reasonable number */ +		if ( s->d1->mtu < dtls1_min_mtu()) +			{ +			s->d1->mtu = 0; +			s->d1->mtu = dtls1_guess_mtu(s->d1->mtu); +			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,  +				s->d1->mtu, NULL); +			} +		} +#if 0  +	mtu = s->d1->mtu; + +	fprintf(stderr, "using MTU = %d\n", mtu); + +	mtu -= (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); + +	curr_mtu = mtu - BIO_wpending(SSL_get_wbio(s)); + +	if ( curr_mtu > 0) +		mtu = curr_mtu; +	else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0) +		return ret; + +	if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu) +		{ +		ret = BIO_flush(SSL_get_wbio(s)); +		if ( ret <= 0) +			return ret; +		mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); +		} + +	OPENSSL_assert(mtu > 0);  /* should have something reasonable now */ + +#endif + +	if ( s->init_off == 0  && type == SSL3_RT_HANDSHAKE) +		OPENSSL_assert(s->init_num ==  +			(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); + +	if (s->write_hash) +		mac_size = EVP_MD_CTX_size(s->write_hash); +	else +		mac_size = 0; + +	if (s->enc_write_ctx &&  +		(EVP_CIPHER_mode( s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) +		blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher); +	else +		blocksize = 0; + +	frag_off = 0; +	while( s->init_num) +		{ +		curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) -  +			DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; + +		if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH) +			{ +			/* grr.. we could get an error if MTU picked was wrong */ +			ret = BIO_flush(SSL_get_wbio(s)); +			if ( ret <= 0) +				return ret; +			curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH - +				mac_size - blocksize; +			} + +		if ( s->init_num > curr_mtu) +			len = curr_mtu; +		else +			len = s->init_num; + + +		/* XDTLS: this function is too long.  split out the CCS part */ +		if ( type == SSL3_RT_HANDSHAKE) +			{ +			if ( s->init_off != 0) +				{ +				OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH); +				s->init_off -= DTLS1_HM_HEADER_LENGTH; +				s->init_num += DTLS1_HM_HEADER_LENGTH; + +				/* write atleast DTLS1_HM_HEADER_LENGTH bytes */ +				if ( len <= DTLS1_HM_HEADER_LENGTH)   +					len += DTLS1_HM_HEADER_LENGTH; +				} + +			dtls1_fix_message_header(s, frag_off,  +				len - DTLS1_HM_HEADER_LENGTH); + +			dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]); + +			OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH); +			} + +		ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off], +			len); +		if (ret < 0) +			{ +			/* might need to update MTU here, but we don't know +			 * which previous packet caused the failure -- so can't +			 * really retransmit anything.  continue as if everything +			 * is fine and wait for an alert to handle the +			 * retransmit  +			 */ +			if ( BIO_ctrl(SSL_get_wbio(s), +				BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 ) +				s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), +					BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); +			else +				return(-1); +			} +		else +			{ + +			/* bad if this assert fails, only part of the handshake +			 * message got sent.  but why would this happen? */ +			OPENSSL_assert(len == (unsigned int)ret); + +			if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting) +				{ +				/* should not be done for 'Hello Request's, but in that case +				 * we'll ignore the result anyway */ +				unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off]; +				const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; +				int xlen; + +				if (frag_off == 0 && s->version != DTLS1_BAD_VER) +					{ +					/* reconstruct message header is if it +					 * is being sent in single fragment */ +					*p++ = msg_hdr->type; +					l2n3(msg_hdr->msg_len,p); +					s2n (msg_hdr->seq,p); +					l2n3(0,p); +					l2n3(msg_hdr->msg_len,p); +					p  -= DTLS1_HM_HEADER_LENGTH; +					xlen = ret; +					} +				else +					{ +					p  += DTLS1_HM_HEADER_LENGTH; +					xlen = ret - DTLS1_HM_HEADER_LENGTH; +					} + +				ssl3_finish_mac(s, p, xlen); +				} + +			if (ret == s->init_num) +				{ +				if (s->msg_callback) +					s->msg_callback(1, s->version, type, s->init_buf->data,  +						(size_t)(s->init_off + s->init_num), s,  +						s->msg_callback_arg); + +				s->init_off = 0;  /* done writing this message */ +				s->init_num = 0; + +				return(1); +				} +			s->init_off+=ret; +			s->init_num-=ret; +			frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); +			} +		} +	return(0); +	} + + +/* Obtain handshake message of message type 'mt' (any if mt == -1), + * maximum acceptable body length 'max'. + * Read an entire handshake message.  Handshake messages arrive in + * fragments. + */ +long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) +	{ +	int i, al; +	struct hm_header_st *msg_hdr; +	unsigned char *p; +	unsigned long msg_len; + +	/* s3->tmp is used to store messages that are unexpected, caused +	 * by the absence of an optional handshake message */ +	if (s->s3->tmp.reuse_message) +		{ +		s->s3->tmp.reuse_message=0; +		if ((mt >= 0) && (s->s3->tmp.message_type != mt)) +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); +			goto f_err; +			} +		*ok=1; +		s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; +		s->init_num = (int)s->s3->tmp.message_size; +		return s->init_num; +		} + +	msg_hdr = &s->d1->r_msg_hdr; +	memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); + +again: +	i = dtls1_get_message_fragment(s, st1, stn, max, ok); +	if ( i == DTLS1_HM_BAD_FRAGMENT || +		i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */ +		goto again; +	else if ( i <= 0 && !*ok) +		return i; + +	p = (unsigned char *)s->init_buf->data; +	msg_len = msg_hdr->msg_len; + +	/* reconstruct message header */ +	*(p++) = msg_hdr->type; +	l2n3(msg_len,p); +	s2n (msg_hdr->seq,p); +	l2n3(0,p); +	l2n3(msg_len,p); +	if (s->version != DTLS1_BAD_VER) { +		p       -= DTLS1_HM_HEADER_LENGTH; +		msg_len += DTLS1_HM_HEADER_LENGTH; +	} + +	ssl3_finish_mac(s, p, msg_len); +	if (s->msg_callback) +		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, +			p, msg_len, +			s, s->msg_callback_arg); + +	memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); + +	/* Don't change sequence numbers while listening */ +	if (!s->d1->listen) +		s->d1->handshake_read_seq++; + +	s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; +	return s->init_num; + +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +	*ok = 0; +	return -1; +	} + + +static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max) +	{ +	size_t frag_off,frag_len,msg_len; + +	msg_len  = msg_hdr->msg_len; +	frag_off = msg_hdr->frag_off; +	frag_len = msg_hdr->frag_len; + +	/* sanity checking */ +	if ( (frag_off+frag_len) > msg_len) +		{ +		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); +		return SSL_AD_ILLEGAL_PARAMETER; +		} + +	if ( (frag_off+frag_len) > (unsigned long)max) +		{ +		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); +		return SSL_AD_ILLEGAL_PARAMETER; +		} + +	if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */ +		{ +		/* msg_len is limited to 2^24, but is effectively checked +		 * against max above */ +		if (!BUF_MEM_grow_clean(s->init_buf,msg_len+DTLS1_HM_HEADER_LENGTH)) +			{ +			SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB); +			return SSL_AD_INTERNAL_ERROR; +			} + +		s->s3->tmp.message_size  = msg_len; +		s->d1->r_msg_hdr.msg_len = msg_len; +		s->s3->tmp.message_type  = msg_hdr->type; +		s->d1->r_msg_hdr.type    = msg_hdr->type; +		s->d1->r_msg_hdr.seq     = msg_hdr->seq; +		} +	else if (msg_len != s->d1->r_msg_hdr.msg_len) +		{ +		/* They must be playing with us! BTW, failure to enforce +		 * upper limit would open possibility for buffer overrun. */ +		SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE); +		return SSL_AD_ILLEGAL_PARAMETER; +		} + +	return 0; /* no error */ +	} + + +static int +dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) +	{ +	/* (0) check whether the desired fragment is available +	 * if so: +	 * (1) copy over the fragment to s->init_buf->data[] +	 * (2) update s->init_num +	 */ +	pitem *item; +	hm_fragment *frag; +	int al; + +	*ok = 0; +	item = pqueue_peek(s->d1->buffered_messages); +	if ( item == NULL) +		return 0; + +	frag = (hm_fragment *)item->data; +	 +	/* Don't return if reassembly still in progress */ +	if (frag->reassembly != NULL) +		return 0; + +	if ( s->d1->handshake_read_seq == frag->msg_header.seq) +		{ +		unsigned long frag_len = frag->msg_header.frag_len; +		pqueue_pop(s->d1->buffered_messages); + +		al=dtls1_preprocess_fragment(s,&frag->msg_header,max); + +		if (al==0) /* no alert */ +			{ +			unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH; +			memcpy(&p[frag->msg_header.frag_off], +				frag->fragment,frag->msg_header.frag_len); +			} + +		dtls1_hm_fragment_free(frag); +		pitem_free(item); + +		if (al==0) +			{ +			*ok = 1; +			return frag_len; +			} + +		ssl3_send_alert(s,SSL3_AL_FATAL,al); +		s->init_num = 0; +		*ok = 0; +		return -1; +		} +	else +		return 0; +	} + + +static int +dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) +	{ +	hm_fragment *frag = NULL; +	pitem *item = NULL; +	int i = -1, is_complete; +	unsigned char seq64be[8]; +	unsigned long frag_len = msg_hdr->frag_len, max_len; + +	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) +		goto err; + +	/* Determine maximum allowed message size. Depends on (user set) +	 * maximum certificate length, but 16k is minimum. +	 */ +	if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list) +		max_len = s->max_cert_list; +	else +		max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; + +	if ((msg_hdr->frag_off+frag_len) > max_len) +		goto err; + +	/* Try to find item in queue */ +	memset(seq64be,0,sizeof(seq64be)); +	seq64be[6] = (unsigned char) (msg_hdr->seq>>8); +	seq64be[7] = (unsigned char) msg_hdr->seq; +	item = pqueue_find(s->d1->buffered_messages, seq64be); + +	if (item == NULL) +		{ +		frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); +		if ( frag == NULL) +			goto err; +		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); +		frag->msg_header.frag_len = frag->msg_header.msg_len; +		frag->msg_header.frag_off = 0; +		} +	else +		frag = (hm_fragment*) item->data; + +	/* If message is already reassembled, this must be a +	 * retransmit and can be dropped. +	 */ +	if (frag->reassembly == NULL) +		{ +		unsigned char devnull [256]; + +		while (frag_len) +			{ +			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +				devnull, +				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0); +			if (i<=0) goto err; +			frag_len -= i; +			} +		return DTLS1_HM_FRAGMENT_RETRY; +		} + +	/* read the body of the fragment (header has already been read */ +	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +		frag->fragment + msg_hdr->frag_off,frag_len,0); +	if (i<=0 || (unsigned long)i!=frag_len) +		goto err; + +	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, +	                    (long)(msg_hdr->frag_off + frag_len)); + +	RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, +	                           is_complete); + +	if (is_complete) +		{ +		OPENSSL_free(frag->reassembly); +		frag->reassembly = NULL; +		} + +	if (item == NULL) +		{ +		memset(seq64be,0,sizeof(seq64be)); +		seq64be[6] = (unsigned char)(msg_hdr->seq>>8); +		seq64be[7] = (unsigned char)(msg_hdr->seq); + +		item = pitem_new(seq64be, frag); +		if (item == NULL) +			{ +			goto err; +			i = -1; +			} + +		pqueue_insert(s->d1->buffered_messages, item); +		} + +	return DTLS1_HM_FRAGMENT_RETRY; + +err: +	if (frag != NULL) dtls1_hm_fragment_free(frag); +	if (item != NULL) OPENSSL_free(item); +	*ok = 0; +	return i; +	} + + +static int +dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) +{ +	int i=-1; +	hm_fragment *frag = NULL; +	pitem *item = NULL; +	unsigned char seq64be[8]; +	unsigned long frag_len = msg_hdr->frag_len; + +	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) +		goto err; + +	/* Try to find item in queue, to prevent duplicate entries */ +	memset(seq64be,0,sizeof(seq64be)); +	seq64be[6] = (unsigned char) (msg_hdr->seq>>8); +	seq64be[7] = (unsigned char) msg_hdr->seq; +	item = pqueue_find(s->d1->buffered_messages, seq64be); + +	/* If we already have an entry and this one is a fragment, +	 * don't discard it and rather try to reassemble it. +	 */ +	if (item != NULL && frag_len < msg_hdr->msg_len) +		item = NULL; + +	/* Discard the message if sequence number was already there, is +	 * too far in the future, already in the queue or if we received +	 * a FINISHED before the SERVER_HELLO, which then must be a stale +	 * retransmit. +	 */ +	if (msg_hdr->seq <= s->d1->handshake_read_seq || +		msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || +		(s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) +		{ +		unsigned char devnull [256]; + +		while (frag_len) +			{ +			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +				devnull, +				frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0); +			if (i<=0) goto err; +			frag_len -= i; +			} +		} +	else +		{ +		if (frag_len && frag_len < msg_hdr->msg_len) +			return dtls1_reassemble_fragment(s, msg_hdr, ok); + +		frag = dtls1_hm_fragment_new(frag_len, 0); +		if ( frag == NULL) +			goto err; + +		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + +		if (frag_len) +			{ +			/* read the body of the fragment (header has already been read */ +			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +				frag->fragment,frag_len,0); +			if (i<=0 || (unsigned long)i!=frag_len) +				goto err; +			} + +		memset(seq64be,0,sizeof(seq64be)); +		seq64be[6] = (unsigned char)(msg_hdr->seq>>8); +		seq64be[7] = (unsigned char)(msg_hdr->seq); + +		item = pitem_new(seq64be, frag); +		if ( item == NULL) +			goto err; + +		pqueue_insert(s->d1->buffered_messages, item); +		} + +	return DTLS1_HM_FRAGMENT_RETRY; + +err: +	if ( frag != NULL) dtls1_hm_fragment_free(frag); +	if ( item != NULL) OPENSSL_free(item); +	*ok = 0; +	return i; +	} + + +static long +dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) +	{ +	unsigned char wire[DTLS1_HM_HEADER_LENGTH]; +	unsigned long len, frag_off, frag_len; +	int i,al; +	struct hm_header_st msg_hdr; + +	/* see if we have the required fragment already */ +	if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok) +		{ +		if (*ok)	s->init_num = frag_len; +		return frag_len; +		} + +	/* read handshake message header */ +	i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire, +		DTLS1_HM_HEADER_LENGTH, 0); +	if (i <= 0) 	/* nbio, or an error */ +		{ +		s->rwstate=SSL_READING; +		*ok = 0; +		return i; +		} +	OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH); + +	/* parse the message fragment header */ +	dtls1_get_message_header(wire, &msg_hdr); + +	/*  +	 * if this is a future (or stale) message it gets buffered +	 * (or dropped)--no further processing at this time +	 * While listening, we accept seq 1 (ClientHello with cookie) +	 * although we're still expecting seq 0 (ClientHello) +	 */ +	if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1)) +		return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); + +	len = msg_hdr.msg_len; +	frag_off = msg_hdr.frag_off; +	frag_len = msg_hdr.frag_len; + +	if (frag_len && frag_len < len) +		return dtls1_reassemble_fragment(s, &msg_hdr, ok); + +	if (!s->server && s->d1->r_msg_hdr.frag_off == 0 && +		wire[0] == SSL3_MT_HELLO_REQUEST) +		{ +		/* The server may always send 'Hello Request' messages -- +		 * we are doing a handshake anyway now, so ignore them +		 * if their format is correct. Does not count for +		 * 'Finished' MAC. */ +		if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) +			{ +			if (s->msg_callback) +				s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,  +					wire, DTLS1_HM_HEADER_LENGTH, s,  +					s->msg_callback_arg); +			 +			s->init_num = 0; +			return dtls1_get_message_fragment(s, st1, stn, +				max, ok); +			} +		else /* Incorrectly formated Hello request */ +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); +			goto f_err; +			} +		} + +	if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max))) +		goto f_err; + +	/* XDTLS:  ressurect this when restart is in place */ +	s->state=stn; + +	if ( frag_len > 0) +		{ +		unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH; + +		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +			&p[frag_off],frag_len,0); +		/* XDTLS:  fix this--message fragments cannot span multiple packets */ +		if (i <= 0) +			{ +			s->rwstate=SSL_READING; +			*ok = 0; +			return i; +			} +		} +	else +		i = 0; + +	/* XDTLS:  an incorrectly formatted fragment should cause the  +	 * handshake to fail */ +	OPENSSL_assert(i == (int)frag_len); + +	*ok = 1; + +	/* Note that s->init_num is *not* used as current offset in +	 * s->init_buf->data, but as a counter summing up fragments' +	 * lengths: as soon as they sum up to handshake packet +	 * length, we assume we have got all the fragments. */ +	s->init_num = frag_len; +	return frag_len; + +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +	s->init_num = 0; + +	*ok=0; +	return(-1); +	} + +int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen) +	{ +	unsigned char *p,*d; +	int i; +	unsigned long l; + +	if (s->state == a) +		{ +		d=(unsigned char *)s->init_buf->data; +		p= &(d[DTLS1_HM_HEADER_LENGTH]); + +		i=s->method->ssl3_enc->final_finish_mac(s, +			sender,slen,s->s3->tmp.finish_md); +		s->s3->tmp.finish_md_len = i; +		memcpy(p, s->s3->tmp.finish_md, i); +		p+=i; +		l=i; + +	/* Copy the finished so we can use it for +	 * renegotiation checks +	 */ +	if(s->type == SSL_ST_CONNECT) +		{ +		OPENSSL_assert(i <= EVP_MAX_MD_SIZE); +		memcpy(s->s3->previous_client_finished,  +		       s->s3->tmp.finish_md, i); +		s->s3->previous_client_finished_len=i; +		} +	else +		{ +		OPENSSL_assert(i <= EVP_MAX_MD_SIZE); +		memcpy(s->s3->previous_server_finished,  +		       s->s3->tmp.finish_md, i); +		s->s3->previous_server_finished_len=i; +		} + +#ifdef OPENSSL_SYS_WIN16 +		/* MSVC 1.5 does not clear the top bytes of the word unless +		 * I do this. +		 */ +		l&=0xffff; +#endif + +		d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l); +		s->init_num=(int)l+DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); + +		s->state=b; +		} + +	/* SSL3_ST_SEND_xxxxxx_HELLO_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +/* 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 dtls1_send_change_cipher_spec(SSL *s, int a, int b) +	{  +	unsigned char *p; + +	if (s->state == a) +		{ +		p=(unsigned char *)s->init_buf->data; +		*p++=SSL3_MT_CCS; +		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; +		s->init_num=DTLS1_CCS_HEADER_LENGTH; + +		if (s->version == DTLS1_BAD_VER) { +			s->d1->next_handshake_write_seq++; +			s2n(s->d1->handshake_write_seq,p); +			s->init_num+=2; +		} + +		s->init_off=0; + +		dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,  +			s->d1->handshake_write_seq, 0, 0); + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 1); + +		s->state=b; +		} + +	/* SSL3_ST_CW_CHANGE_B */ +	return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); +	} + +static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) +	{ +	int n; +	unsigned char *p; + +	n=i2d_X509(x,NULL); +	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) +		{ +		SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); +		return 0; +		} +	p=(unsigned char *)&(buf->data[*l]); +	l2n3(n,p); +	i2d_X509(x,&p); +	*l+=n+3; + +	return 1; +	} +unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) +	{ +	unsigned char *p; +	int i; +	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; +	BUF_MEM *buf; + +	/* TLSv1 sends a chain with nothing in it, instead of an alert */ +	buf=s->init_buf; +	if (!BUF_MEM_grow_clean(buf,10)) +		{ +		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); +		return(0); +		} +	if (x != NULL) +		{ +		X509_STORE_CTX xs_ctx; + +		if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) +  			{ +  			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); +  			return(0); +  			} +   +		X509_verify_cert(&xs_ctx); +		/* Don't leave errors in the queue */ +		ERR_clear_error(); +		for (i=0; i < sk_X509_num(xs_ctx.chain); i++) +  			{ +			x = sk_X509_value(xs_ctx.chain, i); + +			if (!dtls1_add_cert_to_buf(buf, &l, x)) +  				{ +				X509_STORE_CTX_cleanup(&xs_ctx); +				return 0; +  				} +  			} +  		X509_STORE_CTX_cleanup(&xs_ctx); +  		} +  	/* Thawte special :-) */ +	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++) +		{ +		x=sk_X509_value(s->ctx->extra_certs,i); +		if (!dtls1_add_cert_to_buf(buf, &l, x)) +			return 0; +		} + +	l-= (3 + DTLS1_HM_HEADER_LENGTH); + +	p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); +	l2n3(l,p); +	l+=3; +	p=(unsigned char *)&(buf->data[0]); +	p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l); + +	l+=DTLS1_HM_HEADER_LENGTH; +	return(l); +	} + +int dtls1_read_failed(SSL *s, int code) +	{ +	if ( code > 0) +		{ +		fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__); +		return 1; +		} + +	if (!dtls1_is_timer_expired(s)) +		{ +		/* not a timeout, none of our business,  +		   let higher layers handle this.  in fact it's probably an error */ +		return code; +		} + +	if ( ! SSL_in_init(s))  /* done, no need to send a retransmit */ +		{ +		BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); +		return code; +		} + +#if 0 /* for now, each alert contains only one record number */ +	item = pqueue_peek(state->rcvd_records); +	if ( item ) +		{ +		/* send an alert immediately for all the missing records */ +		} +	else +#endif + +#if 0  /* no more alert sending, just retransmit the last set of messages */ +	if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT) +		ssl3_send_alert(s,SSL3_AL_WARNING, +			DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); +#endif + +	return dtls1_handle_timeout(s); +	} + +int +dtls1_get_queue_priority(unsigned short seq, int is_ccs) +	{ +	/* The index of the retransmission queue actually is the message sequence number, +	 * since the queue only contains messages of a single handshake. However, the +	 * ChangeCipherSpec has no message sequence number and so using only the sequence +	 * will result in the CCS and Finished having the same index. To prevent this, +	 * the sequence number is multiplied by 2. In case of a CCS 1 is subtracted. +	 * This does not only differ CSS and Finished, it also maintains the order of the +	 * index (important for priority queues) and fits in the unsigned short variable. +	 */	 +	return seq * 2 - is_ccs; +	} + +int +dtls1_retransmit_buffered_messages(SSL *s) +	{ +	pqueue sent = s->d1->sent_messages; +	piterator iter; +	pitem *item; +	hm_fragment *frag; +	int found = 0; + +	iter = pqueue_iterator(sent); + +	for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) +		{ +		frag = (hm_fragment *)item->data; +			if ( dtls1_retransmit_message(s, +				(unsigned short)dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs), +				0, &found) <= 0 && found) +			{ +			fprintf(stderr, "dtls1_retransmit_message() failed\n"); +			return -1; +			} +		} + +	return 1; +	} + +int +dtls1_buffer_message(SSL *s, int is_ccs) +	{ +	pitem *item; +	hm_fragment *frag; +	unsigned char seq64be[8]; + +	/* this function is called immediately after a message has  +	 * been serialized */ +	OPENSSL_assert(s->init_off == 0); + +	frag = dtls1_hm_fragment_new(s->init_num, 0); + +	memcpy(frag->fragment, s->init_buf->data, s->init_num); + +	if ( is_ccs) +		{ +		OPENSSL_assert(s->d1->w_msg_hdr.msg_len +  +			       ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_num); +		} +	else +		{ +		OPENSSL_assert(s->d1->w_msg_hdr.msg_len +  +			DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num); +		} + +	frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; +	frag->msg_header.seq = s->d1->w_msg_hdr.seq; +	frag->msg_header.type = s->d1->w_msg_hdr.type; +	frag->msg_header.frag_off = 0; +	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; +	frag->msg_header.is_ccs = is_ccs; + +	/* save current state*/ +	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx; +	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash; +	frag->msg_header.saved_retransmit_state.compress = s->compress; +	frag->msg_header.saved_retransmit_state.session = s->session; +	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch; +	 +	memset(seq64be,0,sizeof(seq64be)); +	seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq, +														  frag->msg_header.is_ccs)>>8); +	seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq, +														  frag->msg_header.is_ccs)); + +	item = pitem_new(seq64be, frag); +	if ( item == NULL) +		{ +		dtls1_hm_fragment_free(frag); +		return 0; +		} + +#if 0 +	fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type); +	fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len); +	fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num); +#endif + +	pqueue_insert(s->d1->sent_messages, item); +	return 1; +	} + +int +dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, +	int *found) +	{ +	int ret; +	/* XDTLS: for now assuming that read/writes are blocking */ +	pitem *item; +	hm_fragment *frag ; +	unsigned long header_length; +	unsigned char seq64be[8]; +	struct dtls1_retransmit_state saved_state; +	unsigned char save_write_sequence[8]; + +	/* +	  OPENSSL_assert(s->init_num == 0); +	  OPENSSL_assert(s->init_off == 0); +	 */ + +	/* XDTLS:  the requested message ought to be found, otherwise error */ +	memset(seq64be,0,sizeof(seq64be)); +	seq64be[6] = (unsigned char)(seq>>8); +	seq64be[7] = (unsigned char)seq; + +	item = pqueue_find(s->d1->sent_messages, seq64be); +	if ( item == NULL) +		{ +		fprintf(stderr, "retransmit:  message %d non-existant\n", seq); +		*found = 0; +		return 0; +		} + +	*found = 1; +	frag = (hm_fragment *)item->data; + +	if ( frag->msg_header.is_ccs) +		header_length = DTLS1_CCS_HEADER_LENGTH; +	else +		header_length = DTLS1_HM_HEADER_LENGTH; + +	memcpy(s->init_buf->data, frag->fragment,  +		frag->msg_header.msg_len + header_length); +		s->init_num = frag->msg_header.msg_len + header_length; + +	dtls1_set_message_header_int(s, frag->msg_header.type,  +		frag->msg_header.msg_len, frag->msg_header.seq, 0,  +		frag->msg_header.frag_len); + +	/* save current state */ +	saved_state.enc_write_ctx = s->enc_write_ctx; +	saved_state.write_hash = s->write_hash; +	saved_state.compress = s->compress; +	saved_state.session = s->session; +	saved_state.epoch = s->d1->w_epoch; +	saved_state.epoch = s->d1->w_epoch; +	 +	s->d1->retransmitting = 1; +	 +	/* restore state in which the message was originally sent */ +	s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx; +	s->write_hash = frag->msg_header.saved_retransmit_state.write_hash; +	s->compress = frag->msg_header.saved_retransmit_state.compress; +	s->session = frag->msg_header.saved_retransmit_state.session; +	s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch; +	 +	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1) +	{ +		memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence)); +		memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence)); +	} +	 +	ret = dtls1_do_write(s, frag->msg_header.is_ccs ?  +						 SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); +	 +	/* restore current state */ +	s->enc_write_ctx = saved_state.enc_write_ctx; +	s->write_hash = saved_state.write_hash; +	s->compress = saved_state.compress; +	s->session = saved_state.session; +	s->d1->w_epoch = saved_state.epoch; +	 +	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1) +	{ +		memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence)); +		memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence)); +	} + +	s->d1->retransmitting = 0; + +	(void)BIO_flush(SSL_get_wbio(s)); +	return ret; +	} + +/* call this function when the buffered messages are no longer needed */ +void +dtls1_clear_record_buffer(SSL *s) +	{ +	pitem *item; + +	for(item = pqueue_pop(s->d1->sent_messages); +		item != NULL; item = pqueue_pop(s->d1->sent_messages)) +		{ +		dtls1_hm_fragment_free((hm_fragment *)item->data); +		pitem_free(item); +		} +	} + + +unsigned char * +dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, +			unsigned long len, unsigned long frag_off, unsigned long frag_len) +	{ +	/* Don't change sequence numbers while listening */ +	if (frag_off == 0 && !s->d1->listen) +		{ +		s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; +		s->d1->next_handshake_write_seq++; +		} + +	dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, +		frag_off, frag_len); + +	return p += DTLS1_HM_HEADER_LENGTH; +	} + + +/* don't actually do the writing, wait till the MTU has been retrieved */ +static void +dtls1_set_message_header_int(SSL *s, unsigned char mt, +			    unsigned long len, unsigned short seq_num, unsigned long frag_off, +			    unsigned long frag_len) +	{ +	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + +	msg_hdr->type = mt; +	msg_hdr->msg_len = len; +	msg_hdr->seq = seq_num; +	msg_hdr->frag_off = frag_off; +	msg_hdr->frag_len = frag_len; +	} + +static void +dtls1_fix_message_header(SSL *s, unsigned long frag_off, +			unsigned long frag_len) +	{ +	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + +	msg_hdr->frag_off = frag_off; +	msg_hdr->frag_len = frag_len; +	} + +static unsigned char * +dtls1_write_message_header(SSL *s, unsigned char *p) +	{ +	struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + +	*p++ = msg_hdr->type; +	l2n3(msg_hdr->msg_len, p); + +	s2n(msg_hdr->seq, p); +	l2n3(msg_hdr->frag_off, p); +	l2n3(msg_hdr->frag_len, p); + +	return p; +	} + +static unsigned int  +dtls1_min_mtu(void) +	{ +	return (g_probable_mtu[(sizeof(g_probable_mtu) /  +		sizeof(g_probable_mtu[0])) - 1]); +	} + +static unsigned int  +dtls1_guess_mtu(unsigned int curr_mtu) +	{ +	unsigned int i; + +	if ( curr_mtu == 0 ) +		return g_probable_mtu[0] ; + +	for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++) +		if ( curr_mtu > g_probable_mtu[i]) +			return g_probable_mtu[i]; + +	return curr_mtu; +	} + +void +dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) +	{ +	memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); +	msg_hdr->type = *(data++); +	n2l3(data, msg_hdr->msg_len); + +	n2s(data, msg_hdr->seq); +	n2l3(data, msg_hdr->frag_off); +	n2l3(data, msg_hdr->frag_len); +	} + +void +dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr) +	{ +	memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st)); + +	ccs_hdr->type = *(data++); +	} diff --git a/main/openssl/ssl/d1_clnt.c b/main/openssl/ssl/d1_clnt.c new file mode 100644 index 00000000..57766717 --- /dev/null +++ b/main/openssl/ssl/d1_clnt.c @@ -0,0 +1,1542 @@ +/* ssl/d1_clnt.c */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 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" +#ifndef OPENSSL_NO_KRB5 +#include "kssl_lcl.h" +#endif +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/md5.h> +#include <openssl/bn.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif + +static const SSL_METHOD *dtls1_get_client_method(int ver); +static int dtls1_get_hello_verify(SSL *s); + +static const SSL_METHOD *dtls1_get_client_method(int ver) +	{ +	if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER) +		return(DTLSv1_client_method()); +	else +		return(NULL); +	} + +IMPLEMENT_dtls1_meth_func(DTLSv1_client_method, +			ssl_undefined_function, +			dtls1_connect, +			dtls1_get_client_method) + +int dtls1_connect(SSL *s) +	{ +	BUF_MEM *buf=NULL; +	unsigned long Time=(unsigned long)time(NULL); +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int ret= -1; +	int new_state,state,skip=0;; + +	RAND_add(&Time,sizeof(Time),0); +	ERR_clear_error(); +	clear_sys_error(); + +	if (s->info_callback != NULL) +		cb=s->info_callback; +	else if (s->ctx->info_callback != NULL) +		cb=s->ctx->info_callback; +	 +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);  + +	for (;;) +		{ +		state=s->state; + +		switch(s->state) +			{ +		case SSL_ST_RENEGOTIATE: +			s->new_session=1; +			s->state=SSL_ST_CONNECT; +			s->ctx->stats.sess_connect_renegotiate++; +			/* break */ +		case SSL_ST_BEFORE: +		case SSL_ST_CONNECT: +		case SSL_ST_BEFORE|SSL_ST_CONNECT: +		case SSL_ST_OK|SSL_ST_CONNECT: + +			s->server=0; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) && +			    (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00)) +				{ +				SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR); +				ret = -1; +				goto end; +				} +				 +			/* s->version=SSL3_VERSION; */ +			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; +				buf=NULL; +				} + +			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } + +			/* setup buffing BIO */ +			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; } + +			/* don't push the buffering BIO quite yet */ + +			s->state=SSL3_ST_CW_CLNT_HELLO_A; +			s->ctx->stats.sess_connect++; +			s->init_num=0; +			/* mark client_random uninitialized */ +			memset(s->s3->client_random,0,sizeof(s->s3->client_random)); +			s->d1->send_cookie = 0; +			s->hit = 0; +			break; + +		case SSL3_ST_CW_CLNT_HELLO_A: +		case SSL3_ST_CW_CLNT_HELLO_B: + +			s->shutdown=0; + +			/* every DTLS ClientHello resets Finished MAC */ +			ssl3_init_finished_mac(s); + +			dtls1_start_timer(s); +			ret=dtls1_client_hello(s); +			if (ret <= 0) goto end; + +			if ( s->d1->send_cookie) +				{ +				s->state=SSL3_ST_CW_FLUSH; +				s->s3->tmp.next_state=SSL3_ST_CR_SRVR_HELLO_A; +				} +			else +				s->state=SSL3_ST_CR_SRVR_HELLO_A; + +			s->init_num=0; + +			/* turn on buffering for the next lot of output */ +			if (s->bbio != s->wbio) +				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; +			else +				{ +				dtls1_stop_timer(s); +				if (s->hit) +					s->state=SSL3_ST_CR_FINISHED_A; +				else +					s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; +				} +			s->init_num=0; +			break; + +		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: +		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + +			ret = dtls1_get_hello_verify(s); +			if ( ret <= 0) +				goto end; +			dtls1_stop_timer(s); +			if ( s->d1->send_cookie) /* start again, with a cookie */ +				s->state=SSL3_ST_CW_CLNT_HELLO_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: +#ifndef OPENSSL_NO_TLSEXT +			ret=ssl3_check_finished(s); +			if (ret <= 0) goto end; +			if (ret == 2) +				{ +				s->hit = 1; +				if (s->tlsext_ticket_expected) +					s->state=SSL3_ST_CR_SESSION_TICKET_A; +				else +					s->state=SSL3_ST_CR_FINISHED_A; +				s->init_num=0; +				break; +				} +#endif +			/* Check if it is anon DH or PSK */ +			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && +			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +				{ +				ret=ssl3_get_server_certificate(s); +				if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT +				if (s->tlsext_status_expected) +					s->state=SSL3_ST_CR_CERT_STATUS_A; +				else +					s->state=SSL3_ST_CR_KEY_EXCH_A; +				} +			else +				{ +				skip = 1; +				s->state=SSL3_ST_CR_KEY_EXCH_A; +				} +#else +				} +			else +				skip=1; + +			s->state=SSL3_ST_CR_KEY_EXCH_A; +#endif +			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: +		case SSL3_ST_CW_CERT_D: +			dtls1_start_timer(s); +			ret=dtls1_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: +			dtls1_start_timer(s); +			ret=dtls1_send_client_key_exchange(s); +			if (ret <= 0) goto end; +			/* EAY EAY EAY need to check for DH fix cert +			 * sent back */ +			/* For TLS, cert_req is set to 2, so a cert chain +			 * of nothing is sent, but no verify packet is sent */ +			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: +			dtls1_start_timer(s); +			ret=dtls1_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: +			if (!s->hit) +				dtls1_start_timer(s); +			ret=dtls1_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; +#ifdef OPENSSL_NO_COMP +			s->session->compress_meth=0; +#else +			if (s->s3->tmp.new_compression == NULL) +				s->session->compress_meth=0; +			else +				s->session->compress_meth= +					s->s3->tmp.new_compression->id; +#endif +			if (!s->method->ssl3_enc->setup_key_block(s)) +				{ +				ret= -1; +				goto end; +				} + +			if (!s->method->ssl3_enc->change_cipher_state(s, +				SSL3_CHANGE_CIPHER_CLIENT_WRITE)) +				{ +				ret= -1; +				goto end; +				} +			 +			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); +			break; + +		case SSL3_ST_CW_FINISHED_A: +		case SSL3_ST_CW_FINISHED_B: +			if (!s->hit) +				dtls1_start_timer(s); +			ret=dtls1_send_finished(s, +				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B, +				s->method->ssl3_enc->client_finished_label, +				s->method->ssl3_enc->client_finished_label_len); +			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 +				{ +#ifndef OPENSSL_NO_TLSEXT +				/* Allow NewSessionTicket if ticket expected */ +				if (s->tlsext_ticket_expected) +					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A; +				else +#endif +				 +				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A; +				} +			s->init_num=0; +			break; + +#ifndef OPENSSL_NO_TLSEXT +		case SSL3_ST_CR_SESSION_TICKET_A: +		case SSL3_ST_CR_SESSION_TICKET_B: +			ret=ssl3_get_new_session_ticket(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_CR_FINISHED_A; +			s->init_num=0; +		break; + +		case SSL3_ST_CR_CERT_STATUS_A: +		case SSL3_ST_CR_CERT_STATUS_B: +			ret=ssl3_get_cert_status(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_CR_KEY_EXCH_A; +			s->init_num=0; +		break; +#endif + +		case SSL3_ST_CR_FINISHED_A: +		case SSL3_ST_CR_FINISHED_B: +			s->d1->change_cipher_spec_ok = 1; +			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, +				SSL3_ST_CR_FINISHED_B); +			if (ret <= 0) goto end; +			dtls1_stop_timer(s); + +			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: +			s->rwstate=SSL_WRITING; +			if (BIO_flush(s->wbio) <= 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); + +#if 0 +			if (s->init_buf != NULL) +				{ +				BUF_MEM_free(s->init_buf); +				s->init_buf=NULL; +				} +#endif + +			/* If we are not 'joining' the last two packets, +			 * remove the buffering now */ +			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER)) +				ssl_free_wbio_buffer(s); +			/* else do it later in ssl3_write */ + +			s->init_num=0; +			s->new_session=0; + +			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); +			if (s->hit) s->ctx->stats.sess_hit++; + +			ret=1; +			/* s->server=0; */ +			s->handshake_func=dtls1_connect; +			s->ctx->stats.sess_connect_good++; + +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + +			/* done with handshaking */ +			s->d1->handshake_read_seq  = 0; +			s->d1->next_handshake_write_seq = 0; +			goto end; +			/* break; */ +			 +		default: +			SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE); +			ret= -1; +			goto end; +			/* break; */ +			} + +		/* did we do anything */ +		if (!s->s3->tmp.reuse_message && !skip) +			{ +			if (s->debug) +				{ +				if ((ret=BIO_flush(s->wbio)) <= 0) +					goto end; +				} + +			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: +	s->in_handshake--; +	if (buf != NULL) +		BUF_MEM_free(buf); +	if (cb != NULL) +		cb(s,SSL_CB_CONNECT_EXIT,ret); +	return(ret); +	} + +int dtls1_client_hello(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	unsigned int i,j; +	unsigned long Time,l; +	SSL_COMP *comp; + +	buf=(unsigned char *)s->init_buf->data; +	if (s->state == SSL3_ST_CW_CLNT_HELLO_A) +		{ +		SSL_SESSION *sess = s->session; +		if ((s->session == NULL) || +			(s->session->ssl_version != s->version) || +#ifdef OPENSSL_NO_TLSEXT +			!sess->session_id_length || +#else +			(!sess->session_id_length && !sess->tlsext_tick) || +#endif +			(s->session->not_resumable)) +			{ +		        if (!s->session_creation_enabled) +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +				SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); +				goto err; +				} +			if (!ssl_get_new_session(s,0)) +				goto err; +			} +		/* else use the pre-loaded session */ + +		p=s->s3->client_random; + +		/* if client_random is initialized, reuse it, we are +		 * required to use same upon reply to HelloVerify */ +		for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ; +		if (i==sizeof(s->s3->client_random)) +			{ +			Time=(unsigned long)time(NULL);	/* Time */ +			l2n(Time,p); +			RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4); +			} + +		/* Do the message type and length last */ +		d=p= &(buf[DTLS1_HM_HEADER_LENGTH]); + +		*(p++)=s->version>>8; +		*(p++)=s->version&0xff; +		s->client_version=s->version; + +		/* 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) +			{ +			if (i > sizeof s->session->session_id) +				{ +				SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); +				goto err; +				} +			memcpy(p,s->session->session_id,i); +			p+=i; +			} +		 +		/* cookie stuff */ +		if ( s->d1->cookie_len > sizeof(s->d1->cookie)) +			{ +			SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); +			goto err; +			} +		*(p++) = s->d1->cookie_len; +		memcpy(p, s->d1->cookie, s->d1->cookie_len); +		p += s->d1->cookie_len; + +		/* Ciphers supported */ +		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0); +		if (i == 0) +			{ +			SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); +			goto err; +			} +		s2n(i,p); +		p+=i; + +		/* COMPRESSION */ +		if (s->ctx->comp_methods == NULL) +			j=0; +		else +			j=sk_SSL_COMP_num(s->ctx->comp_methods); +		*(p++)=1+j; +		for (i=0; i<j; i++) +			{ +			comp=sk_SSL_COMP_value(s->ctx->comp_methods,i); +			*(p++)=comp->id; +			} +		*(p++)=0; /* Add the NULL method */ + +#ifndef OPENSSL_NO_TLSEXT +		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) +			{ +			SSLerr(SSL_F_DTLS1_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); +			goto err; +			} +#endif		 + +		l=(p-d); +		d=buf; + +		d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO, l, 0, l); + +		s->state=SSL3_ST_CW_CLNT_HELLO_B; +		/* number of bytes to write */ +		s->init_num=p-buf; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} + +	/* SSL3_ST_CW_CLNT_HELLO_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +err: +	return(-1); +	} + +static int dtls1_get_hello_verify(SSL *s) +	{ +	int n, al, ok = 0; +	unsigned char *data; +	unsigned int cookie_len; + +	n=s->method->ssl_get_message(s, +		DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A, +		DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, +		-1, +		s->max_cert_list, +		&ok); + +	if (!ok) return((int)n); + +	if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) +		{ +		s->d1->send_cookie = 0; +		s->s3->tmp.reuse_message=1; +		return(1); +		} + +	data = (unsigned char *)s->init_msg; + +	if ((data[0] != (s->version>>8)) || (data[1] != (s->version&0xff))) +		{ +		SSLerr(SSL_F_DTLS1_GET_HELLO_VERIFY,SSL_R_WRONG_SSL_VERSION); +		s->version=(s->version&0xff00)|data[1]; +		al = SSL_AD_PROTOCOL_VERSION; +		goto f_err; +		} +	data+=2; + +	cookie_len = *(data++); +	if ( cookie_len > sizeof(s->d1->cookie)) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		goto f_err; +		} + +	memcpy(s->d1->cookie, data, cookie_len); +	s->d1->cookie_len = cookie_len; + +	s->d1->send_cookie = 1; +	return 1; + +f_err: +	ssl3_send_alert(s, SSL3_AL_FATAL, al); +	return -1; +	} + +int dtls1_send_client_key_exchange(SSL *s) +	{ +	unsigned char *p,*d; +	int n; +	unsigned long alg_k; +#ifndef OPENSSL_NO_RSA +	unsigned char *q; +	EVP_PKEY *pkey=NULL; +#endif +#ifndef OPENSSL_NO_KRB5 +        KSSL_ERR kssl_err; +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_ECDH +	EC_KEY *clnt_ecdh = NULL; +	const EC_POINT *srvr_ecpoint = NULL; +	EVP_PKEY *srvr_pub_pkey = NULL; +	unsigned char *encodedPoint = NULL; +	int encoded_pt_len = 0; +	BN_CTX * bn_ctx = NULL; +#endif + +	if (s->state == SSL3_ST_CW_KEY_EXCH_A) +		{ +		d=(unsigned char *)s->init_buf->data; +		p= &(d[DTLS1_HM_HEADER_LENGTH]); +		 +		alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + +                /* Fool emacs indentation */ +                if (0) {} +#ifndef OPENSSL_NO_RSA +		else if (alg_k & SSL_kRSA) +			{ +			RSA *rsa; +			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + +			if (s->session->sess_cert->peer_rsa_tmp != NULL) +				rsa=s->session->sess_cert->peer_rsa_tmp; +			else +				{ +				pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); +				if ((pkey == NULL) || +					(pkey->type != EVP_PKEY_RSA) || +					(pkey->pkey.rsa == NULL)) +					{ +					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); +					goto err; +					} +				rsa=pkey->pkey.rsa; +				EVP_PKEY_free(pkey); +				} +				 +			tmp_buf[0]=s->client_version>>8; +			tmp_buf[1]=s->client_version&0xff; +			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0) +					goto err; + +			s->session->master_key_length=sizeof tmp_buf; + +			q=p; +			/* Fix buf for TLS and [incidentally] DTLS */ +			if (s->version > SSL3_VERSION) +				p+=2; +			n=RSA_public_encrypt(sizeof tmp_buf, +				tmp_buf,p,rsa,RSA_PKCS1_PADDING); +#ifdef PKCS1_CHECK +			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++; +			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70; +#endif +			if (n <= 0) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT); +				goto err; +				} + +			/* Fix buf for TLS and [incidentally] DTLS */ +			if (s->version > SSL3_VERSION) +				{ +				s2n(n,q); +				n+=2; +				} + +			s->session->master_key_length= +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, +					tmp_buf,sizeof tmp_buf); +			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf); +			} +#endif +#ifndef OPENSSL_NO_KRB5 +		else if (alg_k & SSL_kKRB5) +                        { +                        krb5_error_code	krb5rc; +                        KSSL_CTX	*kssl_ctx = s->kssl_ctx; +                        /*  krb5_data	krb5_ap_req;  */ +                        krb5_data	*enc_ticket; +                        krb5_data	authenticator, *authp = NULL; +			EVP_CIPHER_CTX	ciph_ctx; +			const EVP_CIPHER *enc = NULL; +			unsigned char	iv[EVP_MAX_IV_LENGTH]; +			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; +			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH  +						+ EVP_MAX_IV_LENGTH]; +			int 		padl, outl = sizeof(epms); + +			EVP_CIPHER_CTX_init(&ciph_ctx); + +#ifdef KSSL_DEBUG +                        printf("ssl3_send_client_key_exchange(%lx & %lx)\n", +                                alg_k, SSL_kKRB5); +#endif	/* KSSL_DEBUG */ + +			authp = NULL; +#ifdef KRB5SENDAUTH +			if (KRB5SENDAUTH)  authp = &authenticator; +#endif	/* KRB5SENDAUTH */ + +                        krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, +				&kssl_err); +			enc = kssl_map_enc(kssl_ctx->enctype); +                        if (enc == NULL) +                            goto err; +#ifdef KSSL_DEBUG +                        { +                        printf("kssl_cget_tkt rtn %d\n", krb5rc); +                        if (krb5rc && kssl_err.text) +			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); +                        } +#endif	/* KSSL_DEBUG */ + +                        if (krb5rc) +                                { +                                ssl3_send_alert(s,SSL3_AL_FATAL, +						SSL_AD_HANDSHAKE_FAILURE); +                                SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +						kssl_err.reason); +                                goto err; +                                } + +			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ +			**  in place of RFC 2712 KerberosWrapper, as in: +			** +                        **  Send ticket (copy to *p, set n = length) +                        **  n = krb5_ap_req.length; +                        **  memcpy(p, krb5_ap_req.data, krb5_ap_req.length); +                        **  if (krb5_ap_req.data)   +                        **    kssl_krb5_free_data_contents(NULL,&krb5_ap_req); +                        ** +			**  Now using real RFC 2712 KerberosWrapper +			**  (Thanks to Simon Wilkinson <sxw@sxw.org.uk>) +			**  Note: 2712 "opaque" types are here replaced +			**  with a 2-byte length followed by the value. +			**  Example: +			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms +			**  Where "xx xx" = length bytes.  Shown here with +			**  optional authenticator omitted. +			*/ + +			/*  KerberosWrapper.Ticket		*/ +			s2n(enc_ticket->length,p); +			memcpy(p, enc_ticket->data, enc_ticket->length); +			p+= enc_ticket->length; +			n = enc_ticket->length + 2; + +			/*  KerberosWrapper.Authenticator	*/ +			if (authp  &&  authp->length)   +				{ +				s2n(authp->length,p); +				memcpy(p, authp->data, authp->length); +				p+= authp->length; +				n+= authp->length + 2; +				 +				free(authp->data); +				authp->data = NULL; +				authp->length = 0; +				} +			else +				{ +				s2n(0,p);/*  null authenticator length	*/ +				n+=2; +				} +  +			if (RAND_bytes(tmp_buf,sizeof tmp_buf) <= 0) +			    goto err; + +			/*  20010420 VRS.  Tried it this way; failed. +			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); +			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx, +			**				kssl_ctx->length); +			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); +			*/ + +			memset(iv, 0, sizeof iv);  /* per RFC 1510 */ +			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL, +				kssl_ctx->key,iv); +			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf, +				sizeof tmp_buf); +			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); +			outl += padl; +			if (outl > (int)sizeof epms) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); +				goto err; +				} +			EVP_CIPHER_CTX_cleanup(&ciph_ctx); + +			/*  KerberosWrapper.EncryptedPreMasterSecret	*/ +			s2n(outl,p); +			memcpy(p, epms, outl); +			p+=outl; +			n+=outl + 2; + +                        s->session->master_key_length= +                                s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, +					tmp_buf, sizeof tmp_buf); + +			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); +			OPENSSL_cleanse(epms, outl); +                        } +#endif +#ifndef OPENSSL_NO_DH +		else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) +			{ +			DH *dh_srvr,*dh_clnt; + +			if (s->session->sess_cert->peer_dh_tmp != NULL) +				dh_srvr=s->session->sess_cert->peer_dh_tmp; +			else +				{ +				/* we get them from the cert */ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +				SSLerr(SSL_F_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); +				goto err; +				} +			if (!DH_generate_key(dh_clnt)) +				{ +				SSLerr(SSL_F_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); +				goto err; +				} + +			/* generate master key from the result */ +			s->session->master_key_length= +				s->method->ssl3_enc->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*/ +			} +#endif +#ifndef OPENSSL_NO_ECDH  +		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) +			{ +			const EC_GROUP *srvr_group = NULL; +			EC_KEY *tkey; +			int ecdh_clnt_cert = 0; +			int field_size = 0; + +			/* Did we send out the client's +			 * ECDH share for use in premaster +			 * computation as part of client certificate? +			 * If so, set ecdh_clnt_cert to 1. +			 */ +			if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL))  +				{ +				/* XXX: For now, we do not support client +				 * authentication using ECDH certificates. +				 * To add such support, one needs to add +				 * code that checks for appropriate  +				 * conditions and sets ecdh_clnt_cert to 1. +				 * For example, the cert have an ECC +				 * key on the same curve as the server's +				 * and the key should be authorized for +				 * key agreement. +				 * +				 * One also needs to add code in ssl3_connect +				 * to skip sending the certificate verify +				 * message. +				 * +				 * if ((s->cert->key->privatekey != NULL) && +				 *     (s->cert->key->privatekey->type == +				 *      EVP_PKEY_EC) && ...) +				 * ecdh_clnt_cert = 1; +				 */ +				} + +			if (s->session->sess_cert->peer_ecdh_tmp != NULL) +				{ +				tkey = s->session->sess_cert->peer_ecdh_tmp; +				} +			else +				{ +				/* Get the Server Public Key from Cert */ +				srvr_pub_pkey = X509_get_pubkey(s->session-> \ +				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); +				if ((srvr_pub_pkey == NULL) || +				    (srvr_pub_pkey->type != EVP_PKEY_EC) || +				    (srvr_pub_pkey->pkey.ec == NULL)) +					{ +					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +					    ERR_R_INTERNAL_ERROR); +					goto err; +					} + +				tkey = srvr_pub_pkey->pkey.ec; +				} + +			srvr_group   = EC_KEY_get0_group(tkey); +			srvr_ecpoint = EC_KEY_get0_public_key(tkey); + +			if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +				    ERR_R_INTERNAL_ERROR); +				goto err; +				} + +			if ((clnt_ecdh=EC_KEY_new()) == NULL)  +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +				goto err; +				} + +			if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); +				goto err; +				} +			if (ecdh_clnt_cert)  +				{  +				/* Reuse key info from our certificate +				 * We only need our private key to perform +				 * the ECDH computation. +				 */ +				const BIGNUM *priv_key; +				tkey = s->cert->key->privatekey->pkey.ec; +				priv_key = EC_KEY_get0_private_key(tkey); +				if (priv_key == NULL) +					{ +					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +					goto err; +					} +				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) +					{ +					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); +					goto err; +					} +				} +			else  +				{ +				/* Generate a new ECDH key pair */ +				if (!(EC_KEY_generate_key(clnt_ecdh))) +					{ +					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); +					goto err; +					} +				} + +			/* use the 'p' output buffer for the ECDH key, but +			 * make sure to clear it out afterwards +			 */ + +			field_size = EC_GROUP_get_degree(srvr_group); +			if (field_size <= 0) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,  +				       ERR_R_ECDH_LIB); +				goto err; +				} +			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); +			if (n <= 0) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,  +				       ERR_R_ECDH_LIB); +				goto err; +				} + +			/* generate master key from the result */ +			s->session->master_key_length = s->method->ssl3_enc \ +			    -> generate_master_secret(s,  +				s->session->master_key, +				p, n); + +			memset(p, 0, n); /* clean up */ + +			if (ecdh_clnt_cert)  +				{ +				/* Send empty client key exch message */ +				n = 0; +				} +			else  +				{ +				/* First check the size of encoding and +				 * allocate memory accordingly. +				 */ +				encoded_pt_len =  +				    EC_POINT_point2oct(srvr_group,  +					EC_KEY_get0_public_key(clnt_ecdh),  +					POINT_CONVERSION_UNCOMPRESSED,  +					NULL, 0, NULL); + +				encodedPoint = (unsigned char *)  +				    OPENSSL_malloc(encoded_pt_len *  +					sizeof(unsigned char));  +				bn_ctx = BN_CTX_new(); +				if ((encodedPoint == NULL) ||  +				    (bn_ctx == NULL))  +					{ +					SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +					goto err; +					} + +				/* Encode the public key */ +				n = EC_POINT_point2oct(srvr_group,  +				    EC_KEY_get0_public_key(clnt_ecdh),  +				    POINT_CONVERSION_UNCOMPRESSED,  +				    encodedPoint, encoded_pt_len, bn_ctx); + +				*p = n; /* length of encoded point */ +				/* Encoded point will be copied here */ +				p += 1;  +				/* copy the point */ +				memcpy((unsigned char *)p, encodedPoint, n); +				/* increment n to account for length field */ +				n += 1;  +				} + +			/* Free allocated memory */ +			BN_CTX_free(bn_ctx); +			if (encodedPoint != NULL) OPENSSL_free(encodedPoint); +			if (clnt_ecdh != NULL)  +				 EC_KEY_free(clnt_ecdh); +			EVP_PKEY_free(srvr_pub_pkey); +			} +#endif /* !OPENSSL_NO_ECDH */ + +#ifndef OPENSSL_NO_PSK +		else if (alg_k & SSL_kPSK) +			{ +			char identity[PSK_MAX_IDENTITY_LEN]; +			unsigned char *t = NULL; +			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; +			unsigned int pre_ms_len = 0, psk_len = 0; +			int psk_err = 1; + +			n = 0; +			if (s->psk_client_callback == NULL) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_PSK_NO_CLIENT_CB); +				goto err; +				} + +			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, +				identity, PSK_MAX_IDENTITY_LEN, +				psk_or_pre_ms, sizeof(psk_or_pre_ms)); +			if (psk_len > PSK_MAX_PSK_LEN) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_INTERNAL_ERROR); +				goto psk_err; +				} +			else if (psk_len == 0) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_PSK_IDENTITY_NOT_FOUND); +				goto psk_err; +				} + +			/* create PSK pre_master_secret */ +			pre_ms_len = 2+psk_len+2+psk_len; +			t = psk_or_pre_ms; +			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); +			s2n(psk_len, t); +			memset(t, 0, psk_len); +			t+=psk_len; +			s2n(psk_len, t); + +			if (s->session->psk_identity_hint != NULL) +				OPENSSL_free(s->session->psk_identity_hint); +			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); +			if (s->ctx->psk_identity_hint != NULL && +				s->session->psk_identity_hint == NULL) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} + +			if (s->session->psk_identity != NULL) +				OPENSSL_free(s->session->psk_identity); +			s->session->psk_identity = BUF_strdup(identity); +			if (s->session->psk_identity == NULL) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} + +			s->session->master_key_length = +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, +					psk_or_pre_ms, pre_ms_len);  +			n = strlen(identity); +			s2n(n, p); +			memcpy(p, identity, n); +			n+=2; +			psk_err = 0; +		psk_err: +			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); +			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); +			if (psk_err != 0) +				{ +				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); +				goto err; +				} +			} +#endif +		else +			{ +			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +			SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); +			goto err; +			} +		 +		d = dtls1_set_message_header(s, d, +		SSL3_MT_CLIENT_KEY_EXCHANGE, n, 0, n); +		/* +		 *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; +		 l2n3(n,d); +		 l2n(s->d1->handshake_write_seq,d); +		 s->d1->handshake_write_seq++; +		*/ +		 +		s->state=SSL3_ST_CW_KEY_EXCH_B; +		/* number of bytes to write */ +		s->init_num=n+DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} +	 +	/* SSL3_ST_CW_KEY_EXCH_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +err: +#ifndef OPENSSL_NO_ECDH +	BN_CTX_free(bn_ctx); +	if (encodedPoint != NULL) OPENSSL_free(encodedPoint); +	if (clnt_ecdh != NULL)  +		EC_KEY_free(clnt_ecdh); +	EVP_PKEY_free(srvr_pub_pkey); +#endif +	return(-1); +	} + +int dtls1_send_client_verify(SSL *s) +	{ +	unsigned char *p,*d; +	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; +	EVP_PKEY *pkey; +#ifndef OPENSSL_NO_RSA +	unsigned u=0; +#endif +	unsigned long n; +#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) +	int j; +#endif + +	if (s->state == SSL3_ST_CW_CERT_VRFY_A) +		{ +		d=(unsigned char *)s->init_buf->data; +		p= &(d[DTLS1_HM_HEADER_LENGTH]); +		pkey=s->cert->key->privatekey; + +		s->method->ssl3_enc->cert_verify_mac(s, +		NID_sha1, +			&(data[MD5_DIGEST_LENGTH])); + +#ifndef OPENSSL_NO_RSA +		if (pkey->type == EVP_PKEY_RSA) +			{ +			s->method->ssl3_enc->cert_verify_mac(s, +				NID_md5, +				&(data[0])); +			if (RSA_sign(NID_md5_sha1, data, +					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, +					&(p[2]), &u, pkey->pkey.rsa) <= 0 ) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB); +				goto err; +				} +			s2n(u,p); +			n=u+2; +			} +		else +#endif +#ifndef OPENSSL_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_DTLS1_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB); +				goto err; +				} +			s2n(j,p); +			n=j+2; +			} +		else +#endif +#ifndef OPENSSL_NO_ECDSA +			if (pkey->type == EVP_PKEY_EC) +			{ +			if (!ECDSA_sign(pkey->save_type, +				&(data[MD5_DIGEST_LENGTH]), +				SHA_DIGEST_LENGTH,&(p[2]), +				(unsigned int *)&j,pkey->pkey.ec)) +				{ +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY, +				    ERR_R_ECDSA_LIB); +				goto err; +				} +			s2n(j,p); +			n=j+2; +			} +		else +#endif +			{ +			SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); +			goto err; +			} + +		d = dtls1_set_message_header(s, d, +			SSL3_MT_CERTIFICATE_VERIFY, n, 0, n) ; + +		s->init_num=(int)n+DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); + +		s->state = SSL3_ST_CW_CERT_VRFY_B; +		} + +	/* s->state = SSL3_ST_CW_CERT_VRFY_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +err: +	return(-1); +	} + +int dtls1_send_client_certificate(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; +		i = ssl_do_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_DTLS1_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) +			{ +			if (s->version == SSL3_VERSION) +				{ +				s->s3->tmp.cert_req=0; +				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE); +				return(1); +				} +			else +				{ +				s->s3->tmp.cert_req=2; +				} +			} + +		/* 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=dtls1_output_cert_chain(s, +			(s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509); +		s->init_num=(int)l; +		s->init_off=0; + +		/* set header called by dtls1_output_cert_chain() */ + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} +	/* SSL3_ST_CW_CERT_D */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + + diff --git a/main/openssl/ssl/d1_enc.c b/main/openssl/ssl/d1_enc.c new file mode 100644 index 00000000..becbab91 --- /dev/null +++ b/main/openssl/ssl/d1_enc.c @@ -0,0 +1,289 @@ +/* ssl/d1_enc.c */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 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" +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/md5.h> +#include <openssl/rand.h> +#ifdef KSSL_DEBUG +#include <openssl/des.h> +#endif + +int dtls1_enc(SSL *s, int send) +	{ +	SSL3_RECORD *rec; +	EVP_CIPHER_CTX *ds; +	unsigned long l; +	int bs,i,ii,j,k,n=0; +	const EVP_CIPHER *enc; + +	if (send) +		{ +		if (EVP_MD_CTX_md(s->write_hash)) +			{ +			n=EVP_MD_CTX_size(s->write_hash); +			if (n < 0) +				return -1; +			} +		ds=s->enc_write_ctx; +		rec= &(s->s3->wrec); +		if (s->enc_write_ctx == NULL) +			enc=NULL; +		else +			{ +			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); +			if ( rec->data != rec->input) +				/* we can't write into the input stream */ +				fprintf(stderr, "%s:%d: rec->data != rec->input\n", +					__FILE__, __LINE__); +			else if ( EVP_CIPHER_block_size(ds->cipher) > 1) +				{ +				if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) <= 0) +					return -1; +				} +			} +		} +	else +		{ +		if (EVP_MD_CTX_md(s->read_hash)) +			{ +			n=EVP_MD_CTX_size(s->read_hash); +			if (n < 0) +				return -1; +			} +		ds=s->enc_read_ctx; +		rec= &(s->s3->rrec); +		if (s->enc_read_ctx == NULL) +			enc=NULL; +		else +			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); +		} + +#ifdef KSSL_DEBUG +	printf("dtls1_enc(%d)\n", send); +#endif    /* KSSL_DEBUG */ + +	if ((s->session == NULL) || (ds == NULL) || +		(enc == NULL)) +		{ +		memmove(rec->data,rec->input,rec->length); +		rec->input=rec->data; +		} +	else +		{ +		l=rec->length; +		bs=EVP_CIPHER_block_size(ds->cipher); + +		if ((bs != 1) && send) +			{ +			i=bs-((int)l%bs); + +			/* Add weird padding of upto 256 bytes */ + +			/* we need to add 'i' padding bytes of value j */ +			j=i-1; +			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) +				{ +				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) +					j++; +				} +			for (k=(int)l; k<(int)(l+i); k++) +				rec->input[k]=j; +			l+=i; +			rec->length+=i; +			} + +#ifdef KSSL_DEBUG +		{ +                unsigned long ui; +		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", +                        ds,rec->data,rec->input,l); +		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", +                        ds->buf_len, ds->cipher->key_len, +                        DES_KEY_SZ, DES_SCHEDULE_SZ, +                        ds->cipher->iv_len); +		printf("\t\tIV: "); +		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]); +		printf("\n"); +		printf("\trec->input="); +		for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]); +		printf("\n"); +		} +#endif	/* KSSL_DEBUG */ + +		if (!send) +			{ +			if (l == 0 || l%bs != 0) +				return -1; +			} +		 +		EVP_Cipher(ds,rec->data,rec->input,l); + +#ifdef KSSL_DEBUG +		{ +                unsigned long i; +                printf("\trec->data="); +		for (i=0; i<l; i++) +                        printf(" %02x", rec->data[i]);  printf("\n"); +                } +#endif	/* KSSL_DEBUG */ + +		if ((bs != 1) && !send) +			{ +			ii=i=rec->data[l-1]; /* padding_length */ +			i++; +			if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) +				{ +				/* First packet is even in size, so check */ +				if ((memcmp(s->s3->read_sequence, +					"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) +					s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; +				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) +					i--; +				} +			/* TLS 1.0 does not bound the number of padding bytes by the block size. +			 * All of them must have value 'padding_length'. */ +			if (i > (int)rec->length) +				{ +				/* Incorrect padding. SSLerr() and ssl3_alert are done +				 * by caller: we don't want to reveal whether this is +				 * a decryption error or a MAC verification failure +				 * (see http://www.openssl.org/~bodo/tls-cbc.txt)  +				 */ +				return -1; +				} +			for (j=(int)(l-i); j<(int)l; j++) +				{ +				if (rec->data[j] != ii) +					{ +					/* Incorrect padding */ +					return -1; +					} +				} +			rec->length-=i; + +			rec->data += bs;    /* skip the implicit IV */ +			rec->input += bs; +			rec->length -= bs; +			} +		} +	return(1); +	} + diff --git a/main/openssl/ssl/d1_lib.c b/main/openssl/ssl/d1_lib.c new file mode 100644 index 00000000..48e8b6ff --- /dev/null +++ b/main/openssl/ssl/d1_lib.c @@ -0,0 +1,443 @@ +/* ssl/d1_lib.c */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#define USE_SOCKETS +#include <openssl/objects.h> +#include "ssl_locl.h" + +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) +#include <sys/timeb.h> +#endif + +static void get_current_time(struct timeval *t); +const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT; +int dtls1_listen(SSL *s, struct sockaddr *client); + +SSL3_ENC_METHOD DTLSv1_enc_data={ +    dtls1_enc, +	tls1_mac, +	tls1_setup_key_block, +	tls1_generate_master_secret, +	tls1_change_cipher_state, +	tls1_final_finish_mac, +	TLS1_FINISH_MAC_LENGTH, +	tls1_cert_verify_mac, +	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, +	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, +	tls1_alert_code, +	}; + +long dtls1_default_timeout(void) +	{ +	/* 2 hours, the 24 hours mentioned in the DTLSv1 spec +	 * is way too long for http, the cache would over fill */ +	return(60*60*2); +	} + +int dtls1_new(SSL *s) +	{ +	DTLS1_STATE *d1; + +	if (!ssl3_new(s)) return(0); +	if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0); +	memset(d1,0, sizeof *d1); + +	/* d1->handshake_epoch=0; */ + +	d1->unprocessed_rcds.q=pqueue_new(); +	d1->processed_rcds.q=pqueue_new(); +	d1->buffered_messages = pqueue_new(); +	d1->sent_messages=pqueue_new(); +	d1->buffered_app_data.q=pqueue_new(); + +	if ( s->server) +		{ +		d1->cookie_len = sizeof(s->d1->cookie); +		} + +	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q  +        || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q) +		{ +        if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q); +        if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q); +        if ( d1->buffered_messages) pqueue_free(d1->buffered_messages); +		if ( d1->sent_messages) pqueue_free(d1->sent_messages); +		if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q); +		OPENSSL_free(d1); +		return (0); +		} + +	s->d1=d1; +	s->method->ssl_clear(s); +	return(1); +	} + +static void dtls1_clear_queues(SSL *s) +	{ +    pitem *item = NULL; +    hm_fragment *frag = NULL; +	DTLS1_RECORD_DATA *rdata; + +    while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) +        { +		rdata = (DTLS1_RECORD_DATA *) item->data; +		if (rdata->rbuf.buf) +			{ +			OPENSSL_free(rdata->rbuf.buf); +			} +        OPENSSL_free(item->data); +        pitem_free(item); +        } + +    while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) +        { +		rdata = (DTLS1_RECORD_DATA *) item->data; +		if (rdata->rbuf.buf) +			{ +			OPENSSL_free(rdata->rbuf.buf); +			} +        OPENSSL_free(item->data); +        pitem_free(item); +        } + +    while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL) +        { +        frag = (hm_fragment *)item->data; +        OPENSSL_free(frag->fragment); +        OPENSSL_free(frag); +        pitem_free(item); +        } + +    while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL) +        { +        frag = (hm_fragment *)item->data; +        OPENSSL_free(frag->fragment); +        OPENSSL_free(frag); +        pitem_free(item); +        } + +	while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) +		{ +		frag = (hm_fragment *)item->data; +		OPENSSL_free(frag->fragment); +		OPENSSL_free(frag); +		pitem_free(item); +		} +	} + +void dtls1_free(SSL *s) +	{ +	ssl3_free(s); + +	dtls1_clear_queues(s); + +    pqueue_free(s->d1->unprocessed_rcds.q); +    pqueue_free(s->d1->processed_rcds.q); +    pqueue_free(s->d1->buffered_messages); +	pqueue_free(s->d1->sent_messages); +	pqueue_free(s->d1->buffered_app_data.q); + +	OPENSSL_free(s->d1); +	} + +void dtls1_clear(SSL *s) +	{ +    pqueue unprocessed_rcds; +    pqueue processed_rcds; +    pqueue buffered_messages; +	pqueue sent_messages; +	pqueue buffered_app_data; +	 +	if (s->d1) +		{ +		unprocessed_rcds = s->d1->unprocessed_rcds.q; +		processed_rcds = s->d1->processed_rcds.q; +		buffered_messages = s->d1->buffered_messages; +		sent_messages = s->d1->sent_messages; +		buffered_app_data = s->d1->buffered_app_data.q; + +		dtls1_clear_queues(s); + +		memset(s->d1, 0, sizeof(*(s->d1))); + +		if (s->server) +			{ +			s->d1->cookie_len = sizeof(s->d1->cookie); +			} + +		s->d1->unprocessed_rcds.q = unprocessed_rcds; +		s->d1->processed_rcds.q = processed_rcds; +		s->d1->buffered_messages = buffered_messages; +		s->d1->sent_messages = sent_messages; +		s->d1->buffered_app_data.q = buffered_app_data; +		} + +	ssl3_clear(s); +	if (s->options & SSL_OP_CISCO_ANYCONNECT) +		s->version=DTLS1_BAD_VER; +	else +		s->version=DTLS1_VERSION; +	} + +long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) +	{ +	int ret=0; + +	switch (cmd) +		{ +	case DTLS_CTRL_GET_TIMEOUT: +		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) +			{ +			ret = 1; +			} +		break; +	case DTLS_CTRL_HANDLE_TIMEOUT: +		ret = dtls1_handle_timeout(s); +		break; +	case DTLS_CTRL_LISTEN: +		ret = dtls1_listen(s, parg); +		break; + +	default: +		ret = ssl3_ctrl(s, cmd, larg, parg); +		break; +		} +	return(ret); +	} + +/* + * As it's impossible to use stream ciphers in "datagram" mode, this + * simple filter is designed to disengage them in DTLS. Unfortunately + * there is no universal way to identify stream SSL_CIPHER, so we have + * to explicitly list their SSL_* codes. Currently RC4 is the only one + * available, but if new ones emerge, they will have to be added... + */ +const SSL_CIPHER *dtls1_get_cipher(unsigned int u) +	{ +	const SSL_CIPHER *ciph = ssl3_get_cipher(u); + +	if (ciph != NULL) +		{ +		if (ciph->algorithm_enc == SSL_RC4) +			return NULL; +		} + +	return ciph; +	} + +void dtls1_start_timer(SSL *s) +	{ +	/* If timer is not set, initialize duration with 1 second */ +	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) +		{ +		s->d1->timeout_duration = 1; +		} +	 +	/* Set timeout to current time */ +	get_current_time(&(s->d1->next_timeout)); + +	/* Add duration to current time */ +	s->d1->next_timeout.tv_sec += s->d1->timeout_duration; +	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); +	} + +struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft) +	{ +	struct timeval timenow; + +	/* If no timeout is set, just return NULL */ +	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) +		{ +		return NULL; +		} + +	/* Get current time */ +	get_current_time(&timenow); + +	/* If timer already expired, set remaining time to 0 */ +	if (s->d1->next_timeout.tv_sec < timenow.tv_sec || +		(s->d1->next_timeout.tv_sec == timenow.tv_sec && +		 s->d1->next_timeout.tv_usec <= timenow.tv_usec)) +		{ +		memset(timeleft, 0, sizeof(struct timeval)); +		return timeleft; +		} + +	/* Calculate time left until timer expires */ +	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval)); +	timeleft->tv_sec -= timenow.tv_sec; +	timeleft->tv_usec -= timenow.tv_usec; +	if (timeleft->tv_usec < 0) +		{ +		timeleft->tv_sec--; +		timeleft->tv_usec += 1000000; +		} + +	/* If remaining time is less than 15 ms, set it to 0 +	 * to prevent issues because of small devergences with +	 * socket timeouts. +	 */ +	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) +		{ +		memset(timeleft, 0, sizeof(struct timeval)); +		} +	 + +	return timeleft; +	} + +int dtls1_is_timer_expired(SSL *s) +	{ +	struct timeval timeleft; + +	/* Get time left until timeout, return false if no timer running */ +	if (dtls1_get_timeout(s, &timeleft) == NULL) +		{ +		return 0; +		} + +	/* Return false if timer is not expired yet */ +	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) +		{ +		return 0; +		} + +	/* Timer expired, so return true */	 +	return 1; +	} + +void dtls1_double_timeout(SSL *s) +	{ +	s->d1->timeout_duration *= 2; +	if (s->d1->timeout_duration > 60) +		s->d1->timeout_duration = 60; +	dtls1_start_timer(s); +	} + +void dtls1_stop_timer(SSL *s) +	{ +	/* Reset everything */ +	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); +	s->d1->timeout_duration = 1; +	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); +	/* Clear retransmission buffer */ +	dtls1_clear_record_buffer(s); +	} + +int dtls1_handle_timeout(SSL *s) +	{ +	DTLS1_STATE *state; + +	/* if no timer is expired, don't do anything */ +	if (!dtls1_is_timer_expired(s)) +		{ +		return 0; +		} + +	dtls1_double_timeout(s); +	state = s->d1; +	state->timeout.num_alerts++; +	if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) +		{ +		/* fail the connection, enough alerts have been sent */ +		SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED); +		return -1; +		} + +	state->timeout.read_timeouts++; +	if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) +		{ +		state->timeout.read_timeouts = 1; +		} + +	dtls1_start_timer(s); +	return dtls1_retransmit_buffered_messages(s); +	} + +static void get_current_time(struct timeval *t) +{ +#ifdef OPENSSL_SYS_WIN32 +	struct _timeb tb; +	_ftime(&tb); +	t->tv_sec = (long)tb.time; +	t->tv_usec = (long)tb.millitm * 1000; +#elif defined(OPENSSL_SYS_VMS) +	struct timeb tb; +	ftime(&tb); +	t->tv_sec = (long)tb.time; +	t->tv_usec = (long)tb.millitm * 1000; +#else +	gettimeofday(t, NULL); +#endif +} + +int dtls1_listen(SSL *s, struct sockaddr *client) +	{ +	int ret; + +	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); +	s->d1->listen = 1; + +	ret = SSL_accept(s); +	if (ret <= 0) return ret; +	 +	(void) BIO_dgram_get_peer(SSL_get_rbio(s), client); +	return 1; +	} diff --git a/main/openssl/ssl/d1_meth.c b/main/openssl/ssl/d1_meth.c new file mode 100644 index 00000000..5c4004bf --- /dev/null +++ b/main/openssl/ssl/d1_meth.c @@ -0,0 +1,77 @@ +/* ssl/d1_meth.h */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <openssl/objects.h> +#include "ssl_locl.h" + +static const SSL_METHOD *dtls1_get_method(int ver); +static const SSL_METHOD *dtls1_get_method(int ver) +	{ +	if (ver == DTLS1_VERSION) +		return(DTLSv1_method()); +	else +		return(NULL); +	} + +IMPLEMENT_dtls1_meth_func(DTLSv1_method, +			dtls1_accept, +			dtls1_connect, +			dtls1_get_method) + diff --git a/main/openssl/ssl/d1_pkt.c b/main/openssl/ssl/d1_pkt.c new file mode 100644 index 00000000..91562f35 --- /dev/null +++ b/main/openssl/ssl/d1_pkt.c @@ -0,0 +1,1800 @@ +/* ssl/d1_pkt.c */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 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" +#include <openssl/evp.h> +#include <openssl/buffer.h> +#include <openssl/pqueue.h> +#include <openssl/rand.h> + +/* mod 128 saturating subtract of two 64-bit values in big-endian order */ +static int satsub64be(const unsigned char *v1,const unsigned char *v2) +{	int ret,sat,brw,i; + +	if (sizeof(long) == 8) do +	{	const union { long one; char little; } is_endian = {1}; +		long l; + +		if (is_endian.little)			break; +		/* not reached on little-endians */ +		/* following test is redundant, because input is +		 * always aligned, but I take no chances... */ +		if (((size_t)v1|(size_t)v2)&0x7)	break; + +		l  = *((long *)v1); +		l -= *((long *)v2); +		if (l>128)		return 128; +		else if (l<-128)	return -128; +		else			return (int)l; +	} while (0); + +	ret = (int)v1[7]-(int)v2[7]; +	sat = 0; +	brw = ret>>8;	/* brw is either 0 or -1 */ +	if (ret & 0x80) +	{	for (i=6;i>=0;i--) +		{	brw += (int)v1[i]-(int)v2[i]; +			sat |= ~brw; +			brw >>= 8; +		} +	} +	else +	{	for (i=6;i>=0;i--) +		{	brw += (int)v1[i]-(int)v2[i]; +			sat |= brw; +			brw >>= 8; +		} +	} +	brw <<= 8;	/* brw is either 0 or -256 */ + +	if (sat&0xff)	return brw | 0x80; +	else		return brw + (ret&0xFF); +} + +static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,  +	int len, int peek); +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap); +static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap); +static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,  +    unsigned int *is_next_epoch); +#if 0 +static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr, +	unsigned short *priority, unsigned long *offset); +#endif +static int dtls1_buffer_record(SSL *s, record_pqueue *q, +	unsigned char *priority); +static int dtls1_process_record(SSL *s); +static void dtls1_clear_timeouts(SSL *s); + +/* copy buffered record into SSL structure */ +static int +dtls1_copy_record(SSL *s, pitem *item) +    { +    DTLS1_RECORD_DATA *rdata; + +    rdata = (DTLS1_RECORD_DATA *)item->data; +     +    if (s->s3->rbuf.buf != NULL) +        OPENSSL_free(s->s3->rbuf.buf); +     +    s->packet = rdata->packet; +    s->packet_length = rdata->packet_length; +    memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER)); +    memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD)); +	 +	/* Set proper sequence number for mac calculation */ +	memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6); +     +    return(1); +    } + + +static int +dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) +	{ +	DTLS1_RECORD_DATA *rdata; +	pitem *item; + +	/* Limit the size of the queue to prevent DOS attacks */ +	if (pqueue_size(queue->q) >= 100) +		return 0; +		 +	rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA)); +	item = pitem_new(priority, rdata); +	if (rdata == NULL || item == NULL) +		{ +		if (rdata != NULL) OPENSSL_free(rdata); +		if (item != NULL) pitem_free(item); +		 +		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR); +		return(0); +		} +	 +	rdata->packet = s->packet; +	rdata->packet_length = s->packet_length; +	memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER)); +	memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD)); + +	item->data = rdata; + +	/* insert should not fail, since duplicates are dropped */ +	if (pqueue_insert(queue->q, item) == NULL) +		{ +		OPENSSL_free(rdata); +		pitem_free(item); +		return(0); +		} + +	s->packet = NULL; +	s->packet_length = 0; +	memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER)); +	memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD)); +	 +	if (!ssl3_setup_buffers(s)) +		{ +		SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR); +		OPENSSL_free(rdata); +		pitem_free(item); +		return(0); +		} +	 +	return(1); +	} + + +static int +dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) +    { +    pitem *item; + +    item = pqueue_pop(queue->q); +    if (item) +        { +        dtls1_copy_record(s, item); + +        OPENSSL_free(item->data); +		pitem_free(item); + +        return(1); +        } + +    return(0); +    } + + +/* retrieve a buffered record that belongs to the new epoch, i.e., not processed  + * yet */ +#define dtls1_get_unprocessed_record(s) \ +                   dtls1_retrieve_buffered_record((s), \ +                   &((s)->d1->unprocessed_rcds)) + +/* retrieve a buffered record that belongs to the current epoch, ie, processed */ +#define dtls1_get_processed_record(s) \ +                   dtls1_retrieve_buffered_record((s), \ +                   &((s)->d1->processed_rcds)) + +static int +dtls1_process_buffered_records(SSL *s) +    { +    pitem *item; +     +    item = pqueue_peek(s->d1->unprocessed_rcds.q); +    if (item) +        { +        /* Check if epoch is current. */ +        if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch) +            return(1);  /* Nothing to do. */ +         +        /* Process all the records. */ +        while (pqueue_peek(s->d1->unprocessed_rcds.q)) +            { +            dtls1_get_unprocessed_record(s); +            if ( ! dtls1_process_record(s)) +                return(0); +            dtls1_buffer_record(s, &(s->d1->processed_rcds),  +                s->s3->rrec.seq_num); +            } +        } + +    /* sync epoch numbers once all the unprocessed records  +     * have been processed */ +    s->d1->processed_rcds.epoch = s->d1->r_epoch; +    s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1; + +    return(1); +    } + + +#if 0 + +static int +dtls1_get_buffered_record(SSL *s) +	{ +	pitem *item; +	PQ_64BIT priority =  +		(((PQ_64BIT)s->d1->handshake_read_seq) << 32) |  +		((PQ_64BIT)s->d1->r_msg_hdr.frag_off); +	 +	if ( ! SSL_in_init(s))  /* if we're not (re)negotiating,  +							   nothing buffered */ +		return 0; + + +	item = pqueue_peek(s->d1->rcvd_records); +	if (item && item->priority == priority) +		{ +		/* Check if we've received the record of interest.  It must be +		 * a handshake record, since data records as passed up without +		 * buffering */ +		DTLS1_RECORD_DATA *rdata; +		item = pqueue_pop(s->d1->rcvd_records); +		rdata = (DTLS1_RECORD_DATA *)item->data; +		 +		if (s->s3->rbuf.buf != NULL) +			OPENSSL_free(s->s3->rbuf.buf); +		 +		s->packet = rdata->packet; +		s->packet_length = rdata->packet_length; +		memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER)); +		memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD)); +		 +		OPENSSL_free(item->data); +		pitem_free(item); +		 +		/* s->d1->next_expected_seq_num++; */ +		return(1); +		} +	 +	return 0; +	} + +#endif + +static int +dtls1_process_record(SSL *s) +{ +	int i,al; +	int clear=0; +	int enc_err; +	SSL_SESSION *sess; +	SSL3_RECORD *rr; +	unsigned int mac_size; +	unsigned char md[EVP_MAX_MD_SIZE]; + + +	rr= &(s->s3->rrec); +	sess = s->session; + +	/* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, +	 * and we have that many bytes in s->packet +	 */ +	rr->input= &(s->packet[DTLS1_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 */  + +	/* We now have - encrypted [ MAC [ compressed [ plain ] ] ] +	 * rr->length bytes of encrypted compressed stuff. */ + +	/* check is not needed I believe */ +	if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) +		{ +		al=SSL_AD_RECORD_OVERFLOW; +		SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG); +		goto f_err; +		} + +	/* decrypt in place in 'rr->input' */ +	rr->data=rr->input; + +	enc_err = s->method->ssl3_enc->enc(s,0); +	if (enc_err <= 0) +		{ +		/* decryption failed, silently discard message */ +		if (enc_err < 0) +			{ +			rr->length = 0; +			s->packet_length = 0; +			} +		goto err; +		} + +#ifdef TLS_DEBUG +printf("dec %d\n",rr->length); +{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } +printf("\n"); +#endif + +	/* 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) +		{ +		/* !clear => s->read_hash != NULL => mac_size != -1 */ +		int t; +		t=EVP_MD_CTX_size(s->read_hash); +		OPENSSL_assert(t >= 0); +		mac_size=t; + +		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size) +			{ +#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ +			al=SSL_AD_RECORD_OVERFLOW; +			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); +			goto f_err; +#else +			goto err; +#endif			 +			} +		/* check the MAC for rr->input (it's in mac_size bytes at the tail) */ +		if (rr->length < mac_size) +			{ +#if 0 /* OK only for stream ciphers */ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT); +			goto f_err; +#else +			goto err; +#endif +			} +		rr->length-=mac_size; +		i=s->method->ssl3_enc->mac(s,md,0); +		if (i < 0 || memcmp(md,&(rr->data[rr->length]),mac_size) != 0) +			{ +			goto err; +			} +		} + +	/* r->length is now just compressed */ +	if (s->expand != NULL) +		{ +		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) +			{ +			al=SSL_AD_RECORD_OVERFLOW; +			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG); +			goto f_err; +			} +		if (!ssl3_do_uncompress(s)) +			{ +			al=SSL_AD_DECOMPRESSION_FAILURE; +			SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_BAD_DECOMPRESSION); +			goto f_err; +			} +		} + +	if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) +		{ +		al=SSL_AD_RECORD_OVERFLOW; +		SSLerr(SSL_F_DTLS1_PROCESS_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; +	dtls1_record_bitmap_update(s, &(s->d1->bitmap));/* Mark receipt of record. */ +	return(1); + +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	return(0); +} + + +/* 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 + */ +/* used only by dtls1_read_bytes */ +int dtls1_get_record(SSL *s) +	{ +	int ssl_major,ssl_minor; +	int i,n; +	SSL3_RECORD *rr; +	unsigned char *p = NULL; +	unsigned short version; +	DTLS1_BITMAP *bitmap; +	unsigned int is_next_epoch; + +	rr= &(s->s3->rrec); + +	/* The epoch may have changed.  If so, process all the +	 * pending records.  This is a non-blocking operation. */ +	dtls1_process_buffered_records(s); + +	/* if we're renegotiating, then there may be buffered records */ +	if (dtls1_get_processed_record(s)) +		return 1; + +	/* get something from the wire */ +again: +	/* check if we have the header */ +	if (	(s->rstate != SSL_ST_READ_BODY) || +		(s->packet_length < DTLS1_RT_HEADER_LENGTH))  +		{ +		n=ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); +		/* read timeout is handled by dtls1_read_bytes */ +		if (n <= 0) return(n); /* error or non-blocking */ + +		/* this packet contained a partial record, dump it */ +		if (s->packet_length != DTLS1_RT_HEADER_LENGTH) +			{ +			s->packet_length = 0; +			goto again; +			} + +		s->rstate=SSL_ST_READ_BODY; + +		p=s->packet; + +		/* Pull apart the header into the DTLS1_RECORD */ +		rr->type= *(p++); +		ssl_major= *(p++); +		ssl_minor= *(p++); +		version=(ssl_major<<8)|ssl_minor; + +		/* sequence number is 64 bits, with top 2 bytes = epoch */  +		n2s(p,rr->epoch); + +		memcpy(&(s->s3->read_sequence[2]), p, 6); +		p+=6; + +		n2s(p,rr->length); + +		/* Lets check version */ +		if (!s->first_packet) +			{ +			if (version != s->version) +				{ +				/* unexpected version, silently discard */ +				rr->length = 0; +				s->packet_length = 0; +				goto again; +				} +			} + +		if ((version & 0xff00) != (s->version & 0xff00)) +			{ +			/* wrong version, silently discard record */ +			rr->length = 0; +			s->packet_length = 0; +			goto again; +			} + +		if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) +			{ +			/* record too long, silently discard it */ +			rr->length = 0; +			s->packet_length = 0; +			goto again; +			} + +		/* If we receive a valid record larger than the current buffer size, +		 * allocate some memory for it. +		 */ +		if (rr->length > s->s3->rbuf.len - DTLS1_RT_HEADER_LENGTH) +			{ +			unsigned char *pp; +			unsigned int newlen = rr->length + DTLS1_RT_HEADER_LENGTH; +			if ((pp=OPENSSL_realloc(s->s3->rbuf.buf, newlen))==NULL) +				{ +				SSLerr(SSL_F_DTLS1_GET_RECORD,ERR_R_MALLOC_FAILURE); +				return(-1); +				} +			p = pp + (p - s->s3->rbuf.buf); +			s->s3->rbuf.buf=pp; +			s->s3->rbuf.len=newlen; +			s->packet= &(s->s3->rbuf.buf[0]); +			} + +		/* now s->rstate == SSL_ST_READ_BODY */ +		} + +	/* s->rstate == SSL_ST_READ_BODY, get and decode the data */ + +	if (rr->length > s->packet_length-DTLS1_RT_HEADER_LENGTH) +		{ +		/* now s->packet_length == DTLS1_RT_HEADER_LENGTH */ +		i=rr->length; +		n=ssl3_read_n(s,i,i,1); +		if (n <= 0) return(n); /* error or non-blocking io */ + +		/* this packet contained a partial record, dump it */ +		if ( n != i) +			{ +			rr->length = 0; +			s->packet_length = 0; +			goto again; +			} + +		/* now n == rr->length, +		 * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length */ +		} +	s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */ + +	/* match epochs.  NULL means the packet is dropped on the floor */ +	bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); +	if ( bitmap == NULL) +		{ +		rr->length = 0; +		s->packet_length = 0;  /* dump this record */ +		goto again;   /* get another record */ +		} + +	/* Check whether this is a repeat, or aged record. +	 * Don't check if we're listening and this message is +	 * a ClientHello. They can look as if they're replayed, +	 * since they arrive from different connections and +	 * would be dropped unnecessarily. +	 */ +	if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE && +		*p == SSL3_MT_CLIENT_HELLO) && +		!dtls1_record_replay_check(s, bitmap)) +		{ +		rr->length = 0; +		s->packet_length=0; /* dump this record */ +		goto again;     /* get another record */ +		} + +	/* just read a 0 length packet */ +	if (rr->length == 0) goto again; + +	/* If this record is from the next epoch (either HM or ALERT), +	 * and a handshake is currently in progress, buffer it since it +	 * cannot be processed at this time. However, do not buffer +	 * anything while listening. +	 */ +	if (is_next_epoch) +		{ +		if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) +			{ +			dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num); +			} +		rr->length = 0; +		s->packet_length = 0; +		goto again; +		} + +	if (!dtls1_process_record(s)) +		{ +		rr->length = 0; +		s->packet_length = 0;  /* dump this record */ +		goto again;   /* get another record */ +		} + +	dtls1_clear_timeouts(s);  /* done waiting */ +	return(1); + +	} + +/* Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + *   -  0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify), ChangeCipherSpec records (not really + * a surprise, but handled as if it were), or renegotiation requests. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + *     Change cipher spec protocol + *             just 1 byte needed, no need for keeping anything stored + *     Alert protocol + *             2 bytes needed (AlertLevel, AlertDescription) + *     Handshake protocol + *             4 bytes needed (HandshakeType, uint24 length) -- we just have + *             to detect unexpected Client Hello and Hello Request messages + *             here, anything else is handled by higher layers + *     Application data protocol + *             none of our business + */ +int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) +	{ +	int al,i,j,ret; +	unsigned int n; +	SSL3_RECORD *rr; +	void (*cb)(const SSL *ssl,int type2,int val)=NULL; + +	if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ +		if (!ssl3_setup_buffers(s)) +			return(-1); + +    /* XXX: check what the second '&& type' is about */ +	if ((type && (type != SSL3_RT_APPLICATION_DATA) &&  +		(type != SSL3_RT_HANDSHAKE) && type) || +	    (peek && (type != SSL3_RT_APPLICATION_DATA))) +		{ +		SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); +		return -1; +		} + +	/* check whether there's a handshake message (client hello?) waiting */ +	if ( (ret = have_handshake_fragment(s, type, buf, len, peek))) +		return ret; + +	/* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */ + +	if (!s->in_handshake && SSL_in_init(s)) +		{ +		/* type == SSL3_RT_APPLICATION_DATA */ +		i=s->handshake_func(s); +		if (i < 0) return(i); +		if (i == 0) +			{ +			SSLerr(SSL_F_DTLS1_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,     - offset into 'data' for next read +	 * s->s3->rrec.length,  - number of bytes. */ +	rr = &(s->s3->rrec); + +	/* We are not handshaking and have no data yet, +	 * so process data buffered during the last handshake +	 * in advance, if any. +	 */ +	if (s->state == SSL_ST_OK && rr->length == 0) +		{ +		pitem *item; +		item = pqueue_pop(s->d1->buffered_app_data.q); +		if (item) +			{ +			dtls1_copy_record(s, item); + +			OPENSSL_free(item->data); +			pitem_free(item); +			} +		} + +	/* Check for timeout */ +	if (dtls1_handle_timeout(s) > 0) +		goto start; + +	/* get new packet if necessary */ +	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) +		{ +		ret=dtls1_get_record(s); +		if (ret <= 0)  +			{ +			ret = dtls1_read_failed(s, ret); +			/* anything other than a timeout is an error */ +			if (ret <= 0)   +				return(ret); +			else +				goto start; +			} +		} + +	/* we now have a packet which can be read and processed */ + +	if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, +	                               * reset by ssl3_get_finished */ +		&& (rr->type != SSL3_RT_HANDSHAKE)) +		{ +		/* We now have application data between CCS and Finished. +		 * Most likely the packets were reordered on their way, so +		 * buffer the application data for later processing rather +		 * than dropping the connection. +		 */ +		dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num); +		rr->length = 0; +		goto start; +		} + +	/* If the other end has shut down, throw anything we read away +	 * (even in 'peek' mode) */ +	if (s->shutdown & SSL_RECEIVED_SHUTDOWN) +		{ +		rr->length=0; +		s->rwstate=SSL_NOTHING; +		return(0); +		} + + +	if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ +		{ +		/* 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=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_DTLS1_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 = (unsigned int)len; + +		memcpy(buf,&(rr->data[rr->off]),n); +		if (!peek) +			{ +			rr->length-=n; +			rr->off+=n; +			if (rr->length == 0) +				{ +				s->rstate=SSL_ST_READ_HEADER; +				rr->off=0; +				} +			} +		return(n); +		} + + +	/* If we get here, then type != rr->type; if we have a handshake +	 * message, then it was unexpected (Hello Request or Client Hello). */ + +	/* In case of record types for which we have 'fragment' storage, +	 * fill that so that we can process the data at a fixed place. +	 */ +		{ +		unsigned int k, dest_maxlen = 0; +		unsigned char *dest = NULL; +		unsigned int *dest_len = NULL; + +		if (rr->type == SSL3_RT_HANDSHAKE) +			{ +			dest_maxlen = sizeof s->d1->handshake_fragment; +			dest = s->d1->handshake_fragment; +			dest_len = &s->d1->handshake_fragment_len; +			} +		else if (rr->type == SSL3_RT_ALERT) +			{ +			dest_maxlen = sizeof(s->d1->alert_fragment); +			dest = s->d1->alert_fragment; +			dest_len = &s->d1->alert_fragment_len; +			} +		/* else it's a CCS message, or application data or wrong */ +		else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) +			{ +			/* Application data while renegotiating +			 * is allowed. Try again reading. +			 */ +			if (rr->type == SSL3_RT_APPLICATION_DATA) +				{ +				BIO *bio; +				s->s3->in_read_app_data=2; +				bio=SSL_get_rbio(s); +				s->rwstate=SSL_READING; +				BIO_clear_retry_flags(bio); +				BIO_set_retry_read(bio); +				return(-1); +				} + +			/* Not certain if this is the right error handling */ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD); +			goto f_err; +			} + +		if (dest_maxlen > 0) +			{ +            /* XDTLS:  In a pathalogical case, the Client Hello +             *  may be fragmented--don't always expect dest_maxlen bytes */ +			if ( rr->length < dest_maxlen) +				{ +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +				/* +				 * for normal alerts rr->length is 2, while +				 * dest_maxlen is 7 if we were to handle this +				 * non-existing alert... +				 */ +				FIX ME +#endif +				s->rstate=SSL_ST_READ_HEADER; +				rr->length = 0; +				goto start; +				} + +			/* now move 'n' bytes: */ +			for ( k = 0; k < dest_maxlen; k++) +				{ +				dest[k] = rr->data[rr->off++]; +				rr->length--; +				} +			*dest_len = dest_maxlen; +			} +		} + +	/* s->d1->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE; +	 * s->d1->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT. +	 * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ + +	/* If we are a client, check for an incoming 'Hello Request': */ +	if ((!s->server) && +		(s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && +		(s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && +		(s->session != NULL) && (s->session->cipher != NULL)) +		{ +		s->d1->handshake_fragment_len = 0; + +		if ((s->d1->handshake_fragment[1] != 0) || +			(s->d1->handshake_fragment[2] != 0) || +			(s->d1->handshake_fragment[3] != 0)) +			{ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); +			goto err; +			} + +		/* no need to check sequence number on HELLO REQUEST messages */ + +		if (s->msg_callback) +			s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,  +				s->d1->handshake_fragment, 4, s, s->msg_callback_arg); + +		if (SSL_is_init_finished(s) && +			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && +			!s->s3->renegotiate) +			{ +			ssl3_renegotiate(s); +			if (ssl3_renegotiate_check(s)) +				{ +				i=s->handshake_func(s); +				if (i < 0) return(i); +				if (i == 0) +					{ +					SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); +					return(-1); +					} + +				if (!(s->mode & SSL_MODE_AUTO_RETRY)) +					{ +					if (s->s3->rbuf.left == 0) /* no read-ahead left? */ +						{ +						BIO *bio; +						/* In the case where we try to read application data, +						 * but we trigger an SSL handshake, we return -1 with +						 * the retry option set.  Otherwise renegotiation may +						 * cause nasty problems in the blocking world */ +						s->rwstate=SSL_READING; +						bio=SSL_get_rbio(s); +						BIO_clear_retry_flags(bio); +						BIO_set_retry_read(bio); +						return(-1); +						} +					} +				} +			} +		/* we either finished a handshake or ignored the request, +		 * now try again to obtain the (application) data we were asked for */ +		goto start; +		} + +	if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) +		{ +		int alert_level = s->d1->alert_fragment[0]; +		int alert_descr = s->d1->alert_fragment[1]; + +		s->d1->alert_fragment_len = 0; + +		if (s->msg_callback) +			s->msg_callback(0, s->version, SSL3_RT_ALERT,  +				s->d1->alert_fragment, 2, s, s->msg_callback_arg); + +		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 = (alert_level << 8) | alert_descr; +			cb(s, SSL_CB_READ_ALERT, j); +			} + +		if (alert_level == 1) /* warning */ +			{ +			s->s3->warn_alert = alert_descr; +			if (alert_descr == SSL_AD_CLOSE_NOTIFY) +				{ +				s->shutdown |= SSL_RECEIVED_SHUTDOWN; +				return(0); +				} +#if 0 +            /* XXX: this is a possible improvement in the future */ +			/* now check if it's a missing record */ +			if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) +				{ +				unsigned short seq; +				unsigned int frag_off; +				unsigned char *p = &(s->d1->alert_fragment[2]); + +				n2s(p, seq); +				n2l3(p, frag_off); + +				dtls1_retransmit_message(s, +										 dtls1_get_queue_priority(frag->msg_header.seq, 0), +										 frag_off, &found); +				if ( ! found  && SSL_in_init(s)) +					{ +					/* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */ +					/* requested a message not yet sent,  +					   send an alert ourselves */ +					ssl3_send_alert(s,SSL3_AL_WARNING, +						DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); +					} +				} +#endif +			} +		else if (alert_level == 2) /* fatal */ +			{ +			char tmp[16]; + +			s->rwstate=SSL_NOTHING; +			s->s3->fatal_alert = alert_descr; +			SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr); +			BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr); +			ERR_add_error_data(2,"SSL alert number ",tmp); +			s->shutdown|=SSL_RECEIVED_SHUTDOWN; +			SSL_CTX_remove_session(s->ctx,s->session); +			return(0); +			} +		else +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE); +			goto f_err; +			} + +		goto start; +		} + +	if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */ +		{ +		s->rwstate=SSL_NOTHING; +		rr->length=0; +		return(0); +		} + +	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) +		{ +		struct ccs_header_st ccs_hdr; +		unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH; + +		dtls1_get_ccs_header(rr->data, &ccs_hdr); + +		if (s->version == DTLS1_BAD_VER) +			ccs_hdr_len = 3; + +		/* 'Change Cipher Spec' is just a single byte, so we know +		 * exactly what the record payload has to look like */ +		/* XDTLS: check that epoch is consistent */ +		if (	(rr->length != ccs_hdr_len) ||  +			(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) +			{ +			i=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); +			goto err; +			} + +		rr->length=0; + +		if (s->msg_callback) +			s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,  +				rr->data, 1, s, s->msg_callback_arg); + +		/* We can't process a CCS now, because previous handshake +		 * messages are still missing, so just drop it. +		 */ +		if (!s->d1->change_cipher_spec_ok) +			{ +			goto start; +			} + +		s->d1->change_cipher_spec_ok = 0; + +		s->s3->change_cipher_spec=1; +		if (!ssl3_do_change_cipher_spec(s)) +			goto err; + +		/* do this whenever CCS is processed */ +		dtls1_reset_seq_numbers(s, SSL3_CC_READ); + +		if (s->version == DTLS1_BAD_VER) +			s->d1->handshake_read_seq++; + +		goto start; +		} + +	/* Unexpected handshake message (Client Hello, or protocol violation) */ +	if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&  +		!s->in_handshake) +		{ +		struct hm_header_st msg_hdr; +		 +		/* this may just be a stale retransmit */ +		dtls1_get_message_header(rr->data, &msg_hdr); +		if( rr->epoch != s->d1->r_epoch) +			{ +			rr->length = 0; +			goto start; +			} + +		/* If we are server, we may have a repeated FINISHED of the +		 * client here, then retransmit our CCS and FINISHED. +		 */ +		if (msg_hdr.type == SSL3_MT_FINISHED) +			{ +			dtls1_retransmit_buffered_messages(s); +			rr->length = 0; +			goto start; +			} + +		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && +			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) +			{ +#if 0 /* worked only because C operator preferences are not as expected (and +       * because this is not really needed for clients except for detecting +       * protocol violations): */ +			s->state=SSL_ST_BEFORE|(s->server) +				?SSL_ST_ACCEPT +				:SSL_ST_CONNECT; +#else +			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; +#endif +			s->new_session=1; +			} +		i=s->handshake_func(s); +		if (i < 0) return(i); +		if (i == 0) +			{ +			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); +			return(-1); +			} + +		if (!(s->mode & SSL_MODE_AUTO_RETRY)) +			{ +			if (s->s3->rbuf.left == 0) /* no read-ahead left? */ +				{ +				BIO *bio; +				/* In the case where we try to read application data, +				 * but we trigger an SSL handshake, we return -1 with +				 * the retry option set.  Otherwise renegotiation may +				 * cause nasty problems in the blocking world */ +				s->rwstate=SSL_READING; +				bio=SSL_get_rbio(s); +				BIO_clear_retry_flags(bio); +				BIO_set_retry_read(bio); +				return(-1); +				} +			} +		goto start; +		} + +	switch (rr->type) +		{ +	default: +#ifndef OPENSSL_NO_TLS +		/* TLS just ignores unknown message types */ +		if (s->version == TLS1_VERSION) +			{ +			rr->length = 0; +			goto start; +			} +#endif +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD); +		goto f_err; +	case SSL3_RT_CHANGE_CIPHER_SPEC: +	case SSL3_RT_ALERT: +	case SSL3_RT_HANDSHAKE: +		/* we already handled all of these, with the possible exception +		 * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that +		 * should not happen when type != rr->type */ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_DTLS1_READ_BYTES,ERR_R_INTERNAL_ERROR); +		goto f_err; +	case SSL3_RT_APPLICATION_DATA: +		/* At this point, we were expecting handshake data, +		 * but have application data.  If the library was +		 * running inside ssl3_read() (i.e. in_read_app_data +		 * is set) and it makes sense to read application data +		 * at this point (session renegotiation not yet started), +		 * we will indulge it. +		 */ +		if (s->s3->in_read_app_data && +			(s->s3->total_renegotiations != 0) && +			(( +				(s->state & SSL_ST_CONNECT) && +				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) && +				(s->state <= SSL3_ST_CR_SRVR_HELLO_A) +				) || ( +					(s->state & SSL_ST_ACCEPT) && +					(s->state <= SSL3_ST_SW_HELLO_REQ_A) && +					(s->state >= SSL3_ST_SR_CLNT_HELLO_A) +					) +				)) +			{ +			s->s3->in_read_app_data=2; +			return(-1); +			} +		else +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD); +			goto f_err; +			} +		} +	/* not reached */ + +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	return(-1); +	} + +int +dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len) +	{ +	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_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); +			return -1; +			} +		} + +	if (len > SSL3_RT_MAX_PLAIN_LENGTH) +		{ +			SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_DTLS_MESSAGE_TOO_BIG); +			return -1; +		} + +	i = dtls1_write_bytes(s, type, buf_, len); +	return i; +	} + + +	/* this only happens when a client hello is received and a handshake  +	 * is started. */ +static int +have_handshake_fragment(SSL *s, int type, unsigned char *buf,  +	int len, int peek) +	{ +	 +	if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0)) +		/* (partially) satisfy request from storage */ +		{ +		unsigned char *src = s->d1->handshake_fragment; +		unsigned char *dst = buf; +		unsigned int k,n; +		 +		/* peek == 0 */ +		n = 0; +		while ((len > 0) && (s->d1->handshake_fragment_len > 0)) +			{ +			*dst++ = *src++; +			len--; s->d1->handshake_fragment_len--; +			n++; +			} +		/* move any remaining fragment bytes: */ +		for (k = 0; k < s->d1->handshake_fragment_len; k++) +			s->d1->handshake_fragment[k] = *src++; +		return n; +		} +	 +	return 0; +	} + + + + +/* Call this to write data in records of type 'type' + * It will return <= 0 if not all data has been sent or non-blocking IO. + */ +int dtls1_write_bytes(SSL *s, int type, const void *buf, int len) +	{ +	int i; + +	OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH); +	s->rwstate=SSL_NOTHING; +	i=do_dtls1_write(s, type, buf, len, 0); +	return i; +	} + +int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment) +	{ +	unsigned char *p,*pseq; +	int i,mac_size,clear=0; +	int prefix_len = 0; +	SSL3_RECORD *wr; +	SSL3_BUFFER *wb; +	SSL_SESSION *sess; +	int bs; +	unsigned int len_with_overhead = len + SSL3_RT_DEFAULT_WRITE_OVERHEAD; + +	/* first check if there is a SSL3_BUFFER still being written +	 * out.  This will happen with non blocking IO */ +	if (s->s3->wbuf.left != 0) +		{ +		OPENSSL_assert(0); /* XDTLS:  want to see if we ever get here */ +		return(ssl3_write_pending(s,type,buf,len)); +		} + +	if (s->s3->wbuf.len < len_with_overhead) +		{ +		if ((p=OPENSSL_realloc(s->s3->wbuf.buf, len_with_overhead)) == NULL) { +			SSLerr(SSL_F_DO_DTLS1_WRITE,ERR_R_MALLOC_FAILURE); +			goto err; +		} +		s->s3->wbuf.buf = p; +		s->s3->wbuf.len = len_with_overhead; +		} + +	/* If we have an alert to send, lets send it */ +	if (s->s3->alert_dispatch) +		{ +		i=s->method->ssl_dispatch_alert(s); +		if (i <= 0) +			return(i); +		/* if it went, fall through and send more stuff */ +		} + +	if (len == 0 && !create_empty_fragment) +		return 0; + +	wr= &(s->s3->wrec); +	wb= &(s->s3->wbuf); +	sess=s->session; + +	if (	(sess == NULL) || +		(s->enc_write_ctx == NULL) || +		(EVP_MD_CTX_md(s->write_hash) == NULL)) +		clear=1; + +	if (clear) +		mac_size=0; +	else +		{ +		mac_size=EVP_MD_CTX_size(s->write_hash); +		if (mac_size < 0) +			goto err; +		} + +	/* DTLS implements explicit IV, so no need for empty fragments */ +#if 0 +	/* 'create_empty_fragment' is true only when this function calls itself */ +	if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done +	    && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER) +		{ +		/* countermeasure against known-IV weakness in CBC ciphersuites +		 * (see http://www.openssl.org/~bodo/tls-cbc.txt)  +		 */ + +		if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) +			{ +			/* recursive function call with 'create_empty_fragment' set; +			 * this prepares and buffers the data for an empty fragment +			 * (these 'prefix_len' bytes are sent out later +			 * together with the actual payload) */ +			prefix_len = s->method->do_ssl_write(s, type, buf, 0, 1); +			if (prefix_len <= 0) +				goto err; + +			if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE) +				{ +				/* insufficient space */ +				SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR); +				goto err; +				} +			} +		 +		s->s3->empty_fragment_done = 1; +		} +#endif +	p = wb->buf + prefix_len; + +	/* write the header */ + +	*(p++)=type&0xff; +	wr->type=type; + +	*(p++)=(s->version>>8); +	*(p++)=s->version&0xff; + +	/* field where we are to write out packet epoch, seq num and len */ +	pseq=p;  +	p+=10; + +	/* lets setup the record stuff. */ + +	/* Make space for the explicit IV in case of CBC. +	 * (this is a bit of a boundary violation, but what the heck). +	 */ +	if ( s->enc_write_ctx &&  +		(EVP_CIPHER_mode( s->enc_write_ctx->cipher ) & EVP_CIPH_CBC_MODE)) +		bs = EVP_CIPHER_block_size(s->enc_write_ctx->cipher); +	else +		bs = 0; + +	wr->data=p + bs;  /* make room for IV in case of CBC */ +	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 (s->compress != NULL) +		{ +		if (!ssl3_do_compress(s)) +			{ +			SSLerr(SSL_F_DO_DTLS1_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) +		{ +		if(s->method->ssl3_enc->mac(s,&(p[wr->length + bs]),1) < 0) +			goto err; +		wr->length+=mac_size; +		} + +	/* this is true regardless of mac size */ +	wr->input=p; +	wr->data=p; + + +	/* ssl3_enc can only have an error on read */ +	if (bs)	/* bs != 0 in case of CBC */ +		{ +		RAND_pseudo_bytes(p,bs); +		/* master IV and last CBC residue stand for +		 * the rest of randomness */ +		wr->length += bs; +		} + +	s->method->ssl3_enc->enc(s,1); + +	/* record length after mac and block padding */ +/*	if (type == SSL3_RT_APPLICATION_DATA || +	(type == SSL3_RT_ALERT && ! SSL_in_init(s))) */ +	 +	/* there's only one epoch between handshake and app data */ +	 +	s2n(s->d1->w_epoch, pseq); + +	/* XDTLS: ?? */ +/*	else +	s2n(s->d1->handshake_epoch, pseq); */ + +	memcpy(pseq, &(s->s3->write_sequence[2]), 6); +	pseq+=6; +	s2n(wr->length,pseq); + +	/* 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+=DTLS1_RT_HEADER_LENGTH; + +#if 0  /* this is now done at the message layer */ +	/* buffer the record, making it easy to handle retransmits */ +	if ( type == SSL3_RT_HANDSHAKE || type == SSL3_RT_CHANGE_CIPHER_SPEC) +		dtls1_buffer_record(s, wr->data, wr->length,  +			*((PQ_64BIT *)&(s->s3->write_sequence[0]))); +#endif + +	ssl3_record_sequence_update(&(s->s3->write_sequence[0])); + +	if (create_empty_fragment) +		{ +		/* we are in a recursive call; +		 * just return the length, don't write out anything here +		 */ +		return wr->length; +		} + +	/* now let's set up wb */ +	wb->left = prefix_len + wr->length; +	wb->offset = 0; + +	/* memorize arguments so that ssl3_write_pending can detect bad write retries later */ +	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; +	} + + + +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap) +	{ +	int cmp; +	unsigned int shift; +	const unsigned char *seq = s->s3->read_sequence; + +	cmp = satsub64be(seq,bitmap->max_seq_num); +	if (cmp > 0) +		{ +		memcpy (s->s3->rrec.seq_num,seq,8); +		return 1; /* this record in new */ +		} +	shift = -cmp; +	if (shift >= sizeof(bitmap->map)*8) +		return 0; /* stale, outside the window */ +	else if (bitmap->map & (1UL<<shift)) +		return 0; /* record previously received */ + +	memcpy (s->s3->rrec.seq_num,seq,8); +	return 1; +	} + + +static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap) +	{ +	int cmp; +	unsigned int shift; +	const unsigned char *seq = s->s3->read_sequence; + +	cmp = satsub64be(seq,bitmap->max_seq_num); +	if (cmp > 0) +		{ +		shift = cmp; +		if (shift < sizeof(bitmap->map)*8) +			bitmap->map <<= shift, bitmap->map |= 1UL; +		else +			bitmap->map = 1UL; +		memcpy(bitmap->max_seq_num,seq,8); +		} +	else	{ +		shift = -cmp; +		if (shift < sizeof(bitmap->map)*8) +			bitmap->map |= 1UL<<shift; +		} +	} + + +int dtls1_dispatch_alert(SSL *s) +	{ +	int i,j; +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	unsigned char buf[DTLS1_AL_HEADER_LENGTH]; +	unsigned char *ptr = &buf[0]; + +	s->s3->alert_dispatch=0; + +	memset(buf, 0x00, sizeof(buf)); +	*ptr++ = s->s3->send_alert[0]; +	*ptr++ = s->s3->send_alert[1]; + +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +	if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) +		{	 +		s2n(s->d1->handshake_read_seq, ptr); +#if 0 +		if ( s->d1->r_msg_hdr.frag_off == 0)  /* waiting for a new msg */ + +		else +			s2n(s->d1->r_msg_hdr.seq, ptr); /* partial msg read */ +#endif + +#if 0 +		fprintf(stderr, "s->d1->handshake_read_seq = %d, s->d1->r_msg_hdr.seq = %d\n",s->d1->handshake_read_seq,s->d1->r_msg_hdr.seq); +#endif +		l2n3(s->d1->r_msg_hdr.frag_off, ptr); +		} +#endif + +	i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0); +	if (i <= 0) +		{ +		s->s3->alert_dispatch=1; +		/* fprintf( stderr, "not done with alert\n" ); */ +		} +	else +		{ +		if (s->s3->send_alert[0] == SSL3_AL_FATAL +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +		    || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +#endif +		    ) +			(void)BIO_flush(s->wbio); + +		if (s->msg_callback) +			s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,  +				2, s, s->msg_callback_arg); + +		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); +	} + + +static DTLS1_BITMAP * +dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch) +    { +     +    *is_next_epoch = 0; + +    /* In current epoch, accept HM, CCS, DATA, & ALERT */ +    if (rr->epoch == s->d1->r_epoch) +        return &s->d1->bitmap; + +    /* Only HM and ALERT messages can be from the next epoch */ +    else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) && +        (rr->type == SSL3_RT_HANDSHAKE || +            rr->type == SSL3_RT_ALERT)) +        { +        *is_next_epoch = 1; +        return &s->d1->next_bitmap; +        } + +    return NULL; +    } + +#if 0 +static int +dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr, unsigned short *priority, +	unsigned long *offset) +	{ + +	/* alerts are passed up immediately */ +	if ( rr->type == SSL3_RT_APPLICATION_DATA || +		rr->type == SSL3_RT_ALERT) +		return 0; + +	/* Only need to buffer if a handshake is underway. +	 * (this implies that Hello Request and Client Hello are passed up +	 * immediately) */ +	if ( SSL_in_init(s)) +		{ +		unsigned char *data = rr->data; +		/* need to extract the HM/CCS sequence number here */ +		if ( rr->type == SSL3_RT_HANDSHAKE || +			rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) +			{ +			unsigned short seq_num; +			struct hm_header_st msg_hdr; +			struct ccs_header_st ccs_hdr; + +			if ( rr->type == SSL3_RT_HANDSHAKE) +				{ +				dtls1_get_message_header(data, &msg_hdr); +				seq_num = msg_hdr.seq; +				*offset = msg_hdr.frag_off; +				} +			else +				{ +				dtls1_get_ccs_header(data, &ccs_hdr); +				seq_num = ccs_hdr.seq; +				*offset = 0; +				} +				 +			/* this is either a record we're waiting for, or a +			 * retransmit of something we happened to previously  +			 * receive (higher layers will drop the repeat silently */ +			if ( seq_num < s->d1->handshake_read_seq) +				return 0; +			if (rr->type == SSL3_RT_HANDSHAKE &&  +				seq_num == s->d1->handshake_read_seq && +				msg_hdr.frag_off < s->d1->r_msg_hdr.frag_off) +				return 0; +			else if ( seq_num == s->d1->handshake_read_seq && +				(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC || +					msg_hdr.frag_off == s->d1->r_msg_hdr.frag_off)) +				return 0; +			else +				{ +				*priority = seq_num; +				return 1; +				} +			} +		else /* unknown record type */ +			return 0; +		} + +	return 0; +	} +#endif + +void +dtls1_reset_seq_numbers(SSL *s, int rw) +	{ +	unsigned char *seq; +	unsigned int seq_bytes = sizeof(s->s3->read_sequence); + +	if ( rw & SSL3_CC_READ) +		{ +		seq = s->s3->read_sequence; +		s->d1->r_epoch++; +		memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP)); +		memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP)); +		} +	else +		{ +		seq = s->s3->write_sequence; +		memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence)); +		s->d1->w_epoch++; +		} + +	memset(seq, 0x00, seq_bytes); +	} + + +static void +dtls1_clear_timeouts(SSL *s) +	{ +	memset(&(s->d1->timeout), 0x00, sizeof(struct dtls1_timeout_st)); +	} diff --git a/main/openssl/ssl/d1_srvr.c b/main/openssl/ssl/d1_srvr.c new file mode 100644 index 00000000..a6a4c87e --- /dev/null +++ b/main/openssl/ssl/d1_srvr.c @@ -0,0 +1,1563 @@ +/* ssl/d1_srvr.c */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 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" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/md5.h> +#include <openssl/bn.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif + +static const SSL_METHOD *dtls1_get_server_method(int ver); +static int dtls1_send_hello_verify_request(SSL *s); + +static const SSL_METHOD *dtls1_get_server_method(int ver) +	{ +	if (ver == DTLS1_VERSION) +		return(DTLSv1_server_method()); +	else +		return(NULL); +	} + +IMPLEMENT_dtls1_meth_func(DTLSv1_server_method, +			dtls1_accept, +			ssl_undefined_function, +			dtls1_get_server_method) + +int dtls1_accept(SSL *s) +	{ +	BUF_MEM *buf; +	unsigned long Time=(unsigned long)time(NULL); +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	unsigned long alg_k; +	int ret= -1; +	int new_state,state,skip=0; +	int listen; + +	RAND_add(&Time,sizeof(Time),0); +	ERR_clear_error(); +	clear_sys_error(); + +	if (s->info_callback != NULL) +		cb=s->info_callback; +	else if (s->ctx->info_callback != NULL) +		cb=s->ctx->info_callback; +	 +	listen = s->d1->listen; + +	/* init things to blank */ +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + +	s->d1->listen = listen; + +	if (s->cert == NULL) +		{ +		SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET); +		return(-1); +		} + +	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: + +			s->server=1; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) +				{ +				SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); +				return -1; +				} +			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; +				} + +			s->init_num=0; + +			if (s->state != SSL_ST_RENEGOTIATE) +				{ +				/* Ok, we now need to push on a buffering BIO so that +				 * the output is sent in a way that TCP likes :-) +				 */ +				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } + +				ssl3_init_finished_mac(s); +				s->state=SSL3_ST_SR_CLNT_HELLO_A; +				s->ctx->stats.sess_accept++; +				} +			else +				{ +				/* s->state == SSL_ST_RENEGOTIATE, +				 * we will just send a HelloRequest */ +				s->ctx->stats.sess_accept_renegotiate++; +				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; +			dtls1_start_timer(s); +			ret=dtls1_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: +			s->state=SSL_ST_OK; +			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; +			dtls1_stop_timer(s); + +			if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) +				s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; +			else +				s->state = SSL3_ST_SW_SRVR_HELLO_A; + +			s->init_num=0; + +			/* Reflect ClientHello sequence to remain stateless while listening */ +			if (listen) +				{ +				memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); +				} + +			/* If we're just listening, stop here */ +			if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) +				{ +				ret = 2; +				s->d1->listen = 0; +				/* Set expected sequence numbers +				 * to continue the handshake. +				 */ +				s->d1->handshake_read_seq = 2; +				s->d1->handshake_write_seq = 1; +				s->d1->next_handshake_write_seq = 1; +				goto end; +				} +			 +			break; +			 +		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: +		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + +			ret = dtls1_send_hello_verify_request(s); +			if ( ret <= 0) goto end; +			s->state=SSL3_ST_SW_FLUSH; +			s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; + +			/* HelloVerifyRequest resets Finished MAC */ +			if (s->version != DTLS1_BAD_VER) +				ssl3_init_finished_mac(s); +			break; +			 +		case SSL3_ST_SW_SRVR_HELLO_A: +		case SSL3_ST_SW_SRVR_HELLO_B: +			s->new_session = 2; +			dtls1_start_timer(s); +			ret=dtls1_send_server_hello(s); +			if (ret <= 0) goto end; + +#ifndef OPENSSL_NO_TLSEXT +			if (s->hit) +				{ +				if (s->tlsext_ticket_expected) +					s->state=SSL3_ST_SW_SESSION_TICKET_A; +				else +					s->state=SSL3_ST_SW_CHANGE_A; +				} +#else +			if (s->hit) +					s->state=SSL3_ST_SW_CHANGE_A; +#endif +			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 or normal PSK */ +			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) +				&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +				{ +				dtls1_start_timer(s); +				ret=dtls1_send_server_certificate(s); +				if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT +				if (s->tlsext_status_expected) +					s->state=SSL3_ST_SW_CERT_STATUS_A; +				else +					s->state=SSL3_ST_SW_KEY_EXCH_A; +				} +			else +				{ +				skip = 1; +				s->state=SSL3_ST_SW_KEY_EXCH_A; +				} +#else +				} +			else +				skip=1; + +			s->state=SSL3_ST_SW_KEY_EXCH_A; +#endif +			s->init_num=0; +			break; + +		case SSL3_ST_SW_KEY_EXCH_A: +		case SSL3_ST_SW_KEY_EXCH_B: +			alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + +			/* clear this, it may get reset by +			 * send_server_key_exchange */ +			if ((s->options & SSL_OP_EPHEMERAL_RSA) +#ifndef OPENSSL_NO_KRB5 +				&& !(alg_k & SSL_kKRB5) +#endif /* OPENSSL_NO_KRB5 */ +				) +				/* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key +				 * even when forbidden by protocol specs +				 * (handshake may fail as clients are not required to +				 * be able to handle this) */ +				s->s3->tmp.use_rsa_tmp=1; +			else +				s->s3->tmp.use_rsa_tmp=0; + +			/* only send if a DH key exchange or +			 * RSA but we have a sign only certificate */ +			if (s->s3->tmp.use_rsa_tmp +			/* PSK: send ServerKeyExchange if PSK identity +			 * hint if provided */ +#ifndef OPENSSL_NO_PSK +			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) +#endif +			    || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) +			    || (alg_k & SSL_kEECDH) +			    || ((alg_k & SSL_kRSA) +				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL +				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) +					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) +					) +				    ) +				) +			    ) +				{ +				dtls1_start_timer(s); +				ret=dtls1_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 (/* don't request cert unless asked for it: */ +				!(s->verify_mode & SSL_VERIFY_PEER) || +				/* if SSL_VERIFY_CLIENT_ONCE is set, +				 * don't request cert during re-negotiation: */ +				((s->session->peer != NULL) && +				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || +				/* never request cert in anonymous ciphersuites +				 * (see section "Certificate request" in SSL 3 drafts +				 * and in RFC 2246): */ +				((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && +				 /* ... except when the application insists on verification +				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */ +				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || +				 /* never request cert in Kerberos ciphersuites */ +				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) +				/* With normal PSK Certificates and +				 * Certificate Requests are omitted */ +				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +				{ +				/* no cert request */ +				skip=1; +				s->s3->tmp.cert_request=0; +				s->state=SSL3_ST_SW_SRVR_DONE_A; +				} +			else +				{ +				s->s3->tmp.cert_request=1; +				dtls1_start_timer(s); +				ret=dtls1_send_certificate_request(s); +				if (ret <= 0) goto end; +#ifndef NETSCAPE_HANG_BUG +				s->state=SSL3_ST_SW_SRVR_DONE_A; +#else +				s->state=SSL3_ST_SW_FLUSH; +				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; +#endif +				s->init_num=0; +				} +			break; + +		case SSL3_ST_SW_SRVR_DONE_A: +		case SSL3_ST_SW_SRVR_DONE_B: +			dtls1_start_timer(s); +			ret=dtls1_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: +			s->rwstate=SSL_WRITING; +			if (BIO_flush(s->wbio) <= 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: +			/* Check for second client hello (MS SGC) */ +			ret = ssl3_check_client_hello(s); +			if (ret <= 0) +				goto end; +			dtls1_stop_timer(s); +			if (ret == 2) +				s->state = SSL3_ST_SR_CLNT_HELLO_C; +			else { +				/* 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; +				dtls1_stop_timer(s); +				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; +			dtls1_stop_timer(s); +			s->state=SSL3_ST_SR_CERT_VRFY_A; +			s->init_num=0; + +			if (ret == 2) +				{ +				/* For the ECDH ciphersuites when +				 * the client sends its ECDH pub key in +				 * a certificate, the CertificateVerify +				 * message is not sent. +				 */ +				s->state=SSL3_ST_SR_FINISHED_A; +				s->init_num = 0; +				} +			else +				{ +				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 */  +				s->method->ssl3_enc->cert_verify_mac(s, +					NID_md5, +					&(s->s3->tmp.cert_verify_md[0])); +				s->method->ssl3_enc->cert_verify_mac(s, +					NID_sha1, +					&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); +				} +			break; + +		case SSL3_ST_SR_CERT_VRFY_A: +		case SSL3_ST_SR_CERT_VRFY_B: + +			s->d1->change_cipher_spec_ok = 1; +			/* we should decide if we expected this one */ +			ret=ssl3_get_cert_verify(s); +			if (ret <= 0) goto end; +			dtls1_stop_timer(s); + +			s->state=SSL3_ST_SR_FINISHED_A; +			s->init_num=0; +			break; + +		case SSL3_ST_SR_FINISHED_A: +		case SSL3_ST_SR_FINISHED_B: +			s->d1->change_cipher_spec_ok = 1; +			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, +				SSL3_ST_SR_FINISHED_B); +			if (ret <= 0) goto end; +			dtls1_stop_timer(s); +			if (s->hit) +				s->state=SSL_ST_OK; +#ifndef OPENSSL_NO_TLSEXT +			else if (s->tlsext_ticket_expected) +				s->state=SSL3_ST_SW_SESSION_TICKET_A; +#endif +			else +				s->state=SSL3_ST_SW_CHANGE_A; +			s->init_num=0; +			break; + +#ifndef OPENSSL_NO_TLSEXT +		case SSL3_ST_SW_SESSION_TICKET_A: +		case SSL3_ST_SW_SESSION_TICKET_B: +			ret=dtls1_send_newsession_ticket(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_SW_CHANGE_A; +			s->init_num=0; +			break; + +		case SSL3_ST_SW_CERT_STATUS_A: +		case SSL3_ST_SW_CERT_STATUS_B: +			ret=ssl3_send_cert_status(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_SW_KEY_EXCH_A; +			s->init_num=0; +			break; + +#endif + +		case SSL3_ST_SW_CHANGE_A: +		case SSL3_ST_SW_CHANGE_B: + +			s->session->cipher=s->s3->tmp.new_cipher; +			if (!s->method->ssl3_enc->setup_key_block(s)) +				{ ret= -1; goto end; } + +			ret=dtls1_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 (!s->method->ssl3_enc->change_cipher_state(s, +				SSL3_CHANGE_CIPHER_SERVER_WRITE)) +				{ +				ret= -1; +				goto end; +				} + +			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); +			break; + +		case SSL3_ST_SW_FINISHED_A: +		case SSL3_ST_SW_FINISHED_B: +			ret=dtls1_send_finished(s, +				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, +				s->method->ssl3_enc->server_finished_label, +				s->method->ssl3_enc->server_finished_label_len); +			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); + +#if 0 +			BUF_MEM_free(s->init_buf); +			s->init_buf=NULL; +#endif + +			/* remove buffering on output */ +			ssl_free_wbio_buffer(s); + +			s->init_num=0; + +			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */ +				{ +				/* actually not necessarily a 'new' session unless +				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ +				 +				s->new_session=0; +				 +				ssl_update_cache(s,SSL_SESS_CACHE_SERVER); +				 +				s->ctx->stats.sess_accept_good++; +				/* s->server=1; */ +				s->handshake_func=dtls1_accept; + +				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); +				} +			 +			ret = 1; + +			/* done handshaking, next message is client hello */ +			s->d1->handshake_read_seq = 0; +			/* next message is server hello */ +			s->d1->handshake_write_seq = 0; +			s->d1->next_handshake_write_seq = 0; +			goto end; +			/* break; */ + +		default: +			SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE); +			ret= -1; +			goto end; +			/* break; */ +			} +		 +		if (!s->s3->tmp.reuse_message && !skip) +			{ +			if (s->debug) +				{ +				if ((ret=BIO_flush(s->wbio)) <= 0) +					goto end; +				} + + +			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); */ + +	s->in_handshake--; +	if (cb != NULL) +		cb(s,SSL_CB_ACCEPT_EXIT,ret); +	return(ret); +	} + +int dtls1_send_hello_request(SSL *s) +	{ +	unsigned char *p; + +	if (s->state == SSL3_ST_SW_HELLO_REQ_A) +		{ +		p=(unsigned char *)s->init_buf->data; +		p = dtls1_set_message_header(s, p, SSL3_MT_HELLO_REQUEST, 0, 0, 0); + +		s->state=SSL3_ST_SW_HELLO_REQ_B; +		/* number of bytes to write */ +		s->init_num=DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; + +		/* no need to buffer this message, since there are no retransmit  +		 * requests for it */ +		} + +	/* SSL3_ST_SW_HELLO_REQ_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int dtls1_send_hello_verify_request(SSL *s) +	{ +	unsigned int msg_len; +	unsigned char *msg, *buf, *p; + +	if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) +		{ +		buf = (unsigned char *)s->init_buf->data; + +		msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]); +		*(p++) = s->version >> 8; +		*(p++) = s->version & 0xFF; + +		if (s->ctx->app_gen_cookie_cb == NULL || +		     s->ctx->app_gen_cookie_cb(s, s->d1->cookie, +			 &(s->d1->cookie_len)) == 0) +			{ +			SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,ERR_R_INTERNAL_ERROR); +			return 0; +			} + +		*(p++) = (unsigned char) s->d1->cookie_len; +		memcpy(p, s->d1->cookie, s->d1->cookie_len); +		p += s->d1->cookie_len; +		msg_len = p - msg; + +		dtls1_set_message_header(s, buf, +			DTLS1_MT_HELLO_VERIFY_REQUEST, msg_len, 0, msg_len); + +		s->state=DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; +		/* number of bytes to write */ +		s->init_num=p-buf; +		s->init_off=0; +		} + +	/* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int dtls1_send_server_hello(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	int i; +	unsigned int 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=(unsigned long)time(NULL);			/* Time */ +		l2n(Time,p); +		RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); +		/* Do the message type and length last */ +		d=p= &(buf[DTLS1_HM_HEADER_LENGTH]); + +		*(p++)=s->version>>8; +		*(p++)=s->version&0xff; + +		/* 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 +		 * 12-Jan-98 - I'll now support the '0' length stuff. +		 */ +		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) +			s->session->session_id_length=0; + +		sl=s->session->session_id_length; +		if (sl > sizeof s->session->session_id) +			{ +			SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		*(p++)=sl; +		memcpy(p,s->session->session_id,sl); +		p+=sl; + +		/* put the cipher */ +		if (s->s3->tmp.new_cipher == NULL) +			return -1; +		i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p); +		p+=i; + +		/* put the compression method */ +#ifdef OPENSSL_NO_COMP +		*(p++)=0; +#else +		if (s->s3->tmp.new_compression == NULL) +			*(p++)=0; +		else +			*(p++)=s->s3->tmp.new_compression->id; +#endif + +#ifndef OPENSSL_NO_TLSEXT +		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) +			{ +			SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); +			return -1; +			} +#endif + +		/* do the header */ +		l=(p-d); +		d=buf; + +		d = dtls1_set_message_header(s, d, SSL3_MT_SERVER_HELLO, l, 0, l); + +		s->state=SSL3_ST_SW_SRVR_HELLO_B; +		/* number of bytes to write */ +		s->init_num=p-buf; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} + +	/* SSL3_ST_SW_SRVR_HELLO_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int dtls1_send_server_done(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 = dtls1_set_message_header(s, p, SSL3_MT_SERVER_DONE, 0, 0, 0); + +		s->state=SSL3_ST_SW_SRVR_DONE_B; +		/* number of bytes to write */ +		s->init_num=DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} + +	/* SSL3_ST_SW_SRVR_DONE_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int dtls1_send_server_key_exchange(SSL *s) +	{ +#ifndef OPENSSL_NO_RSA +	unsigned char *q; +	int j,num; +	RSA *rsa; +	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; +	unsigned int u; +#endif +#ifndef OPENSSL_NO_DH +	DH *dh=NULL,*dhp; +#endif +#ifndef OPENSSL_NO_ECDH +	EC_KEY *ecdh=NULL, *ecdhp; +	unsigned char *encodedPoint = NULL; +	int encodedlen = 0; +	int curve_id = 0; +	BN_CTX *bn_ctx = NULL;  +#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; + +	EVP_MD_CTX_init(&md_ctx); +	if (s->state == SSL3_ST_SW_KEY_EXCH_A) +		{ +		type=s->s3->tmp.new_cipher->algorithm_mkey; +		cert=s->cert; + +		buf=s->init_buf; + +		r[0]=r[1]=r[2]=r[3]=NULL; +		n=0; +#ifndef OPENSSL_NO_RSA +		if (type & SSL_kRSA) +			{ +			rsa=cert->rsa_tmp; +			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) +				{ +				rsa=s->cert->rsa_tmp_cb(s, +				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), +				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); +				if(rsa == NULL) +				{ +					al=SSL_AD_HANDSHAKE_FAILURE; +					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY); +					goto f_err; +				} +				RSA_up_ref(rsa); +				cert->rsa_tmp=rsa; +				} +			if (rsa == NULL) +				{ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_DTLS1_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 OPENSSL_NO_DH +			if (type & SSL_kEDH) +			{ +			dhp=cert->dh_tmp; +			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) +				dhp=s->cert->dh_tmp_cb(s, +				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), +				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); +			if (dhp == NULL) +				{ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); +				goto f_err; +				} + +			if (s->s3->tmp.dh != NULL) +				{ +				DH_free(dh); +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); +				goto err; +				} + +			if ((dh=DHparams_dup(dhp)) == NULL) +				{ +				SSLerr(SSL_F_DTLS1_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->options & SSL_OP_SINGLE_DH_USE))) +				{ +				if(!DH_generate_key(dh)) +				    { +				    SSLerr(SSL_F_DTLS1_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_DTLS1_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 +#ifndef OPENSSL_NO_ECDH +			if (type & SSL_kEECDH) +			{ +			const EC_GROUP *group; + +			ecdhp=cert->ecdh_tmp; +			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) +				{ +				ecdhp=s->cert->ecdh_tmp_cb(s, +				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), +				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); +				} +			if (ecdhp == NULL) +				{ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY); +				goto f_err; +				} + +			if (s->s3->tmp.ecdh != NULL) +				{ +				EC_KEY_free(s->s3->tmp.ecdh);  +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); +				goto err; +				} + +			/* Duplicate the ECDH structure. */ +			if (ecdhp == NULL) +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} +			if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} + +			s->s3->tmp.ecdh=ecdh; +			if ((EC_KEY_get0_public_key(ecdh) == NULL) || +			    (EC_KEY_get0_private_key(ecdh) == NULL) || +			    (s->options & SSL_OP_SINGLE_ECDH_USE)) +				{ +				if(!EC_KEY_generate_key(ecdh)) +				    { +				    SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				    goto err; +				    } +				} + +			if (((group = EC_KEY_get0_group(ecdh)) == NULL) || +			    (EC_KEY_get0_public_key(ecdh)  == NULL) || +			    (EC_KEY_get0_private_key(ecdh) == NULL)) +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} + +			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && +			    (EC_GROUP_get_degree(group) > 163))  +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); +				goto err; +				} + +			/* XXX: For now, we only support ephemeral ECDH +			 * keys over named (not generic) curves. For  +			 * supported named curves, curve_id is non-zero. +			 */ +			if ((curve_id =  +			    tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) +			    == 0) +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); +				goto err; +				} + +			/* Encode the public key. +			 * First check the size of encoding and +			 * allocate memory accordingly. +			 */ +			encodedlen = EC_POINT_point2oct(group,  +			    EC_KEY_get0_public_key(ecdh), +			    POINT_CONVERSION_UNCOMPRESSED,  +			    NULL, 0, NULL); + +			encodedPoint = (unsigned char *)  +			    OPENSSL_malloc(encodedlen*sizeof(unsigned char));  +			bn_ctx = BN_CTX_new(); +			if ((encodedPoint == NULL) || (bn_ctx == NULL)) +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +				goto err; +				} + + +			encodedlen = EC_POINT_point2oct(group,  +			    EC_KEY_get0_public_key(ecdh),  +			    POINT_CONVERSION_UNCOMPRESSED,  +			    encodedPoint, encodedlen, bn_ctx); + +			if (encodedlen == 0)  +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} + +			BN_CTX_free(bn_ctx);  bn_ctx=NULL; + +			/* XXX: For now, we only support named (not  +			 * generic) curves in ECDH ephemeral key exchanges. +			 * In this situation, we need four additional bytes +			 * to encode the entire ServerECDHParams +			 * structure.  +			 */ +			n = 4 + encodedlen; + +			/* We'll generate the serverKeyExchange message +			 * explicitly so we can set these to NULLs +			 */ +			r[0]=NULL; +			r[1]=NULL; +			r[2]=NULL; +			r[3]=NULL; +			} +		else  +#endif /* !OPENSSL_NO_ECDH */ +#ifndef OPENSSL_NO_PSK +			if (type & SSL_kPSK) +				{ +				/* reserve size for record length and PSK identity hint*/ +				n+=2+strlen(s->ctx->psk_identity_hint); +				} +			else +#endif /* !OPENSSL_NO_PSK */ +			{ +			al=SSL_AD_HANDSHAKE_FAILURE; +			SSLerr(SSL_F_DTLS1_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->algorithm_auth & SSL_aNULL) +			&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +			{ +			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) +				== NULL) +				{ +				al=SSL_AD_DECODE_ERROR; +				goto f_err; +				} +			kn=EVP_PKEY_size(pkey); +			} +		else +			{ +			pkey=NULL; +			kn=0; +			} + +		if (!BUF_MEM_grow_clean(buf,n+DTLS1_HM_HEADER_LENGTH+kn)) +			{ +			SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); +			goto err; +			} +		d=(unsigned char *)s->init_buf->data; +		p= &(d[DTLS1_HM_HEADER_LENGTH]); + +		for (i=0; r[i] != NULL; i++) +			{ +			s2n(nr[i],p); +			BN_bn2bin(r[i],p); +			p+=nr[i]; +			} + +#ifndef OPENSSL_NO_ECDH +		if (type & SSL_kEECDH)  +			{ +			/* XXX: For now, we only support named (not generic) curves. +			 * In this situation, the serverKeyExchange message has: +			 * [1 byte CurveType], [2 byte CurveName] +			 * [1 byte length of encoded point], followed by +			 * the actual encoded point itself +			 */ +			*p = NAMED_CURVE_TYPE; +			p += 1; +			*p = 0; +			p += 1; +			*p = curve_id; +			p += 1; +			*p = encodedlen; +			p += 1; +			memcpy((unsigned char*)p,  +			    (unsigned char *)encodedPoint,  +			    encodedlen); +			OPENSSL_free(encodedPoint); +			p += encodedlen; +			} +#endif + +#ifndef OPENSSL_NO_PSK +		if (type & SSL_kPSK) +			{ +			/* copy PSK identity hint */ +			s2n(strlen(s->ctx->psk_identity_hint), p);  +			strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); +			p+=strlen(s->ctx->psk_identity_hint); +			} +#endif + +		/* not anonymous */ +		if (pkey != NULL) +			{ +			/* n is the length of the params, they start at +			 * &(d[DTLS1_HM_HEADER_LENGTH]) and p points to the space +			 * at the end. */ +#ifndef OPENSSL_NO_RSA +			if (pkey->type == EVP_PKEY_RSA) +				{ +				q=md_buf; +				j=0; +				for (num=2; num > 0; num--) +					{ +					EVP_DigestInit_ex(&md_ctx,(num == 2) +						?s->ctx->md5:s->ctx->sha1, NULL); +					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[DTLS1_HM_HEADER_LENGTH]),n); +					EVP_DigestFinal_ex(&md_ctx,q, +						(unsigned int *)&i); +					q+=i; +					j+=i; +					} +				if (RSA_sign(NID_md5_sha1, md_buf, j, +					&(p[2]), &u, pkey->pkey.rsa) <= 0) +					{ +					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); +					goto err; +					} +				s2n(u,p); +				n+=u+2; +				} +			else +#endif +#if !defined(OPENSSL_NO_DSA) +				if (pkey->type == EVP_PKEY_DSA) +				{ +				/* lets do DSS */ +				EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL); +				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[DTLS1_HM_HEADER_LENGTH]),n); +				if (!EVP_SignFinal(&md_ctx,&(p[2]), +					(unsigned int *)&i,pkey)) +					{ +					SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA); +					goto err; +					} +				s2n(i,p); +				n+=i+2; +				} +			else +#endif +#if !defined(OPENSSL_NO_ECDSA) +				if (pkey->type == EVP_PKEY_EC) +				{ +				/* let's do ECDSA */ +				EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL); +				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_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA); +					goto err; +					} +				s2n(i,p); +				n+=i+2; +				} +			else +#endif +				{ +				/* Is this error check actually needed? */ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE); +				goto f_err; +				} +			} + +		d = dtls1_set_message_header(s, d, +			SSL3_MT_SERVER_KEY_EXCHANGE, n, 0, n); + +		/* we should now have things packed up, so lets send +		 * it off */ +		s->init_num=n+DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} + +	s->state = SSL3_ST_SW_KEY_EXCH_B; +	EVP_MD_CTX_cleanup(&md_ctx); +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +#ifndef OPENSSL_NO_ECDH +	if (encodedPoint != NULL) OPENSSL_free(encodedPoint); +	BN_CTX_free(bn_ctx); +#endif +	EVP_MD_CTX_cleanup(&md_ctx); +	return(-1); +	} + +int dtls1_send_certificate_request(SSL *s) +	{ +	unsigned char *p,*d; +	int i,j,nl,off,n; +	STACK_OF(X509_NAME) *sk=NULL; +	X509_NAME *name; +	BUF_MEM *buf; +	unsigned int msg_len; + +	if (s->state == SSL3_ST_SW_CERT_REQ_A) +		{ +		buf=s->init_buf; + +		d=p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); + +		/* 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_X509_NAME_num(sk); i++) +				{ +				name=sk_X509_NAME_value(sk,i); +				j=i2d_X509_NAME(name,NULL); +				if (!BUF_MEM_grow_clean(buf,DTLS1_HM_HEADER_LENGTH+n+j+2)) +					{ +					SSLerr(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB); +					goto err; +					} +				p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH+n]); +				if (!(s->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[DTLS1_HM_HEADER_LENGTH+off]); +		s2n(nl,p); + +		d=(unsigned char *)buf->data; +		*(d++)=SSL3_MT_CERTIFICATE_REQUEST; +		l2n3(n,d); +		s2n(s->d1->handshake_write_seq,d); +		s->d1->handshake_write_seq++; + +		/* we should now have things packed up, so lets send +		 * it off */ + +		s->init_num=n+DTLS1_HM_HEADER_LENGTH; +		s->init_off=0; +#ifdef NETSCAPE_HANG_BUG +/* XXX: what to do about this? */ +		p=(unsigned char *)s->init_buf->data + s->init_num; + +		/* do the header */ +		*(p++)=SSL3_MT_SERVER_DONE; +		*(p++)=0; +		*(p++)=0; +		*(p++)=0; +		s->init_num += 4; +#endif + +		/* XDTLS:  set message header ? */ +		msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH; +		dtls1_set_message_header(s, (void *)s->init_buf->data, +			SSL3_MT_CERTIFICATE_REQUEST, msg_len, 0, msg_len); + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); + +		s->state = SSL3_ST_SW_CERT_REQ_B; +		} + +	/* SSL3_ST_SW_CERT_REQ_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +err: +	return(-1); +	} + +int dtls1_send_server_certificate(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) +			{ +			/* VRS: allow null cert if auth == KRB5 */ +			if ((s->s3->tmp.new_cipher->algorithm_mkey != SSL_kKRB5) || +			    (s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5)) +				{ +				SSLerr(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR); +				return(0); +				} +			} + +		l=dtls1_output_cert_chain(s,x); +		s->state=SSL3_ST_SW_CERT_B; +		s->init_num=(int)l; +		s->init_off=0; + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} + +	/* SSL3_ST_SW_CERT_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +#ifndef OPENSSL_NO_TLSEXT +int dtls1_send_newsession_ticket(SSL *s) +	{ +	if (s->state == SSL3_ST_SW_SESSION_TICKET_A) +		{ +		unsigned char *p, *senc, *macstart; +		int len, slen; +		unsigned int hlen, msg_len; +		EVP_CIPHER_CTX ctx; +		HMAC_CTX hctx; +		SSL_CTX *tctx = s->initial_ctx; +		unsigned char iv[EVP_MAX_IV_LENGTH]; +		unsigned char key_name[16]; + +		/* get session encoding length */ +		slen = i2d_SSL_SESSION(s->session, NULL); +		/* Some length values are 16 bits, so forget it if session is + 		 * too long + 		 */ +		if (slen > 0xFF00) +			return -1; +		/* Grow buffer if need be: the length calculation is as + 		 * follows 12 (DTLS handshake message header) + + 		 * 4 (ticket lifetime hint) + 2 (ticket length) + + 		 * 16 (key name) + max_iv_len (iv length) + + 		 * session_length + max_enc_block_size (max encrypted session + 		 * length) + max_md_size (HMAC). + 		 */ +		if (!BUF_MEM_grow(s->init_buf, +			DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH + +			EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) +			return -1; +		senc = OPENSSL_malloc(slen); +		if (!senc) +			return -1; +		p = senc; +		i2d_SSL_SESSION(s->session, &p); + +		p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]); +		EVP_CIPHER_CTX_init(&ctx); +		HMAC_CTX_init(&hctx); +		/* Initialize HMAC and cipher contexts. If callback present +		 * it does all the work otherwise use generated values +		 * from parent ctx. +		 */ +		if (tctx->tlsext_ticket_key_cb) +			{ +			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, +							 &hctx, 1) < 0) +				{ +				OPENSSL_free(senc); +				return -1; +				} +			} +		else +			{ +			RAND_pseudo_bytes(iv, 16); +			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, +					tctx->tlsext_tick_aes_key, iv); +			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, +					tlsext_tick_md(), NULL); +			memcpy(key_name, tctx->tlsext_tick_key_name, 16); +			} +		l2n(s->session->tlsext_tick_lifetime_hint, p); +		/* Skip ticket length for now */ +		p += 2; +		/* Output key name */ +		macstart = p; +		memcpy(p, key_name, 16); +		p += 16; +		/* output IV */ +		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); +		p += EVP_CIPHER_CTX_iv_length(&ctx); +		/* Encrypt session data */ +		EVP_EncryptUpdate(&ctx, p, &len, senc, slen); +		p += len; +		EVP_EncryptFinal(&ctx, p, &len); +		p += len; +		EVP_CIPHER_CTX_cleanup(&ctx); + +		HMAC_Update(&hctx, macstart, p - macstart); +		HMAC_Final(&hctx, p, &hlen); +		HMAC_CTX_cleanup(&hctx); + +		p += hlen; +		/* Now write out lengths: p points to end of data written */ +		/* Total length */ +		len = p - (unsigned char *)(s->init_buf->data); +		/* Ticket length */ +		p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4; +		s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p); + +		/* number of bytes to write */ +		s->init_num= len; +		s->state=SSL3_ST_SW_SESSION_TICKET_B; +		s->init_off=0; +		OPENSSL_free(senc); + +		/* XDTLS:  set message header ? */ +		msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH; +		dtls1_set_message_header(s, (void *)s->init_buf->data, +			SSL3_MT_NEWSESSION_TICKET, msg_len, 0, msg_len); + +		/* buffer the message to handle re-xmits */ +		dtls1_buffer_message(s, 0); +		} + +	/* SSL3_ST_SW_SESSION_TICKET_B */ +	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); +	} +#endif diff --git a/main/openssl/ssl/dtls1.h b/main/openssl/ssl/dtls1.h new file mode 100644 index 00000000..2900d1d8 --- /dev/null +++ b/main/openssl/ssl/dtls1.h @@ -0,0 +1,267 @@ +/* ssl/dtls1.h */ +/*  + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.   + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DTLS1_H  +#define HEADER_DTLS1_H  + +#include <openssl/buffer.h> +#include <openssl/pqueue.h> +#ifdef OPENSSL_SYS_VMS +#include <resource.h> +#include <sys/timeb.h> +#endif +#ifdef OPENSSL_SYS_WIN32 +/* Needed for struct timeval */ +#include <winsock.h> +#elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_) +#include <sys/timeval.h> +#else +#include <sys/time.h> +#endif + +#ifdef  __cplusplus +extern "C" { +#endif + +#define DTLS1_VERSION			0xFEFF +#define DTLS1_BAD_VER			0x0100 + +#if 0 +/* this alert description is not specified anywhere... */ +#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110 +#endif + +/* lengths of messages */ +#define DTLS1_COOKIE_LENGTH                     256 + +#define DTLS1_RT_HEADER_LENGTH                  13 + +#define DTLS1_HM_HEADER_LENGTH                  12 + +#define DTLS1_HM_BAD_FRAGMENT                   -2 +#define DTLS1_HM_FRAGMENT_RETRY                 -3 + +#define DTLS1_CCS_HEADER_LENGTH                  1 + +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +#define DTLS1_AL_HEADER_LENGTH                   7 +#else +#define DTLS1_AL_HEADER_LENGTH                   2 +#endif + + +typedef struct dtls1_bitmap_st +	{ +	unsigned long map;		/* track 32 packets on 32-bit systems +					   and 64 - on 64-bit systems */ +	unsigned char max_seq_num[8];	/* max record number seen so far, +					   64-bit value in big-endian +					   encoding */ +	} DTLS1_BITMAP; + +struct dtls1_retransmit_state +	{ +	EVP_CIPHER_CTX *enc_write_ctx;	/* cryptographic state */ +	EVP_MD_CTX *write_hash;			/* used for mac generation */ +#ifndef OPENSSL_NO_COMP +	COMP_CTX *compress;				/* compression */ +#else +	char *compress;	 +#endif +	SSL_SESSION *session; +	unsigned short epoch; +	}; + +struct hm_header_st +	{ +	unsigned char type; +	unsigned long msg_len; +	unsigned short seq; +	unsigned long frag_off; +	unsigned long frag_len; +	unsigned int is_ccs; +	struct dtls1_retransmit_state saved_retransmit_state; +	}; + +struct ccs_header_st +	{ +	unsigned char type; +	unsigned short seq; +	}; + +struct dtls1_timeout_st +	{ +	/* Number of read timeouts so far */ +	unsigned int read_timeouts; +	 +	/* Number of write timeouts so far */ +	unsigned int write_timeouts; +	 +	/* Number of alerts received so far */ +	unsigned int num_alerts; +	}; + +typedef struct record_pqueue_st +	{ +	unsigned short epoch; +	pqueue q; +	} record_pqueue; + +typedef struct hm_fragment_st +	{ +	struct hm_header_st msg_header; +	unsigned char *fragment; +	unsigned char *reassembly; +	} hm_fragment; + +typedef struct dtls1_state_st +	{ +	unsigned int send_cookie; +	unsigned char cookie[DTLS1_COOKIE_LENGTH]; +	unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH]; +	unsigned int cookie_len; + +	/*  +	 * The current data and handshake epoch.  This is initially +	 * undefined, and starts at zero once the initial handshake is +	 * completed  +	 */ +	unsigned short r_epoch; +	unsigned short w_epoch; + +	/* records being received in the current epoch */ +	DTLS1_BITMAP bitmap; + +	/* renegotiation starts a new set of sequence numbers */ +	DTLS1_BITMAP next_bitmap; + +	/* handshake message numbers */ +	unsigned short handshake_write_seq; +	unsigned short next_handshake_write_seq; + +	unsigned short handshake_read_seq; + +	/* save last sequence number for retransmissions */ +	unsigned char last_write_sequence[8]; + +	/* Received handshake records (processed and unprocessed) */ +	record_pqueue unprocessed_rcds; +	record_pqueue processed_rcds; + +	/* Buffered handshake messages */ +	pqueue buffered_messages; + +	/* Buffered (sent) handshake records */ +	pqueue sent_messages; + +	/* Buffered application records. +	 * Only for records between CCS and Finished +	 * to prevent either protocol violation or +	 * unnecessary message loss. +	 */ +	record_pqueue buffered_app_data; + +	/* Is set when listening for new connections with dtls1_listen() */ +	unsigned int listen; + +	unsigned int mtu; /* max DTLS packet size */ + +	struct hm_header_st w_msg_hdr; +	struct hm_header_st r_msg_hdr; + +	struct dtls1_timeout_st timeout; + +	/* Indicates when the last handshake msg sent will timeout */ +	struct timeval next_timeout; + +	/* Timeout duration */ +	unsigned short timeout_duration; + +	/* storage for Alert/Handshake protocol data received but not +	 * yet processed by ssl3_read_bytes: */ +	unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH]; +	unsigned int alert_fragment_len; +	unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH]; +	unsigned int handshake_fragment_len; + +	unsigned int retransmitting; +	unsigned int change_cipher_spec_ok; + +	} DTLS1_STATE; + +typedef struct dtls1_record_data_st +	{ +	unsigned char *packet; +	unsigned int   packet_length; +	SSL3_BUFFER    rbuf; +	SSL3_RECORD    rrec; +	} DTLS1_RECORD_DATA; + + +/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ +#define DTLS1_TMO_READ_COUNT                      2 +#define DTLS1_TMO_WRITE_COUNT                     2 + +#define DTLS1_TMO_ALERT_COUNT                     12 + +#ifdef  __cplusplus +} +#endif +#endif + diff --git a/main/openssl/ssl/kssl.c b/main/openssl/ssl/kssl.c new file mode 100644 index 00000000..b820e374 --- /dev/null +++ b/main/openssl/ssl/kssl.c @@ -0,0 +1,2205 @@ +/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */ +/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + +/*  ssl/kssl.c  --  Routines to support (& debug) Kerberos5 auth for openssl +** +**  19990701	VRS 	Started. +**  200011??	Jeffrey Altman, Richard Levitte +**          		Generalized for Heimdal, Newer MIT, & Win32. +**          		Integrated into main OpenSSL 0.9.7 snapshots. +**  20010413	Simon Wilkinson, VRS +**          		Real RFC2712 KerberosWrapper replaces AP_REQ. +*/ + +#include <openssl/opensslconf.h> + +#include <string.h> + +#define KRB5_PRIVATE	1 + +#include <openssl/ssl.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/krb5_asn.h> +#include "kssl_lcl.h" + +#ifndef OPENSSL_NO_KRB5 + +#ifndef ENOMEM +#define ENOMEM KRB5KRB_ERR_GENERIC +#endif + +/*  + * When OpenSSL is built on Windows, we do not want to require that + * the Kerberos DLLs be available in order for the OpenSSL DLLs to + * work.  Therefore, all Kerberos routines are loaded at run time + * and we do not link to a .LIB file. + */ + +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +/*  + * The purpose of the following pre-processor statements is to provide + * compatibility with different releases of MIT Kerberos for Windows. + * All versions up to 1.2 used macros.  But macros do not allow for + * a binary compatible interface for DLLs.  Therefore, all macros are + * being replaced by function calls.  The following code will allow + * an OpenSSL DLL built on Windows to work whether or not the macro + * or function form of the routines are utilized. + */ +#ifdef  krb5_cc_get_principal +#define NO_DEF_KRB5_CCACHE +#undef  krb5_cc_get_principal +#endif +#define krb5_cc_get_principal    kssl_krb5_cc_get_principal + +#define krb5_free_data_contents  kssl_krb5_free_data_contents    +#define krb5_free_context        kssl_krb5_free_context          +#define krb5_auth_con_free       kssl_krb5_auth_con_free         +#define krb5_free_principal      kssl_krb5_free_principal        +#define krb5_mk_req_extended     kssl_krb5_mk_req_extended       +#define krb5_get_credentials     kssl_krb5_get_credentials       +#define krb5_cc_default          kssl_krb5_cc_default            +#define krb5_sname_to_principal  kssl_krb5_sname_to_principal    +#define krb5_init_context        kssl_krb5_init_context          +#define krb5_free_ticket         kssl_krb5_free_ticket           +#define krb5_rd_req              kssl_krb5_rd_req                +#define krb5_kt_default          kssl_krb5_kt_default            +#define krb5_kt_resolve          kssl_krb5_kt_resolve            +/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */ +#ifndef krb5_kt_close +#define krb5_kt_close            kssl_krb5_kt_close +#endif /* krb5_kt_close */ +#ifndef krb5_kt_get_entry +#define krb5_kt_get_entry        kssl_krb5_kt_get_entry +#endif /* krb5_kt_get_entry */ +#define krb5_auth_con_init       kssl_krb5_auth_con_init         + +#define krb5_principal_compare   kssl_krb5_principal_compare +#define krb5_decrypt_tkt_part    kssl_krb5_decrypt_tkt_part +#define krb5_timeofday           kssl_krb5_timeofday +#define krb5_rc_default          kssl_krb5_rc_default + +#ifdef krb5_rc_initialize +#undef krb5_rc_initialize +#endif +#define krb5_rc_initialize   kssl_krb5_rc_initialize + +#ifdef krb5_rc_get_lifespan +#undef krb5_rc_get_lifespan +#endif +#define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan + +#ifdef krb5_rc_destroy +#undef krb5_rc_destroy +#endif +#define krb5_rc_destroy      kssl_krb5_rc_destroy + +#define valid_cksumtype      kssl_valid_cksumtype +#define krb5_checksum_size   kssl_krb5_checksum_size +#define krb5_kt_free_entry   kssl_krb5_kt_free_entry +#define krb5_auth_con_setrcache  kssl_krb5_auth_con_setrcache +#define krb5_auth_con_getrcache  kssl_krb5_auth_con_getrcache +#define krb5_get_server_rcache   kssl_krb5_get_server_rcache + +/* Prototypes for built in stubs */ +void kssl_krb5_free_data_contents(krb5_context, krb5_data *); +void kssl_krb5_free_principal(krb5_context, krb5_principal ); +krb5_error_code kssl_krb5_kt_resolve(krb5_context, +                                     krb5_const char *, +                                     krb5_keytab *); +krb5_error_code kssl_krb5_kt_default(krb5_context, +                                     krb5_keytab *); +krb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *); +krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *,  +                                 krb5_const krb5_data *, +                                 krb5_const_principal, krb5_keytab,  +                                 krb5_flags *,krb5_ticket **); + +krb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal, +                                         krb5_const_principal); +krb5_error_code kssl_krb5_mk_req_extended(krb5_context, +                                          krb5_auth_context  *, +                                          krb5_const krb5_flags, +                                          krb5_data  *, +                                          krb5_creds  *, +                                          krb5_data  * ); +krb5_error_code kssl_krb5_init_context(krb5_context *); +void kssl_krb5_free_context(krb5_context); +krb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache  *); +krb5_error_code kssl_krb5_sname_to_principal(krb5_context, +                                             krb5_const char  *, +                                             krb5_const char  *, +                                             krb5_int32, +                                             krb5_principal  *); +krb5_error_code kssl_krb5_get_credentials(krb5_context, +                                          krb5_const krb5_flags, +                                          krb5_ccache, +                                          krb5_creds  *, +                                          krb5_creds  *  *); +krb5_error_code kssl_krb5_auth_con_init(krb5_context, +                                        krb5_auth_context  *); +krb5_error_code kssl_krb5_cc_get_principal(krb5_context context,  +                                           krb5_ccache cache, +                                           krb5_principal *principal); +krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context); +size_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype); +krb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype); +krb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * ); +krb5_error_code kssl_krb5_auth_con_setrcache(krb5_context,  +                                             krb5_auth_context,  +                                             krb5_rcache); +krb5_error_code kssl_krb5_get_server_rcache(krb5_context,  +                                            krb5_const krb5_data *, +                                            krb5_rcache *); +krb5_error_code kssl_krb5_auth_con_getrcache(krb5_context,  +                                             krb5_auth_context, +                                             krb5_rcache *); + +/* Function pointers (almost all Kerberos functions are _stdcall) */ +static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *) +	=NULL; +static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal ) +	=NULL; +static krb5_error_code(_stdcall *p_krb5_kt_resolve) +			(krb5_context, krb5_const char *, krb5_keytab *)=NULL; +static krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context, +                                                     krb5_keytab *)=NULL; +static krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context,  +                                                      krb5_ticket *)=NULL; +static krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context,  +                                                 krb5_auth_context *,  +                                                 krb5_const krb5_data *, +                                                 krb5_const_principal,  +                                                 krb5_keytab, krb5_flags *, +                                                 krb5_ticket **)=NULL; +static krb5_error_code (_stdcall *p_krb5_mk_req_extended) +			(krb5_context, krb5_auth_context *, +			 krb5_const krb5_flags, krb5_data *, krb5_creds *, +			 krb5_data * )=NULL; +static krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL; +static void (_stdcall *p_krb5_free_context)(krb5_context)=NULL; +static krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context, +                                                     krb5_ccache  *)=NULL; +static krb5_error_code (_stdcall *p_krb5_sname_to_principal) +			(krb5_context, krb5_const char *, krb5_const char *, +			 krb5_int32, krb5_principal *)=NULL; +static krb5_error_code (_stdcall *p_krb5_get_credentials) +			(krb5_context, krb5_const krb5_flags, krb5_ccache, +			 krb5_creds *, krb5_creds **)=NULL; +static krb5_error_code (_stdcall *p_krb5_auth_con_init) +			(krb5_context, krb5_auth_context *)=NULL; +static krb5_error_code (_stdcall *p_krb5_cc_get_principal) +			(krb5_context context, krb5_ccache cache, +			 krb5_principal *principal)=NULL; +static krb5_error_code (_stdcall *p_krb5_auth_con_free) +			(krb5_context, krb5_auth_context)=NULL; +static krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part) +                        (krb5_context, krb5_const krb5_keyblock *, +                                           krb5_ticket *)=NULL; +static krb5_error_code (_stdcall *p_krb5_timeofday) +                        (krb5_context context, krb5_int32 *timeret)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_default) +                        (krb5_context context, krb5_rcache *rc)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_initialize) +                        (krb5_context context, krb5_rcache rc, +                                     krb5_deltat lifespan)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_get_lifespan) +                        (krb5_context context, krb5_rcache rc, +                                       krb5_deltat *lifespan)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_destroy) +                        (krb5_context context, krb5_rcache rc)=NULL; +static krb5_boolean (_stdcall *p_krb5_principal_compare) +                     (krb5_context, krb5_const_principal, krb5_const_principal)=NULL; +static size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumtype ctype)=NULL; +static krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL; +static krb5_error_code (_stdcall *p_krb5_kt_free_entry) +                        (krb5_context,krb5_keytab_entry * )=NULL; +static krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context,  +                                                               krb5_auth_context,  +                                                               krb5_rcache)=NULL; +static krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context,  +                                                              krb5_const krb5_data *,  +                                                              krb5_rcache *)=NULL; +static krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context,  +                                                      krb5_auth_context, +                                                      krb5_rcache *)=NULL; +static krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context,  +                                                    krb5_keytab keytab)=NULL; +static krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context,  +                                                        krb5_keytab keytab, +                       krb5_const_principal principal, krb5_kvno vno, +                       krb5_enctype enctype, krb5_keytab_entry *entry)=NULL; +static int krb5_loaded = 0;     /* only attempt to initialize func ptrs once */ + +/* Function to Load the Kerberos 5 DLL and initialize function pointers */ +void +load_krb5_dll(void) +	{ +	HANDLE hKRB5_32; +     +	krb5_loaded++; +	hKRB5_32 = LoadLibrary(TEXT("KRB5_32")); +	if (!hKRB5_32) +		return; + +	(FARPROC) p_krb5_free_data_contents = +		GetProcAddress( hKRB5_32, "krb5_free_data_contents" ); +	(FARPROC) p_krb5_free_context = +		GetProcAddress( hKRB5_32, "krb5_free_context" ); +	(FARPROC) p_krb5_auth_con_free = +		GetProcAddress( hKRB5_32, "krb5_auth_con_free" ); +	(FARPROC) p_krb5_free_principal = +		GetProcAddress( hKRB5_32, "krb5_free_principal" ); +	(FARPROC) p_krb5_mk_req_extended = +		GetProcAddress( hKRB5_32, "krb5_mk_req_extended" ); +	(FARPROC) p_krb5_get_credentials = +		GetProcAddress( hKRB5_32, "krb5_get_credentials" ); +	(FARPROC) p_krb5_cc_get_principal = +		GetProcAddress( hKRB5_32, "krb5_cc_get_principal" ); +	(FARPROC) p_krb5_cc_default = +		GetProcAddress( hKRB5_32, "krb5_cc_default" ); +	(FARPROC) p_krb5_sname_to_principal = +		GetProcAddress( hKRB5_32, "krb5_sname_to_principal" ); +	(FARPROC) p_krb5_init_context = +		GetProcAddress( hKRB5_32, "krb5_init_context" ); +	(FARPROC) p_krb5_free_ticket = +		GetProcAddress( hKRB5_32, "krb5_free_ticket" ); +	(FARPROC) p_krb5_rd_req = +		GetProcAddress( hKRB5_32, "krb5_rd_req" ); +	(FARPROC) p_krb5_principal_compare = +		GetProcAddress( hKRB5_32, "krb5_principal_compare" ); +	(FARPROC) p_krb5_decrypt_tkt_part = +		GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" ); +	(FARPROC) p_krb5_timeofday = +		GetProcAddress( hKRB5_32, "krb5_timeofday" ); +	(FARPROC) p_krb5_rc_default = +		GetProcAddress( hKRB5_32, "krb5_rc_default" ); +	(FARPROC) p_krb5_rc_initialize = +		GetProcAddress( hKRB5_32, "krb5_rc_initialize" ); +	(FARPROC) p_krb5_rc_get_lifespan = +		GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" ); +	(FARPROC) p_krb5_rc_destroy = +		GetProcAddress( hKRB5_32, "krb5_rc_destroy" ); +	(FARPROC) p_krb5_kt_default = +		GetProcAddress( hKRB5_32, "krb5_kt_default" ); +	(FARPROC) p_krb5_kt_resolve = +		GetProcAddress( hKRB5_32, "krb5_kt_resolve" ); +	(FARPROC) p_krb5_auth_con_init = +		GetProcAddress( hKRB5_32, "krb5_auth_con_init" ); +        (FARPROC) p_valid_cksumtype = +                GetProcAddress( hKRB5_32, "valid_cksumtype" ); +        (FARPROC) p_krb5_checksum_size = +                GetProcAddress( hKRB5_32, "krb5_checksum_size" ); +        (FARPROC) p_krb5_kt_free_entry = +                GetProcAddress( hKRB5_32, "krb5_kt_free_entry" ); +        (FARPROC) p_krb5_auth_con_setrcache = +                GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" ); +        (FARPROC) p_krb5_get_server_rcache = +                GetProcAddress( hKRB5_32, "krb5_get_server_rcache" ); +        (FARPROC) p_krb5_auth_con_getrcache = +                GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" ); +        (FARPROC) p_krb5_kt_close = +                GetProcAddress( hKRB5_32, "krb5_kt_close" ); +        (FARPROC) p_krb5_kt_get_entry = +                GetProcAddress( hKRB5_32, "krb5_kt_get_entry" ); +	} + +/* Stubs for each function to be dynamicly loaded */ +void +kssl_krb5_free_data_contents(krb5_context CO, krb5_data  * data) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_free_data_contents ) +		p_krb5_free_data_contents(CO,data); +	} + +krb5_error_code +kssl_krb5_mk_req_extended (krb5_context CO, +                          krb5_auth_context  * pACO, +                          krb5_const krb5_flags F, +                          krb5_data  * pD1, +                          krb5_creds  * pC, +                          krb5_data  * pD2) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_mk_req_extended ) +		return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2)); +	else +		return KRB5KRB_ERR_GENERIC; +	} +krb5_error_code +kssl_krb5_auth_con_init(krb5_context CO, +                       krb5_auth_context  * pACO) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_auth_con_init ) +		return(p_krb5_auth_con_init(CO,pACO)); +	else +		return KRB5KRB_ERR_GENERIC; +	} +krb5_error_code +kssl_krb5_auth_con_free (krb5_context CO, +                        krb5_auth_context ACO) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_auth_con_free ) +		return(p_krb5_auth_con_free(CO,ACO)); +	else +		return KRB5KRB_ERR_GENERIC; +	} +krb5_error_code +kssl_krb5_get_credentials(krb5_context CO, +                         krb5_const krb5_flags F, +                         krb5_ccache CC, +                         krb5_creds  * pCR, +                         krb5_creds  ** ppCR) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_get_credentials ) +		return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR)); +	else +		return KRB5KRB_ERR_GENERIC; +	} +krb5_error_code +kssl_krb5_sname_to_principal(krb5_context CO, +                            krb5_const char  * pC1, +                            krb5_const char  * pC2, +                            krb5_int32 I, +                            krb5_principal  * pPR) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_sname_to_principal ) +		return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +kssl_krb5_cc_default(krb5_context CO, +                    krb5_ccache  * pCC) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_cc_default ) +		return(p_krb5_cc_default(CO,pCC)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +kssl_krb5_init_context(krb5_context * pCO) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_init_context ) +		return(p_krb5_init_context(pCO)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +void +kssl_krb5_free_context(krb5_context CO) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_free_context ) +		p_krb5_free_context(CO); +	} + +void +kssl_krb5_free_principal(krb5_context c, krb5_principal p) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_free_principal ) +		p_krb5_free_principal(c,p); +	} + +krb5_error_code +kssl_krb5_kt_resolve(krb5_context con, +                    krb5_const char * sz, +                    krb5_keytab * kt) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_kt_resolve ) +		return(p_krb5_kt_resolve(con,sz,kt)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +kssl_krb5_kt_default(krb5_context con, +                    krb5_keytab * kt) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_kt_default ) +		return(p_krb5_kt_default(con,kt)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +kssl_krb5_free_ticket(krb5_context con, +                     krb5_ticket * kt) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_free_ticket ) +		return(p_krb5_free_ticket(con,kt)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +kssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon, +                krb5_const krb5_data * data, +                krb5_const_principal princ, krb5_keytab keytab, +                krb5_flags * flags, krb5_ticket ** pptkt) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_rd_req ) +		return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_boolean +krb5_principal_compare(krb5_context con, krb5_const_principal princ1, +                krb5_const_principal princ2) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_principal_compare ) +		return(p_krb5_principal_compare(con,princ1,princ2)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +krb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, +                krb5_ticket *ticket) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_decrypt_tkt_part ) +		return(p_krb5_decrypt_tkt_part(con,keys,ticket)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +krb5_timeofday(krb5_context con, krb5_int32 *timeret) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_timeofday ) +		return(p_krb5_timeofday(con,timeret)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +krb5_rc_default(krb5_context con, krb5_rcache *rc) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_rc_default ) +		return(p_krb5_rc_default(con,rc)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +krb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_rc_initialize ) +		return(p_krb5_rc_initialize(con, rc, lifespan)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +krb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_rc_get_lifespan ) +		return(p_krb5_rc_get_lifespan(con, rc, lifespanp)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +krb5_rc_destroy(krb5_context con, krb5_rcache rc) +	{ +	if (!krb5_loaded) +		load_krb5_dll(); + +	if ( p_krb5_rc_destroy ) +		return(p_krb5_rc_destroy(con, rc)); +	else +		return KRB5KRB_ERR_GENERIC; +	} + +size_t  +krb5_checksum_size(krb5_context context,krb5_cksumtype ctype) +        { +        if (!krb5_loaded) +                load_krb5_dll(); + +        if ( p_krb5_checksum_size ) +                return(p_krb5_checksum_size(context, ctype)); +        else +                return KRB5KRB_ERR_GENERIC; +        } + +krb5_boolean  +valid_cksumtype(krb5_cksumtype ctype) +        { +        if (!krb5_loaded) +                load_krb5_dll(); + +        if ( p_valid_cksumtype ) +                return(p_valid_cksumtype(ctype)); +        else +                return KRB5KRB_ERR_GENERIC; +        } + +krb5_error_code  +krb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry) +        { +        if (!krb5_loaded) +                load_krb5_dll(); + +        if ( p_krb5_kt_free_entry ) +                return(p_krb5_kt_free_entry(con,entry)); +        else +                return KRB5KRB_ERR_GENERIC; +        } +                  +/* Structure definitions  */ +#ifndef NO_DEF_KRB5_CCACHE +#ifndef krb5_x +#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) +#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) +#endif  + +typedef	krb5_pointer	krb5_cc_cursor;	/* cursor for sequential lookup */ + +typedef struct _krb5_ccache +	{ +	krb5_magic magic; +	struct _krb5_cc_ops FAR *ops; +	krb5_pointer data; +	} *krb5_ccache; + +typedef struct _krb5_cc_ops +	{ +	krb5_magic magic; +	char  *prefix; +	char  * (KRB5_CALLCONV *get_name) +		(krb5_context, krb5_ccache); +	krb5_error_code (KRB5_CALLCONV *resolve) +		(krb5_context, krb5_ccache  *, const char  *); +	krb5_error_code (KRB5_CALLCONV *gen_new) +		(krb5_context, krb5_ccache  *); +	krb5_error_code (KRB5_CALLCONV *init) +		(krb5_context, krb5_ccache, krb5_principal); +	krb5_error_code (KRB5_CALLCONV *destroy) +		(krb5_context, krb5_ccache); +	krb5_error_code (KRB5_CALLCONV *close) +		(krb5_context, krb5_ccache); +	krb5_error_code (KRB5_CALLCONV *store) +		(krb5_context, krb5_ccache, krb5_creds  *); +	krb5_error_code (KRB5_CALLCONV *retrieve) +		(krb5_context, krb5_ccache, +		krb5_flags, krb5_creds  *, krb5_creds  *); +	krb5_error_code (KRB5_CALLCONV *get_princ) +		(krb5_context, krb5_ccache, krb5_principal  *); +	krb5_error_code (KRB5_CALLCONV *get_first) +		(krb5_context, krb5_ccache, krb5_cc_cursor  *); +	krb5_error_code (KRB5_CALLCONV *get_next) +		(krb5_context, krb5_ccache, +		krb5_cc_cursor  *, krb5_creds  *); +	krb5_error_code (KRB5_CALLCONV *end_get) +		(krb5_context, krb5_ccache, krb5_cc_cursor  *); +	krb5_error_code (KRB5_CALLCONV *remove_cred) +		(krb5_context, krb5_ccache, +		krb5_flags, krb5_creds  *); +	krb5_error_code (KRB5_CALLCONV *set_flags) +		(krb5_context, krb5_ccache, krb5_flags); +	} krb5_cc_ops; +#endif /* NO_DEF_KRB5_CCACHE */ + +krb5_error_code  +kssl_krb5_cc_get_principal +    (krb5_context context, krb5_ccache cache, +      krb5_principal *principal) +	{ +	if ( p_krb5_cc_get_principal ) +		return(p_krb5_cc_get_principal(context,cache,principal)); +	else +		return(krb5_x +			((cache)->ops->get_princ,(context, cache, principal))); +	} + +krb5_error_code +kssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon, +                             krb5_rcache rcache) +        { +        if ( p_krb5_auth_con_setrcache ) +                 return(p_krb5_auth_con_setrcache(con,acon,rcache)); +        else +                 return KRB5KRB_ERR_GENERIC; +        } + +krb5_error_code +kssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data, +                            krb5_rcache * rcache)  +        { +	if ( p_krb5_get_server_rcache ) +		return(p_krb5_get_server_rcache(con,data,rcache)); +	else +		return KRB5KRB_ERR_GENERIC; +        } + +krb5_error_code +kssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon, +                             krb5_rcache * prcache) +        { +	if ( p_krb5_auth_con_getrcache ) +		return(p_krb5_auth_con_getrcache(con,acon, prcache)); +	else +		return KRB5KRB_ERR_GENERIC; +	} +  +krb5_error_code +kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab) +	{ +	if ( p_krb5_kt_close ) +		return(p_krb5_kt_close(context,keytab)); +	else  +		return KRB5KRB_ERR_GENERIC; +	} + +krb5_error_code +kssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, +                       krb5_const_principal principal, krb5_kvno vno, +                       krb5_enctype enctype, krb5_keytab_entry *entry) +	{ +	if ( p_krb5_kt_get_entry ) +		return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,entry)); +	else +		return KRB5KRB_ERR_GENERIC; +        } +#endif  /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ + + +/* memory allocation functions for non-temporary storage + * (e.g. stuff that gets saved into the kssl context) */ +static void* kssl_calloc(size_t nmemb, size_t size) +{ +	void* p; +	 +	p=OPENSSL_malloc(nmemb*size); +	if (p){ +		memset(p, 0, nmemb*size); +	} +	return p; +} + +#define kssl_malloc(size) OPENSSL_malloc((size)) +#define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size) +#define kssl_free(ptr) OPENSSL_free((ptr)) + + +char +*kstring(char *string) +        { +        static char	*null = "[NULL]"; + +	return ((string == NULL)? null: string); +        } + +/*	Given KRB5 enctype (basically DES or 3DES), +**	return closest match openssl EVP_ encryption algorithm. +**	Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes. +**	Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK. +*/ +const EVP_CIPHER * +kssl_map_enc(krb5_enctype enctype) +        { +	switch (enctype) +		{ +	case ENCTYPE_DES_HMAC_SHA1:		/*    EVP_des_cbc();       */ +	case ENCTYPE_DES_CBC_CRC: +	case ENCTYPE_DES_CBC_MD4: +	case ENCTYPE_DES_CBC_MD5: +	case ENCTYPE_DES_CBC_RAW: +				return EVP_des_cbc(); +				break; +	case ENCTYPE_DES3_CBC_SHA1:		/*    EVP_des_ede3_cbc();  */ +	case ENCTYPE_DES3_CBC_SHA: +	case ENCTYPE_DES3_CBC_RAW: +				return EVP_des_ede3_cbc(); +				break; +	default:                return NULL; +				break; +		} +	} + + +/*	Return true:1 if p "looks like" the start of the real authenticator +**	described in kssl_skip_confound() below.  The ASN.1 pattern is +**	"62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and +**	xx and yy are possibly multi-byte length fields. +*/ +static int 	kssl_test_confound(unsigned char *p) +	{ +	int 	len = 2; +	int 	xx = 0, yy = 0; + +	if (*p++ != 0x62)  return 0; +	if (*p > 0x82)  return 0; +	switch(*p)  { +		case 0x82:  p++;          xx = (*p++ << 8);  xx += *p++;  break; +		case 0x81:  p++;          xx =  *p++;  break; +		case 0x80:  return 0; +		default:    xx = *p++;  break; +		} +	if (*p++ != 0x30)  return 0; +	if (*p > 0x82)  return 0; +	switch(*p)  { +		case 0x82:  p++; len+=2;  yy = (*p++ << 8);  yy += *p++;  break; +		case 0x81:  p++; len++;   yy =  *p++;  break; +		case 0x80:  return 0; +		default:    yy = *p++;  break; +		} + +	return (xx - len == yy)? 1: 0; +	} + +/*	Allocate, fill, and return cksumlens array of checksum lengths. +**	This array holds just the unique elements from the krb5_cksumarray[]. +**	array[n] == 0 signals end of data. +** +**      The krb5_cksumarray[] was an internal variable that has since been +**      replaced by a more general method for storing the data.  It should +**      not be used.  Instead we use real API calls and make a guess for  +**      what the highest assigned CKSUMTYPE_ constant is.  As of 1.2.2 +**      it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3).  So we will use 0x0010. +*/ +static size_t  *populate_cksumlens(void) +	{ +	int 		i, j, n; +	static size_t 	*cklens = NULL; + +#ifdef KRB5_MIT_OLD11 +	n = krb5_max_cksum; +#else +	n = 0x0010; +#endif	/* KRB5_MIT_OLD11 */ +  +#ifdef KRB5CHECKAUTH +	if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1)))  return NULL; + +	for (i=0; i < n; i++)  { +		if (!valid_cksumtype(i))  continue;	/*  array has holes  */ +		for (j=0; j < n; j++)  { +			if (cklens[j] == 0)  { +				cklens[j] = krb5_checksum_size(NULL,i); +				break;		/*  krb5 elem was new: add   */ +				} +			if (cklens[j] == krb5_checksum_size(NULL,i))  { +				break;		/*  ignore duplicate elements */ +				} +			} +		} +#endif	/* KRB5CHECKAUTH */ + +	return cklens; +	} + +/*	Return pointer to start of real authenticator within authenticator, or +**	return NULL on error. +**	Decrypted authenticator looks like this: +**		[0 or 8 byte confounder] [4-24 byte checksum] [real authent'r] +**	This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the +**	krb5_auth_con_getcksumtype() function advertised in its krb5.h. +*/ +unsigned char	*kssl_skip_confound(krb5_enctype etype, unsigned char *a) +	{ +	int 		i, conlen; +	size_t		cklen; +	static size_t 	*cksumlens = NULL; +	unsigned char	*test_auth; + +	conlen = (etype)? 8: 0; + +	if (!cksumlens  &&  !(cksumlens = populate_cksumlens()))  return NULL; +	for (i=0; (cklen = cksumlens[i]) != 0; i++) +		{ +		test_auth = a + conlen + cklen; +		if (kssl_test_confound(test_auth))  return test_auth; +		} + +	return NULL; +	} + + +/*	Set kssl_err error info when reason text is a simple string +**		kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; } +*/ +void +kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) +        { +	if (kssl_err == NULL)  return; + +	kssl_err->reason = reason; +	BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text); +	return; +        } + + +/*	Display contents of krb5_data struct, for debugging +*/ +void +print_krb5_data(char *label, krb5_data *kdata) +        { +	int i; + +	printf("%s[%d] ", label, kdata->length); +	for (i=0; i < (int)kdata->length; i++) +                { +		if (0 &&  isprint((int) kdata->data[i])) +                        printf(	"%c ",  kdata->data[i]); +		else +                        printf(	"%02x ", (unsigned char) kdata->data[i]); +		} +	printf("\n"); +        } + + +/*	Display contents of krb5_authdata struct, for debugging +*/ +void +print_krb5_authdata(char *label, krb5_authdata **adata) +        { +	if (adata == NULL) +                { +		printf("%s, authdata==0\n", label); +		return; +		} +	printf("%s [%p]\n", label, (void *)adata); +#if 0 +	{ +        int 	i; +	printf("%s[at%d:%d] ", label, adata->ad_type, adata->length); +	for (i=0; i < adata->length; i++) +                { +                printf((isprint(adata->contents[i]))? "%c ": "%02x", +                        adata->contents[i]); +		} +	printf("\n"); +	} +#endif +	} + + +/*	Display contents of krb5_keyblock struct, for debugging +*/ +void +print_krb5_keyblock(char *label, krb5_keyblock *keyblk) +        { +	int i; + +	if (keyblk == NULL) +                { +		printf("%s, keyblk==0\n", label); +		return; +		} +#ifdef KRB5_HEIMDAL +	printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, +					   keyblk->keyvalue->length); +	for (i=0; i < (int)keyblk->keyvalue->length; i++) +                { +		printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); +		} +	printf("\n"); +#else +	printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); +	for (i=0; i < (int)keyblk->length; i++) +                { +		printf("%02x",keyblk->contents[i]); +		} +	printf("\n"); +#endif +        } + + +/*	Display contents of krb5_principal_data struct, for debugging +**	(krb5_principal is typedef'd == krb5_principal_data *) +*/ +static void +print_krb5_princ(char *label, krb5_principal_data *princ) +        { +	int i, ui, uj; + +	printf("%s principal Realm: ", label); +	if (princ == NULL)  return; +	for (ui=0; ui < (int)princ->realm.length; ui++)  putchar(princ->realm.data[ui]); +	printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); +	for (i=0; i < (int)princ->length; i++) +                { +		printf("\t%d [%d]: ", i, princ->data[i].length); +		for (uj=0; uj < (int)princ->data[i].length; uj++)  { +			putchar(princ->data[i].data[uj]); +			} +		printf("\n"); +		} +	return; +        } + + +/*	Given krb5 service (typically "kssl") and hostname in kssl_ctx, +**	Return encrypted Kerberos ticket for service @ hostname. +**	If authenp is non-NULL, also return encrypted authenticator, +**	whose data should be freed by caller. +**	(Originally was: Create Kerberos AP_REQ message for SSL Client.) +** +**	19990628	VRS 	Started; Returns Kerberos AP_REQ message. +**	20010409	VRS 	Modified for RFC2712; Returns enc tkt. +**	20010606	VRS 	May also return optional authenticator. +*/ +krb5_error_code +kssl_cget_tkt(	/* UPDATE */	KSSL_CTX *kssl_ctx, +                /* OUT    */	krb5_data **enc_ticketp, +                /* UPDATE */	krb5_data *authenp, +                /* OUT    */	KSSL_ERR *kssl_err) +	{ +	krb5_error_code		krb5rc = KRB5KRB_ERR_GENERIC; +	krb5_context		krb5context = NULL; +	krb5_auth_context	krb5auth_context = NULL; +	krb5_ccache 		krb5ccdef = NULL; +	krb5_creds		krb5creds, *krb5credsp = NULL; +	krb5_data		krb5_app_req; + +	kssl_err_set(kssl_err, 0, ""); +	memset((char *)&krb5creds, 0, sizeof(krb5creds)); + +	if (!kssl_ctx) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "No kssl_ctx defined.\n"); +		goto err; +		} +	else if (!kssl_ctx->service_host) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "kssl_ctx service_host undefined.\n"); +		goto err; +		} + +	if ((krb5rc = krb5_init_context(&krb5context)) != 0) +                { +		BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, +                        "krb5_init_context() fails: %d\n", krb5rc); +		kssl_err->reason = SSL_R_KRB5_C_INIT; +		goto err; +		} + +	if ((krb5rc = krb5_sname_to_principal(krb5context, +                kssl_ctx->service_host, +                (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, +                KRB5_NT_SRV_HST, &krb5creds.server)) != 0) +                { +		BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, +                        "krb5_sname_to_principal() fails for %s/%s\n", +                        kssl_ctx->service_host, +                        (kssl_ctx->service_name)? kssl_ctx->service_name: +						  KRB5SVC); +		kssl_err->reason = SSL_R_KRB5_C_INIT; +		goto err; +		} + +	if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, +                        "krb5_cc_default fails.\n"); +		goto err; +		} + +	if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, +                &krb5creds.client)) != 0) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, +                        "krb5_cc_get_principal() fails.\n"); +		goto err; +		} + +	if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, +                &krb5creds, &krb5credsp)) != 0) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, +                        "krb5_get_credentials() fails.\n"); +		goto err; +		} + +	*enc_ticketp = &krb5credsp->ticket; +#ifdef KRB5_HEIMDAL +	kssl_ctx->enctype = krb5credsp->session.keytype; +#else +	kssl_ctx->enctype = krb5credsp->keyblock.enctype; +#endif + +	krb5rc = KRB5KRB_ERR_GENERIC; +	/*	caller should free data of krb5_app_req  */ +	/*  20010406 VRS deleted for real KerberosWrapper +	**  20010605 VRS reinstated to offer Authenticator to KerberosWrapper +	*/ +	krb5_app_req.length = 0; +	if (authenp) +                { +		krb5_data	krb5in_data; +		const unsigned char	*p; +		long		arlen; +		KRB5_APREQBODY	*ap_req; + +		authenp->length = 0; +		krb5in_data.data = NULL; +		krb5in_data.length = 0; +		if ((krb5rc = krb5_mk_req_extended(krb5context, +			&krb5auth_context, 0, &krb5in_data, krb5credsp, +			&krb5_app_req)) != 0) +			{ +			kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, +				"krb5_mk_req_extended() fails.\n"); +			goto err; +			} + +		arlen = krb5_app_req.length; +		p = (unsigned char *)krb5_app_req.data; +		ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); +		if (ap_req) +			{ +			authenp->length = i2d_KRB5_ENCDATA( +					ap_req->authenticator, NULL); +			if (authenp->length  &&  +				(authenp->data = malloc(authenp->length))) +				{ +				unsigned char	*adp = (unsigned char *)authenp->data; +				authenp->length = i2d_KRB5_ENCDATA( +						ap_req->authenticator, &adp); +				} +			} + +		if (ap_req)  KRB5_APREQ_free((KRB5_APREQ *) ap_req); +		if (krb5_app_req.length)   +                        kssl_krb5_free_data_contents(krb5context,&krb5_app_req); +		} +#ifdef KRB5_HEIMDAL +	if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, +                        "kssl_ctx_setkey() fails.\n"); +		} +#else +	if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, +                        "kssl_ctx_setkey() fails.\n"); +		} +#endif +	else	krb5rc = 0; + + err: +#ifdef KSSL_DEBUG +	kssl_ctx_show(kssl_ctx); +#endif	/* KSSL_DEBUG */ + +	if (krb5creds.client)	krb5_free_principal(krb5context, +							krb5creds.client); +	if (krb5creds.server)	krb5_free_principal(krb5context, +							krb5creds.server); +	if (krb5auth_context)	krb5_auth_con_free(krb5context, +							krb5auth_context); +	if (krb5context)	krb5_free_context(krb5context); +	return (krb5rc); +	} + + +/*  Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket. +**  Return Kerberos error code and kssl_err struct on error. +**  Allocates krb5_ticket and krb5_principal; caller should free these. +** +**	20010410	VRS	Implemented krb5_decode_ticket() as +**				old_krb5_decode_ticket(). Missing from MIT1.0.6. +**	20010615	VRS 	Re-cast as openssl/asn1 d2i_*() functions. +**				Re-used some of the old krb5_decode_ticket() +**				code here.  This tkt should alloc/free just +**				like the real thing. +*/ +static krb5_error_code +kssl_TKT2tkt(	/* IN     */	krb5_context	krb5context, +		/* IN     */	KRB5_TKTBODY	*asn1ticket, +		/* OUT    */	krb5_ticket	**krb5ticket, +		/* OUT    */	KSSL_ERR *kssl_err  ) +        { +        krb5_error_code			krb5rc = KRB5KRB_ERR_GENERIC; +	krb5_ticket 			*new5ticket = NULL; +	ASN1_GENERALSTRING		*gstr_svc, *gstr_host; + +	*krb5ticket = NULL; + +	if (asn1ticket == NULL  ||  asn1ticket->realm == NULL  || +		asn1ticket->sname == NULL  ||  +		sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) +		{ +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"Null field in asn1ticket.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		return KRB5KRB_ERR_GENERIC; +		} + +	if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL) +		{ +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"Unable to allocate new krb5_ticket.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		return ENOMEM;		/*  or  KRB5KRB_ERR_GENERIC;	*/ +		} + +	gstr_svc  = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0); +	gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1); + +	if ((krb5rc = kssl_build_principal_2(krb5context, +			&new5ticket->server, +			asn1ticket->realm->length, (char *)asn1ticket->realm->data, +			gstr_svc->length,  (char *)gstr_svc->data, +			gstr_host->length, (char *)gstr_host->data)) != 0) +		{ +		free(new5ticket); +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"Error building ticket server principal.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		return krb5rc;		/*  or  KRB5KRB_ERR_GENERIC;	*/ +		} + +	krb5_princ_type(krb5context, new5ticket->server) = +			asn1ticket->sname->nametype->data[0]; +	new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0]; +	new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0]; +	new5ticket->enc_part.ciphertext.length = +			asn1ticket->encdata->cipher->length; +	if ((new5ticket->enc_part.ciphertext.data = +		calloc(1, asn1ticket->encdata->cipher->length)) == NULL) +		{ +		free(new5ticket); +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"Error allocating cipher in krb5ticket.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		return KRB5KRB_ERR_GENERIC; +		} +	else +		{ +		memcpy(new5ticket->enc_part.ciphertext.data, +			asn1ticket->encdata->cipher->data, +			asn1ticket->encdata->cipher->length); +		} + +	*krb5ticket = new5ticket; +	return 0; +	} + + +/*	Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"), +**		and krb5 AP_REQ message & message length, +**	Return Kerberos session key and client principle +**		to SSL Server in KSSL_CTX *kssl_ctx. +** +**	19990702	VRS 	Started. +*/ +krb5_error_code +kssl_sget_tkt(	/* UPDATE */	KSSL_CTX		*kssl_ctx, +		/* IN     */	krb5_data		*indata, +		/* OUT    */	krb5_ticket_times	*ttimes, +		/* OUT    */	KSSL_ERR		*kssl_err  ) +        { +        krb5_error_code			krb5rc = KRB5KRB_ERR_GENERIC; +        static krb5_context		krb5context = NULL; +	static krb5_auth_context	krb5auth_context = NULL; +	krb5_ticket 			*krb5ticket = NULL; +	KRB5_TKTBODY 			*asn1ticket = NULL; +	const unsigned char		*p; +	krb5_keytab 			krb5keytab = NULL; +	krb5_keytab_entry		kt_entry; +	krb5_principal			krb5server; +        krb5_rcache                     rcache = NULL; + +	kssl_err_set(kssl_err, 0, ""); + +	if (!kssl_ctx) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +			"No kssl_ctx defined.\n"); +		goto err; +		} + +#ifdef KSSL_DEBUG +	printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name)); +#endif	/* KSSL_DEBUG */ + +	if (!krb5context  &&  (krb5rc = krb5_init_context(&krb5context))) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "krb5_init_context() fails.\n"); +		goto err; +		} +	if (krb5auth_context  && +		(krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "krb5_auth_con_free() fails.\n"); +		goto err; +		} +	else  krb5auth_context = NULL; +	if (!krb5auth_context  && +		(krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "krb5_auth_con_init() fails.\n"); +		goto err; +		} + +  +	if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context, +		&rcache))) +		{ + 		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +			"krb5_auth_con_getrcache() fails.\n"); + 		goto err; +		} +  +	if ((krb5rc = krb5_sname_to_principal(krb5context, NULL, +                (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, +                KRB5_NT_SRV_HST, &krb5server)) != 0) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "krb5_sname_to_principal() fails.\n"); +		goto err; +		} + +	if (rcache == NULL)  +                { +                if ((krb5rc = krb5_get_server_rcache(krb5context, +			krb5_princ_component(krb5context, krb5server, 0), +			&rcache))) +                        { +		        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                                "krb5_get_server_rcache() fails.\n"); +                  	goto err; +                        } +                } + +        if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache))) +                { +                kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +			"krb5_auth_con_setrcache() fails.\n"); +                goto err; +                } + + +	/*	kssl_ctx->keytab_file == NULL ==> use Kerberos default +	*/ +	if (kssl_ctx->keytab_file) +		{ +		krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, +                        &krb5keytab); +		if (krb5rc) +			{ +			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +				"krb5_kt_resolve() fails.\n"); +			goto err; +			} +		} +	else +		{ +                krb5rc = krb5_kt_default(krb5context,&krb5keytab); +                if (krb5rc) +			{ +			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,  +				"krb5_kt_default() fails.\n"); +			goto err; +			} +		} + +	/*	Actual Kerberos5 krb5_recvauth() has initial conversation here +	**	o	check KRB5_SENDAUTH_BADAUTHVERS +	**		unless KRB5_RECVAUTH_SKIP_VERSION +	**	o	check KRB5_SENDAUTH_BADAPPLVERS +	**	o	send "0" msg if all OK +	*/ + +	/*  20010411 was using AP_REQ instead of true KerberosWrapper +	** +	**  if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, +	**			&krb5in_data, krb5server, krb5keytab, +	**			&ap_option, &krb5ticket)) != 0)  { Error } +	*/ + +	p = (unsigned char *)indata->data; +	if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p, +						(long) indata->length)) == NULL) +		{ +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"d2i_KRB5_TICKET() ASN.1 decode failure.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		goto err; +		} +	 +	/* Was:  krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */ +	if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket, +					kssl_err)) != 0) +		{ +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"Error converting ASN.1 ticket to krb5_ticket.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		goto err; +		} + +	if (! krb5_principal_compare(krb5context, krb5server, +						  krb5ticket->server))  { +		krb5rc = KRB5_PRINC_NOMATCH; +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"server principal != ticket principal\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		goto err; +		} +	if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, +			krb5ticket->server, krb5ticket->enc_part.kvno, +			krb5ticket->enc_part.enctype, &kt_entry)) != 0)  { +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"krb5_kt_get_entry() fails with %x.\n", krb5rc); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		goto err; +		} +	if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key, +			krb5ticket)) != 0)  { +		BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, +			"krb5_decrypt_tkt_part() failed.\n"); +		kssl_err->reason = SSL_R_KRB5_S_RD_REQ; +		goto err; +		} +	else  { +		krb5_kt_free_entry(krb5context, &kt_entry); +#ifdef KSSL_DEBUG +		{ +		int i; krb5_address **paddr = krb5ticket->enc_part2->caddrs; +		printf("Decrypted ticket fields:\n"); +		printf("\tflags: %X, transit-type: %X", +			krb5ticket->enc_part2->flags, +			krb5ticket->enc_part2->transited.tr_type); +		print_krb5_data("\ttransit-data: ", +			&(krb5ticket->enc_part2->transited.tr_contents)); +		printf("\tcaddrs: %p, authdata: %p\n", +			krb5ticket->enc_part2->caddrs, +			krb5ticket->enc_part2->authorization_data); +		if (paddr) +			{ +			printf("\tcaddrs:\n"); +			for (i=0; paddr[i] != NULL; i++) +				{ +				krb5_data d; +				d.length=paddr[i]->length; +				d.data=paddr[i]->contents; +				print_krb5_data("\t\tIP: ", &d); +				} +			} +		printf("\tstart/auth/end times: %d / %d / %d\n", +			krb5ticket->enc_part2->times.starttime, +			krb5ticket->enc_part2->times.authtime, +			krb5ticket->enc_part2->times.endtime); +		} +#endif	/* KSSL_DEBUG */ +		} + +	krb5rc = KRB5_NO_TKT_SUPPLIED; +	if (!krb5ticket  ||	!krb5ticket->enc_part2  || +                !krb5ticket->enc_part2->client  || +                !krb5ticket->enc_part2->client->data  || +                !krb5ticket->enc_part2->session) +                { +                kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, +                        "bad ticket from krb5_rd_req.\n"); +		} +	else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT, +		 &krb5ticket->enc_part2->client->realm, +		 krb5ticket->enc_part2->client->data, +		 krb5ticket->enc_part2->client->length)) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, +                        "kssl_ctx_setprinc() fails.\n"); +		} +	else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) +                { +		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, +                        "kssl_ctx_setkey() fails.\n"); +		} +	else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) +                { +		krb5rc = KRB5KRB_AP_ERR_TKT_INVALID; +                kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, +                        "invalid ticket from krb5_rd_req.\n"); +		} +	else	krb5rc = 0; + +	kssl_ctx->enctype	= krb5ticket->enc_part.enctype; +	ttimes->authtime	= krb5ticket->enc_part2->times.authtime; +	ttimes->starttime	= krb5ticket->enc_part2->times.starttime; +	ttimes->endtime 	= krb5ticket->enc_part2->times.endtime; +	ttimes->renew_till	= krb5ticket->enc_part2->times.renew_till; + + err: +#ifdef KSSL_DEBUG +	kssl_ctx_show(kssl_ctx); +#endif	/* KSSL_DEBUG */ + +	if (asn1ticket) 	KRB5_TICKET_free((KRB5_TICKET *) asn1ticket); +        if (krb5keytab)         krb5_kt_close(krb5context, krb5keytab); +	if (krb5ticket) 	krb5_free_ticket(krb5context, krb5ticket); +	if (krb5server) 	krb5_free_principal(krb5context, krb5server); +	return (krb5rc); +        } + + +/*	Allocate & return a new kssl_ctx struct. +*/ +KSSL_CTX	* +kssl_ctx_new(void) +        { +	return ((KSSL_CTX *) kssl_calloc(1, sizeof(KSSL_CTX))); +        } + + +/*	Frees a kssl_ctx struct and any allocated memory it holds. +**	Returns NULL. +*/ +KSSL_CTX	* +kssl_ctx_free(KSSL_CTX *kssl_ctx) +        { +	if (kssl_ctx == NULL)  return kssl_ctx; + +	if (kssl_ctx->key)  		OPENSSL_cleanse(kssl_ctx->key, +							      kssl_ctx->length); +	if (kssl_ctx->key)  		kssl_free(kssl_ctx->key); +	if (kssl_ctx->client_princ) 	kssl_free(kssl_ctx->client_princ); +	if (kssl_ctx->service_host) 	kssl_free(kssl_ctx->service_host); +	if (kssl_ctx->service_name) 	kssl_free(kssl_ctx->service_name); +	if (kssl_ctx->keytab_file) 	kssl_free(kssl_ctx->keytab_file); + +	kssl_free(kssl_ctx); +	return (KSSL_CTX *) NULL; +        } + + +/*	Given an array of (krb5_data *) entity (and optional realm), +**	set the plain (char *) client_princ or service_host member +**	of the kssl_ctx struct. +*/ +krb5_error_code +kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, +        krb5_data *realm, krb5_data *entity, int nentities) +        { +	char	**princ; +	int 	length; +	int i; + +	if (kssl_ctx == NULL  ||  entity == NULL)  return KSSL_CTX_ERR; + +	switch (which) +                { +        case KSSL_CLIENT:	princ = &kssl_ctx->client_princ;	break; +        case KSSL_SERVER:	princ = &kssl_ctx->service_host;	break; +        default:		return KSSL_CTX_ERR;			break; +		} +	if (*princ)  kssl_free(*princ); + +	/* Add up all the entity->lengths */ +	length = 0; +	for (i=0; i < nentities; i++) +		{ +		length += entity[i].length; +		} +	/* Add in space for the '/' character(s) (if any) */ +	length += nentities-1; +	/* Space for the ('@'+realm+NULL | NULL) */ +	length += ((realm)? realm->length + 2: 1); + +	if ((*princ = kssl_calloc(1, length)) == NULL) +		return KSSL_CTX_ERR; +	else +		{ +		for (i = 0; i < nentities; i++) +			{ +			strncat(*princ, entity[i].data, entity[i].length); +			if (i < nentities-1) +				{ +				strcat (*princ, "/"); +				} +			} +		if (realm) +                        { +			strcat (*princ, "@"); +			(void) strncat(*princ, realm->data, realm->length); +			} +		} + +	return KSSL_CTX_OK; +        } + + +/*	Set one of the plain (char *) string members of the kssl_ctx struct. +**	Default values should be: +**		which == KSSL_SERVICE	=>	"khost" (KRB5SVC) +**		which == KSSL_KEYTAB	=>	"/etc/krb5.keytab" (KRB5KEYTAB) +*/ +krb5_error_code +kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) +        { +	char	**string; + +	if (!kssl_ctx)  return KSSL_CTX_ERR; + +	switch (which) +                { +        case KSSL_SERVICE:	string = &kssl_ctx->service_name;	break; +        case KSSL_SERVER:	string = &kssl_ctx->service_host;	break; +        case KSSL_CLIENT:	string = &kssl_ctx->client_princ;	break; +        case KSSL_KEYTAB:	string = &kssl_ctx->keytab_file;	break; +        default:		return KSSL_CTX_ERR;			break; +		} +	if (*string)  kssl_free(*string); + +	if (!text) +                { +		*string = '\0'; +		return KSSL_CTX_OK; +		} + +	if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL) +		return KSSL_CTX_ERR; +	else +		strcpy(*string, text); + +	return KSSL_CTX_OK; +        } + + +/*	Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx +**	struct.  Clear kssl_ctx->key if Kerberos session key is NULL. +*/ +krb5_error_code +kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) +        { +	int 		length; +	krb5_enctype	enctype; +	krb5_octet FAR	*contents = NULL; + +	if (!kssl_ctx)  return KSSL_CTX_ERR; + +	if (kssl_ctx->key) +                { +		OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); +		kssl_free(kssl_ctx->key); +		} + +	if (session) +                { + +#ifdef KRB5_HEIMDAL +		length = session->keyvalue->length; +		enctype = session->keytype; +		contents = session->keyvalue->contents; +#else +		length = session->length; +		enctype = session->enctype; +		contents = session->contents; +#endif +		kssl_ctx->enctype = enctype; +		kssl_ctx->length  = length; +		} +	else +                { +		kssl_ctx->enctype = ENCTYPE_UNKNOWN; +		kssl_ctx->length  = 0; +		return KSSL_CTX_OK; +		} + +	if ((kssl_ctx->key = +                (krb5_octet FAR *) kssl_calloc(1, kssl_ctx->length)) == NULL) +                { +		kssl_ctx->length  = 0; +		return KSSL_CTX_ERR; +		} +	else +		memcpy(kssl_ctx->key, contents, length); + +	return KSSL_CTX_OK; +        } + + +/*	Display contents of kssl_ctx struct +*/ +void +kssl_ctx_show(KSSL_CTX *kssl_ctx) +        { +	int 	i; + +	printf("kssl_ctx: "); +	if (kssl_ctx == NULL) +                { +		printf("NULL\n"); +		return; +		} +	else +		printf("%p\n", (void *)kssl_ctx); + +	printf("\tservice:\t%s\n", +                (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL"); +	printf("\tclient:\t%s\n", +                (kssl_ctx->client_princ)? kssl_ctx->client_princ: "NULL"); +	printf("\tserver:\t%s\n", +                (kssl_ctx->service_host)? kssl_ctx->service_host: "NULL"); +	printf("\tkeytab:\t%s\n", +                (kssl_ctx->keytab_file)? kssl_ctx->keytab_file: "NULL"); +	printf("\tkey [%d:%d]:\t", +                kssl_ctx->enctype, kssl_ctx->length); + +	for (i=0; i < kssl_ctx->length  &&  kssl_ctx->key; i++) +                { +		printf("%02x", kssl_ctx->key[i]); +		} +	printf("\n"); +	return; +        } + +    int  +    kssl_keytab_is_available(KSSL_CTX *kssl_ctx) +{ +    krb5_context		krb5context = NULL; +    krb5_keytab 		krb5keytab = NULL; +    krb5_keytab_entry           entry; +    krb5_principal              princ = NULL; +    krb5_error_code  		krb5rc = KRB5KRB_ERR_GENERIC; +    int rc = 0; + +    if ((krb5rc = krb5_init_context(&krb5context))) +        return(0); + +    /*	kssl_ctx->keytab_file == NULL ==> use Kerberos default +    */ +    if (kssl_ctx->keytab_file) +    { +        krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, +                                  &krb5keytab); +        if (krb5rc) +            goto exit; +    } +    else +    { +        krb5rc = krb5_kt_default(krb5context,&krb5keytab); +        if (krb5rc) +            goto exit; +    } + +    /* the host key we are looking for */ +    krb5rc = krb5_sname_to_principal(krb5context, NULL,  +                                     kssl_ctx->service_name ? kssl_ctx->service_name: KRB5SVC, +                                     KRB5_NT_SRV_HST, &princ); + +    if (krb5rc) +	goto exit; + +    krb5rc = krb5_kt_get_entry(krb5context, krb5keytab,  +                                princ, +                                0 /* IGNORE_VNO */, +                                0 /* IGNORE_ENCTYPE */, +                                &entry); +    if ( krb5rc == KRB5_KT_NOTFOUND ) { +        rc = 1; +        goto exit; +    } else if ( krb5rc ) +        goto exit; +     +    krb5_kt_free_entry(krb5context, &entry); +    rc = 1; + +  exit: +    if (krb5keytab)     krb5_kt_close(krb5context, krb5keytab); +    if (princ)          krb5_free_principal(krb5context, princ); +    if (krb5context)	krb5_free_context(krb5context); +    return(rc); +} + +int  +kssl_tgt_is_available(KSSL_CTX *kssl_ctx) +        { +        krb5_error_code		krb5rc = KRB5KRB_ERR_GENERIC; +        krb5_context		krb5context = NULL; +        krb5_ccache 		krb5ccdef = NULL; +        krb5_creds		krb5creds, *krb5credsp = NULL; +        int                     rc = 0; + +        memset((char *)&krb5creds, 0, sizeof(krb5creds)); + +        if (!kssl_ctx) +            return(0); + +        if (!kssl_ctx->service_host) +            return(0); + +        if ((krb5rc = krb5_init_context(&krb5context)) != 0) +            goto err; + +        if ((krb5rc = krb5_sname_to_principal(krb5context, +                                              kssl_ctx->service_host, +                                              (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, +                                              KRB5_NT_SRV_HST, &krb5creds.server)) != 0) +            goto err; + +        if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) +            goto err; + +        if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, +                                             &krb5creds.client)) != 0) +            goto err; + +        if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, +                                            &krb5creds, &krb5credsp)) != 0) +            goto err; + +        rc = 1; + +      err: +#ifdef KSSL_DEBUG +	kssl_ctx_show(kssl_ctx); +#endif	/* KSSL_DEBUG */ + +	if (krb5creds.client)	krb5_free_principal(krb5context, krb5creds.client); +	if (krb5creds.server)	krb5_free_principal(krb5context, krb5creds.server); +	if (krb5context)	krb5_free_context(krb5context); +        return(rc); +	} + +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32) +void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) +	{ +#ifdef KRB5_HEIMDAL +	data->length = 0; +        if (data->data) +            free(data->data); +#elif defined(KRB5_MIT_OLD11) +	if (data->data)  { +		krb5_xfree(data->data); +		data->data = 0; +		} +#else +	krb5_free_data_contents(NULL, data); +#endif +	} +#endif /* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */ + + +/*  Given pointers to KerberosTime and struct tm structs, convert the +**  KerberosTime string to struct tm.  Note that KerberosTime is a +**  ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional +**  seconds as defined in RFC 1510. +**  Return pointer to the (partially) filled in struct tm on success, +**  return NULL on failure. +*/ +static struct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm) +	{ +	char 		c, *p; + +	if (!k_tm)  return NULL; +	if (gtime == NULL  ||  gtime->length < 14)  return NULL; +	if (gtime->data == NULL)  return NULL; + +	p = (char *)>ime->data[14]; + +	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_sec  = atoi(p);      *(p+2) = c; +	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_min  = atoi(p);      *(p+2) = c; +	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_hour = atoi(p);      *(p+2) = c; +	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_mday = atoi(p);      *(p+2) = c; +	c = *p;	 *p = '\0';  p -= 2;  k_tm->tm_mon  = atoi(p)-1;    *(p+2) = c; +	c = *p;	 *p = '\0';  p -= 4;  k_tm->tm_year = atoi(p)-1900; *(p+4) = c; + +	return k_tm; +	} + + +/*  Helper function for kssl_validate_times(). +**  We need context->clockskew, but krb5_context is an opaque struct. +**  So we try to sneek the clockskew out through the replay cache. +**	If that fails just return a likely default (300 seconds). +*/ +static krb5_deltat get_rc_clockskew(krb5_context context) +	{ +	krb5_rcache 	rc; +	krb5_deltat 	clockskew; + +	if (krb5_rc_default(context, &rc))  return KSSL_CLOCKSKEW; +	if (krb5_rc_initialize(context, rc, 0))  return KSSL_CLOCKSKEW; +	if (krb5_rc_get_lifespan(context, rc, &clockskew))  { +		clockskew = KSSL_CLOCKSKEW; +		} +	(void) krb5_rc_destroy(context, rc); +	return clockskew; +	} + + +/*  kssl_validate_times() combines (and more importantly exposes) +**  the MIT KRB5 internal function krb5_validate_times() and the +**  in_clock_skew() macro.  The authenticator client time is checked +**  to be within clockskew secs of the current time and the current +**  time is checked to be within the ticket start and expire times. +**  Either check may be omitted by supplying a NULL value. +**  Returns 0 for valid times, SSL_R_KRB5* error codes otherwise. +**  See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c +**  20010420 VRS +*/ +krb5_error_code  kssl_validate_times(	krb5_timestamp atime, +					krb5_ticket_times *ttimes) +	{ +	krb5_deltat 	skew; +	krb5_timestamp	start, now; +	krb5_error_code	rc; +	krb5_context	context; + +	if ((rc = krb5_init_context(&context)))	 return SSL_R_KRB5_S_BAD_TICKET; +	skew = get_rc_clockskew(context);  +	if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET; +	krb5_free_context(context); + +	if (atime  &&  labs(atime - now) >= skew)  return SSL_R_KRB5_S_TKT_SKEW; + +	if (! ttimes)  return 0; + +	start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime; +	if (start - now > skew)  return SSL_R_KRB5_S_TKT_NYV; +	if ((now - ttimes->endtime) > skew)  return SSL_R_KRB5_S_TKT_EXPIRED; + +#ifdef KSSL_DEBUG +	printf("kssl_validate_times: %d |<-  | %d - %d | < %d  ->| %d\n", +		start, atime, now, skew, ttimes->endtime); +#endif	/* KSSL_DEBUG */ + +	return 0; +	} + + +/*  Decode and decrypt given DER-encoded authenticator, then pass +**  authenticator ctime back in *atimep (or 0 if time unavailable). +**  Returns krb5_error_code and kssl_err on error.  A NULL  +**  authenticator (authentp->length == 0) is not considered an error. +**  Note that kssl_check_authent() makes use of the KRB5 session key; +**  you must call kssl_sget_tkt() to get the key before calling this routine. +*/ +krb5_error_code  kssl_check_authent( +			/* IN     */	KSSL_CTX	*kssl_ctx, +                        /* IN     */   	krb5_data	*authentp, +			/* OUT    */	krb5_timestamp	*atimep, +			/* OUT    */    KSSL_ERR	*kssl_err  ) +	{ +        krb5_error_code		krb5rc = 0; +	KRB5_ENCDATA		*dec_authent = NULL; +	KRB5_AUTHENTBODY	*auth = NULL; +	krb5_enctype		enctype; +	EVP_CIPHER_CTX		ciph_ctx; +	const EVP_CIPHER	*enc = NULL; +	unsigned char		iv[EVP_MAX_IV_LENGTH]; +	const unsigned char	*p; +	unsigned char		*unenc_authent; +	int 			outl, unencbufsize; +	struct tm		tm_time, *tm_l, *tm_g; +	time_t			now, tl, tg, tr, tz_offset; + +	EVP_CIPHER_CTX_init(&ciph_ctx); +	*atimep = 0; +	kssl_err_set(kssl_err, 0, ""); + +#ifndef KRB5CHECKAUTH +	authentp = NULL; +#else +#if	KRB5CHECKAUTH == 0 +	authentp = NULL; +#endif +#endif	/* KRB5CHECKAUTH */ + +	if (authentp == NULL  ||  authentp->length == 0)  return 0; + +#ifdef KSSL_DEBUG +        { +        unsigned int ui; +	printf("kssl_check_authent: authenticator[%d]:\n",authentp->length); +	p = authentp->data;  +	for (ui=0; ui < authentp->length; ui++)  printf("%02x ",p[ui]); +	printf("\n"); +        } +#endif	/* KSSL_DEBUG */ + +	unencbufsize = 2 * authentp->length; +	if ((unenc_authent = calloc(1, unencbufsize)) == NULL) +		{ +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +			"Unable to allocate authenticator buffer.\n"); +		krb5rc = KRB5KRB_ERR_GENERIC; +		goto err; +		} + +	p = (unsigned char *)authentp->data; +	if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, +					(long) authentp->length)) == NULL)  +		{ +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "Error decoding authenticator.\n"); +		krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; +		goto err; +		} + +	enctype = dec_authent->etype->data[0];	/* should = kssl_ctx->enctype */ +#if !defined(KRB5_MIT_OLD11) +            switch ( enctype ) { +            case ENCTYPE_DES3_CBC_SHA1:		/*    EVP_des_ede3_cbc();  */ +            case ENCTYPE_DES3_CBC_SHA: +            case ENCTYPE_DES3_CBC_RAW: +                krb5rc = 0;                     /* Skip, can't handle derived keys */ +                goto err; +            } +#endif +	enc = kssl_map_enc(enctype); +	memset(iv, 0, sizeof iv);       /* per RFC 1510 */ + +	if (enc == NULL) +		{ +		/*  Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1. +		**  This enctype indicates the authenticator was encrypted +		**  using key-usage derived keys which openssl cannot decrypt. +		*/ +		goto err; +		} + +        if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0)) +                { +                kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "EVP_CipherInit error decrypting authenticator.\n"); +                krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; +                goto err; +                } +        outl = dec_authent->cipher->length; +        if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl)) +                { +                kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "EVP_Cipher error decrypting authenticator.\n"); +                krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; +                goto err; +                } +        EVP_CIPHER_CTX_cleanup(&ciph_ctx); + +#ifdef KSSL_DEBUG +	{ +	int padl; +	printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); +	for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]); +	printf("\n"); +	} +#endif	/* KSSL_DEBUG */ + +	if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) +		{ +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "confounded by authenticator.\n"); +		krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; +		goto err; +		} +	outl -= p - unenc_authent; + +	if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p, +							  (long) outl))==NULL) +		{ +		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, +                        "Error decoding authenticator body.\n"); +		krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; +		goto err; +		} + +	memset(&tm_time,0,sizeof(struct tm)); +	if (k_gmtime(auth->ctime, &tm_time)  && +		((tr = mktime(&tm_time)) != (time_t)(-1))) + 		{ + 		now  = time(&now); + 		tm_l = localtime(&now); 	tl = mktime(tm_l); + 		tm_g = gmtime(&now);		tg = mktime(tm_g); + 		tz_offset = tg - tl; + +		*atimep = (krb5_timestamp)(tr - tz_offset); + 		} + +#ifdef KSSL_DEBUG +	printf("kssl_check_authent: returns %d for client time ", *atimep); +	if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) +		printf("%.*s\n", auth->ctime->length, auth->ctime->data); +	else	printf("NULL\n"); +#endif	/* KSSL_DEBUG */ + + err: +	if (auth)		KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); +	if (dec_authent)	KRB5_ENCDATA_free(dec_authent); +	if (unenc_authent)	free(unenc_authent); +	EVP_CIPHER_CTX_cleanup(&ciph_ctx); +	return krb5rc; +	} + + +/*  Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host), +**  because I dont't know how to stub varargs. +**  Returns krb5_error_code == ENOMEM on alloc error, otherwise +**  passes back newly constructed principal, which should be freed by caller. +*/ +krb5_error_code  kssl_build_principal_2( +			/* UPDATE */	krb5_context	context, +			/* OUT    */	krb5_principal	*princ, +			/* IN     */	int rlen,  const char *realm, +			/* IN	  */	int slen,  const char *svc, +			/* IN	  */	int hlen,  const char *host) +	{ +	krb5_data		*p_data = NULL; +	krb5_principal		new_p = NULL; +        char			*new_r = NULL; + +	if ((p_data = (krb5_data *) calloc(2, sizeof(krb5_data))) == NULL  || +	    (new_p = (krb5_principal) calloc(1, sizeof(krb5_principal_data))) +			== NULL)  goto err; +	new_p->length = 2; +	new_p->data = p_data; + +	if ((new_r = calloc(1, rlen + 1)) == NULL)  goto err; +	memcpy(new_r, realm, rlen); +	krb5_princ_set_realm_length(context, new_p, rlen); +	krb5_princ_set_realm_data(context, new_p, new_r); + +	if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL)  goto err; +	memcpy(new_p->data[0].data, svc, slen); +	new_p->data[0].length = slen; + +	if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL)  goto err; +	memcpy(new_p->data[1].data, host, hlen); +	new_p->data[1].length = hlen; +	 +	krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN; +	*princ = new_p; +	return 0; + + err: +	if (new_p  &&  new_p[0].data)	free(new_p[0].data); +	if (new_p  &&  new_p[1].data)	free(new_p[1].data); +	if (new_p)	free(new_p); +	if (new_r)	free(new_r); +	return ENOMEM; +	} + + +#else /* !OPENSSL_NO_KRB5 */ + +#if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) +static void *dummy=&dummy; +#endif + +#endif	/* !OPENSSL_NO_KRB5	*/ + diff --git a/main/openssl/ssl/kssl.h b/main/openssl/ssl/kssl.h new file mode 100644 index 00000000..a3d20e1c --- /dev/null +++ b/main/openssl/ssl/kssl.h @@ -0,0 +1,179 @@ +/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */ +/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000. + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* +**	19990701	VRS 	Started. +*/ + +#ifndef	KSSL_H +#define	KSSL_H + +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_KRB5 + +#include <stdio.h> +#include <ctype.h> +#include <krb5.h> + +#ifdef  __cplusplus +extern "C" { +#endif + +/* +**	Depending on which KRB5 implementation used, some types from +**	the other may be missing.  Resolve that here and now +*/ +#ifdef KRB5_HEIMDAL +typedef unsigned char krb5_octet; +#define FAR +#else + +#ifndef FAR +#define FAR +#endif + +#endif + +/*	Uncomment this to debug kssl problems or +**	to trace usage of the Kerberos session key +** +**	#define		KSSL_DEBUG +*/ + +#ifndef	KRB5SVC +#define KRB5SVC	"host" +#endif + +#ifndef	KRB5KEYTAB +#define KRB5KEYTAB	"/etc/krb5.keytab" +#endif + +#ifndef KRB5SENDAUTH +#define KRB5SENDAUTH	1 +#endif + +#ifndef KRB5CHECKAUTH +#define KRB5CHECKAUTH	1 +#endif + +#ifndef KSSL_CLOCKSKEW +#define	KSSL_CLOCKSKEW	300; +#endif + +#define	KSSL_ERR_MAX	255 +typedef struct kssl_err_st  { +	int  reason; +	char text[KSSL_ERR_MAX+1]; +	} KSSL_ERR; + + +/*	Context for passing +**		(1) Kerberos session key to SSL, and +**		(2)	Config data between application and SSL lib +*/ +typedef struct kssl_ctx_st +        { +                                /*	used by:    disposition:            */ +	char *service_name;	/*	C,S	    default ok (kssl)       */ +	char *service_host;	/*	C	    input, REQUIRED         */ +	char *client_princ;	/*	S	    output from krb5 ticket */ +	char *keytab_file;	/*      S	    NULL (/etc/krb5.keytab) */ +	char *cred_cache;	/*	C	    NULL (default)          */ +	krb5_enctype enctype; +	int length; +	krb5_octet FAR *key; +	} KSSL_CTX; + +#define	KSSL_CLIENT 	1 +#define KSSL_SERVER 	2 +#define	KSSL_SERVICE	3 +#define	KSSL_KEYTAB 	4 + +#define KSSL_CTX_OK 	0 +#define KSSL_CTX_ERR	1 +#define KSSL_NOMEM	2 + +/* Public (for use by applications that use OpenSSL with Kerberos 5 support */ +krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text); +KSSL_CTX *kssl_ctx_new(void); +KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx); +void kssl_ctx_show(KSSL_CTX *kssl_ctx); +krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, +        krb5_data *realm, krb5_data *entity, int nentities); +krb5_error_code	kssl_cget_tkt(KSSL_CTX *kssl_ctx,  krb5_data **enc_tktp, +        krb5_data *authenp, KSSL_ERR *kssl_err); +krb5_error_code	kssl_sget_tkt(KSSL_CTX *kssl_ctx,  krb5_data *indata, +        krb5_ticket_times *ttimes, KSSL_ERR *kssl_err); +krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session); +void	kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text); +void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data); +krb5_error_code  kssl_build_principal_2(krb5_context context, +			krb5_principal *princ, int rlen, const char *realm, +			int slen, const char *svc, int hlen, const char *host); +krb5_error_code  kssl_validate_times(krb5_timestamp atime, +					krb5_ticket_times *ttimes); +krb5_error_code  kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp, +			            krb5_timestamp *atimep, KSSL_ERR *kssl_err); +unsigned char	*kssl_skip_confound(krb5_enctype enctype, unsigned char *authn); + +#ifdef  __cplusplus +} +#endif +#endif	/* OPENSSL_NO_KRB5	*/ +#endif	/* KSSL_H 	*/ diff --git a/main/openssl/ssl/kssl_lcl.h b/main/openssl/ssl/kssl_lcl.h new file mode 100644 index 00000000..c039c91b --- /dev/null +++ b/main/openssl/ssl/kssl_lcl.h @@ -0,0 +1,87 @@ +/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */ +/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000. + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef	KSSL_LCL_H +#define	KSSL_LCL_H + +#include <openssl/kssl.h> + +#ifndef OPENSSL_NO_KRB5 + +#ifdef  __cplusplus +extern "C" { +#endif + +/* Private (internal to OpenSSL) */ +void print_krb5_data(char *label, krb5_data *kdata); +void print_krb5_authdata(char *label, krb5_authdata **adata); +void print_krb5_keyblock(char *label, krb5_keyblock *keyblk); + +char *kstring(char *string); +char *knumber(int len, krb5_octet *contents); + +const EVP_CIPHER *kssl_map_enc(krb5_enctype enctype); + +int kssl_keytab_is_available(KSSL_CTX *kssl_ctx); +int kssl_tgt_is_available(KSSL_CTX *kssl_ctx); + +#ifdef  __cplusplus +} +#endif +#endif	/* OPENSSL_NO_KRB5	*/ +#endif	/* KSSL_LCL_H 	*/ diff --git a/main/openssl/ssl/s23_clnt.c b/main/openssl/ssl/s23_clnt.c new file mode 100644 index 00000000..f41fe3ab --- /dev/null +++ b/main/openssl/ssl/s23_clnt.c @@ -0,0 +1,703 @@ +/* ssl/s23_clnt.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include "ssl_locl.h" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + +static const SSL_METHOD *ssl23_get_client_method(int ver); +static int ssl23_client_hello(SSL *s); +static int ssl23_get_server_hello(SSL *s); +static const SSL_METHOD *ssl23_get_client_method(int ver) +	{ +#ifndef OPENSSL_NO_SSL2 +	if (ver == SSL2_VERSION) +		return(SSLv2_client_method()); +#endif +	if (ver == SSL3_VERSION) +		return(SSLv3_client_method()); +	else if (ver == TLS1_VERSION) +		return(TLSv1_client_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl23_meth_func(SSLv23_client_method, +			ssl_undefined_function, +			ssl23_connect, +			ssl23_get_client_method) + +int ssl23_connect(SSL *s) +	{ +	BUF_MEM *buf=NULL; +	unsigned long Time=(unsigned long)time(NULL); +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int ret= -1; +	int new_state,state; + +	RAND_add(&Time,sizeof(Time),0); +	ERR_clear_error(); +	clear_sys_error(); + +	if (s->info_callback != NULL) +		cb=s->info_callback; +	else if (s->ctx->info_callback != NULL) +		cb=s->ctx->info_callback; +	 +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);  + +	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 (s->session != NULL) +				{ +				SSLerr(SSL_F_SSL23_CONNECT,SSL_R_SSL23_DOING_SESSION_ID_REUSE); +				ret= -1; +				goto end; +				} +			s->server=0; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			/* s->version=TLS1_VERSION; */ +			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; +				buf=NULL; +				} + +			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } + +			ssl3_init_finished_mac(s); + +			s->state=SSL23_ST_CW_CLNT_HELLO_A; +			s->ctx->stats.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) { (void)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 (buf != NULL) +		BUF_MEM_free(buf); +	if (cb != NULL) +		cb(s,SSL_CB_CONNECT_EXIT,ret); +	return(ret); +	} + +static int ssl23_no_ssl2_ciphers(SSL *s) +	{ +	SSL_CIPHER *cipher; +	STACK_OF(SSL_CIPHER) *ciphers; +	int i; +	ciphers = SSL_get_ciphers(s); +	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) +		{ +		cipher = sk_SSL_CIPHER_value(ciphers, i); +		if (cipher->algorithm_ssl == SSL_SSLV2) +			return 0; +		} +	return 1; +	} + +static int ssl23_client_hello(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	int i,ch_len; +	unsigned long Time,l; +	int ssl2_compat; +	int version = 0, version_major, version_minor; +#ifndef OPENSSL_NO_COMP +	int j; +	SSL_COMP *comp; +#endif +	int ret; + +	ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1; + +	if (ssl2_compat && ssl23_no_ssl2_ciphers(s)) +		ssl2_compat = 0; + +	if (!(s->options & SSL_OP_NO_TLSv1)) +		{ +		version = TLS1_VERSION; +		} +	else if (!(s->options & SSL_OP_NO_SSLv3)) +		{ +		version = SSL3_VERSION; +		} +	else if (!(s->options & SSL_OP_NO_SSLv2)) +		{ +		version = SSL2_VERSION; +		} +#ifndef OPENSSL_NO_TLSEXT +	if (version != SSL2_VERSION) +		{ +		/* have to disable SSL 2.0 compatibility if we need TLS extensions */ + +		if (s->tlsext_hostname != NULL) +			ssl2_compat = 0; +		if (s->tlsext_status_type != -1) +			ssl2_compat = 0; +#ifdef TLSEXT_TYPE_opaque_prf_input +		if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL) +			ssl2_compat = 0; +#endif +		} +#endif + +	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; +		Time=(unsigned long)time(NULL);		/* Time */ +		l2n(Time,p); +		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) +			return -1; + +		if (version == TLS1_VERSION) +			{ +			version_major = TLS1_VERSION_MAJOR; +			version_minor = TLS1_VERSION_MINOR; +			} +		else if (version == SSL3_VERSION) +			{ +			version_major = SSL3_VERSION_MAJOR; +			version_minor = SSL3_VERSION_MINOR; +			} +		else if (version == SSL2_VERSION) +			{ +			version_major = SSL2_VERSION_MAJOR; +			version_minor = SSL2_VERSION_MINOR; +			} +		else +			{ +			SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_PROTOCOLS_AVAILABLE); +			return(-1); +			} + +		s->client_version = version; + +		if (ssl2_compat) +			{ +			/* create SSL 2.0 compatible Client Hello */ + +			/* two byte record header will be written last */ +			d = &(buf[2]); +			p = d + 9; /* leave space for message type, version, individual length fields */ + +			*(d++) = SSL2_MT_CLIENT_HELLO; +			*(d++) = version_major; +			*(d++) = version_minor; +			 +			/* Ciphers supported */ +			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),p,0); +			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 length (zero since there is no reuse) */ +#if 0 +			s->session->session_id_length=0; +#endif +			s2n(0,d); + +			if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG) +				ch_len=SSL2_CHALLENGE_LENGTH; +			else +				ch_len=SSL2_MAX_CHALLENGE_LENGTH; + +			/* write out sslv2 challenge */ +			/* Note that ch_len must be <= SSL3_RANDOM_SIZE (32), +			   because it is one of SSL2_MAX_CHALLENGE_LENGTH (32) +			   or SSL2_MAX_CHALLENGE_LENGTH (16), but leave the +			   check in for futurproofing */ +			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); +			if (RAND_pseudo_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i) <= 0) +				return -1; + +			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); + +			/* number of bytes to write */ +			s->init_num=i+2; +			s->init_off=0; + +			ssl3_finish_mac(s,&(buf[2]),i); +			} +		else +			{ +			/* create Client Hello in SSL 3.0/TLS 1.0 format */ + +			/* do the record header (5 bytes) and handshake message header (4 bytes) last */ +			d = p = &(buf[9]); +			 +			*(p++) = version_major; +			*(p++) = version_minor; + +			/* Random stuff */ +			memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); +			p += SSL3_RANDOM_SIZE; + +			/* Session ID (zero since there is no reuse) */ +			*(p++) = 0; + +			/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */ +			i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),ssl3_put_cipher_by_char); +			if (i == 0) +				{ +				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); +				return -1; +				} +			s2n(i,p); +			p+=i; + +			/* COMPRESSION */ +#ifdef OPENSSL_NO_COMP +			*(p++)=1; +#else +			if ((s->options & SSL_OP_NO_COMPRESSION) +						|| !s->ctx->comp_methods) +				j=0; +			else +				j=sk_SSL_COMP_num(s->ctx->comp_methods); +			*(p++)=1+j; +			for (i=0; i<j; i++) +				{ +				comp=sk_SSL_COMP_value(s->ctx->comp_methods,i); +				*(p++)=comp->id; +				} +#endif +			*(p++)=0; /* Add the NULL method */ + +#ifndef OPENSSL_NO_TLSEXT +			/* TLS extensions*/ +			if (ssl_prepare_clienthello_tlsext(s) <= 0) +				{ +				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); +				return -1; +				} +			if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) +				{ +				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); +				return -1; +				} +#endif +			 +			l = p-d; + +			/* fill in 4-byte handshake header */ +			d=&(buf[5]); +			*(d++)=SSL3_MT_CLIENT_HELLO; +			l2n3(l,d); + +			l += 4; + +			if (l > SSL3_RT_MAX_PLAIN_LENGTH) +				{ +				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); +				return -1; +				} +			 +			/* fill in 5-byte record header */ +			d=buf; +			*(d++) = SSL3_RT_HANDSHAKE; +			*(d++) = version_major; +			*(d++) = version_minor; /* arguably we should send the *lowest* suported version here +			                         * (indicating, e.g., TLS 1.0 in "SSL 3.0 format") */ +			s2n((int)l,d); + +			/* number of bytes to write */ +			s->init_num=p-buf; +			s->init_off=0; + +			ssl3_finish_mac(s,&(buf[5]), s->init_num - 5); +			} + +		s->state=SSL23_ST_CW_CLNT_HELLO_B; +		s->init_off=0; +		} + +	/* SSL3_ST_CW_CLNT_HELLO_B */ +	ret = ssl23_write_bytes(s); + +	if ((ret >= 2) && s->msg_callback) +		{ +		/* Client Hello has been sent; tell msg_callback */ + +		if (ssl2_compat) +			s->msg_callback(1, SSL2_VERSION, 0, s->init_buf->data+2, ret-2, s, s->msg_callback_arg); +		else +			s->msg_callback(1, version, SSL3_RT_HANDSHAKE, s->init_buf->data+5, ret-5, s, s->msg_callback_arg); +		} + +	return ret; +	} + +static int ssl23_get_server_hello(SSL *s) +	{ +	char buf[8]; +	unsigned char *p; +	int i; +	int n; + +	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)) +		{ +#ifdef OPENSSL_NO_SSL2 +		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); +		goto err; +#else +		/* we are talking sslv2 */ +		/* we need to clean up the SSLv3 setup and put in the +		 * sslv2 stuff. */ +		int ch_len; + +		if (s->options & SSL_OP_NO_SSLv2) +			{ +			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); +			goto err; +			} +		if (s->s2 == NULL) +			{ +			if (!ssl2_new(s)) +				goto err; +			} +		else +			ssl2_clear(s); + +		if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG) +			ch_len=SSL2_CHALLENGE_LENGTH; +		else +			ch_len=SSL2_MAX_CHALLENGE_LENGTH; + +		/* write out sslv2 challenge */ +		/* Note that ch_len must be <= SSL3_RANDOM_SIZE (32), because +		   it is one of SSL2_MAX_CHALLENGE_LENGTH (32) or +		   SSL2_MAX_CHALLENGE_LENGTH (16), but leave the check in for +		   futurproofing */ +		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_clean(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; +		if (!(s->client_version == SSL2_VERSION)) +			/* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */ +			s->s2->ssl2_rollback=1; + +		/* setup the 7 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; +#endif +		} +	else if (p[1] == SSL3_VERSION_MAJOR && +	         (p[2] == SSL3_VERSION_MINOR || p[2] == TLS1_VERSION_MINOR) && +	         ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) || +	          (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) +		{ +		/* we have sslv3 or tls1 (server hello or alert) */ + +		if ((p[2] == SSL3_VERSION_MINOR) && +			!(s->options & SSL_OP_NO_SSLv3)) +			{ +			s->version=SSL3_VERSION; +			s->method=SSLv3_client_method(); +			} +		else if ((p[2] == TLS1_VERSION_MINOR) && +			!(s->options & SSL_OP_NO_TLSv1)) +			{ +			s->version=TLS1_VERSION; +			s->method=TLSv1_client_method(); +			} +		else +			{ +			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); +			goto err; +			} + +		if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) +			{ +			/* fatal alert */ + +			void (*cb)(const SSL *ssl,int type,int val)=NULL; +			int j; + +			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); +				} +			 +			if (s->msg_callback) +				s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg); + +			s->rwstate=SSL_NOTHING; +			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]); +			goto err; +			} + +		if (!ssl_init_wbio_buffer(s,1)) goto err; + +		/* we are in this state */ +		s->state=SSL3_ST_CR_SRVR_HELLO_A; + +		/* put the 7 bytes we have read into the input buffer +		 * for SSLv3 */ +		s->rstate=SSL_ST_READ_HEADER; +		s->packet_length=n; +		if (s->s3->rbuf.buf == NULL) +			if (!ssl3_setup_read_buffer(s)) +				goto err; +		s->packet= &(s->s3->rbuf.buf[0]); +		memcpy(s->packet,buf,n); +		s->s3->rbuf.left=n; +		s->s3->rbuf.offset=0; + +		s->handshake_func=s->method->ssl_connect; +		} +	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 (!s->session_creation_enabled) +		{ +		if (!(s->client_version == SSL2_VERSION)) +			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); +		goto err; +		} +	if (!ssl_get_new_session(s,0)) +		goto err; + +	return(SSL_connect(s)); +err: +	return(-1); +	} diff --git a/main/openssl/ssl/s23_lib.c b/main/openssl/ssl/s23_lib.c new file mode 100644 index 00000000..3bf72831 --- /dev/null +++ b/main/openssl/ssl/s23_lib.c @@ -0,0 +1,187 @@ +/* ssl/s23_lib.c */ +/* Copyright (C) 1995-1998 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 <openssl/objects.h> +#include "ssl_locl.h" + +long ssl23_default_timeout(void) +	{ +	return(300); +	} + +int ssl23_num_ciphers(void) +	{ +	return(ssl3_num_ciphers() +#ifndef OPENSSL_NO_SSL2 +	       + ssl2_num_ciphers() +#endif +	    ); +	} + +const SSL_CIPHER *ssl23_get_cipher(unsigned int u) +	{ +	unsigned int uu=ssl3_num_ciphers(); + +	if (u < uu) +		return(ssl3_get_cipher(u)); +	else +#ifndef OPENSSL_NO_SSL2 +		return(ssl2_get_cipher(u-uu)); +#else +		return(NULL); +#endif +	} + +/* This function needs to check if the ciphers required are actually + * available */ +const SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p) +	{ +	const SSL_CIPHER *cp; + +	cp=ssl3_get_cipher_by_char(p); +#ifndef OPENSSL_NO_SSL2 +	if (cp == NULL) +		cp=ssl2_get_cipher_by_char(p); +#endif +	return(cp); +	} + +int ssl23_put_cipher_by_char(const 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); +	} + +int ssl23_read(SSL *s, void *buf, int len) +	{ +	int n; + +	clear_sys_error(); +	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); +		} +	} + +int ssl23_peek(SSL *s, void *buf, int len) +	{ +	int n; + +	clear_sys_error(); +	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_PEEK,SSL_R_SSL_HANDSHAKE_FAILURE); +			return(-1); +			} +		return(SSL_peek(s,buf,len)); +		} +	else +		{ +		ssl_undefined_function(s); +		return(-1); +		} +	} + +int ssl23_write(SSL *s, const void *buf, int len) +	{ +	int n; + +	clear_sys_error(); +	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/main/openssl/ssl/s23_meth.c b/main/openssl/ssl/s23_meth.c new file mode 100644 index 00000000..c6099efc --- /dev/null +++ b/main/openssl/ssl/s23_meth.c @@ -0,0 +1,88 @@ +/* ssl/s23_meth.c */ +/* Copyright (C) 1995-1998 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 <openssl/objects.h> +#include "ssl_locl.h" + +static const SSL_METHOD *ssl23_get_method(int ver); +static const SSL_METHOD *ssl23_get_method(int ver) +	{ +#ifndef OPENSSL_NO_SSL2 +	if (ver == SSL2_VERSION) +		return(SSLv2_method()); +	else +#endif +#ifndef OPENSSL_NO_SSL3 +	if (ver == SSL3_VERSION) +		return(SSLv3_method()); +	else +#endif +#ifndef OPENSSL_NO_TLS1 +	if (ver == TLS1_VERSION) +		return(TLSv1_method()); +	else +#endif +		return(NULL); +	} + +IMPLEMENT_ssl23_meth_func(SSLv23_method, +			ssl23_accept, +			ssl23_connect, +			ssl23_get_method) + diff --git a/main/openssl/ssl/s23_pkt.c b/main/openssl/ssl/s23_pkt.c new file mode 100644 index 00000000..4ca6a1b2 --- /dev/null +++ b/main/openssl/ssl/s23_pkt.c @@ -0,0 +1,117 @@ +/* ssl/s23_pkt.c */ +/* Copyright (C) 1995-1998 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" +#include <openssl/evp.h> +#include <openssl/buffer.h> + +int ssl23_write_bytes(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; +		} +	} + +/* return regularly only when we have read (at least) 'n' bytes */ +int ssl23_read_bytes(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/main/openssl/ssl/s23_srvr.c b/main/openssl/ssl/s23_srvr.c new file mode 100644 index 00000000..e22879c8 --- /dev/null +++ b/main/openssl/ssl/s23_srvr.c @@ -0,0 +1,599 @@ +/* ssl/s23_srvr.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include "ssl_locl.h" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + +static const SSL_METHOD *ssl23_get_server_method(int ver); +int ssl23_get_client_hello(SSL *s); +static const SSL_METHOD *ssl23_get_server_method(int ver) +	{ +#ifndef OPENSSL_NO_SSL2 +	if (ver == SSL2_VERSION) +		return(SSLv2_server_method()); +#endif +	if (ver == SSL3_VERSION) +		return(SSLv3_server_method()); +	else if (ver == TLS1_VERSION) +		return(TLSv1_server_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl23_meth_func(SSLv23_server_method, +			ssl23_accept, +			ssl_undefined_function, +			ssl23_get_server_method) + +int ssl23_accept(SSL *s) +	{ +	BUF_MEM *buf; +	unsigned long Time=(unsigned long)time(NULL); +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int ret= -1; +	int new_state,state; + +	RAND_add(&Time,sizeof(Time),0); +	ERR_clear_error(); +	clear_sys_error(); + +	if (s->info_callback != NULL) +		cb=s->info_callback; +	else if (s->ctx->info_callback != NULL) +		cb=s->ctx->info_callback; +	 +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);  + +	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: + +			s->server=1; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			/* s->version=SSL3_VERSION; */ +			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->stats.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: +	s->in_handshake--; +	if (cb != NULL) +		cb(s,SSL_CB_ACCEPT_EXIT,ret); +	return(ret); +	} + + +int ssl23_get_client_hello(SSL *s) +	{ +	char buf_space[11]; /* Request this many bytes in initial read. +	                     * We can detect SSL 3.0/TLS 1.0 Client Hellos +	                     * ('type == 3') correctly only when the following +	                     * is in a single record, which is not guaranteed by +	                     * the protocol specification: +	                     * Byte  Content +	                     *  0     type            \ +	                     *  1/2   version          > record header +	                     *  3/4   length          / +	                     *  5     msg_type        \ +	                     *  6-8   length           > Client Hello message +	                     *  9/10  client_version  / +	                     */ +	char *buf= &(buf_space[0]); +	unsigned char *p,*d,*d_len,*dd; +	unsigned int i; +	unsigned int csl,sil,cl; +	int n=0,j; +	int type=0; +	int v[2]; + +	if (s->state ==	SSL23_ST_SR_CLNT_HELLO_A) +		{ +		/* read the initial header */ +		v[0]=v[1]=0; + +		if (!ssl3_setup_buffers(s)) goto err; + +		n=ssl23_read_bytes(s, sizeof buf_space); +		if (n != sizeof buf_space) return(n); /* n == -1 || n == 0 */ + +		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)) +				{ +				v[0]=p[3]; v[1]=p[4]; +				/* SSLv2 */ +				if (!(s->options & SSL_OP_NO_SSLv2)) +					type=1; +				} +			else if (p[3] == SSL3_VERSION_MAJOR) +				{ +				v[0]=p[3]; v[1]=p[4]; +				/* SSLv3/TLSv1 */ +				if (p[4] >= TLS1_VERSION_MINOR) +					{ +					if (!(s->options & SSL_OP_NO_TLSv1)) +						{ +						s->version=TLS1_VERSION; +						/* type=2; */ /* done later to survive restarts */ +						s->state=SSL23_ST_SR_CLNT_HELLO_B; +						} +					else if (!(s->options & SSL_OP_NO_SSLv3)) +						{ +						s->version=SSL3_VERSION; +						/* type=2; */ +						s->state=SSL23_ST_SR_CLNT_HELLO_B; +						} +					else if (!(s->options & SSL_OP_NO_SSLv2)) +						{ +						type=1; +						} +					} +				else if (!(s->options & SSL_OP_NO_SSLv3)) +					{ +					s->version=SSL3_VERSION; +					/* type=2; */ +					s->state=SSL23_ST_SR_CLNT_HELLO_B; +					} +				else if (!(s->options & SSL_OP_NO_SSLv2)) +					type=1; + +				} +			} +		else if ((p[0] == SSL3_RT_HANDSHAKE) && +			 (p[1] == SSL3_VERSION_MAJOR) && +			 (p[5] == SSL3_MT_CLIENT_HELLO) && +			 ((p[3] == 0 && p[4] < 5 /* silly record length? */) +				|| (p[9] >= p[1]))) +			{ +			/* +			 * SSLv3 or tls1 header +			 */ +			 +			v[0]=p[1]; /* major version (= SSL3_VERSION_MAJOR) */ +			/* We must look at client_version inside the Client Hello message +			 * to get the correct minor version. +			 * However if we have only a pathologically small fragment of the +			 * Client Hello message, this would be difficult, and we'd have +			 * to read more records to find out. +			 * No known SSL 3.0 client fragments ClientHello like this, +			 * so we simply assume TLS 1.0 to avoid protocol version downgrade +			 * attacks. */ +			if (p[3] == 0 && p[4] < 6) +				{ +#if 0 +				SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL); +				goto err; +#else +				v[1] = TLS1_VERSION_MINOR; +#endif +				} +			/* if major version number > 3 set minor to a value +			 * which will use the highest version 3 we support. +			 * If TLS 2.0 ever appears we will need to revise +			 * this.... +			 */ +			else if (p[9] > SSL3_VERSION_MAJOR) +				v[1]=0xff; +			else +				v[1]=p[10]; /* minor version according to client_version */ +			if (v[1] >= TLS1_VERSION_MINOR) +				{ +				if (!(s->options & SSL_OP_NO_TLSv1)) +					{ +					s->version=TLS1_VERSION; +					type=3; +					} +				else if (!(s->options & SSL_OP_NO_SSLv3)) +					{ +					s->version=SSL3_VERSION; +					type=3; +					} +				} +			else +				{ +				/* client requests SSL 3.0 */ +				if (!(s->options & SSL_OP_NO_SSLv3)) +					{ +					s->version=SSL3_VERSION; +					type=3; +					} +				else if (!(s->options & SSL_OP_NO_TLSv1)) +					{ +					/* we won't be able to use TLS of course, +					 * but this will send an appropriate alert */ +					s->version=TLS1_VERSION; +					type=3; +					} +				} +			} +		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)) +			{ +			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTP_REQUEST); +			goto err; +			} +		else if (strncmp("CONNECT",(char *)p,7) == 0) +			{ +			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTPS_PROXY_REQUEST); +			goto err; +			} +		} + +	if (s->state == SSL23_ST_SR_CLNT_HELLO_B) +		{ +		/* we have SSLv3/TLSv1 in an SSLv2 header +		 * (other cases skip this state) */ + +		type=2; +		p=s->packet; +		v[0] = p[3]; /* == SSL3_VERSION_MAJOR */ +		v[1] = p[4]; + +/* The SSL2 protocol allows n to be larger, just pick + * a reasonable buffer size. */ +#if SSL3_RT_DEFAULT_PACKET_SIZE < 1024*4 - SSL3_RT_DEFAULT_WRITE_OVERHEAD +#error "SSL3_RT_DEFAULT_PACKET_SIZE is too small." +#endif +		n=((p[0]&0x7f)<<8)|p[1]; +		if (n > SSL3_RT_DEFAULT_PACKET_SIZE - 2) +			{ +			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); +		if (s->msg_callback) +			s->msg_callback(0, SSL2_VERSION, 0, s->packet+2, s->packet_length-2, s, s->msg_callback_arg); /* CLIENT-HELLO */ + +		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) /* We can't have TLS extensions in SSL 2.0 format +		                                          * Client Hello, can we? Error condition should be +		                                          * '>' otherweise */ +			{ +			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); +			goto err; +			} + +		/* record header: msg_type ... */ +		*(d++) = SSL3_MT_CLIENT_HELLO; +		/* ... and length (actual value will be written later) */ +		d_len = d; +		d += 3; + +		/* client_version */ +		*(d++) = SSL3_VERSION_MAJOR; /* == v[0] */ +		*(d++) = v[1]; + +		/* lets populate the random area */ +		/* get the challenge_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; +		 +#if 0 +                /* copy any remaining data with may be extensions */ +	        p = p+csl+sil+cl; +		while (p <  s->packet+s->packet_length) +			{ +			*(d++)=*(p++); +			} +#endif + +		i = (d-(unsigned char *)s->init_buf->data) - 4; +		l2n3((long)i, d_len); + +		/* 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; +		} + +	/* imaginary new state (for program structure): */ +	/* s->state = SSL23_SR_CLNT_HELLO_C */ + +	if (type == 1) +		{ +#ifdef OPENSSL_NO_SSL2 +		SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); +		goto err; +#else +		/* we are talking sslv2 */ +		/* we need to clean up the SSLv3/TLSv1 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_clean(s->init_buf, +			SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) +			{ +			goto err; +			} + +		s->state=SSL2_ST_GET_CLIENT_HELLO_A; +		if (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3) +			s->s2->ssl2_rollback=0; +		else +			/* reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0 +			 * (SSL 3.0 draft/RFC 2246, App. E.2) */ +			s->s2->ssl2_rollback=1; + +		/* setup the n 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; +#endif +		} + +	if ((type == 2) || (type == 3)) +		{ +		/* we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style) */ + +		if (!ssl_init_wbio_buffer(s,1)) goto err; + +		/* 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; +			if (s->s3->rbuf.buf == NULL) +				if (!ssl3_setup_read_buffer(s)) +					goto err; + +			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; +			} + +		if (s->version == TLS1_VERSION) +			s->method = TLSv1_server_method(); +		else +			s->method = SSLv3_server_method(); +#if 0 /* ssl3_get_client_hello does this */ +		s->client_version=(v[0]<<8)|v[1]; +#endif +		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) OPENSSL_free(buf); +	return(SSL_accept(s)); +err: +	if (buf != buf_space) OPENSSL_free(buf); +	return(-1); +	} diff --git a/main/openssl/ssl/s2_clnt.c b/main/openssl/ssl/s2_clnt.c new file mode 100644 index 00000000..00ac158f --- /dev/null +++ b/main/openssl/ssl/s2_clnt.c @@ -0,0 +1,1125 @@ +/* ssl/s2_clnt.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "ssl_locl.h" +#ifndef OPENSSL_NO_SSL2 +#include <stdio.h> +#include <openssl/rand.h> +#include <openssl/buffer.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + +static const SSL_METHOD *ssl2_get_client_method(int ver); +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(SESS_CERT *sc, int len, unsigned char *from, +	unsigned char *to,int padding); +#define BREAK	break + +static const SSL_METHOD *ssl2_get_client_method(int ver) +	{ +	if (ver == SSL2_VERSION) +		return(SSLv2_client_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl2_meth_func(SSLv2_client_method, +			ssl_undefined_function, +			ssl2_connect, +			ssl2_get_client_method) + +int ssl2_connect(SSL *s) +	{ +	unsigned long l=(unsigned long)time(NULL); +	BUF_MEM *buf=NULL; +	int ret= -1; +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int new_state,state; + +	RAND_add(&l,sizeof(l),0); +	ERR_clear_error(); +	clear_sys_error(); + +	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 */ +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + +	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: + +			s->server=0; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			s->version=SSL2_VERSION; +			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)) +				{ +				if (buf == s->init_buf) +					buf=NULL; +				ret= -1; +				goto end; +				} +			s->init_buf=buf; +			buf=NULL; +			s->init_num=0; +			s->state=SSL2_ST_SEND_CLIENT_HELLO_A; +			s->ctx->stats.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: +			if (s->init_buf != NULL) +				{ +				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 successfully 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); +			if (s->hit) s->ctx->stats.sess_hit++; + +			ret=1; +			/* s->server=0; */ +			s->ctx->stats.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 (buf != NULL) +		BUF_MEM_free(buf); +	if (cb != NULL)  +		cb(s,SSL_CB_CONNECT_EXIT,ret); +	return(ret); +	} + +static int get_server_hello(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p; +	int i,j; +	unsigned long len; +	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow; + +	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)); +		s->init_num = 11; + +		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); +			} +#ifdef __APPLE_CC__ +		/* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug +		 * workaround. <appro@fy.chalmers.se> */ +		s->hit=(i=*(p++))?1:0; +#else +		s->hit=(*(p++))?1:0; +#endif +		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; +		} + +	/* SSL2_ST_GET_SERVER_HELLO_B */ +	len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length; +	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) +		{ +		SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG); +		return -1; +		} +	j = (int)len - 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)); +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */ + +	/* things are looking good */ + +	p = buf + 11; +	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->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 in case 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); +			} + +		(void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp); + +		/* get the array of ciphers we will accept */ +		cl=SSL_get_ciphers(s); +		(void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp); + +		/* +		 * If server preference flag set, choose the first +		 * (highest priority) cipher the server sends, otherwise +		 * client preference has priority. +		 */ +		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) +		    { +		    prio = sk; +		    allow = cl; +		    } +		else +		    { +		    prio = cl; +		    allow = sk; +		    } +		/* 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 originally sent and +		 * for performance reasons we should not bother to match +		 * the two lists up just to check. */ +		for (i=0; i<sk_SSL_CIPHER_num(prio); i++) +			{ +			if (sk_SSL_CIPHER_find(allow, +					     sk_SSL_CIPHER_value(prio,i)) >= 0) +				break; +			} + +		if (i >= sk_SSL_CIPHER_num(prio)) +			{ +			ssl2_return_error(s,SSL2_PE_NO_CIPHER); +			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH); +			return(-1); +			} +		s->session->cipher=sk_SSL_CIPHER_value(prio,i); + + +		if (s->session->peer != NULL) /* can't happen*/ +			{ +			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); +			SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR); +			return(-1); +			} + +		s->session->peer = s->session->sess_cert->peer_key->x509; +		/* peer_key->x509 has been set by ssl2_set_certificate. */ +		CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509); +		} + +	if (s->session->sess_cert == NULL  +      || s->session->peer != s->session->sess_cert->peer_key->x509) +		/* can't happen */ +		{ +		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR); +		return(-1); +		} +		 +	s->s2->conn_id_length=s->s2->tmp.conn_id_length; +	if (s->s2->conn_id_length > sizeof s->s2->conn_id) +		{ +		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG); +		return -1; +		} +	memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length); +	return(1); +	} + +static int client_hello(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_VERSION,p);			/* version */ +		n=j=0; + +		n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d,0); +		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*/ +		if (RAND_pseudo_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH) <= 0) +			return -1; +		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(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	int clear,enc,karg,i; +	SSL_SESSION *sess; +	const EVP_CIPHER *c; +	const 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,&c,&md,NULL,NULL,NULL)) +			{ +			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 > SSL_MAX_KEY_ARG_LENGTH) +			{ +			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); +			SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		if (i > 0) +			if (RAND_pseudo_bytes(sess->key_arg,i) <= 0) +				return -1; + +		/* make a master key */ +		i=EVP_CIPHER_key_length(c); +		sess->master_key_length=i; +		if (i > 0) +			{ +			if (i > (int)sizeof(sess->master_key)) +				{ +				ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); +				SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); +				return -1; +				} +			if (RAND_bytes(sess->master_key,i) <= 0) +				{ +				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +				return(-1); +				} +			} + +		if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) +			enc=8; +		else if (SSL_C_IS_EXPORT(sess->cipher)) +			enc=5; +		else +			enc=i; + +		if ((int)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->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); +			} +#ifdef PKCS1_CHECK +		if (s->options & SSL_OP_PKCS1_CHECK_1) d[1]++; +		if (s->options & SSL_OP_PKCS1_CHECK_2) +			sess->master_key[clear]++; +#endif +		s2n(enc,p); +		d+=enc; +		karg=sess->key_arg_length;	 +		s2n(karg,p); /* key arg size */ +		if (karg > (int)sizeof(sess->key_arg)) +			{ +			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +			SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		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(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; +		if (s->s2->conn_id_length > sizeof s->s2->conn_id) +			{ +			SSLerr(SSL_F_CLIENT_FINISHED, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		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(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	int i; +	unsigned int n; +	int cert_ch_len; +	unsigned char *cert_ch; + +	buf=(unsigned char *)s->init_buf->data; + +	/* 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+2-s->init_num); +		if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+2-s->init_num)) +			return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i)); +		s->init_num += i; +		if (s->msg_callback) +			s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* REQUEST-CERTIFICATE */ + +		/* 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); +			} + +		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; +		} + +	cert_ch = buf + 2; +	cert_ch_len = s->init_num - 2; + +	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_MD_CTX_init(&ctx); +		EVP_SignInit_ex(&ctx,s->ctx->rsa_md5, NULL); +		EVP_SignUpdate(&ctx,s->s2->key_material, +			       s->s2->key_material_length); +		EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len); +		i=i2d_X509(s->session->sess_cert->peer_key->x509,&p); +		/* Don't update the signature if it fails - FIXME: probably should handle this better */ +		if(i > 0) +			EVP_SignUpdate(&ctx,buf,(unsigned int)i); + +		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 continue with a 0 length signature +			 */ +			} +		EVP_MD_CTX_cleanup(&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(SSL *s) +	{ +	unsigned char *p; +	int i, n, len; + +	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->init_num += i; + +		s->state= SSL2_ST_GET_SERVER_VERIFY_B; +		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); +				/* try to read the error message */ +				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num); +				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i); +				} +			return(-1); +			} +		} +	 +	p=(unsigned char *)s->init_buf->data; +	len = 1 + s->s2->challenge_length; +	n =  len - s->init_num; +	i = ssl2_read(s,(char *)&(p[s->init_num]),n); +	if (i < n) +		return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i)); +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* SERVER-VERIFY */ +	p += 1; + +	if (memcmp(p,s->s2->challenge,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(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p; +	int i, n, len; + +	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); +				/* try to read the error message */ +				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num); +				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i); +				} +			return(-1); +			} +		s->state=SSL2_ST_GET_SERVER_FINISHED_B; +		} + +	len = 1 + SSL2_SSL_SESSION_ID_LENGTH; +	n = len - s->init_num; +	i = ssl2_read(s,(char *)&(buf[s->init_num]), n); +	if (i < n) /* XXX could be shorter than SSL2_SSL_SESSION_ID_LENGTH, that's the maximum */ +		return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i)); +	s->init_num += i; +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* SERVER-FINISHED */ + +	if (!s->hit) /* new session */ +		{ +		/* new session-id */ +		/* Make sure we were not trying to re-use an old SSL_SESSION +		 * or bad things can happen */ +		/* ZZZZZZZZZZZZZ */ +		s->session->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; +		memcpy(s->session->session_id,p+1,SSL2_SSL_SESSION_ID_LENGTH); +		} +	else +		{ +		if (!(s->options & SSL_OP_MICROSOFT_SESS_ID_BUG)) +			{ +			if ((s->session->session_id_length > sizeof s->session->session_id) +			    || (0 != memcmp(buf + 1, s->session->session_id, +			                    (unsigned int)s->session->session_id_length))) +				{ +				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +				SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_SSL_SESSION_ID_IS_DIFFERENT); +				return(-1); +				} +			} +		} +	s->state = SSL_ST_OK; +	return(1); +	} + +/* loads in the certificate from the server */ +int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data) +	{ +	STACK_OF(X509) *sk=NULL; +	EVP_PKEY *pkey=NULL; +	SESS_CERT *sc=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_X509_new_null()) == NULL || !sk_X509_push(sk,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 <= 0)) +		{ +		SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); +		goto err; +		} +	ERR_clear_error(); /* but we keep s->verify_result */ +	s->session->verify_result = s->verify_result; + +	/* server's cert for this session */ +	sc=ssl_sess_cert_new(); +	if (sc == NULL) +		{ +		ret= -1; +		goto err; +		} +	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert); +	s->session->sess_cert=sc; + +	sc->peer_pkeys[SSL_PKEY_RSA_ENC].x509=x509; +	sc->peer_key= &(sc->peer_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_peer_cert_type(sc,SSL2_CT_X509_CERTIFICATE)) +		goto err; +	ret=1; +err: +	sk_X509_free(sk); +	X509_free(x509); +	EVP_PKEY_free(pkey); +	return(ret); +	} + +static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from, +	     unsigned char *to, int padding) +	{ +	EVP_PKEY *pkey=NULL; +	int i= -1; + +	if ((sc == NULL) || (sc->peer_key->x509 == NULL) || +		((pkey=X509_get_pubkey(sc->peer_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: +	EVP_PKEY_free(pkey); +	return(i); +	} +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/main/openssl/ssl/s2_enc.c b/main/openssl/ssl/s2_enc.c new file mode 100644 index 00000000..ff3395f4 --- /dev/null +++ b/main/openssl/ssl/s2_enc.c @@ -0,0 +1,193 @@ +/* ssl/s2_enc.c */ +/* Copyright (C) 1995-1998 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 "ssl_locl.h" +#ifndef OPENSSL_NO_SSL2 +#include <stdio.h> + +int ssl2_enc_init(SSL *s, int client) +	{ +	/* Max number of bytes needed */ +	EVP_CIPHER_CTX *rs,*ws; +	const EVP_CIPHER *c; +	const EVP_MD *md; +	int num; + +	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL)) +		{ +		ssl2_return_error(s,SSL2_PE_NO_CIPHER); +		SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS); +		return(0); +		} +	ssl_replace_hash(&s->read_hash,md); +	ssl_replace_hash(&s->write_hash,md); + +	if ((s->enc_read_ctx == NULL) && +		((s->enc_read_ctx=(EVP_CIPHER_CTX *) +		OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) +		goto err; + +	/* make sure it's intialized in case the malloc for enc_write_ctx fails +	 * and we exit with an error */ +	rs= s->enc_read_ctx; +	EVP_CIPHER_CTX_init(rs); + +	if ((s->enc_write_ctx == NULL) && +		((s->enc_write_ctx=(EVP_CIPHER_CTX *) +		OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) +		goto err; + +	ws= s->enc_write_ctx; +	EVP_CIPHER_CTX_init(ws); + +	num=c->key_len; +	s->s2->key_material_length=num*2; +	OPENSSL_assert(s->s2->key_material_length <= sizeof s->s2->key_material); + +	if (ssl2_generate_key_material(s) <= 0) +		return 0; + +	OPENSSL_assert(c->iv_len <= (int)sizeof(s->session->key_arg)); +	EVP_EncryptInit_ex(ws,c,NULL,&(s->s2->key_material[(client)?num:0]), +		s->session->key_arg); +	EVP_DecryptInit_ex(rs,c,NULL,&(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 s->s2->padding and s->[rw]length + * if we are encrypting */ +void ssl2_enc(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(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_MD_CTX_init(&c); +	EVP_MD_CTX_copy(&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_ex(&c,md,NULL); +	EVP_MD_CTX_cleanup(&c); +	} +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/main/openssl/ssl/s2_lib.c b/main/openssl/ssl/s2_lib.c new file mode 100644 index 00000000..99146041 --- /dev/null +++ b/main/openssl/ssl/s2_lib.c @@ -0,0 +1,556 @@ +/* ssl/s2_lib.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "ssl_locl.h" +#ifndef OPENSSL_NO_SSL2 +#include <stdio.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/md5.h> + +const char ssl2_version_str[]="SSLv2" OPENSSL_VERSION_PTEXT; + +#define SSL2_NUM_CIPHERS (sizeof(ssl2_ciphers)/sizeof(SSL_CIPHER)) + +/* list of available SSLv2 ciphers (sorted by id) */ +OPENSSL_GLOBAL const SSL_CIPHER ssl2_ciphers[]={ +#if 0 +/* NULL_WITH_MD5 v3 */ +	{ +	1, +	SSL2_TXT_NULL_WITH_MD5, +	SSL2_CK_NULL_WITH_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_eNULL, +	SSL_MD5, +	SSL_SSLV2, +	SSL_EXPORT|SSL_EXP40|SSL_STRONG_NONE, +	0, +	0, +	0, +	}, +#endif + +/* 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_SSLV2, +	SSL_NOT_EXP|SSL_MEDIUM, +	0, +	128, +	128, +	}, + +/* 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_SSLV2, +	SSL_EXPORT|SSL_EXP40, +	SSL2_CF_5_BYTE_ENC, +	40, +	128, +	}, + +/* 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_SSLV2, +	SSL_NOT_EXP|SSL_MEDIUM, +	0, +	128, +	128, +	}, + +/* 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_SSLV2, +	SSL_EXPORT|SSL_EXP40, +	SSL2_CF_5_BYTE_ENC, +	40, +	128, +	}, + +#ifndef OPENSSL_NO_IDEA +/* 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_SSLV2, +	SSL_NOT_EXP|SSL_MEDIUM, +	0, +	128, +	128, +	}, +#endif + +/* 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_SSLV2, +	SSL_NOT_EXP|SSL_LOW, +	0, +	56, +	56, +	}, + +/* 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_SSLV2, +	SSL_NOT_EXP|SSL_HIGH, +	0, +	168, +	168, +	}, + +#if 0 +/* RC4_64_WITH_MD5 */ +	{ +	1, +	SSL2_TXT_RC4_64_WITH_MD5, +	SSL2_CK_RC4_64_WITH_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV2, +	SSL_NOT_EXP|SSL_LOW, +	SSL2_CF_8_BYTE_ENC, +	64, +	64, +	}, +#endif + +#if 0 +/* NULL SSLeay (testing) */ +	{	 +	0, +	SSL2_TXT_NULL, +	SSL2_CK_NULL, +	0, +	0, +	0, +	0, +	SSL_SSLV2, +	SSL_STRONG_NONE, +	0, +	0, +	0, +	}, +#endif + +/* end of list :-) */ +	}; + +long ssl2_default_timeout(void) +	{ +	return(300); +	} + +int ssl2_num_ciphers(void) +	{ +	return(SSL2_NUM_CIPHERS); +	} + +const SSL_CIPHER *ssl2_get_cipher(unsigned int u) +	{ +	if (u < SSL2_NUM_CIPHERS) +		return(&(ssl2_ciphers[SSL2_NUM_CIPHERS-1-u])); +	else +		return(NULL); +	} + +int ssl2_pending(const SSL *s) +	{ +	return SSL_in_init(s) ? 0 : s->s2->ract_data_length; +	} + +int ssl2_new(SSL *s) +	{ +	SSL2_STATE *s2; + +	if ((s2=OPENSSL_malloc(sizeof *s2)) == NULL) goto err; +	memset(s2,0,sizeof *s2); + +#if SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER + 3 > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2 +#  error "assertion failed" +#endif + +	if ((s2->rbuf=OPENSSL_malloc( +		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) == NULL) goto err; +	/* wbuf needs one byte more because when using two-byte headers, +	 * we leave the first byte unused in do_ssl_write (s2_pkt.c) */ +	if ((s2->wbuf=OPENSSL_malloc( +		SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+3)) == NULL) goto err; +	s->s2=s2; + +	ssl2_clear(s); +	return(1); +err: +	if (s2 != NULL) +		{ +		if (s2->wbuf != NULL) OPENSSL_free(s2->wbuf); +		if (s2->rbuf != NULL) OPENSSL_free(s2->rbuf); +		OPENSSL_free(s2); +		} +	return(0); +	} + +void ssl2_free(SSL *s) +	{ +	SSL2_STATE *s2; + +	if(s == NULL) +	    return; + +	s2=s->s2; +	if (s2->rbuf != NULL) OPENSSL_free(s2->rbuf); +	if (s2->wbuf != NULL) OPENSSL_free(s2->wbuf); +	OPENSSL_cleanse(s2,sizeof *s2); +	OPENSSL_free(s2); +	s->s2=NULL; +	} + +void ssl2_clear(SSL *s) +	{ +	SSL2_STATE *s2; +	unsigned char *rbuf,*wbuf; + +	s2=s->s2; + +	rbuf=s2->rbuf; +	wbuf=s2->wbuf; + +	memset(s2,0,sizeof *s2); + +	s2->rbuf=rbuf; +	s2->wbuf=wbuf; +	s2->clear_text=1; +	s->packet=s2->rbuf; +	s->version=SSL2_VERSION; +	s->packet_length=0; +	} + +long ssl2_ctrl(SSL *s, int cmd, long larg, void *parg) +	{ +	int ret=0; + +	switch(cmd) +		{ +	case SSL_CTRL_GET_SESSION_REUSED: +		ret=s->hit; +		break; +	default: +		break; +		} +	return(ret); +	} + +long ssl2_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) +	{ +	return(0); +	} + +long ssl2_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +	{ +	return(0); +	} + +long ssl2_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) +	{ +	return(0); +	} + +/* This function needs to check if the ciphers required are actually + * available */ +const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p) +	{ +	SSL_CIPHER c; +	const SSL_CIPHER *cp; +	unsigned long id; + +	id=0x02000000L|((unsigned long)p[0]<<16L)| +		((unsigned long)p[1]<<8L)|(unsigned long)p[2]; +	c.id=id; +	cp = OBJ_bsearch_ssl_cipher_id(&c, ssl2_ciphers, SSL2_NUM_CIPHERS); +	if ((cp == NULL) || (cp->valid == 0)) +		return NULL; +	else +		return cp; +	} + +int ssl2_put_cipher_by_char(const 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); +	} + +int ssl2_generate_key_material(SSL *s) +	{ +	unsigned int i; +	EVP_MD_CTX ctx; +	unsigned char *km; +	unsigned char c='0'; +	const EVP_MD *md5; +	int md_size; + +	md5 = EVP_md5(); + +#ifdef CHARSET_EBCDIC +	c = os_toascii['0']; /* Must be an ASCII '0', not EBCDIC '0', +				see SSLv2 docu */ +#endif +	EVP_MD_CTX_init(&ctx); +	km=s->s2->key_material; + + 	if (s->session->master_key_length < 0 || +			s->session->master_key_length > (int)sizeof(s->session->master_key)) + 		{ + 		SSLerr(SSL_F_SSL2_GENERATE_KEY_MATERIAL, ERR_R_INTERNAL_ERROR); + 		return 0; + 		} +	md_size = EVP_MD_size(md5); +	if (md_size < 0) +	    return 0; +	for (i=0; i<s->s2->key_material_length; i += md_size) +		{ +		if (((km - s->s2->key_material) + md_size) > +				(int)sizeof(s->s2->key_material)) +			{ +			/* EVP_DigestFinal_ex() below would write beyond buffer */ +			SSLerr(SSL_F_SSL2_GENERATE_KEY_MATERIAL, ERR_R_INTERNAL_ERROR); +			return 0; +			} + +		EVP_DigestInit_ex(&ctx, md5, NULL); + +		OPENSSL_assert(s->session->master_key_length >= 0 +		    && s->session->master_key_length +		    < (int)sizeof(s->session->master_key)); +		EVP_DigestUpdate(&ctx,s->session->master_key,s->session->master_key_length); +		EVP_DigestUpdate(&ctx,&c,1); +		c++; +		EVP_DigestUpdate(&ctx,s->s2->challenge,s->s2->challenge_length); +		EVP_DigestUpdate(&ctx,s->s2->conn_id,s->s2->conn_id_length); +		EVP_DigestFinal_ex(&ctx,km,NULL); +		km += md_size; +		} + +	EVP_MD_CTX_cleanup(&ctx); +	return 1; +	} + +void ssl2_return_error(SSL *s, int err) +	{ +	if (!s->error) +		{ +		s->error=3; +		s->error_code=err; + +		ssl2_write_error(s); +		} +	} + + +void ssl2_write_error(SSL *s) +	{ +	unsigned 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; /* number of bytes left to write */ +	s->error=0; +	OPENSSL_assert(error >= 0 && error <= (int)sizeof(buf)); +	i=ssl2_write(s,&(buf[3-error]),error); + +/*	if (i == error) s->rwstate=state; */ + +	if (i < 0) +		s->error=error; +	else +		{ +		s->error=error-i; + +		if (s->error == 0) +			if (s->msg_callback) +				s->msg_callback(1, s->version, 0, buf, 3, s, s->msg_callback_arg); /* ERROR */ +		} +	} + +int ssl2_shutdown(SSL *s) +	{ +	s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); +	return(1); +	} +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/main/openssl/ssl/s2_meth.c b/main/openssl/ssl/s2_meth.c new file mode 100644 index 00000000..f0e8ca59 --- /dev/null +++ b/main/openssl/ssl/s2_meth.c @@ -0,0 +1,84 @@ +/* ssl/s2_meth.c */ +/* Copyright (C) 1995-1998 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 "ssl_locl.h" +#ifndef OPENSSL_NO_SSL2 +#include <stdio.h> +#include <openssl/objects.h> + +static const SSL_METHOD *ssl2_get_method(int ver); +static const SSL_METHOD *ssl2_get_method(int ver) +	{ +	if (ver == SSL2_VERSION) +		return(SSLv2_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl2_meth_func(SSLv2_method, +			 ssl2_accept, +			 ssl2_connect, +			 ssl2_get_method) + +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/main/openssl/ssl/s2_pkt.c b/main/openssl/ssl/s2_pkt.c new file mode 100644 index 00000000..ac963b2d --- /dev/null +++ b/main/openssl/ssl/s2_pkt.c @@ -0,0 +1,744 @@ +/* ssl/s2_pkt.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "ssl_locl.h" +#ifndef OPENSSL_NO_SSL2 +#include <stdio.h> +#include <errno.h> +#define USE_SOCKETS + +static int read_n(SSL *s,unsigned int n,unsigned int max,unsigned int extend); +static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len); +static int write_pending(SSL *s, const unsigned char *buf, unsigned int len); +static int ssl_mt_error(int n); + + +/* SSL 2.0 imlementation for SSL_read/SSL_peek - + * This routine will return 0 to len bytes, decrypted etc if required. + */ +static int ssl2_read_internal(SSL *s, void *buf, int len, int peek) +	{ +	int n; +	unsigned char mac[MAX_MAC_SIZE]; +	unsigned char *p; +	int i; +	int mac_size; + + ssl2_read_again: +	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_INTERNAL,SSL_R_SSL_HANDSHAKE_FAILURE); +			return(-1); +			} +		} + +	clear_sys_error(); +	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); +		if (!peek) +			{ +			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); +		} + +	/* s->s2->ract_data_length == 0 +	 *  +	 * Fill the buffer, then goto ssl2_read_again. +	 */ + +	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_INTERNAL,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) +			{ +			mac_size = 0; +			s->s2->mac_data=p; +			s->s2->ract_data=p; +			if (s->s2->padding) +				{ +				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING); +				return(-1); +				} +			} +		else +			{ +			mac_size=EVP_MD_CTX_size(s->read_hash); +			if (mac_size < 0) +				return -1; +			OPENSSL_assert(mac_size <= MAX_MAC_SIZE); +			s->s2->mac_data=p; +			s->s2->ract_data= &p[mac_size]; +			if (s->s2->padding + mac_size > s->s2->rlength) +				{ +				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING); +				return(-1); +				} +			} + +		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 >= (unsigned int)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_INTERNAL,SSL_R_BAD_MAC_DECODE); +				return(-1); +				} +			} +		INC32(s->s2->read_sequence); /* expect next number */ +		/* s->s2->ract_data is now available for processing */ + +		/* Possibly the packet that we just read had 0 actual data bytes. +		 * (SSLeay/OpenSSL itself never sends such packets; see ssl2_write.) +		 * In this case, returning 0 would be interpreted by the caller +		 * as indicating EOF, so it's not a good idea.  Instead, we just +		 * continue reading; thus ssl2_read_internal may have to process +		 * multiple packets before it can return. +		 * +		 * [Note that using select() for blocking sockets *never* guarantees +		 * that the next SSL_read will not block -- the available +		 * data may contain incomplete packets, and except for SSL 2, +		 * renegotiation can confuse things even more.] */ + +		goto ssl2_read_again; /* This should really be +		                       * "return ssl2_read(s,buf,len)", +		                       * but that would allow for +		                       * denial-of-service attacks if a +		                       * C compiler is used that does not +		                       * recognize end-recursion. */ +		} +	else +		{ +		SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_STATE); +			return(-1); +		} +	} + +int ssl2_read(SSL *s, void *buf, int len) +	{ +	return ssl2_read_internal(s, buf, len, 0); +	} + +int ssl2_peek(SSL *s, void *buf, int len) +	{ +	return ssl2_read_internal(s, buf, len, 1); +	} + +static int read_n(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) +		{ +		clear_sys_error(); +		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(SSL *s, const void *_buf, int len) +	{ +	const unsigned char *buf=_buf; +	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); +		} + +	clear_sys_error(); +	s->rwstate=SSL_NOTHING; +	if (len <= 0) return(len); + +	tot=s->s2->wnum; +	s->s2->wnum=0; + +	n=(len-tot); +	for (;;) +		{ +		i=n_do_ssl_write(s,&(buf[tot]),n); +		if (i <= 0) +			{ +			s->s2->wnum=tot; +			return(i); +			} +		if ((i == (int)n) || +			(s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) +			{ +			return(tot+i); +			} +		 +		n-=i; +		tot+=i; +		} +	} + +static int write_pending(SSL *s, const unsigned 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) && +		 !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))) +		{ +		SSLerr(SSL_F_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); +		return(-1); +		} + +	for (;;) +		{ +		clear_sys_error(); +		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 n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len) +	{ +	unsigned int j,k,olen,p,bs; +	int mac_size; +	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_CTX_size(s->write_hash); +		if (mac_size < 0) +			return -1; +		} + +	/* 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; +		/* Two-byte headers allow for a larger record length than +		 * three-byte headers, but we can't use them if we need +		 * padding or if we have to set the escape bit. */ +		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)) +			{ +			/* j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, thus +			 * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER */ +			s->s2->three_byte_header=0; +			p=0; +			} +		else /* we may have to use a 3 byte header */ +			{ +			/* If s->s2->escape is not set, then +			 * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, and thus +			 * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER. */ +			p=(j%bs); +			p=(p == 0)?0:(bs-p); +			if (s->s2->escape) +				{ +				s->s2->three_byte_header=1; +				if (j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) +					j=SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER; +				} +			else +				s->s2->three_byte_header=(p == 0)?0:1; +			} +		} + +	/* Now +	 *      j <= SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER +	 * holds, and if s->s2->three_byte_header is set, then even +	 *      j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER. +	 */ + +	/* 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 it is a two-byte header, then p == 0) */ + +	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); +	if (p) +		memset(&(s->s2->wact_data[len]),0,p); /* arbitrary padding */ + +	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=buf; + +	s->s2->wpend_ret=len; + +	s->s2->wpend_off=0; +	return(write_pending(s,buf,olen)); +	} + +int ssl2_part_read(SSL *s, unsigned long f, int i) +	{ +	unsigned char *p; +	int j; + +	if (i < 0) +		{ +		/* ssl2_return_error(s); */ +		/* for non-blocking io, +		 * this is not necessarily fatal */ +		return(i); +		} +	else +		{ +		s->init_num+=i; + +		/* Check for error.  While there are recoverable errors, +		 * this function is not called when those must be expected; +		 * any error detected here is fatal. */ +		if (s->init_num >= 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)); +				s->init_num -= 3; +				if (s->init_num > 0) +					memmove(p, p+3, s->init_num); +				} +			} + +		/* If it's not an error message, we have some error anyway -- +		 * the message was shorter than expected.  This too is treated +		 * as fatal (at least if SSL_get_error is asked for its opinion). */ +		return(0); +		} +	} + +int ssl2_do_write(SSL *s) +	{ +	int ret; + +	ret=ssl2_write(s,&s->init_buf->data[s->init_off],s->init_num); +	if (ret == s->init_num) +		{ +		if (s->msg_callback) +			s->msg_callback(1, s->version, 0, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg); +		return(1); +		} +	if (ret < 0) +		return(-1); +	s->init_off+=ret; +	s->init_num-=ret; +	return(0); +	} + +static int ssl_mt_error(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); +	} +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/main/openssl/ssl/s2_srvr.c b/main/openssl/ssl/s2_srvr.c new file mode 100644 index 00000000..bc885e8e --- /dev/null +++ b/main/openssl/ssl/s2_srvr.c @@ -0,0 +1,1142 @@ +/* ssl/s2_srvr.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "ssl_locl.h" +#ifndef OPENSSL_NO_SSL2 +#include <stdio.h> +#include <openssl/bio.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + +static const SSL_METHOD *ssl2_get_server_method(int ver); +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); +#define BREAK	break + +static const SSL_METHOD *ssl2_get_server_method(int ver) +	{ +	if (ver == SSL2_VERSION) +		return(SSLv2_server_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl2_meth_func(SSLv2_server_method, +			ssl2_accept, +			ssl_undefined_function, +			ssl2_get_server_method) + +int ssl2_accept(SSL *s) +	{ +	unsigned long l=(unsigned long)time(NULL); +	BUF_MEM *buf=NULL; +	int ret= -1; +	long num1; +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int new_state,state; + +	RAND_add(&l,sizeof(l),0); +	ERR_clear_error(); +	clear_sys_error(); + +	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 */ +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + +	if (s->cert == NULL) +		{ +		SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET); +		return(-1); +		} + +	clear_sys_error(); +	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: + +			s->server=1; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			s->version=SSL2_VERSION; +			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->stats.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); +			ssl_free_wbio_buffer(s); +			s->init_buf=NULL; +			s->init_num=0; +		/*	ERR_clear_error();*/ + +			ssl_update_cache(s,SSL_SESS_CACHE_SERVER); + +			s->ctx->stats.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(SSL *s) +	{ +	int is_export,i,n,keya,ek; +	unsigned long len; +	unsigned char *p; +	const SSL_CIPHER *cp; +	const EVP_CIPHER *c; +	const 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)); +		s->init_num = 10; + +		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); +		if(i > SSL_MAX_KEY_ARG_LENGTH) +			{ +			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_KEY_ARG_TOO_LONG); +			return -1; +			} +		s->session->key_arg_length=i; +		s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B; +		} + +	/* SSL2_ST_GET_CLIENT_MASTER_KEY_B */ +	p=(unsigned char *)s->init_buf->data; +	if (s->init_buf->length < SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) +		{ +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); +		return -1; +		} +	keya=s->session->key_arg_length; +	len = 10 + (unsigned long)s->s2->tmp.clear + (unsigned long)s->s2->tmp.enc + (unsigned long)keya; +	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) +		{ +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_MESSAGE_TOO_LONG); +		return -1; +		} +	n = (int)len - 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)); +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, p, (size_t)len, s, s->msg_callback_arg); /* CLIENT-MASTER-KEY */ +	p += 10; + +	memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]), +		(unsigned int)keya); + +	if (s->cert->pkeys[SSL_PKEY_RSA_ENC].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); + +	is_export=SSL_C_IS_EXPORT(s->session->cipher); +	 +	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL)) +		{ +		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) +		{ +		is_export=1; +		ek=8; +		} +	else +		ek=5; + +	/* bad decrypt */ +#if 1 +	/* If a bad decrypt, continue with protocol but with a +	 * random master secret (Bleichenbacher attack) */ +	if ((i < 0) || +		((!is_export && (i != EVP_CIPHER_key_length(c))) +		|| (is_export && ((i != ek) || (s->s2->tmp.clear+(unsigned int)i != +			(unsigned int)EVP_CIPHER_key_length(c)))))) +		{ +		ERR_clear_error(); +		if (is_export) +			i=ek; +		else +			i=EVP_CIPHER_key_length(c); +		if (RAND_pseudo_bytes(p,i) <= 0) +			return 0; +		} +#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 ((!is_export && (i != EVP_CIPHER_key_length(c))) +		|| (is_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 (is_export) i+=s->s2->tmp.clear; + +	if (i > SSL_MAX_MASTER_KEY_LENGTH) +		{ +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); +		return -1; +		} +	s->session->master_key_length=i; +	memcpy(s->session->master_key,p,(unsigned int)i); +	return(1); +	} + +static int get_client_hello(SSL *s) +	{ +	int i,n; +	unsigned long len; +	unsigned char *p; +	STACK_OF(SSL_CIPHER) *cs; /* a stack of SSL_CIPHERS */ +	STACK_OF(SSL_CIPHER) *cl; /* the ones we want to use */ +	STACK_OF(SSL_CIPHER) *prio, *allow; +	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)); +		s->init_num = 9; +	 +		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)) +			{ +			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +			SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_INVALID_CHALLENGE_LENGTH); +			return(-1); +			} +		s->state=SSL2_ST_GET_CLIENT_HELLO_C; +		} + +	/* SSL2_ST_GET_CLIENT_HELLO_C */ +	p=(unsigned char *)s->init_buf->data; +	len = 9 + (unsigned long)s->s2->tmp.cipher_spec_length + (unsigned long)s->s2->challenge_length + (unsigned long)s->s2->tmp.session_id_length; +	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) +		{ +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_CLIENT_HELLO,SSL_R_MESSAGE_TOO_LONG); +		return -1; +		} +	n = (int)len - 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)); +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, p, (size_t)len, s, s->msg_callback_arg); /* CLIENT-HELLO */ +	p += 9; + +	/* 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,&(p[s->s2->tmp.cipher_spec_length]), +			s->s2->tmp.session_id_length, NULL); +		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(s); + +		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) +		    { +		    prio=sk_SSL_CIPHER_dup(cl); +		    if (prio == NULL) goto mem_err; +		    allow = cs; +		    } +		else +		    { +		    prio = cs; +		    allow = cl; +		    } +		for (z=0; z<sk_SSL_CIPHER_num(prio); z++) +			{ +			if (sk_SSL_CIPHER_find(allow,sk_SSL_CIPHER_value(prio,z)) < 0) +				{ +				(void)sk_SSL_CIPHER_delete(prio,z); +				z--; +				} +			} +		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) +		    { +		    sk_SSL_CIPHER_free(s->session->ciphers); +		    s->session->ciphers = prio; +		    } +		/* 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 or in the order of the server's preference +		 * if SSL_OP_CIPHER_SERVER_PREFERENCE was set. +		 */ +		} +	p+=s->s2->tmp.cipher_spec_length; +	/* done cipher selection */ + +	/* session id extracted already */ +	p+=s->s2->tmp.session_id_length; + +	/* challenge */ +	if (s->s2->challenge_length > sizeof s->s2->challenge) +		{ +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); +		return -1; +		} +	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(SSL *s) +	{ +	unsigned char *p,*d; +	int n,hit; + +	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 1 +		if (!hit) +			{ +			if (s->session->sess_cert != NULL) +				/* This can't really happen because get_client_hello +				 * has called ssl_get_new_session, which does not set +				 * sess_cert. */ +				ssl_sess_cert_free(s->session->sess_cert); +			s->session->sess_cert = ssl_sess_cert_new(); +			if (s->session->sess_cert == NULL) +				{ +				SSLerr(SSL_F_SERVER_HELLO, ERR_R_MALLOC_FAILURE); +				return(-1); +				} +			} +		/* If 'hit' is set, then s->sess_cert may be non-NULL or NULL, +		 * depending on whether it survived in the internal cache +		 * or was retrieved from an external cache. +		 * If it is NULL, we cannot put any useful data in it anyway, +		 * so we don't touch it. +		 */ + +#else /* That's what used to be done when cert_st and sess_cert_st were +	   * the same. */ +		if (!hit) +			{			/* else add cert to session */ +			CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); +			if (s->session->sess_cert != NULL) +				ssl_cert_free(s->session->sess_cert); +			s->session->sess_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->sess_cert == NULL) +				{ +				CRYPTO_add(&s->cert->references,1, +					CRYPTO_LOCK_SSL_CERT); +				s->session->sess_cert=s->cert; +				} +			} +#endif + +		if (s->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->pkeys[SSL_PKEY_RSA_ENC].x509,NULL); +			s2n(n,p);		/* certificate length */ +			i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&d); +			n=0; +			 +			/* lets send out the ciphers we like in the +			 * prefered order */ +			n=ssl_cipher_list_to_bytes(s,s->session->ciphers,d,0); +			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; +		if (RAND_pseudo_bytes(s->s2->conn_id,(int)s->s2->conn_id_length) <= 0) +			return -1; +		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 performance 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) + 		{ +		if (!ssl_init_wbio_buffer(s,1)) return(-1); + 		} +  +	return(ssl2_do_write(s)); +	} + +static int get_client_finished(SSL *s) +	{ +	unsigned char *p; +	int i, n; +	unsigned long len; + +	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)); +		s->init_num += 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); +				/* try to read the error message */ +				i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num); +				return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i); +				} +			return(-1); +			} +		s->state=SSL2_ST_GET_CLIENT_FINISHED_B; +		} + +	/* SSL2_ST_GET_CLIENT_FINISHED_B */ +	if (s->s2->conn_id_length > sizeof s->s2->conn_id) +		{ +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +		SSLerr(SSL_F_GET_CLIENT_FINISHED, ERR_R_INTERNAL_ERROR); +		return -1; +		} +	len = 1 + (unsigned long)s->s2->conn_id_length; +	n = (int)len - 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_FINISHED,i)); +		} +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* CLIENT-FINISHED */ +	p += 1; +	if (memcmp(p,s->s2->conn_id,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(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; +		if (s->s2->challenge_length > sizeof s->s2->challenge) +			{ +			SSLerr(SSL_F_SERVER_VERIFY, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		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(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; + +		if (s->session->session_id_length > sizeof s->session->session_id) +			{ +			SSLerr(SSL_F_SERVER_FINISH, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		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(SSL *s) +	{ +	const unsigned char *cp; +	unsigned char *p,*p2,*buf2; +	unsigned char *ccd; +	int i,j,ctype,ret= -1; +	unsigned long len; +	X509 *x509=NULL; +	STACK_OF(X509) *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; +		if (RAND_pseudo_bytes(ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH) <= 0) +			return -1; +		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); /* try to read 6 octets ... */ +		if (i < 3-s->init_num) /* ... but don't call ssl2_part_read now if we got at least 3 +		                        * (probably NO-CERTIFICATE-ERROR) */ +			{ +			ret=ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE,i); +			goto end; +			} +		s->init_num += i; + +		if ((s->init_num >= 3) && (p[0] == SSL2_MT_ERROR)) +			{ +			n2s(p,i); +			if (i != SSL2_PE_NO_CERTIFICATE) +				{ +				/* not the error message we expected -- let ssl2_part_read handle it */ +				s->init_num -= 3; +				ret = ssl2_part_read(s,SSL_F_REQUEST_CERTIFICATE, 3); +				goto end; +				} + +			if (s->msg_callback) +				s->msg_callback(0, s->version, 0, p, 3, s, s->msg_callback_arg); /* ERROR */ + +			/* this is the one place where we can recover from an SSL 2.0 error */ + +			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) || (s->init_num < 6)) +			{ +			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); +			SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_SHORT_READ); +			goto end; +			} +		if (s->init_num != 6) +			{ +			SSLerr(SSL_F_REQUEST_CERTIFICATE, ERR_R_INTERNAL_ERROR); +			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; +		} + +	/* SSL2_ST_SEND_REQUEST_CERTIFICATE_D */ +	p=(unsigned char *)s->init_buf->data; +	len = 6 + (unsigned long)s->s2->tmp.clen + (unsigned long)s->s2->tmp.rlen; +	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) +		{ +		SSLerr(SSL_F_REQUEST_CERTIFICATE,SSL_R_MESSAGE_TOO_LONG); +		goto end; +		} +	j = (int)len - 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; +		} +	if (s->msg_callback) +		s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* CLIENT-CERTIFICATE */ +	p += 6; + +	cp = p; +	x509=(X509 *)d2i_X509(NULL,&cp,(long)s->s2->tmp.clen); +	if (x509 == NULL) +		{ +		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_X509_LIB); +		goto msg_end; +		} + +	if (((sk=sk_X509_new_null()) == NULL) || (!sk_X509_push(sk,x509))) +		{ +		SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE); +		goto msg_end; +		} + +	i=ssl_verify_cert_chain(s,sk); + +	if (i > 0)	/* we like the packet, now check the chksum */ +		{ +		EVP_MD_CTX ctx; +		EVP_PKEY *pkey=NULL; + +		EVP_MD_CTX_init(&ctx); +		EVP_VerifyInit_ex(&ctx,s->ctx->rsa_md5, NULL); +		EVP_VerifyUpdate(&ctx,s->s2->key_material, +				 s->s2->key_material_length); +		EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH); + +		i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL); +		buf2=OPENSSL_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->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2); +		EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i); +		OPENSSL_free(buf2); + +		pkey=X509_get_pubkey(x509); +		if (pkey == NULL) goto end; +		i=EVP_VerifyFinal(&ctx,cp,s->s2->tmp.rlen,pkey); +		EVP_PKEY_free(pkey); +		EVP_MD_CTX_cleanup(&ctx); + +		if (i > 0) +			{ +			if (s->session->peer != NULL) +				X509_free(s->session->peer); +			s->session->peer=x509; +			CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); +			s->session->verify_result = s->verify_result; +			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: +	sk_X509_free(sk); +	X509_free(x509); +	return(ret); +	} + +static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from, +	     unsigned char *to, int padding) +	{ +	RSA *rsa; +	int i; + +	if ((c == NULL) || (c->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)) +		{ +		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_NO_PRIVATEKEY); +		return(-1); +		} +	if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey->type != EVP_PKEY_RSA) +		{ +		SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA); +		return(-1); +		} +	rsa=c->pkeys[SSL_PKEY_RSA_ENC].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); +	} +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/main/openssl/ssl/s3_both.c b/main/openssl/ssl/s3_both.c new file mode 100644 index 00000000..508e3902 --- /dev/null +++ b/main/openssl/ssl/s3_both.c @@ -0,0 +1,867 @@ +/* ssl/s3_both.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include "ssl_locl.h" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/x509.h> + +/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ +int ssl3_do_write(SSL *s, int type) +	{ +	int ret; + +	ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off], +	                     s->init_num); +	if (ret < 0) return(-1); +	if (type == SSL3_RT_HANDSHAKE) +		/* should not be done for 'Hello Request's, but in that case +		 * we'll ignore the result anyway */ +		ssl3_finish_mac(s,(unsigned char *)&s->init_buf->data[s->init_off],ret); +	 +	if (ret == s->init_num) +		{ +		if (s->msg_callback) +			s->msg_callback(1, s->version, type, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg); +		return(1); +		} +	s->init_off+=ret; +	s->init_num-=ret; +	return(0); +	} + +int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) +	{ +	unsigned char *p,*d; +	int i; +	unsigned long l; + +	if (s->state == a) +		{ +		d=(unsigned char *)s->init_buf->data; +		p= &(d[4]); + +		i=s->method->ssl3_enc->final_finish_mac(s, +			sender,slen,s->s3->tmp.finish_md); +		s->s3->tmp.finish_md_len = i; +		memcpy(p, s->s3->tmp.finish_md, i); +		p+=i; +		l=i; + +                /* Copy the finished so we can use it for +                   renegotiation checks */ +                if(s->type == SSL_ST_CONNECT) +                        { +                         OPENSSL_assert(i <= EVP_MAX_MD_SIZE); +                         memcpy(s->s3->previous_client_finished,  +                             s->s3->tmp.finish_md, i); +                         s->s3->previous_client_finished_len=i; +                        } +                else +                        { +                        OPENSSL_assert(i <= EVP_MAX_MD_SIZE); +                        memcpy(s->s3->previous_server_finished,  +                            s->s3->tmp.finish_md, i); +                        s->s3->previous_server_finished_len=i; +                        } + +#ifdef OPENSSL_SYS_WIN16 +		/* MSVC 1.5 does not clear the top bytes of the word unless +		 * I do this. +		 */ +		l&=0xffff; +#endif + +		*(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)); +	} + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to far. */ +static void ssl3_take_mac(SSL *s) +	{ +	const char *sender; +	int slen; + +	if (s->state & SSL_ST_CONNECT) +		{ +		sender=s->method->ssl3_enc->server_finished_label; +		slen=s->method->ssl3_enc->server_finished_label_len; +		} +	else +		{ +		sender=s->method->ssl3_enc->client_finished_label; +		slen=s->method->ssl3_enc->client_finished_label_len; +		} + +	s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, +		sender,slen,s->s3->tmp.peer_finish_md); +	} +#endif + +int ssl3_get_finished(SSL *s, int a, int b) +	{ +	int al,i,ok; +	long n; +	unsigned char *p; + +#ifdef OPENSSL_NO_NEXTPROTONEG +	/* the mac has already been generated when we received the +	 * change cipher spec message and is in s->s3->tmp.peer_finish_md +	 */  +#endif + +	n=s->method->ssl_get_message(s, +		a, +		b, +		SSL3_MT_FINISHED, +		64, /* should actually be 36+4 :-) */ +		&ok); + +	if (!ok) return((int)n); + +	/* If this occurs, we have missed a message */ +	if (!s->s3->change_cipher_spec) +		{ +		al=SSL_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_msg; +	i = s->s3->tmp.peer_finish_md_len; + +	if (i != n) +		{ +		al=SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_BAD_DIGEST_LENGTH); +		goto f_err; +		} + +	if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) +		{ +		al=SSL_AD_DECRYPT_ERROR; +		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED); +		goto f_err; +		} + +        /* Copy the finished so we can use it for +           renegotiation checks */ +        if(s->type == SSL_ST_ACCEPT) +                { +                OPENSSL_assert(i <= EVP_MAX_MD_SIZE); +                memcpy(s->s3->previous_client_finished,  +                    s->s3->tmp.peer_finish_md, i); +                s->s3->previous_client_finished_len=i; +                } +        else +                { +                OPENSSL_assert(i <= EVP_MAX_MD_SIZE); +                memcpy(s->s3->previous_server_finished,  +                    s->s3->tmp.peer_finish_md, i); +                s->s3->previous_server_finished_len=i; +                } + +	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(SSL *s, int a, int 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)); +	} + +static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) +	{ +	int n; +	unsigned char *p; + +	n=i2d_X509(x,NULL); +	if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) +		{ +		SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); +		return(-1); +		} +	p=(unsigned char *)&(buf->data[*l]); +	l2n3(n,p); +	i2d_X509(x,&p); +	*l+=n+3; + +	return(0); +	} + +unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) +	{ +	unsigned char *p; +	int i; +	unsigned long l=7; +	BUF_MEM *buf; +	int no_chain; +	STACK_OF(X509) *cert_chain; + +	cert_chain = SSL_get_certificate_chain(s, x); + +	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs || cert_chain) +		no_chain = 1; +	else +		no_chain = 0; + +	/* TLSv1 sends a chain with nothing in it, instead of an alert */ +	buf=s->init_buf; +	if (!BUF_MEM_grow_clean(buf,10)) +		{ +		SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); +		return(0); +		} +	if (x != NULL) +		{ +		if (no_chain) +			{ +			if (ssl3_add_cert_to_buf(buf, &l, x)) +				return(0); +			} +		else +			{ +			X509_STORE_CTX xs_ctx; + +			if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) +				{ +				SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); +				return(0); +				} +			X509_verify_cert(&xs_ctx); +			/* Don't leave errors in the queue */ +			ERR_clear_error(); +			for (i=0; i < sk_X509_num(xs_ctx.chain); i++) +				{ +				x = sk_X509_value(xs_ctx.chain, i); + +				if (ssl3_add_cert_to_buf(buf, &l, x)) +					{ +					X509_STORE_CTX_cleanup(&xs_ctx); +					return 0; +					} +				} +			X509_STORE_CTX_cleanup(&xs_ctx); +			} +		} +	/* Thawte special :-) */ +	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++) +		{ +		x=sk_X509_value(s->ctx->extra_certs,i); +		if (ssl3_add_cert_to_buf(buf, &l, x)) +			return(0); +		} + +	for (i=0; i<sk_X509_num(cert_chain); i++) +		if (ssl3_add_cert_to_buf(buf, &l, sk_X509_value(cert_chain,i))) +			return(0); + +	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); +	} + +/* Obtain handshake message of message type 'mt' (any if mt == -1), + * maximum acceptable body length 'max'. + * The first four bytes (msg_type and length) are read in state 'st1', + * the body is read in state 'stn'. + */ +long ssl3_get_message(SSL *s, int st1, int stn, int 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=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); +			goto f_err; +			} +		*ok=1; +		s->init_msg = s->init_buf->data + 4; +		s->init_num = (int)s->s3->tmp.message_size; +		return s->init_num; +		} + +	p=(unsigned char *)s->init_buf->data; + +	if (s->state == st1) /* s->init_num < 4 */ +		{ +		int skip_message; + +		do +			{ +			while (s->init_num < 4) +				{ +				i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, +					&p[s->init_num],4 - s->init_num, 0); +				if (i <= 0) +					{ +					s->rwstate=SSL_READING; +					*ok = 0; +					return i; +					} +				s->init_num+=i; +				} +			 +			skip_message = 0; +			if (!s->server) +				if (p[0] == SSL3_MT_HELLO_REQUEST) +					/* The server may always send 'Hello Request' messages -- +					 * we are doing a handshake anyway now, so ignore them +					 * if their format is correct. Does not count for +					 * 'Finished' MAC. */ +					if (p[1] == 0 && p[2] == 0 &&p[3] == 0) +						{ +						s->init_num = 0; +						skip_message = 1; + +						if (s->msg_callback) +							s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg); +						} +			} +		while (skip_message); + +		/* s->init_num == 4 */ + +		if ((mt >= 0) && (*p != mt)) +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); +			goto f_err; +			} +		if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) && +					(st1 == SSL3_ST_SR_CERT_A) && +					(stn == SSL3_ST_SR_CERT_B)) +			{ +			/* At this point we have got an MS SGC second client +			 * hello (maybe we should always allow the client to +			 * start a new handshake?). We need to restart the mac. +			 * Don't increment {num,total}_renegotiations because +			 * we have not completed the handshake. */ +			ssl3_init_finished_mac(s); +			} + +		s->s3->tmp.message_type= *(p++); + +		n2l3(p,l); +		if (l > (unsigned long)max) +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); +			goto f_err; +			} +		if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */ +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); +			goto f_err; +			} +		if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l+4)) +			{ +			SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB); +			goto err; +			} +		s->s3->tmp.message_size=l; +		s->state=stn; + +		s->init_msg = s->init_buf->data + 4; +		s->init_num = 0; +		} + +	/* next state (stn) */ +	p = s->init_msg; +	n = s->s3->tmp.message_size - s->init_num; +	while (n > 0) +		{ +		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0); +		if (i <= 0) +			{ +			s->rwstate=SSL_READING; +			*ok = 0; +			return i; +			} +		s->init_num += i; +		n -= i; +		} + +#ifndef OPENSSL_NO_NEXTPROTONEG +	/* If receiving Finished, record MAC of prior handshake messages for +	 * Finished verification. */ +	if (*s->init_buf->data == SSL3_MT_FINISHED) +		ssl3_take_mac(s); +#endif + +	/* Feed this message into MAC computation. */ +	ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); +	if (s->msg_callback) +		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg); +	*ok=1; +	return s->init_num; +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	*ok=0; +	return(-1); +	} + +int ssl_cert_type(X509 *x, EVP_PKEY *pkey) +	{ +	EVP_PKEY *pk; +	int ret= -1,i; + +	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; +		} +	else if (i == EVP_PKEY_DSA) +		{ +		ret=SSL_PKEY_DSA_SIGN; +		} +#ifndef OPENSSL_NO_EC +	else if (i == EVP_PKEY_EC) +		{ +		ret = SSL_PKEY_ECC; +		}	 +#endif +	else if (i == NID_id_GostR3410_94 || i == NID_id_GostR3410_94_cc)  +		{ +		ret = SSL_PKEY_GOST94; +		} +	else if (i == NID_id_GostR3410_2001 || i == NID_id_GostR3410_2001_cc)  +		{ +		ret = SSL_PKEY_GOST01; +		} +err: +	if(!pkey) EVP_PKEY_free(pk); +	return(ret); +	} + +int ssl_verify_alarm_type(long type) +	{ +	int al; + +	switch(type) +		{ +	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: +	case X509_V_ERR_UNABLE_TO_GET_CRL: +	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: +		al=SSL_AD_UNKNOWN_CA; +		break; +	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: +	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: +	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: +	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: +	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: +	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: +	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: +	case X509_V_ERR_CERT_NOT_YET_VALID: +	case X509_V_ERR_CRL_NOT_YET_VALID: +	case X509_V_ERR_CERT_UNTRUSTED: +	case X509_V_ERR_CERT_REJECTED: +		al=SSL_AD_BAD_CERTIFICATE; +		break; +	case X509_V_ERR_CERT_SIGNATURE_FAILURE: +	case X509_V_ERR_CRL_SIGNATURE_FAILURE: +		al=SSL_AD_DECRYPT_ERROR; +		break; +	case X509_V_ERR_CERT_HAS_EXPIRED: +	case X509_V_ERR_CRL_HAS_EXPIRED: +		al=SSL_AD_CERTIFICATE_EXPIRED; +		break; +	case X509_V_ERR_CERT_REVOKED: +		al=SSL_AD_CERTIFICATE_REVOKED; +		break; +	case X509_V_ERR_OUT_OF_MEM: +		al=SSL_AD_INTERNAL_ERROR; +		break; +	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: +	case X509_V_ERR_CERT_CHAIN_TOO_LONG: +	case X509_V_ERR_PATH_LENGTH_EXCEEDED: +	case X509_V_ERR_INVALID_CA: +		al=SSL_AD_UNKNOWN_CA; +		break; +	case X509_V_ERR_APPLICATION_VERIFICATION: +		al=SSL_AD_HANDSHAKE_FAILURE; +		break; +	case X509_V_ERR_INVALID_PURPOSE: +		al=SSL_AD_UNSUPPORTED_CERTIFICATE; +		break; +	default: +		al=SSL_AD_CERTIFICATE_UNKNOWN; +		break; +		} +	return(al); +	} + +#ifndef OPENSSL_NO_BUF_FREELISTS +/* On some platforms, malloc() performance is bad enough that you can't just + * free() and malloc() buffers all the time, so we need to use freelists from + * unused buffers.  Currently, each freelist holds memory chunks of only a + * given size (list->chunklen); other sized chunks are freed and malloced. + * This doesn't help much if you're using many different SSL option settings + * with a given context.  (The options affecting buffer size are + * max_send_fragment, read buffer vs write buffer, + * SSL_OP_MICROSOFT_BIG_WRITE_BUFFER, SSL_OP_NO_COMPRESSION, and + * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.)  Using a separate freelist for every + * possible size is not an option, since max_send_fragment can take on many + * different values. + * + * If you are on a platform with a slow malloc(), and you're using SSL + * connections with many different settings for these options, and you need to + * use the SSL_MOD_RELEASE_BUFFERS feature, you have a few options: + *    - Link against a faster malloc implementation. + *    - Use a separate SSL_CTX for each option set. + *    - Improve this code. + */ +static void * +freelist_extract(SSL_CTX *ctx, int for_read, int sz) +	{ +	SSL3_BUF_FREELIST *list; +	SSL3_BUF_FREELIST_ENTRY *ent = NULL; +	void *result = NULL; + +	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +	list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; +	if (list != NULL && sz == (int)list->chunklen) +		ent = list->head; +	if (ent != NULL) +		{ +		list->head = ent->next; +		result = ent; +		if (--list->len == 0) +			list->chunklen = 0; +		} +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +	if (!result) +		result = OPENSSL_malloc(sz); +	return result; +} + +static void +freelist_insert(SSL_CTX *ctx, int for_read, size_t sz, void *mem) +	{ +	SSL3_BUF_FREELIST *list; +	SSL3_BUF_FREELIST_ENTRY *ent; + +	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +	list = for_read ? ctx->rbuf_freelist : ctx->wbuf_freelist; +	if (list != NULL && +	    (sz == list->chunklen || list->chunklen == 0) && +	    list->len < ctx->freelist_max_len && +	    sz >= sizeof(*ent)) +		{ +		list->chunklen = sz; +		ent = mem; +		ent->next = list->head; +		list->head = ent; +		++list->len; +		mem = NULL; +		} + +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +	if (mem) +		OPENSSL_free(mem); +	} +#else +#define freelist_extract(c,fr,sz) OPENSSL_malloc(sz) +#define freelist_insert(c,fr,sz,m) OPENSSL_free(m) +#endif + +int ssl3_setup_read_buffer(SSL *s) +	{ +	unsigned char *p; +	size_t len,align=0,headerlen; +	 +	if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) +		headerlen = DTLS1_RT_HEADER_LENGTH; +	else +		headerlen = SSL3_RT_HEADER_LENGTH; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 +	align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); +#endif + +	if (s->s3->rbuf.buf == NULL) +		{ +		if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) +			{ +			len = SSL3_RT_DEFAULT_PACKET_SIZE; +			} +  		else +			{ +			len = SSL3_RT_MAX_PLAIN_LENGTH +				+ SSL3_RT_MAX_ENCRYPTED_OVERHEAD +				+ headerlen + align; +			if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) +				{ +				s->s3->init_extra = 1; +				len += SSL3_RT_MAX_EXTRA; +				} +			} +#ifndef OPENSSL_NO_COMP +		if (!(s->options & SSL_OP_NO_COMPRESSION)) +			len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; +#endif +		if ((p=freelist_extract(s->ctx, 1, len)) == NULL) +			goto err; +		s->s3->rbuf.buf = p; +		s->s3->rbuf.len = len; +		} + +	s->packet= &(s->s3->rbuf.buf[0]); +	return 1; + +err: +	SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER,ERR_R_MALLOC_FAILURE); +	return 0; +	} + +int ssl3_setup_write_buffer(SSL *s) +	{ +	unsigned char *p; +	size_t len,align=0,headerlen; + +	if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) +		headerlen = DTLS1_RT_HEADER_LENGTH + 1; +	else +		headerlen = SSL3_RT_HEADER_LENGTH; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 +	align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); +#endif + +	if (s->s3->wbuf.buf == NULL) +		{ +		if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) +			{ +			len = SSL3_RT_DEFAULT_PACKET_SIZE; +			} +  		else +			{ +			len = s->max_send_fragment; +			} +		len += 0 +			+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD +			+ headerlen + align; +#ifndef OPENSSL_NO_COMP +		if (!(s->options & SSL_OP_NO_COMPRESSION)) +			len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; +#endif +		if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) +			len += headerlen + align +				+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; +		if ((p=freelist_extract(s->ctx, 0, len)) == NULL) +			goto err; +		s->s3->wbuf.buf = p; +		s->s3->wbuf.len = len; +		} + +	return 1; + +err: +	SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER,ERR_R_MALLOC_FAILURE); +	return 0; +	} + + +int ssl3_setup_buffers(SSL *s) +	{ +	if (!ssl3_setup_read_buffer(s)) +		return 0; +	if (!ssl3_setup_write_buffer(s)) +		return 0; +	return 1; +	} + +int ssl3_release_write_buffer(SSL *s) +	{ +	if (s->s3->wbuf.buf != NULL) +		{ +		freelist_insert(s->ctx, 0, s->s3->wbuf.len, s->s3->wbuf.buf); +		s->s3->wbuf.buf = NULL; +		} +	return 1; +	} + +int ssl3_release_read_buffer(SSL *s) +	{ +	if (s->s3->rbuf.buf != NULL) +		{ +		freelist_insert(s->ctx, 1, s->s3->rbuf.len, s->s3->rbuf.buf); +		s->s3->rbuf.buf = NULL; +		} +	return 1; +	} diff --git a/main/openssl/ssl/s3_clnt.c b/main/openssl/ssl/s3_clnt.c new file mode 100644 index 00000000..42bcd629 --- /dev/null +++ b/main/openssl/ssl/s3_clnt.c @@ -0,0 +1,3153 @@ +/* ssl/s3_clnt.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by  + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include "ssl_locl.h" +#include "kssl_lcl.h" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/md5.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif +#include <openssl/bn.h> +#ifndef OPENSSL_NO_ENGINE +#include <openssl/engine.h> +#endif + +static const SSL_METHOD *ssl3_get_client_method(int ver); +static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b); + +static const SSL_METHOD *ssl3_get_client_method(int ver) +	{ +	if (ver == SSL3_VERSION) +		return(SSLv3_client_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl3_meth_func(SSLv3_client_method, +			ssl_undefined_function, +			ssl3_connect, +			ssl3_get_client_method) + +int ssl3_connect(SSL *s) +	{ +	BUF_MEM *buf=NULL; +	unsigned long Time=(unsigned long)time(NULL); +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int ret= -1; +	int new_state,state,skip=0; + +	RAND_add(&Time,sizeof(Time),0); +	ERR_clear_error(); +	clear_sys_error(); + +	if (s->info_callback != NULL) +		cb=s->info_callback; +	else if (s->ctx->info_callback != NULL) +		cb=s->ctx->info_callback; +	 +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);  +#if 0	/* Send app data in separate packet, otherwise, some particular site +	 * (only one site so far) closes the socket. +	 * Note: there is a very small chance that two TCP packets +	 * could be arriving at server combined into a single TCP packet, +	 * then trigger that site to break. We haven't encounter that though. +	 */ +	if (SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) +		{ +		/* Send app data along with CCS/Finished */ +		s->s3->flags |= SSL3_FLAGS_DELAY_CLIENT_FINISHED; +		} +#endif + +	for (;;) +		{ +		state=s->state; + +		switch(s->state) +			{ +		case SSL_ST_RENEGOTIATE: +			s->new_session=1; +			s->state=SSL_ST_CONNECT; +			s->ctx->stats.sess_connect_renegotiate++; +			/* break */ +		case SSL_ST_BEFORE: +		case SSL_ST_CONNECT: +		case SSL_ST_BEFORE|SSL_ST_CONNECT: +		case SSL_ST_OK|SSL_ST_CONNECT: + +			s->server=0; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			if ((s->version & 0xff00 ) != 0x0300) +				{ +				SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR); +				ret = -1; +				goto end; +				} +				 +			/* s->version=SSL3_VERSION; */ +			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; +				buf=NULL; +				} + +			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } + +			/* setup buffing BIO */ +			if (!ssl_init_wbio_buffer(s,0)) { 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->stats.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 */ +			if (s->bbio != s->wbio) +				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: +#ifndef OPENSSL_NO_TLSEXT +			ret=ssl3_check_finished(s); +			if (ret <= 0) goto end; +			if (ret == 2) +				{ +				s->hit = 1; +				if (s->tlsext_ticket_expected) +					s->state=SSL3_ST_CR_SESSION_TICKET_A; +				else +					s->state=SSL3_ST_CR_FINISHED_A; +				s->init_num=0; +				break; +				} +#endif +			/* Check if it is anon DH/ECDH */ +			/* or PSK */ +			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && +			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +				{ +				ret=ssl3_get_server_certificate(s); +				if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT +				if (s->tlsext_status_expected) +					s->state=SSL3_ST_CR_CERT_STATUS_A; +				else +					s->state=SSL3_ST_CR_KEY_EXCH_A; +				} +			else +				{ +				skip = 1; +				s->state=SSL3_ST_CR_KEY_EXCH_A; +				} +#else +				} +			else +				skip=1; + +			s->state=SSL3_ST_CR_KEY_EXCH_A; +#endif +			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: +		case SSL3_ST_CW_CERT_D: +			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; +			/* EAY EAY EAY need to check for DH fix cert +			 * sent back */ +			/* For TLS, cert_req is set to 2, so a cert chain +			 * of nothing is sent, but no verify packet is sent */ +			/* XXX: For now, we do not support client  +			 * authentication in ECDH cipher suites with +			 * ECDH (rather than ECDSA) certificates. +			 * We need to skip the certificate verify  +			 * message when client's ECDH public key is sent  +			 * inside the client certificate. +			 */ +			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; +				} +			if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) +				{ +				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; + +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) +			s->state=SSL3_ST_CW_FINISHED_A; +#else +			if (s->next_proto_negotiated) +				s->state=SSL3_ST_CW_NEXT_PROTO_A; +			else +				s->state=SSL3_ST_CW_FINISHED_A; +#endif + +			s->init_num=0; + +			s->session->cipher=s->s3->tmp.new_cipher; +#ifdef OPENSSL_NO_COMP +			s->session->compress_meth=0; +#else +			if (s->s3->tmp.new_compression == NULL) +				s->session->compress_meth=0; +			else +				s->session->compress_meth= +					s->s3->tmp.new_compression->id; +#endif +			if (!s->method->ssl3_enc->setup_key_block(s)) +				{ +				ret= -1; +				goto end; +				} + +			if (!s->method->ssl3_enc->change_cipher_state(s, +				SSL3_CHANGE_CIPHER_CLIENT_WRITE)) +				{ +				ret= -1; +				goto end; +				} + +			break; + +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +		case SSL3_ST_CW_NEXT_PROTO_A: +		case SSL3_ST_CW_NEXT_PROTO_B: +			ret=ssl3_send_next_proto(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_CW_FINISHED_A; +			break; +#endif + +		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, +				s->method->ssl3_enc->client_finished_label, +				s->method->ssl3_enc->client_finished_label_len); +			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 +				{ +				if ((SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) && SSL_get_cipher_bits(s, NULL) >= 128 +				    && s->s3->previous_server_finished_len == 0 /* no cutthrough on renegotiation (would complicate the state machine) */ +				   ) +					{ +					if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) +						{ +						s->state=SSL3_ST_CUTTHROUGH_COMPLETE; +						s->s3->flags|=SSL3_FLAGS_POP_BUFFER; +						s->s3->delay_buf_pop_ret=0; +						} +					else +						{ +						s->s3->tmp.next_state=SSL3_ST_CUTTHROUGH_COMPLETE; +						} +					} +				else +					{ +#ifndef OPENSSL_NO_TLSEXT +					/* Allow NewSessionTicket if ticket expected */ +					if (s->tlsext_ticket_expected) +						s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A; +					else +#endif +						s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A; +					} +				} +			s->init_num=0; +			break; + +#ifndef OPENSSL_NO_TLSEXT +		case SSL3_ST_CR_SESSION_TICKET_A: +		case SSL3_ST_CR_SESSION_TICKET_B: +			ret=ssl3_get_new_session_ticket(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_CR_FINISHED_A; +			s->init_num=0; +		break; + +		case SSL3_ST_CR_CERT_STATUS_A: +		case SSL3_ST_CR_CERT_STATUS_B: +			ret=ssl3_get_cert_status(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_CR_KEY_EXCH_A; +			s->init_num=0; +		break; +#endif + +		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); +			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: +			s->rwstate=SSL_WRITING; +			if (BIO_flush(s->wbio) <= 0) +				{ +				ret= -1; +				goto end; +				} +			s->rwstate=SSL_NOTHING; +			s->state=s->s3->tmp.next_state; +			break; + +		case SSL3_ST_CUTTHROUGH_COMPLETE: +#ifndef OPENSSL_NO_TLSEXT +			/* Allow NewSessionTicket if ticket expected */ +			if (s->tlsext_ticket_expected) +				s->state=SSL3_ST_CR_SESSION_TICKET_A; +			else +#endif +				s->state=SSL3_ST_CR_FINISHED_A; + +			/* SSL_write() will take care of flushing buffered data if +			 * DELAY_CLIENT_FINISHED is set. +			 */ +			if (!(s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)) +				ssl_free_wbio_buffer(s); +			ret = 1; +			goto end; +			/* break; */ + +		case SSL_ST_OK: +			/* clean a few things up */ +			ssl3_cleanup_key_block(s); + +			if (s->init_buf != NULL) +				{ +				BUF_MEM_free(s->init_buf); +				s->init_buf=NULL; +				} + +			/* If we are not 'joining' the last two packets, +			 * remove the buffering now */ +			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER)) +				ssl_free_wbio_buffer(s); +			/* else do it later in ssl3_write */ + +			s->init_num=0; +			s->new_session=0; + +			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); +			if (s->hit) s->ctx->stats.sess_hit++; + +			ret=1; +			/* s->server=0; */ +			s->handshake_func=ssl3_connect; +			s->ctx->stats.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) +				{ +				if ((ret=BIO_flush(s->wbio)) <= 0) +					goto end; +				} + +			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: +	s->in_handshake--; +	if (buf != NULL) +		BUF_MEM_free(buf); +	if (cb != NULL) +		cb(s,SSL_CB_CONNECT_EXIT,ret); +	return(ret); +	} + + +int ssl3_client_hello(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	int i; +	unsigned long Time,l; +#ifndef OPENSSL_NO_COMP +	int j; +	SSL_COMP *comp; +#endif + +	buf=(unsigned char *)s->init_buf->data; +	if (s->state == SSL3_ST_CW_CLNT_HELLO_A) +		{ +		SSL_SESSION *sess = s->session; +		if ((sess == NULL) || +			(sess->ssl_version != s->version) || +#ifdef OPENSSL_NO_TLSEXT +			!sess->session_id_length || +#else +			(!sess->session_id_length && !sess->tlsext_tick) || +#endif +			(sess->not_resumable)) +			{ +		        if (!s->session_creation_enabled) +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +				SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); +				goto err; +				} +			if (!ssl_get_new_session(s,0)) +				goto err; +			} +		/* else use the pre-loaded session */ + +		p=s->s3->client_random; +		Time=(unsigned long)time(NULL);			/* Time */ +		l2n(Time,p); +		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) +			goto err; + +		/* Do the message type and length last */ +		d=p= &(buf[4]); + +		*(p++)=s->version>>8; +		*(p++)=s->version&0xff; +		s->client_version=s->version; + +		/* 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) +			{ +			if (i > (int)sizeof(s->session->session_id)) +				{ +				SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); +				goto err; +				} +			memcpy(p,s->session->session_id,i); +			p+=i; +			} +		 +		/* Ciphers supported */ +		i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0); +		if (i == 0) +			{ +			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); +			goto err; +			} +		s2n(i,p); +		p+=i; + +		/* COMPRESSION */ +#ifdef OPENSSL_NO_COMP +		*(p++)=1; +#else + +		if ((s->options & SSL_OP_NO_COMPRESSION) +					|| !s->ctx->comp_methods) +			j=0; +		else +			j=sk_SSL_COMP_num(s->ctx->comp_methods); +		*(p++)=1+j; +		for (i=0; i<j; i++) +			{ +			comp=sk_SSL_COMP_value(s->ctx->comp_methods,i); +			*(p++)=comp->id; +			} +#endif +		*(p++)=0; /* Add the NULL method */ + +#ifndef OPENSSL_NO_TLSEXT +		/* TLS extensions*/ +		if (ssl_prepare_clienthello_tlsext(s) <= 0) +			{ +			SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); +			goto err; +			} +		if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) +			{ +			SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); +			goto err; +			} +#endif +		 +		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); +	} + +int ssl3_get_server_hello(SSL *s) +	{ +	STACK_OF(SSL_CIPHER) *sk; +	const SSL_CIPHER *c; +	unsigned char *p,*d; +	int i,al,ok; +	unsigned int j; +	long n; +#ifndef OPENSSL_NO_COMP +	SSL_COMP *comp; +#endif + +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_SRVR_HELLO_A, +		SSL3_ST_CR_SRVR_HELLO_B, +		-1, +		20000, /* ?? */ +		&ok); + +	if (!ok) return((int)n); + +	if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) +		{ +		if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) +			{ +			if ( s->d1->send_cookie == 0) +				{ +				s->s3->tmp.reuse_message = 1; +				return 1; +				} +			else /* already sent a cookie */ +				{ +				al=SSL_AD_UNEXPECTED_MESSAGE; +				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE); +				goto f_err; +				} +			} +		} +	 +	if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO) +		{ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_MESSAGE_TYPE); +		goto f_err; +		} + +	d=p=(unsigned char *)s->init_msg; + +	if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff))) +		{ +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION); +		s->version=(s->version&0xff00)|p[1]; +		al=SSL_AD_PROTOCOL_VERSION; +		goto f_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 > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE)) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_LONG); +		goto f_err; +		} + +#ifndef OPENSSL_NO_TLSEXT +	/* check if we want to resume the session based on external pre-shared secret */ +	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) +		{ +		SSL_CIPHER *pref_cipher=NULL; +		s->session->master_key_length=sizeof(s->session->master_key); +		if (s->tls_session_secret_cb(s, s->session->master_key, +					     &s->session->master_key_length, +					     NULL, &pref_cipher, +					     s->tls_session_secret_cb_arg)) +			{ +			s->session->cipher = pref_cipher ? +				pref_cipher : ssl_get_cipher_by_char(s, p+j); +			} +		} +#endif /* OPENSSL_NO_TLSEXT */ + +	if (j != 0 && j == s->session->session_id_length +	    && memcmp(p,s->session->session_id,j) == 0) +	    { +	    if(s->sid_ctx_length != s->session->sid_ctx_length +	       || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length)) +		{ +		/* actually a client application bug */ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); +		goto f_err; +		} +	    s->hit=1; +	    } +	else	/* a miss or crap from the other end */ +		{ +		/* If we were trying for session-id reuse, make a new +		 * SSL_SESSION so we don't stuff up other people */ +		s->hit=0; +		if (s->session->session_id_length > 0) +			{ +		        if (!s->session_creation_enabled) +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); +				goto err; +				} +			if (!ssl_get_new_session(s,0)) +				{ +				al=SSL_AD_INTERNAL_ERROR; +				goto f_err; +				} +			} +		s->session->session_id_length=j; +		memcpy(s->session->session_id,p,j); /* j could be 0 */ +		} +	p+=j; +	c=ssl_get_cipher_by_char(s,p); +	if (c == NULL) +		{ +		/* unknown cipher */ +		al=SSL_AD_ILLEGAL_PARAMETER; +		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_SSL_CIPHER_find(sk,c); +	if (i < 0) +		{ +		/* we did not say we would use this cipher */ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED); +		goto f_err; +		} + +	/* Depending on the session caching (internal/external), the cipher +	   and/or cipher_id values may not be set. Make sure that +	   cipher_id is set and use it for comparison. */ +	if (s->session->cipher) +		s->session->cipher_id = s->session->cipher->id; +	if (s->hit && (s->session->cipher_id != c->id)) +		{ +/* Workaround is now obsolete */ +#if 0 +		if (!(s->options & +			SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)) +#endif +			{ +			al=SSL_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; +	if (!ssl3_digest_cached_records(s)) +		goto f_err; + +	/* lets get the compression algorithm */ +	/* COMPRESSION */ +#ifdef OPENSSL_NO_COMP +	if (*(p++) != 0) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); +		goto f_err; +		} +	/* If compression is disabled we'd better not try to resume a session +	 * using compression. +	 */ +	if (s->session->compress_meth != 0) +		{ +		al=SSL_AD_INTERNAL_ERROR; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION); +		goto f_err; +		} +#else +	j= *(p++); +	if (s->hit && j != s->session->compress_meth) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED); +		goto f_err; +		} +	if (j == 0) +		comp=NULL; +	else if (s->options & SSL_OP_NO_COMPRESSION) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED); +		goto f_err; +		} +	else +		comp=ssl3_comp_find(s->ctx->comp_methods,j); +	 +	if ((j != 0) && (comp == NULL)) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); +		goto f_err; +		} +	else +		{ +		s->s3->tmp.new_compression=comp; +		} +#endif + +#ifndef OPENSSL_NO_TLSEXT +	/* TLS extensions*/ +	if (s->version >= SSL3_VERSION) +		{ +		if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al)) +			{ +			/* 'al' set by ssl_parse_serverhello_tlsext */ +			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT); +			goto f_err;  +			} +		if (ssl_check_serverhello_tlsext(s) <= 0) +			{ +			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT); +				goto err; +			} +		} +#endif + +	if (p != (d+n)) +		{ +		/* wrong packet length */ +		al=SSL_AD_DECODE_ERROR; +		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); +	} + +int ssl3_get_server_certificate(SSL *s) +	{ +	int al,i,ok,ret= -1; +	unsigned long n,nc,llen,l; +	X509 *x=NULL; +	const unsigned char *q,*p; +	unsigned char *d; +	STACK_OF(X509) *sk=NULL; +	SESS_CERT *sc; +	EVP_PKEY *pkey=NULL; +	int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */ + +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_CERT_A, +		SSL3_ST_CR_CERT_B, +		-1, +		s->max_cert_list, +		&ok); + +	if (!ok) return((int)n); + +	if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) || +		((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) &&  +		(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) +		{ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE); +		goto f_err; +		} +	p=d=(unsigned char *)s->init_msg; + +	if ((sk=sk_X509_new_null()) == NULL) +		{ +		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); +		goto err; +		} + +	n2l3(p,llen); +	if (llen+3 != n) +		{ +		al=SSL_AD_DECODE_ERROR; +		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=SSL_AD_DECODE_ERROR; +			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=SSL_AD_BAD_CERTIFICATE; +			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_ASN1_LIB); +			goto f_err; +			} +		if (q != (p+l)) +			{ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); +			goto f_err; +			} +		if (!sk_X509_push(sk,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 <= 0) +#ifndef OPENSSL_NO_KRB5 +	    && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && +		 (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) +#endif /* OPENSSL_NO_KRB5 */ +		) +		{ +		al=ssl_verify_alarm_type(s->verify_result); +		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); +		goto f_err;  +		} +	ERR_clear_error(); /* but we keep s->verify_result */ + +	sc=ssl_sess_cert_new(); +	if (sc == NULL) goto err; + +	if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert); +	s->session->sess_cert=sc; + +	sc->cert_chain=sk; +	/* Inconsistency alert: cert_chain does include the peer's +	 * certificate, which we don't include in s3_srvr.c */ +	x=sk_X509_value(sk,0); +	sk=NULL; + 	/* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/ + +	pkey=X509_get_pubkey(x); + +	/* VRS: allow null cert if auth == KRB5 */ +	need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && +	            (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) +	            ? 0 : 1; + +#ifdef KSSL_DEBUG +	printf("pkey,x = %p, %p\n", pkey,x); +	printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey)); +	printf("cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name, +		s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert); +#endif    /* KSSL_DEBUG */ + +	if (need_cert && ((pkey == NULL) || 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 (need_cert && i < 0) +		{ +		x=NULL; +		al=SSL3_AL_FATAL; +		SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, +			SSL_R_UNKNOWN_CERTIFICATE_TYPE); +		goto f_err; +		} + +	if (need_cert) +		{ +		sc->peer_cert_type=i; +		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); +		/* Why would the following ever happen? +		 * We just created sc a couple of lines ago. */ +		if (sc->peer_pkeys[i].x509 != NULL) +			X509_free(sc->peer_pkeys[i].x509); +		sc->peer_pkeys[i].x509=x; +		sc->peer_key= &(sc->peer_pkeys[i]); + +		if (s->session->peer != NULL) +			X509_free(s->session->peer); +		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); +		s->session->peer=x; +		} +	else +		{ +		sc->peer_cert_type=i; +		sc->peer_key= NULL; + +		if (s->session->peer != NULL) +			X509_free(s->session->peer); +		s->session->peer=NULL; +		} +	s->session->verify_result = s->verify_result; + +	x=NULL; +	ret=1; + +	if (0) +		{ +f_err: +		ssl3_send_alert(s,SSL3_AL_FATAL,al); +		} +err: +	EVP_PKEY_free(pkey); +	X509_free(x); +	sk_X509_pop_free(sk,X509_free); +	return(ret); +	} + +int ssl3_get_key_exchange(SSL *s) +	{ +#ifndef OPENSSL_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_k,alg_a; +	EVP_PKEY *pkey=NULL; +#ifndef OPENSSL_NO_RSA +	RSA *rsa=NULL; +#endif +#ifndef OPENSSL_NO_DH +	DH *dh=NULL; +#endif +#ifndef OPENSSL_NO_ECDH +	EC_KEY *ecdh = NULL; +	BN_CTX *bn_ctx = NULL; +	EC_POINT *srvr_ecpoint = NULL; +	int curve_nid = 0; +	int encoded_pt_len = 0; +#endif + +	/* use same message size as in ssl3_get_certificate_request() +	 * as ServerKeyExchange message may be skipped */ +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_KEY_EXCH_A, +		SSL3_ST_CR_KEY_EXCH_B, +		-1, +		s->max_cert_list, +		&ok); +	if (!ok) return((int)n); + +	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) +		{ +#ifndef OPENSSL_NO_PSK +		/* In plain PSK ciphersuite, ServerKeyExchange can be +		   omitted if no identity hint is sent. Set +		   session->sess_cert anyway to avoid problems +		   later.*/ +		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) +			{ +			s->session->sess_cert=ssl_sess_cert_new(); +			if (s->ctx->psk_identity_hint) +				OPENSSL_free(s->ctx->psk_identity_hint); +			s->ctx->psk_identity_hint = NULL; +			} +#endif +		s->s3->tmp.reuse_message=1; +		return(1); +		} + +	param=p=(unsigned char *)s->init_msg; +	if (s->session->sess_cert != NULL) +		{ +#ifndef OPENSSL_NO_RSA +		if (s->session->sess_cert->peer_rsa_tmp != NULL) +			{ +			RSA_free(s->session->sess_cert->peer_rsa_tmp); +			s->session->sess_cert->peer_rsa_tmp=NULL; +			} +#endif +#ifndef OPENSSL_NO_DH +		if (s->session->sess_cert->peer_dh_tmp) +			{ +			DH_free(s->session->sess_cert->peer_dh_tmp); +			s->session->sess_cert->peer_dh_tmp=NULL; +			} +#endif +#ifndef OPENSSL_NO_ECDH +		if (s->session->sess_cert->peer_ecdh_tmp) +			{ +			EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); +			s->session->sess_cert->peer_ecdh_tmp=NULL; +			} +#endif +		} +	else +		{ +		s->session->sess_cert=ssl_sess_cert_new(); +		} + +	param_len=0; +	alg_k=s->s3->tmp.new_cipher->algorithm_mkey; +	alg_a=s->s3->tmp.new_cipher->algorithm_auth; +	EVP_MD_CTX_init(&md_ctx); + +#ifndef OPENSSL_NO_PSK +	if (alg_k & SSL_kPSK) +		{ +		char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1]; + +		al=SSL_AD_HANDSHAKE_FAILURE; +		n2s(p,i); +		param_len=i+2; +		/* Store PSK identity hint for later use, hint is used +		 * in ssl3_send_client_key_exchange.  Assume that the +		 * maximum length of a PSK identity hint can be as +		 * long as the maximum length of a PSK identity. */ +		if (i > PSK_MAX_IDENTITY_LEN) +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, +				SSL_R_DATA_LENGTH_TOO_LONG); +			goto f_err; +			} +		if (param_len > n) +			{ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, +				SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); +			goto f_err; +			} +		/* If received PSK identity hint contains NULL +		 * characters, the hint is truncated from the first +		 * NULL. p may not be ending with NULL, so create a +		 * NULL-terminated string. */ +		memcpy(tmp_id_hint, p, i); +		memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i); +		if (s->ctx->psk_identity_hint != NULL) +			OPENSSL_free(s->ctx->psk_identity_hint); +		s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint); +		if (s->ctx->psk_identity_hint == NULL) +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); +			goto f_err; +			}	    + +		p+=i; +		n-=param_len; +		} +	else +#endif /* !OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_RSA +	if (alg_k & 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=SSL_AD_DECODE_ERROR; +			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=SSL_AD_DECODE_ERROR; +			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; + +		/* this should be because we are using an export cipher */ +		if (alg_a & SSL_aRSA) +			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); +		else +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); +			goto err; +			} +		s->session->sess_cert->peer_rsa_tmp=rsa; +		rsa=NULL; +		} +#else /* OPENSSL_NO_RSA */ +	if (0) +		; +#endif +#ifndef OPENSSL_NO_DH +	else if (alg_k & 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=SSL_AD_DECODE_ERROR; +			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=SSL_AD_DECODE_ERROR; +			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=SSL_AD_DECODE_ERROR; +			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 OPENSSL_NO_RSA +		if (alg_a & SSL_aRSA) +			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); +#else +		if (0) +			; +#endif +#ifndef OPENSSL_NO_DSA +		else if (alg_a & SSL_aDSS) +			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509); +#endif +		/* else anonymous DH, so no certificate or pkey. */ + +		s->session->sess_cert->peer_dh_tmp=dh; +		dh=NULL; +		} +	else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd)) +		{ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); +		goto f_err; +		} +#endif /* !OPENSSL_NO_DH */ + +#ifndef OPENSSL_NO_ECDH +	else if (alg_k & SSL_kEECDH) +		{ +		EC_GROUP *ngroup; +		const EC_GROUP *group; + +		if ((ecdh=EC_KEY_new()) == NULL) +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +			goto err; +			} + +		/* Extract elliptic curve parameters and the +		 * server's ephemeral ECDH public key. +		 * Keep accumulating lengths of various components in +		 * param_len and make sure it never exceeds n. +		 */ + +		/* XXX: For now we only support named (not generic) curves +		 * and the ECParameters in this case is just three bytes. +		 */ +		param_len=3; +		if ((param_len > n) || +		    (*p != NAMED_CURVE_TYPE) ||  +		    ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0))  +			{ +			al=SSL_AD_INTERNAL_ERROR; +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); +			goto f_err; +			} + +		ngroup = EC_GROUP_new_by_curve_name(curve_nid); +		if (ngroup == NULL) +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB); +			goto err; +			} +		if (EC_KEY_set_group(ecdh, ngroup) == 0) +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_EC_LIB); +			goto err; +			} +		EC_GROUP_free(ngroup); + +		group = EC_KEY_get0_group(ecdh); + +		if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && +		    (EC_GROUP_get_degree(group) > 163)) +			{ +			al=SSL_AD_EXPORT_RESTRICTION; +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); +			goto f_err; +			} + +		p+=3; + +		/* Next, get the encoded ECPoint */ +		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) || +		    ((bn_ctx = BN_CTX_new()) == NULL)) +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +			goto err; +			} + +		encoded_pt_len = *p;  /* length of encoded point */ +		p+=1; +		param_len += (1 + encoded_pt_len); +		if ((param_len > n) || +		    (EC_POINT_oct2point(group, srvr_ecpoint,  +			p, encoded_pt_len, bn_ctx) == 0)) +			{ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT); +			goto f_err; +			} + +		n-=param_len; +		p+=encoded_pt_len; + +		/* The ECC/TLS specification does not mention +		 * the use of DSA to sign ECParameters in the server +		 * key exchange message. We do support RSA and ECDSA. +		 */ +		if (0) ; +#ifndef OPENSSL_NO_RSA +		else if (alg_a & SSL_aRSA) +			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); +#endif +#ifndef OPENSSL_NO_ECDSA +		else if (alg_a & SSL_aECDSA) +			pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); +#endif +		/* else anonymous ECDH, so no certificate or pkey. */ +		EC_KEY_set_public_key(ecdh, srvr_ecpoint); +		s->session->sess_cert->peer_ecdh_tmp=ecdh; +		ecdh=NULL; +		BN_CTX_free(bn_ctx); +		bn_ctx = NULL; +		EC_POINT_free(srvr_ecpoint); +		srvr_ecpoint = NULL; +		} +	else if (alg_k) +		{ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); +		goto f_err; +		} +#endif /* !OPENSSL_NO_ECDH */ + + +	/* 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=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH); +			goto f_err; +			} + +#ifndef OPENSSL_NO_RSA +		if (pkey->type == EVP_PKEY_RSA) +			{ +			int num; + +			j=0; +			q=md_buf; +			for (num=2; num > 0; num--) +				{ +				EVP_DigestInit_ex(&md_ctx,(num == 2) +					?s->ctx->md5:s->ctx->sha1, NULL); +				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_ex(&md_ctx,q,(unsigned int *)&i); +				q+=i; +				j+=i; +				} +			i=RSA_verify(NID_md5_sha1, md_buf, j, p, n, +								pkey->pkey.rsa); +			if (i < 0) +				{ +				al=SSL_AD_DECRYPT_ERROR; +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); +				goto f_err; +				} +			if (i == 0) +				{ +				/* bad signature */ +				al=SSL_AD_DECRYPT_ERROR; +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE); +				goto f_err; +				} +			} +		else +#endif +#ifndef OPENSSL_NO_DSA +			if (pkey->type == EVP_PKEY_DSA) +			{ +			/* lets do DSS */ +			EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL); +			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) <= 0) +				{ +				/* bad signature */ +				al=SSL_AD_DECRYPT_ERROR; +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE); +				goto f_err; +				} +			} +		else +#endif +#ifndef OPENSSL_NO_ECDSA +			if (pkey->type == EVP_PKEY_EC) +			{ +			/* let's do ECDSA */ +			EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL); +			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) <= 0) +				{ +				/* bad signature */ +				al=SSL_AD_DECRYPT_ERROR; +				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE); +				goto f_err; +				} +			} +		else +#endif +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); +			goto err; +			} +		} +	else +		{ +		if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK)) +			/* aNULL or kPSK do not need public keys */ +			{ +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); +			goto err; +			} +		/* still data left over */ +		if (n != 0) +			{ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE); +			goto f_err; +			} +		} +	EVP_PKEY_free(pkey); +	EVP_MD_CTX_cleanup(&md_ctx); +	return(1); +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	EVP_PKEY_free(pkey); +#ifndef OPENSSL_NO_RSA +	if (rsa != NULL) +		RSA_free(rsa); +#endif +#ifndef OPENSSL_NO_DH +	if (dh != NULL) +		DH_free(dh); +#endif +#ifndef OPENSSL_NO_ECDH +	BN_CTX_free(bn_ctx); +	EC_POINT_free(srvr_ecpoint); +	if (ecdh != NULL) +		EC_KEY_free(ecdh); +#endif +	EVP_MD_CTX_cleanup(&md_ctx); +	return(-1); +	} + +int ssl3_get_certificate_request(SSL *s) +	{ +	int ok,ret=0; +	unsigned long n,nc,l; +	unsigned int llen,ctype_num,i; +	X509_NAME *xn=NULL; +	const unsigned char *p,*q; +	unsigned char *d; +	STACK_OF(X509_NAME) *ca_sk=NULL; + +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_CERT_REQ_A, +		SSL3_ST_CR_CERT_REQ_B, +		-1, +		s->max_cert_list, +		&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,SSL_AD_UNEXPECTED_MESSAGE); +		SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_WRONG_MESSAGE_TYPE); +		goto err; +		} + +	/* TLS does not like anon-DH with client cert */ +	if (s->version > SSL3_VERSION) +		{ +		if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) +			{ +			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); +			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER); +			goto err; +			} +		} + +	p=d=(unsigned char *)s->init_msg; + +	if ((ca_sk=sk_X509_NAME_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 0 +{ +FILE *out; +out=fopen("/tmp/vsign.der","w"); +fwrite(p,1,llen,out); +fclose(out); +} +#endif + +	if ((llen+ctype_num+2+1) != n) +		{ +		ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR); +		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->options & SSL_OP_NETSCAPE_CA_DN_BUG)) +				goto cont; /* netscape bugs */ +			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR); +			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 tolerance is on, ignore errors */ +			if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG) +				goto cont; +			else +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR); +				SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_ASN1_LIB); +				goto err; +				} +			} + +		if (q != (p+l)) +			{ +			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR); +			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH); +			goto err; +			} +		if (!sk_X509_NAME_push(ca_sk,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 certificate to return.... */ +	s->s3->tmp.cert_req=1; +	s->s3->tmp.ctype_num=ctype_num; +	if (s->s3->tmp.ca_names != NULL) +		sk_X509_NAME_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_X509_NAME_pop_free(ca_sk,X509_NAME_free); +	return(ret); +	} + +static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b) +	{ +	return(X509_NAME_cmp(*a,*b)); +	} +#ifndef OPENSSL_NO_TLSEXT +int ssl3_get_new_session_ticket(SSL *s) +	{ +	int ok,al,ret=0, ticklen; +	long n; +	const unsigned char *p; +	unsigned char *d; + +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_SESSION_TICKET_A, +		SSL3_ST_CR_SESSION_TICKET_B, +		-1, +		16384, +		&ok); + +	if (!ok) +		return((int)n); + +	if (s->s3->tmp.message_type == SSL3_MT_FINISHED) +		{ +		s->s3->tmp.reuse_message=1; +		return(1); +		} +	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET) +		{ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE); +		goto f_err; +		} +	if (n < 6) +		{ +		/* need at least ticket_lifetime_hint + ticket length */ +		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH); +		goto f_err; +		} + +	p=d=(unsigned char *)s->init_msg; +	n2l(p, s->session->tlsext_tick_lifetime_hint); +	n2s(p, ticklen); +	/* ticket_lifetime_hint + ticket_length + ticket */ +	if (ticklen + 6 != n) +		{ +		al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH); +		goto f_err; +		} +	if (s->session->tlsext_tick) +		{ +		OPENSSL_free(s->session->tlsext_tick); +		s->session->tlsext_ticklen = 0; +		} +	s->session->tlsext_tick = OPENSSL_malloc(ticklen); +	if (!s->session->tlsext_tick) +		{ +		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE); +		goto err; +		} +	memcpy(s->session->tlsext_tick, p, ticklen); +	s->session->tlsext_ticklen = ticklen; +	/* There are two ways to detect a resumed ticket sesion. +	 * One is to set an appropriate session ID and then the server +	 * must return a match in ServerHello. This allows the normal +	 * client session ID matching to work and we know much  +	 * earlier that the ticket has been accepted. +	 *  +	 * The other way is to set zero length session ID when the +	 * ticket is presented and rely on the handshake to determine +	 * session resumption. +	 * +	 * We choose the former approach because this fits in with +	 * assumptions elsewhere in OpenSSL. The session ID is set +	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the +	 * ticket. +	 */  +	EVP_Digest(p, ticklen, +			s->session->session_id, &s->session->session_id_length, +#ifndef OPENSSL_NO_SHA256 +							EVP_sha256(), NULL); +#else +							EVP_sha1(), NULL); +#endif +	ret=1; +	return(ret); +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	return(-1); +	} + +int ssl3_get_cert_status(SSL *s) +	{ +	int ok, al; +	unsigned long resplen,n; +	const unsigned char *p; + +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_CERT_STATUS_A, +		SSL3_ST_CR_CERT_STATUS_B, +		SSL3_MT_CERTIFICATE_STATUS, +		16384, +		&ok); + +	if (!ok) return((int)n); +	if (n < 4) +		{ +		/* need at least status type + length */ +		al = SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH); +		goto f_err; +		} +	p = (unsigned char *)s->init_msg; +	if (*p++ != TLSEXT_STATUSTYPE_ocsp) +		{ +		al = SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE); +		goto f_err; +		} +	n2l3(p, resplen); +	if (resplen + 4 != n) +		{ +		al = SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH); +		goto f_err; +		} +	if (s->tlsext_ocsp_resp) +		OPENSSL_free(s->tlsext_ocsp_resp); +	s->tlsext_ocsp_resp = BUF_memdup(p, resplen); +	if (!s->tlsext_ocsp_resp) +		{ +		al = SSL_AD_INTERNAL_ERROR; +		SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE); +		goto f_err; +		} +	s->tlsext_ocsp_resplen = resplen; +	if (s->ctx->tlsext_status_cb) +		{ +		int ret; +		ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); +		if (ret == 0) +			{ +			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE; +			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE); +			goto f_err; +			} +		if (ret < 0) +			{ +			al = SSL_AD_INTERNAL_ERROR; +			SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE); +			goto f_err; +			} +		} +	return 1; +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +	return(-1); +	} +#endif + +int ssl3_get_server_done(SSL *s) +	{ +	int ok,ret=0; +	long n; + +	n=s->method->ssl_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,SSL_AD_DECODE_ERROR); +		SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH); +		return -1; +		} +	ret=1; +	return(ret); +	} + + +int ssl3_send_client_key_exchange(SSL *s) +	{ +	unsigned char *p,*d; +	int n; +	unsigned long alg_k; +#ifndef OPENSSL_NO_RSA +	unsigned char *q; +	EVP_PKEY *pkey=NULL; +#endif +#ifndef OPENSSL_NO_KRB5 +	KSSL_ERR kssl_err; +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_ECDH +	EC_KEY *clnt_ecdh = NULL; +	const EC_POINT *srvr_ecpoint = NULL; +	EVP_PKEY *srvr_pub_pkey = NULL; +	unsigned char *encodedPoint = NULL; +	int encoded_pt_len = 0; +	BN_CTX * bn_ctx = NULL; +#endif + +	if (s->state == SSL3_ST_CW_KEY_EXCH_A) +		{ +		d=(unsigned char *)s->init_buf->data; +		p= &(d[4]); + +		alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + +		/* Fool emacs indentation */ +		if (0) {} +#ifndef OPENSSL_NO_RSA +		else if (alg_k & SSL_kRSA) +			{ +			RSA *rsa; +			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + +			if (s->session->sess_cert->peer_rsa_tmp != NULL) +				rsa=s->session->sess_cert->peer_rsa_tmp; +			else +				{ +				pkey=X509_get_pubkey(s->session->sess_cert->peer_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,ERR_R_INTERNAL_ERROR); +					goto err; +					} +				rsa=pkey->pkey.rsa; +				EVP_PKEY_free(pkey); +				} +				 +			tmp_buf[0]=s->client_version>>8; +			tmp_buf[1]=s->client_version&0xff; +			if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0) +					goto err; + +			s->session->master_key_length=sizeof tmp_buf; + +			q=p; +			/* Fix buf for TLS and beyond */ +			if (s->version > SSL3_VERSION) +				p+=2; +			n=RSA_public_encrypt(sizeof tmp_buf, +				tmp_buf,p,rsa,RSA_PKCS1_PADDING); +#ifdef PKCS1_CHECK +			if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++; +			if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70; +#endif +			if (n <= 0) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT); +				goto err; +				} + +			/* Fix buf for TLS and beyond */ +			if (s->version > SSL3_VERSION) +				{ +				s2n(n,q); +				n+=2; +				} + +			s->session->master_key_length= +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, +					tmp_buf,sizeof tmp_buf); +			OPENSSL_cleanse(tmp_buf,sizeof tmp_buf); +			} +#endif +#ifndef OPENSSL_NO_KRB5 +		else if (alg_k & SSL_kKRB5) +			{ +			krb5_error_code	krb5rc; +			KSSL_CTX	*kssl_ctx = s->kssl_ctx; +			/*  krb5_data	krb5_ap_req;  */ +			krb5_data	*enc_ticket; +			krb5_data	authenticator, *authp = NULL; +			EVP_CIPHER_CTX	ciph_ctx; +			const EVP_CIPHER *enc = NULL; +			unsigned char	iv[EVP_MAX_IV_LENGTH]; +			unsigned char	tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; +			unsigned char	epms[SSL_MAX_MASTER_KEY_LENGTH  +						+ EVP_MAX_IV_LENGTH]; +			int 		padl, outl = sizeof(epms); + +			EVP_CIPHER_CTX_init(&ciph_ctx); + +#ifdef KSSL_DEBUG +			printf("ssl3_send_client_key_exchange(%lx & %lx)\n", +				alg_k, SSL_kKRB5); +#endif	/* KSSL_DEBUG */ + +			authp = NULL; +#ifdef KRB5SENDAUTH +			if (KRB5SENDAUTH)  authp = &authenticator; +#endif	/* KRB5SENDAUTH */ + +			krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, +				&kssl_err); +			enc = kssl_map_enc(kssl_ctx->enctype); +			if (enc == NULL) +			    goto err; +#ifdef KSSL_DEBUG +			{ +			printf("kssl_cget_tkt rtn %d\n", krb5rc); +			if (krb5rc && kssl_err.text) +			  printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); +			} +#endif	/* KSSL_DEBUG */ + +			if (krb5rc) +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL, +						SSL_AD_HANDSHAKE_FAILURE); +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +						kssl_err.reason); +				goto err; +				} + +			/*  20010406 VRS - Earlier versions used KRB5 AP_REQ +			**  in place of RFC 2712 KerberosWrapper, as in: +			** +			**  Send ticket (copy to *p, set n = length) +			**  n = krb5_ap_req.length; +			**  memcpy(p, krb5_ap_req.data, krb5_ap_req.length); +			**  if (krb5_ap_req.data)   +			**    kssl_krb5_free_data_contents(NULL,&krb5_ap_req); +			** +			**  Now using real RFC 2712 KerberosWrapper +			**  (Thanks to Simon Wilkinson <sxw@sxw.org.uk>) +			**  Note: 2712 "opaque" types are here replaced +			**  with a 2-byte length followed by the value. +			**  Example: +			**  KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms +			**  Where "xx xx" = length bytes.  Shown here with +			**  optional authenticator omitted. +			*/ + +			/*  KerberosWrapper.Ticket		*/ +			s2n(enc_ticket->length,p); +			memcpy(p, enc_ticket->data, enc_ticket->length); +			p+= enc_ticket->length; +			n = enc_ticket->length + 2; + +			/*  KerberosWrapper.Authenticator	*/ +			if (authp  &&  authp->length)   +				{ +				s2n(authp->length,p); +				memcpy(p, authp->data, authp->length); +				p+= authp->length; +				n+= authp->length + 2; +				 +				free(authp->data); +				authp->data = NULL; +				authp->length = 0; +				} +			else +				{ +				s2n(0,p);/*  null authenticator length	*/ +				n+=2; +				} +  +			    tmp_buf[0]=s->client_version>>8; +			    tmp_buf[1]=s->client_version&0xff; +			    if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0) +				goto err; + +			/*  20010420 VRS.  Tried it this way; failed. +			**	EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); +			**	EVP_CIPHER_CTX_set_key_length(&ciph_ctx, +			**				kssl_ctx->length); +			**	EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); +			*/ + +			memset(iv, 0, sizeof iv);  /* per RFC 1510 */ +			EVP_EncryptInit_ex(&ciph_ctx,enc, NULL, +				kssl_ctx->key,iv); +			EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf, +				sizeof tmp_buf); +			EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); +			outl += padl; +			if (outl > (int)sizeof epms) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); +				goto err; +				} +			EVP_CIPHER_CTX_cleanup(&ciph_ctx); + +			/*  KerberosWrapper.EncryptedPreMasterSecret	*/ +			s2n(outl,p); +			memcpy(p, epms, outl); +			p+=outl; +			n+=outl + 2; + +			s->session->master_key_length= +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, +					tmp_buf, sizeof tmp_buf); + +			OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); +			OPENSSL_cleanse(epms, outl); +			} +#endif +#ifndef OPENSSL_NO_DH +		else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) +			{ +			DH *dh_srvr,*dh_clnt; + +			if (s->session->sess_cert == NULL)  +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); +				goto err; +				} + +			if (s->session->sess_cert->peer_dh_tmp != NULL) +				dh_srvr=s->session->sess_cert->peer_dh_tmp; +			else +				{ +				/* we get them from the cert */ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_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); +				DH_free(dh_clnt); +				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); +				DH_free(dh_clnt); +				goto err; +				} + +			/* generate master key from the result */ +			s->session->master_key_length= +				s->method->ssl3_enc->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*/ +			} +#endif + +#ifndef OPENSSL_NO_ECDH  +		else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) +			{ +			const EC_GROUP *srvr_group = NULL; +			EC_KEY *tkey; +			int ecdh_clnt_cert = 0; +			int field_size = 0; + +			/* Did we send out the client's +			 * ECDH share for use in premaster +			 * computation as part of client certificate? +			 * If so, set ecdh_clnt_cert to 1. +			 */ +			if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL))  +				{ +				/* XXX: For now, we do not support client +				 * authentication using ECDH certificates. +				 * To add such support, one needs to add +				 * code that checks for appropriate  +				 * conditions and sets ecdh_clnt_cert to 1. +				 * For example, the cert have an ECC +				 * key on the same curve as the server's +				 * and the key should be authorized for +				 * key agreement. +				 * +				 * One also needs to add code in ssl3_connect +				 * to skip sending the certificate verify +				 * message. +				 * +				 * if ((s->cert->key->privatekey != NULL) && +				 *     (s->cert->key->privatekey->type == +				 *      EVP_PKEY_EC) && ...) +				 * ecdh_clnt_cert = 1; +				 */ +				} + +			if (s->session->sess_cert->peer_ecdh_tmp != NULL) +				{ +				tkey = s->session->sess_cert->peer_ecdh_tmp; +				} +			else +				{ +				/* Get the Server Public Key from Cert */ +				srvr_pub_pkey = X509_get_pubkey(s->session-> \ +				    sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); +				if ((srvr_pub_pkey == NULL) || +				    (srvr_pub_pkey->type != EVP_PKEY_EC) || +				    (srvr_pub_pkey->pkey.ec == NULL)) +					{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					    ERR_R_INTERNAL_ERROR); +					goto err; +					} + +				tkey = srvr_pub_pkey->pkey.ec; +				} + +			srvr_group   = EC_KEY_get0_group(tkey); +			srvr_ecpoint = EC_KEY_get0_public_key(tkey); + +			if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +				    ERR_R_INTERNAL_ERROR); +				goto err; +				} + +			if ((clnt_ecdh=EC_KEY_new()) == NULL)  +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +				goto err; +				} + +			if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); +				goto err; +				} +			if (ecdh_clnt_cert)  +				{  +				/* Reuse key info from our certificate +				 * We only need our private key to perform +				 * the ECDH computation. +				 */ +				const BIGNUM *priv_key; +				tkey = s->cert->key->privatekey->pkey.ec; +				priv_key = EC_KEY_get0_private_key(tkey); +				if (priv_key == NULL) +					{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +					goto err; +					} +				if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) +					{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); +					goto err; +					} +				} +			else  +				{ +				/* Generate a new ECDH key pair */ +				if (!(EC_KEY_generate_key(clnt_ecdh))) +					{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); +					goto err; +					} +				} + +			/* use the 'p' output buffer for the ECDH key, but +			 * make sure to clear it out afterwards +			 */ + +			field_size = EC_GROUP_get_degree(srvr_group); +			if (field_size <= 0) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,  +				       ERR_R_ECDH_LIB); +				goto err; +				} +			n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); +			if (n <= 0) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,  +				       ERR_R_ECDH_LIB); +				goto err; +				} + +			/* generate master key from the result */ +			s->session->master_key_length = s->method->ssl3_enc \ +			    -> generate_master_secret(s,  +				s->session->master_key, +				p, n); + +			memset(p, 0, n); /* clean up */ + +			if (ecdh_clnt_cert)  +				{ +				/* Send empty client key exch message */ +				n = 0; +				} +			else  +				{ +				/* First check the size of encoding and +				 * allocate memory accordingly. +				 */ +				encoded_pt_len =  +				    EC_POINT_point2oct(srvr_group,  +					EC_KEY_get0_public_key(clnt_ecdh),  +					POINT_CONVERSION_UNCOMPRESSED,  +					NULL, 0, NULL); + +				encodedPoint = (unsigned char *)  +				    OPENSSL_malloc(encoded_pt_len *  +					sizeof(unsigned char));  +				bn_ctx = BN_CTX_new(); +				if ((encodedPoint == NULL) ||  +				    (bn_ctx == NULL))  +					{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +					goto err; +					} + +				/* Encode the public key */ +				n = EC_POINT_point2oct(srvr_group,  +				    EC_KEY_get0_public_key(clnt_ecdh),  +				    POINT_CONVERSION_UNCOMPRESSED,  +				    encodedPoint, encoded_pt_len, bn_ctx); + +				*p = n; /* length of encoded point */ +				/* Encoded point will be copied here */ +				p += 1;  +				/* copy the point */ +				memcpy((unsigned char *)p, encodedPoint, n); +				/* increment n to account for length field */ +				n += 1;  +				} + +			/* Free allocated memory */ +			BN_CTX_free(bn_ctx); +			if (encodedPoint != NULL) OPENSSL_free(encodedPoint); +			if (clnt_ecdh != NULL)  +				 EC_KEY_free(clnt_ecdh); +			EVP_PKEY_free(srvr_pub_pkey); +			} +#endif /* !OPENSSL_NO_ECDH */ +		else if (alg_k & SSL_kGOST)  +			{ +			/* GOST key exchange message creation */ +			EVP_PKEY_CTX *pkey_ctx; +			X509 *peer_cert;  +			size_t msglen; +			unsigned int md_len; +			int keytype; +			unsigned char premaster_secret[32],shared_ukm[32], tmp[256]; +			EVP_MD_CTX *ukm_hash; +			EVP_PKEY *pub_key; + +			/* Get server sertificate PKEY and create ctx from it */ +			peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509; +			if (!peer_cert)  +				peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509; +			if (!peer_cert)		{ +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); +					goto err; +				}	 +				 +			pkey_ctx=EVP_PKEY_CTX_new(pub_key=X509_get_pubkey(peer_cert),NULL); +			/* If we have send a certificate, and certificate key + +			 * parameters match those of server certificate, use +			 * certificate key for key exchange +			 */ + +			 /* Otherwise, generate ephemeral key pair */ +					 +			EVP_PKEY_encrypt_init(pkey_ctx); +			  /* Generate session key */	 +		    RAND_bytes(premaster_secret,32); +			/* If we have client certificate, use its secret as peer key */ +			if (s->s3->tmp.cert_req && s->cert->key->privatekey) { +				if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) { +					/* If there was an error - just ignore it. Ephemeral key +					* would be used +					*/ +					ERR_clear_error(); +				} +			}			 +			/* Compute shared IV and store it in algorithm-specific +			 * context data */ +			ukm_hash = EVP_MD_CTX_create(); +			EVP_DigestInit(ukm_hash,EVP_get_digestbynid(NID_id_GostR3411_94)); +			EVP_DigestUpdate(ukm_hash,s->s3->client_random,SSL3_RANDOM_SIZE); +			EVP_DigestUpdate(ukm_hash,s->s3->server_random,SSL3_RANDOM_SIZE); +			EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len); +			EVP_MD_CTX_destroy(ukm_hash); +			if (EVP_PKEY_CTX_ctrl(pkey_ctx,-1,EVP_PKEY_OP_ENCRYPT,EVP_PKEY_CTRL_SET_IV, +				8,shared_ukm)<0) { +					SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +						SSL_R_LIBRARY_BUG); +					goto err; +				}	 +			/* Make GOST keytransport blob message */ +			/*Encapsulate it into sequence */ +			*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; +			msglen=255; +			if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) { +			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_LIBRARY_BUG); +				goto err; +			} +			if (msglen >= 0x80) +				{ +				*(p++)=0x81; +				*(p++)= msglen & 0xff; +				n=msglen+3; +				} +			else +				{ +				*(p++)= msglen & 0xff; +				n=msglen+2; +				} +			memcpy(p, tmp, msglen); +			/* Check if pubkey from client certificate was used */ +			if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) +				{ +				/* Set flag "skip certificate verify" */ +				s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; +				} +			EVP_PKEY_CTX_free(pkey_ctx); +			s->session->master_key_length= +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key,premaster_secret,32); +			EVP_PKEY_free(pub_key); + +			} +#ifndef OPENSSL_NO_PSK +		else if (alg_k & SSL_kPSK) +			{ +			char identity[PSK_MAX_IDENTITY_LEN]; +			unsigned char *t = NULL; +			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; +			unsigned int pre_ms_len = 0, psk_len = 0; +			int psk_err = 1; + +			n = 0; +			if (s->psk_client_callback == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_PSK_NO_CLIENT_CB); +				goto err; +				} + +			psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, +				identity, PSK_MAX_IDENTITY_LEN, +				psk_or_pre_ms, sizeof(psk_or_pre_ms)); +			if (psk_len > PSK_MAX_PSK_LEN) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_INTERNAL_ERROR); +				goto psk_err; +				} +			else if (psk_len == 0) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					SSL_R_PSK_IDENTITY_NOT_FOUND); +				goto psk_err; +				} + +			/* create PSK pre_master_secret */ +			pre_ms_len = 2+psk_len+2+psk_len; +			t = psk_or_pre_ms; +			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); +			s2n(psk_len, t); +			memset(t, 0, psk_len); +			t+=psk_len; +			s2n(psk_len, t); + +			if (s->session->psk_identity_hint != NULL) +				OPENSSL_free(s->session->psk_identity_hint); +			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); +			if (s->ctx->psk_identity_hint != NULL && +				s->session->psk_identity_hint == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} + +			if (s->session->psk_identity != NULL) +				OPENSSL_free(s->session->psk_identity); +			s->session->psk_identity = BUF_strdup(identity); +			if (s->session->psk_identity == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} + +			s->session->master_key_length = +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, +					psk_or_pre_ms, pre_ms_len);  +			n = strlen(identity); +			s2n(n, p); +			memcpy(p, identity, n); +			n+=2; +			psk_err = 0; +		psk_err: +			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); +			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); +			if (psk_err != 0) +				{ +				ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); +				goto err; +				} +			} +#endif +		else +			{ +			ssl3_send_alert(s, SSL3_AL_FATAL, +			    SSL_AD_HANDSHAKE_FAILURE); +			SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, +			    ERR_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: +#ifndef OPENSSL_NO_ECDH +	BN_CTX_free(bn_ctx); +	if (encodedPoint != NULL) OPENSSL_free(encodedPoint); +	if (clnt_ecdh != NULL)  +		EC_KEY_free(clnt_ecdh); +	EVP_PKEY_free(srvr_pub_pkey); +#endif +	return(-1); +	} + +int ssl3_send_client_verify(SSL *s) +	{ +	unsigned char *p,*d; +	unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; +	EVP_PKEY *pkey; +	EVP_PKEY_CTX *pctx=NULL; +#ifndef OPENSSL_NO_RSA +	unsigned u=0; +#endif +	unsigned long n; +	int j; + +	if (s->state == SSL3_ST_CW_CERT_VRFY_A) +		{ +		d=(unsigned char *)s->init_buf->data; +		p= &(d[4]); +		pkey=s->cert->key->privatekey; +/* Create context from key and test if sha1 is allowed as digest */ +		pctx = EVP_PKEY_CTX_new(pkey,NULL); +		EVP_PKEY_sign_init(pctx); +		if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0) +			{ +			s->method->ssl3_enc->cert_verify_mac(s, +						NID_sha1, +						&(data[MD5_DIGEST_LENGTH])); +			} +		else +			{ +			ERR_clear_error(); +			} +#ifndef OPENSSL_NO_RSA +		if (pkey->type == EVP_PKEY_RSA) +			{ +			s->method->ssl3_enc->cert_verify_mac(s, +				NID_md5, +			 	&(data[0])); +			if (RSA_sign(NID_md5_sha1, data, +					 MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, +					&(p[2]), &u, pkey->pkey.rsa) <= 0 ) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB); +				goto err; +				} +			s2n(u,p); +			n=u+2; +			} +		else +#endif +#ifndef OPENSSL_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 +#ifndef OPENSSL_NO_ECDSA +			if (pkey->type == EVP_PKEY_EC) +			{ +			if (!ECDSA_sign(pkey->save_type, +				&(data[MD5_DIGEST_LENGTH]), +				SHA_DIGEST_LENGTH,&(p[2]), +				(unsigned int *)&j,pkey->pkey.ec)) +				{ +				SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, +				    ERR_R_ECDSA_LIB); +				goto err; +				} +			s2n(j,p); +			n=j+2; +			} +		else +#endif +		if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)  +		{ +		unsigned char signbuf[64]; +		int i; +		size_t sigsize=64; +		s->method->ssl3_enc->cert_verify_mac(s, +			NID_id_GostR3411_94, +			data); +		if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) { +			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, +			ERR_R_INTERNAL_ERROR); +			goto err; +		} +		for (i=63,j=0; i>=0; j++, i--) { +			p[2+j]=signbuf[i]; +		}	 +		s2n(j,p); +		n=j+2; +		} +		else +		{ +			SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); +			goto err; +		} +		*(d++)=SSL3_MT_CERTIFICATE_VERIFY; +		l2n3(n,d); + +		s->state=SSL3_ST_CW_CERT_VRFY_B; +		s->init_num=(int)n+4; +		s->init_off=0; +		} +	EVP_PKEY_CTX_free(pctx); +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +err: +	EVP_PKEY_CTX_free(pctx); +	return(-1); +	} + +int ssl3_send_client_certificate(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; +		i = ssl_do_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) +			{ +			if (s->version == SSL3_VERSION) +				{ +				s->s3->tmp.cert_req=0; +				ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE); +				return(1); +				} +			else +				{ +				s->s3->tmp.cert_req=2; +				} +			} + +		/* 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->s3->tmp.cert_req == 2)?NULL: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)) + +int ssl3_check_cert_and_algorithm(SSL *s) +	{ +	int i,idx; +	long alg_k,alg_a; +	EVP_PKEY *pkey=NULL; +	SESS_CERT *sc; +#ifndef OPENSSL_NO_RSA +	RSA *rsa; +#endif +#ifndef OPENSSL_NO_DH +	DH *dh; +#endif + +	alg_k=s->s3->tmp.new_cipher->algorithm_mkey; +	alg_a=s->s3->tmp.new_cipher->algorithm_auth; + +	/* we don't have a certificate */ +	if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK)) +		return(1); + +	sc=s->session->sess_cert; +	if (sc == NULL) +		{ +		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR); +		goto err; +		} + +#ifndef OPENSSL_NO_RSA +	rsa=s->session->sess_cert->peer_rsa_tmp; +#endif +#ifndef OPENSSL_NO_DH +	dh=s->session->sess_cert->peer_dh_tmp; +#endif + +	/* This is the passed certificate */ + +	idx=sc->peer_cert_type; +#ifndef OPENSSL_NO_ECDH +	if (idx == SSL_PKEY_ECC) +		{ +		if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, +		    s->s3->tmp.new_cipher) == 0)  +			{ /* check failed */ +			SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT); +			goto f_err; +			} +		else  +			{ +			return 1; +			} +		} +#endif +	pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); +	i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); +	EVP_PKEY_free(pkey); + +	 +	/* Check that we have a certificate if we require one */ +	if ((alg_a & 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 OPENSSL_NO_DSA +	else if ((alg_a & 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 +#ifndef OPENSSL_NO_RSA +	if ((alg_k & 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; +		} +#endif +#ifndef OPENSSL_NO_DH +	if ((alg_k & 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 ((alg_k & 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 OPENSSL_NO_DSA +	else if ((alg_k & 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 (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) +		{ +#ifndef OPENSSL_NO_RSA +		if (alg_k & SSL_kRSA) +			{ +			if (rsa == NULL +			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) +				{ +				SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY); +				goto f_err; +				} +			} +		else +#endif +#ifndef OPENSSL_NO_DH +			if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) +			    { +			    if (dh == NULL +				|| DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) +				{ +				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,SSL_AD_HANDSHAKE_FAILURE); +err: +	return(0); +	} + +/* Check to see if handshake is full or resumed. Usually this is just a + * case of checking to see if a cache hit has occurred. In the case of + * session tickets we have to check the next message to be sure. + */ + +#ifndef OPENSSL_NO_TLSEXT +# ifndef OPENSSL_NO_NEXTPROTONEG +int ssl3_send_next_proto(SSL *s) +	{ +	unsigned int len, padding_len; +	unsigned char *d; + +	if (s->state == SSL3_ST_CW_NEXT_PROTO_A) +		{ +		len = s->next_proto_negotiated_len; +		padding_len = 32 - ((len + 2) % 32); +		d = (unsigned char *)s->init_buf->data; +		d[4] = len; +		memcpy(d + 5, s->next_proto_negotiated, len); +		d[5 + len] = padding_len; +		memset(d + 6 + len, 0, padding_len); +		*(d++)=SSL3_MT_NEXT_PROTO; +		l2n3(2 + len + padding_len, d); +		s->state = SSL3_ST_CW_NEXT_PROTO_B; +		s->init_num = 4 + 2 + len + padding_len; +		s->init_off = 0; +		} + +	return ssl3_do_write(s, SSL3_RT_HANDSHAKE); +	} +# endif + +int ssl3_check_finished(SSL *s) +	{ +	int ok; +	long n; +	/* If we have no ticket it cannot be a resumed session. */ +	if (!s->session->tlsext_tick) +		return 1; +	/* this function is called when we really expect a Certificate +	 * message, so permit appropriate message length */ +	n=s->method->ssl_get_message(s, +		SSL3_ST_CR_CERT_A, +		SSL3_ST_CR_CERT_B, +		-1, +		s->max_cert_list, +		&ok); +	if (!ok) return((int)n); +	s->s3->tmp.reuse_message = 1; +	if ((s->s3->tmp.message_type == SSL3_MT_FINISHED) +		|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET)) +		return 2; + +	return 1; +	} +#endif + +int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) +	{ +	int i = 0; +#ifndef OPENSSL_NO_ENGINE +	if (s->ctx->client_cert_engine) +		{ +		i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s, +						SSL_get_client_CA_list(s), +						px509, ppkey, NULL, NULL, NULL); +		if (i != 0) +			return i; +		} +#endif +	if (s->ctx->client_cert_cb) +		i = s->ctx->client_cert_cb(s,px509,ppkey); +	return i; +	} diff --git a/main/openssl/ssl/s3_enc.c b/main/openssl/ssl/s3_enc.c new file mode 100644 index 00000000..b1459707 --- /dev/null +++ b/main/openssl/ssl/s3_enc.c @@ -0,0 +1,849 @@ +/* ssl/s3_enc.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include "ssl_locl.h" +#include <openssl/evp.h> +#include <openssl/md5.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 }; +static int ssl3_handshake_mac(SSL *s, int md_nid, +	const char *sender, int len, unsigned char *p); +static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) +	{ +	EVP_MD_CTX m5; +	EVP_MD_CTX s1; +	unsigned char buf[16],smd[SHA_DIGEST_LENGTH]; +	unsigned char c='A'; +	unsigned int i,j,k; + +#ifdef CHARSET_EBCDIC +	c = os_toascii[c]; /*'A' in ASCII */ +#endif +	k=0; +	EVP_MD_CTX_init(&m5); +	EVP_MD_CTX_init(&s1); +	for (i=0; (int)i<num; i+=MD5_DIGEST_LENGTH) +		{ +		k++; +		if (k > sizeof buf) +			{ +			/* bug: 'buf' is too small for this ciphersuite */ +			SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR); +			return 0; +			} +		 +		for (j=0; j<k; j++) +			buf[j]=c; +		c++; +		EVP_DigestInit_ex(&s1,EVP_sha1(), NULL); +		EVP_DigestUpdate(&s1,buf,k); +		EVP_DigestUpdate(&s1,s->session->master_key, +			s->session->master_key_length); +		EVP_DigestUpdate(&s1,s->s3->server_random,SSL3_RANDOM_SIZE); +		EVP_DigestUpdate(&s1,s->s3->client_random,SSL3_RANDOM_SIZE); +		EVP_DigestFinal_ex(&s1,smd,NULL); + +		EVP_DigestInit_ex(&m5,EVP_md5(), NULL); +		EVP_DigestUpdate(&m5,s->session->master_key, +			s->session->master_key_length); +		EVP_DigestUpdate(&m5,smd,SHA_DIGEST_LENGTH); +		if ((int)(i+MD5_DIGEST_LENGTH) > num) +			{ +			EVP_DigestFinal_ex(&m5,smd,NULL); +			memcpy(km,smd,(num-i)); +			} +		else +			EVP_DigestFinal_ex(&m5,km,NULL); + +		km+=MD5_DIGEST_LENGTH; +		} +	OPENSSL_cleanse(smd,SHA_DIGEST_LENGTH); +	EVP_MD_CTX_cleanup(&m5); +	EVP_MD_CTX_cleanup(&s1); +	return 1; +	} + +int ssl3_change_cipher_state(SSL *s, int which) +	{ +	unsigned char *p,*mac_secret; +	unsigned char exp_key[EVP_MAX_KEY_LENGTH]; +	unsigned char exp_iv[EVP_MAX_IV_LENGTH]; +	unsigned char *ms,*key,*iv,*er1,*er2; +	EVP_CIPHER_CTX *dd; +	const EVP_CIPHER *c; +#ifndef OPENSSL_NO_COMP +	COMP_METHOD *comp; +#endif +	const EVP_MD *m; +	EVP_MD_CTX md; +	int is_exp,n,i,j,k,cl; +	int reuse_dd = 0; + +	is_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); +	c=s->s3->tmp.new_sym_enc; +	m=s->s3->tmp.new_hash; +	/* m == NULL will lead to a crash later */ +	OPENSSL_assert(m); +#ifndef OPENSSL_NO_COMP +	if (s->s3->tmp.new_compression == NULL) +		comp=NULL; +	else +		comp=s->s3->tmp.new_compression->method; +#endif + +	if (which & SSL3_CC_READ) +		{ +		if (s->enc_read_ctx != NULL) +			reuse_dd = 1; +		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) +			goto err; +		else +			/* make sure it's intialized in case we exit later with an error */ +			EVP_CIPHER_CTX_init(s->enc_read_ctx); +		dd= s->enc_read_ctx; + +		ssl_replace_hash(&s->read_hash,m); +#ifndef OPENSSL_NO_COMP +		/* COMPRESS */ +		if (s->expand != NULL) +			{ +			COMP_CTX_free(s->expand); +			s->expand=NULL; +			} +		if (comp != NULL) +			{ +			s->expand=COMP_CTX_new(comp); +			if (s->expand == NULL) +				{ +				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); +				goto err2; +				} +			if (s->s3->rrec.comp == NULL) +				s->s3->rrec.comp=(unsigned char *) +					OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH); +			if (s->s3->rrec.comp == NULL) +				goto err; +			} +#endif +		memset(&(s->s3->read_sequence[0]),0,8); +		mac_secret= &(s->s3->read_mac_secret[0]); +		} +	else +		{ +		if (s->enc_write_ctx != NULL) +			reuse_dd = 1; +		else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) +			goto err; +		else +			/* make sure it's intialized in case we exit later with an error */ +			EVP_CIPHER_CTX_init(s->enc_write_ctx); +		dd= s->enc_write_ctx; +		ssl_replace_hash(&s->write_hash,m); +#ifndef OPENSSL_NO_COMP +		/* COMPRESS */ +		if (s->compress != NULL) +			{ +			COMP_CTX_free(s->compress); +			s->compress=NULL; +			} +		if (comp != NULL) +			{ +			s->compress=COMP_CTX_new(comp); +			if (s->compress == NULL) +				{ +				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); +				goto err2; +				} +			} +#endif +		memset(&(s->s3->write_sequence[0]),0,8); +		mac_secret= &(s->s3->write_mac_secret[0]); +		} + +	if (reuse_dd) +		EVP_CIPHER_CTX_cleanup(dd); + +	p=s->s3->tmp.key_block; +	i=EVP_MD_size(m); +	if (i < 0) +		goto err2; +	cl=EVP_CIPHER_key_length(c); +	j=is_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? +		 cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; +	/* Was j=(is_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,ERR_R_INTERNAL_ERROR); +		goto err2; +		} + +	EVP_MD_CTX_init(&md); +	memcpy(mac_secret,ms,i); +	if (is_exp) +		{ +		/* In here I set both the read and write key/iv to the +		 * same value since only the correct one will be used :-). +		 */ +		EVP_DigestInit_ex(&md,EVP_md5(), NULL); +		EVP_DigestUpdate(&md,key,j); +		EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE); +		EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE); +		EVP_DigestFinal_ex(&md,&(exp_key[0]),NULL); +		key= &(exp_key[0]); + +		if (k > 0) +			{ +			EVP_DigestInit_ex(&md,EVP_md5(), NULL); +			EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE); +			EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE); +			EVP_DigestFinal_ex(&md,&(exp_iv[0]),NULL); +			iv= &(exp_iv[0]); +			} +		} + +	s->session->key_arg_length=0; + +	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); + +	OPENSSL_cleanse(&(exp_key[0]),sizeof(exp_key)); +	OPENSSL_cleanse(&(exp_iv[0]),sizeof(exp_iv)); +	EVP_MD_CTX_cleanup(&md); +	return(1); +err: +	SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); +err2: +	return(0); +	} + +int ssl3_setup_key_block(SSL *s) +	{ +	unsigned char *p; +	const EVP_CIPHER *c; +	const EVP_MD *hash; +	int num; +	int ret = 0; +	SSL_COMP *comp; + +	if (s->s3->tmp.key_block_length != 0) +		return(1); + +	if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL,&comp)) +		{ +		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; +#ifdef OPENSSL_NO_COMP +	s->s3->tmp.new_compression=NULL; +#else +	s->s3->tmp.new_compression=comp; +#endif + +	num=EVP_MD_size(hash); +	if (num < 0) +		return 0; + +	num=EVP_CIPHER_key_length(c)+num+EVP_CIPHER_iv_length(c); +	num*=2; + +	ssl3_cleanup_key_block(s); + +	if ((p=OPENSSL_malloc(num)) == NULL) +		goto err; + +	s->s3->tmp.key_block_length=num; +	s->s3->tmp.key_block=p; + +	ret = ssl3_generate_key_block(s,p,num); + +	if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) +		{ +		/* enable vulnerability countermeasure for CBC ciphers with +		 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) +		 */ +		s->s3->need_empty_fragments = 1; + +		if (s->session->cipher != NULL) +			{ +			if (s->session->cipher->algorithm_enc == SSL_eNULL) +				s->s3->need_empty_fragments = 0; +			 +#ifndef OPENSSL_NO_RC4 +			if (s->session->cipher->algorithm_enc == SSL_RC4) +				s->s3->need_empty_fragments = 0; +#endif +			} +		} + +	return ret; +		 +err: +	SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); +	return(0); +	} + +void ssl3_cleanup_key_block(SSL *s) +	{ +	if (s->s3->tmp.key_block != NULL) +		{ +		OPENSSL_cleanse(s->s3->tmp.key_block, +			s->s3->tmp.key_block_length); +		OPENSSL_free(s->s3->tmp.key_block); +		s->s3->tmp.key_block=NULL; +		} +	s->s3->tmp.key_block_length=0; +	} + +int ssl3_enc(SSL *s, int send) +	{ +	SSL3_RECORD *rec; +	EVP_CIPHER_CTX *ds; +	unsigned long l; +	int bs,i; +	const EVP_CIPHER *enc; + +	if (send) +		{ +		ds=s->enc_write_ctx; +		rec= &(s->s3->wrec); +		if (s->enc_write_ctx == NULL) +			enc=NULL; +		else +			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); +		} +	else +		{ +		ds=s->enc_read_ctx; +		rec= &(s->s3->rrec); +		if (s->enc_read_ctx == NULL) +			enc=NULL; +		else +			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); +		} + +	if ((s->session == NULL) || (ds == NULL) || +		(enc == NULL)) +		{ +		memmove(rec->data,rec->input,rec->length); +		rec->input=rec->data; +		} +	else +		{ +		l=rec->length; +		bs=EVP_CIPHER_block_size(ds->cipher); + +		/* COMPRESS */ + +		if ((bs != 1) && send) +			{ +			i=bs-((int)l%bs); + +			/* we need to add 'i-1' padding bytes */ +			l+=i; +			/* the last of these zero bytes will be overwritten +			 * with the padding length. */ +			memset(&rec->input[rec->length], 0, i); +			rec->length+=i; +			rec->input[l-1]=(i-1); +			} +		 +		if (!send) +			{ +			if (l == 0 || l%bs != 0) +				{ +				SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); +				return 0; +				} +			/* otherwise, rec->length >= bs */ +			} +		 +		EVP_Cipher(ds,rec->data,rec->input,l); + +		if ((bs != 1) && !send) +			{ +			i=rec->data[l-1]+1; +			/* SSL 3.0 bounds the number of padding bytes by the block size; +			 * padding bytes (except the last one) are arbitrary */ +			if (i > bs) +				{ +				/* Incorrect padding. SSLerr() and ssl3_alert are done +				 * by caller: we don't want to reveal whether this is +				 * a decryption error or a MAC verification failure +				 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ +				return -1; +				} +			/* now i <= bs <= rec->length */ +			rec->length-=i; +			} +		} +	return(1); +	} + +void ssl3_init_finished_mac(SSL *s) +	{ +	if (s->s3->handshake_buffer) BIO_free(s->s3->handshake_buffer); +	if (s->s3->handshake_dgst) ssl3_free_digest_list(s); +    s->s3->handshake_buffer=BIO_new(BIO_s_mem());	 +	(void)BIO_set_close(s->s3->handshake_buffer,BIO_CLOSE); +	} + +void ssl3_free_digest_list(SSL *s)  +	{ +	int i; +	if (!s->s3->handshake_dgst) return; +	for (i=0;i<SSL_MAX_DIGEST;i++)  +		{ +		if (s->s3->handshake_dgst[i]) +			EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]); +		} +	OPENSSL_free(s->s3->handshake_dgst); +	s->s3->handshake_dgst=NULL; +	}	 +		 + + +void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len) +	{ +	if (s->s3->handshake_buffer)  +		{ +		BIO_write (s->s3->handshake_buffer,(void *)buf,len); +		}  +	else  +		{ +		int i; +		for (i=0;i< SSL_MAX_DIGEST;i++)  +			{ +			if (s->s3->handshake_dgst[i]!= NULL) +			EVP_DigestUpdate(s->s3->handshake_dgst[i],buf,len); +			} +		}	 +	} + +int ssl3_digest_cached_records(SSL *s) +	{ +	int i; +	long mask; +	const EVP_MD *md; +	long hdatalen; +	void *hdata; + +	/* Allocate handshake_dgst array */ +	ssl3_free_digest_list(s); +	s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); +	memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *)); +	hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata); +	if (hdatalen <= 0) +		{ +		SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); +		return 0; +		} + +	/* Loop through bitso of algorithm2 field and create MD_CTX-es */ +	for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++)  +		{ +		if ((mask & s->s3->tmp.new_cipher->algorithm2) && md)  +			{ +			s->s3->handshake_dgst[i]=EVP_MD_CTX_create(); +			EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL); +			EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen); +			}  +		else  +			{	 +			s->s3->handshake_dgst[i]=NULL; +			} +		} +	/* Free handshake_buffer BIO */ +	BIO_free(s->s3->handshake_buffer); +	s->s3->handshake_buffer = NULL; + +	return 1; +	} + +int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p) +	{ +	return(ssl3_handshake_mac(s,md_nid,NULL,0,p)); +	} +int ssl3_final_finish_mac(SSL *s,  +	     const char *sender, int len, unsigned char *p) +	{ +	int ret; +	ret=ssl3_handshake_mac(s,NID_md5,sender,len,p); +	p+=ret; +	ret+=ssl3_handshake_mac(s,NID_sha1,sender,len,p); +	return(ret); +	} +static int ssl3_handshake_mac(SSL *s, int md_nid, +	     const char *sender, int len, unsigned char *p) +	{ +	unsigned int ret; +	int npad,n; +	unsigned int i; +	unsigned char md_buf[EVP_MAX_MD_SIZE]; +	EVP_MD_CTX ctx,*d=NULL; + +	if (s->s3->handshake_buffer)  +		if (!ssl3_digest_cached_records(s)) +			return 0; + +	/* Search for digest of specified type in the handshake_dgst +	 * array*/ +	for (i=0;i<SSL_MAX_DIGEST;i++)  +		{ +		  if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid)  +		  	{ +		  	d=s->s3->handshake_dgst[i]; +			break; +			} +		} +	if (!d) { +		SSLerr(SSL_F_SSL3_HANDSHAKE_MAC,SSL_R_NO_REQUIRED_DIGEST); +		return 0; +	}	 +	EVP_MD_CTX_init(&ctx); +	EVP_MD_CTX_copy_ex(&ctx,d); +	n=EVP_MD_CTX_size(&ctx); +	if (n < 0) +		return 0; + +	npad=(48/n)*n; +	if (sender != NULL) +		EVP_DigestUpdate(&ctx,sender,len); +	EVP_DigestUpdate(&ctx,s->session->master_key, +		s->session->master_key_length); +	EVP_DigestUpdate(&ctx,ssl3_pad_1,npad); +	EVP_DigestFinal_ex(&ctx,md_buf,&i); + +	EVP_DigestInit_ex(&ctx,EVP_MD_CTX_md(&ctx), NULL); +	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_ex(&ctx,p,&ret); + +	EVP_MD_CTX_cleanup(&ctx); + +	return((int)ret); +	} + +int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) +	{ +	SSL3_RECORD *rec; +	unsigned char *mac_sec,*seq; +	EVP_MD_CTX md_ctx; +	const EVP_MD_CTX *hash; +	unsigned char *p,rec_char; +	unsigned int md_size; +	int npad; +	int t; + +	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; +		} + +	t=EVP_MD_CTX_size(hash); +	if (t < 0) +		return -1; +	md_size=t; +	npad=(48/md_size)*md_size; + +	/* Chop the digest off the end :-) */ +	EVP_MD_CTX_init(&md_ctx); + +	EVP_MD_CTX_copy_ex( &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_ex( &md_ctx,md,NULL); + +	EVP_MD_CTX_copy_ex( &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_ex( &md_ctx,md,&md_size); + +	EVP_MD_CTX_cleanup(&md_ctx); + +	ssl3_record_sequence_update(seq); +	return(md_size); +	} + +void ssl3_record_sequence_update(unsigned char *seq) +	{ +	int i; + +	for (i=7; i>=0; i--) +		{ +		++seq[i]; +		if (seq[i] != 0) break;  +		} +	} + +int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, +	     int len) +	{ +	static const unsigned char *salt[3]={ +#ifndef CHARSET_EBCDIC +		(const unsigned char *)"A", +		(const unsigned char *)"BB", +		(const unsigned char *)"CCC", +#else +		(const unsigned char *)"\x41", +		(const unsigned char *)"\x42\x42", +		(const unsigned char *)"\x43\x43\x43", +#endif +		}; +	unsigned char buf[EVP_MAX_MD_SIZE]; +	EVP_MD_CTX ctx; +	int i,ret=0; +	unsigned int n; + +	EVP_MD_CTX_init(&ctx); +	for (i=0; i<3; i++) +		{ +		EVP_DigestInit_ex(&ctx,s->ctx->sha1, NULL); +		EVP_DigestUpdate(&ctx,salt[i],strlen((const 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_ex(&ctx,buf,&n); + +		EVP_DigestInit_ex(&ctx,s->ctx->md5, NULL); +		EVP_DigestUpdate(&ctx,p,len); +		EVP_DigestUpdate(&ctx,buf,n); +		EVP_DigestFinal_ex(&ctx,out,&n); +		out+=n; +		ret+=n; +		} +	EVP_MD_CTX_cleanup(&ctx); +	return(ret); +	} + +int ssl3_alert_code(int code) +	{ +	switch (code) +		{ +	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY); +	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE); +	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC); +	case SSL_AD_DECRYPTION_FAILED:	return(SSL3_AD_BAD_RECORD_MAC); +	case SSL_AD_RECORD_OVERFLOW:	return(SSL3_AD_BAD_RECORD_MAC); +	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE); +	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_NO_CERTIFICATE:	return(SSL3_AD_NO_CERTIFICATE); +	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE); +	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE); +	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED); +	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED); +	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN); +	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER); +	case SSL_AD_UNKNOWN_CA:		return(SSL3_AD_BAD_CERTIFICATE); +	case SSL_AD_ACCESS_DENIED:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_DECODE_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_DECRYPT_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_EXPORT_RESTRICTION:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_PROTOCOL_VERSION:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_INSUFFICIENT_SECURITY:return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_INTERNAL_ERROR:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_USER_CANCELLED:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_NO_RENEGOTIATION:	return(-1); /* Don't send it :-) */ +	case SSL_AD_UNSUPPORTED_EXTENSION: return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_UNRECOGNIZED_NAME:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); +	default:			return(-1); +		} +	} + diff --git a/main/openssl/ssl/s3_lib.c b/main/openssl/ssl/s3_lib.c new file mode 100644 index 00000000..28ee4746 --- /dev/null +++ b/main/openssl/ssl/s3_lib.c @@ -0,0 +1,3357 @@ +/* ssl/s3_lib.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by  + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include <openssl/objects.h> +#include "ssl_locl.h" +#include "kssl_lcl.h" +#ifndef OPENSSL_NO_TLSEXT +#ifndef OPENSSL_NO_EC +#include "../crypto/ec/ec_lcl.h" +#endif /* OPENSSL_NO_EC */ +#endif /* OPENSSL_NO_TLSEXT */ +#include <openssl/md5.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif + +const char ssl3_version_str[]="SSLv3" OPENSSL_VERSION_PTEXT; + +#define SSL3_NUM_CIPHERS	(sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER)) + +/* list of available SSLv3 ciphers (sorted by id) */ +OPENSSL_GLOBAL 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_SSLV3, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +/* Cipher 02 */ +	{ +	1, +	SSL3_TXT_RSA_NULL_SHA, +	SSL3_CK_RSA_NULL_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_eNULL, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_STRONG_NONE|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +/* Cipher 03 */ +	{ +	1, +	SSL3_TXT_RSA_RC4_40_MD5, +	SSL3_CK_RSA_RC4_40_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* Cipher 04 */ +	{ +	1, +	SSL3_TXT_RSA_RC4_128_MD5, +	SSL3_CK_RSA_RC4_128_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 05 */ +	{ +	1, +	SSL3_TXT_RSA_RC4_128_SHA, +	SSL3_CK_RSA_RC4_128_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC4, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 06 */ +	{ +	1, +	SSL3_TXT_RSA_RC2_40_MD5, +	SSL3_CK_RSA_RC2_40_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC2, +	SSL_MD5, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* Cipher 07 */ +#ifndef OPENSSL_NO_IDEA +	{ +	1, +	SSL3_TXT_RSA_IDEA_128_SHA, +	SSL3_CK_RSA_IDEA_128_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_IDEA, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +#endif + +/* 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_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* 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_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* Cipher 0C */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	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_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* Cipher 0D */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	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_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* Cipher 0E */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	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_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* Cipher 0F */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	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_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* Cipher 10 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	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_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* 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_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* 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_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* Cipher 17 */ +	{ +	1, +	SSL3_TXT_ADH_RC4_40_MD5, +	SSL3_CK_ADH_RC4_40_MD5, +	SSL_kEDH, +	SSL_aNULL, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* Cipher 18 */ +	{ +	1, +	SSL3_TXT_ADH_RC4_128_MD5, +	SSL3_CK_ADH_RC4_128_MD5, +	SSL_kEDH, +	SSL_aNULL, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* 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_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* 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_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* Cipher 1B */ +	{ +	1, +	SSL3_TXT_ADH_DES_192_CBC_SHA, +	SSL3_CK_ADH_DES_192_CBC_SHA, +	SSL_kEDH, +	SSL_aNULL, +	SSL_3DES, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* Fortezza ciphersuite from SSL 3.0 spec */ +#if 0 +/* Cipher 1C */ +	{ +	0, +	SSL3_TXT_FZA_DMS_NULL_SHA, +	SSL3_CK_FZA_DMS_NULL_SHA, +	SSL_kFZA, +	SSL_aFZA, +	SSL_eNULL, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +/* Cipher 1D */ +	{ +	0, +	SSL3_TXT_FZA_DMS_FZA_SHA, +	SSL3_CK_FZA_DMS_FZA_SHA, +	SSL_kFZA, +	SSL_aFZA, +	SSL_eFZA, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +/* Cipher 1E */ +	{ +	0, +	SSL3_TXT_FZA_DMS_RC4_SHA, +	SSL3_CK_FZA_DMS_RC4_SHA, +	SSL_kFZA, +	SSL_aFZA, +	SSL_RC4, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +#endif + +#ifndef OPENSSL_NO_KRB5 +/* The Kerberos ciphers*/ +/* Cipher 1E */ +	{ +	1, +	SSL3_TXT_KRB5_DES_64_CBC_SHA, +	SSL3_CK_KRB5_DES_64_CBC_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_DES, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* Cipher 1F */ +	{ +	1, +	SSL3_TXT_KRB5_DES_192_CBC3_SHA, +	SSL3_CK_KRB5_DES_192_CBC3_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_3DES, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* Cipher 20 */ +	{ +	1, +	SSL3_TXT_KRB5_RC4_128_SHA, +	SSL3_CK_KRB5_RC4_128_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_RC4, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 21 */ +	{ +	1, +	SSL3_TXT_KRB5_IDEA_128_CBC_SHA, +	SSL3_CK_KRB5_IDEA_128_CBC_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_IDEA, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 22 */ +	{ +	1, +	SSL3_TXT_KRB5_DES_64_CBC_MD5, +	SSL3_CK_KRB5_DES_64_CBC_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_DES, +	SSL_MD5, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_LOW, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +/* Cipher 23 */ +	{ +	1, +	SSL3_TXT_KRB5_DES_192_CBC3_MD5, +	SSL3_CK_KRB5_DES_192_CBC3_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_3DES, +	SSL_MD5, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +/* Cipher 24 */ +	{ +	1, +	SSL3_TXT_KRB5_RC4_128_MD5, +	SSL3_CK_KRB5_RC4_128_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 25 */ +	{ +	1, +	SSL3_TXT_KRB5_IDEA_128_CBC_MD5, +	SSL3_CK_KRB5_IDEA_128_CBC_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_IDEA, +	SSL_MD5, +	SSL_SSLV3, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 26 */ +	{ +	1, +	SSL3_TXT_KRB5_DES_40_CBC_SHA, +	SSL3_CK_KRB5_DES_40_CBC_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_DES, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* Cipher 27 */ +	{ +	1, +	SSL3_TXT_KRB5_RC2_40_CBC_SHA, +	SSL3_CK_KRB5_RC2_40_CBC_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_RC2, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* Cipher 28 */ +	{ +	1, +	SSL3_TXT_KRB5_RC4_40_SHA, +	SSL3_CK_KRB5_RC4_40_SHA, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_RC4, +	SSL_SHA1, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* Cipher 29 */ +	{ +	1, +	SSL3_TXT_KRB5_DES_40_CBC_MD5, +	SSL3_CK_KRB5_DES_40_CBC_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_DES, +	SSL_MD5, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	56, +	}, + +/* Cipher 2A */ +	{ +	1, +	SSL3_TXT_KRB5_RC2_40_CBC_MD5, +	SSL3_CK_KRB5_RC2_40_CBC_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_RC2, +	SSL_MD5, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, + +/* Cipher 2B */ +	{ +	1, +	SSL3_TXT_KRB5_RC4_40_MD5, +	SSL3_CK_KRB5_RC4_40_MD5, +	SSL_kKRB5, +	SSL_aKRB5, +	SSL_RC4, +	SSL_MD5, +	SSL_SSLV3, +	SSL_EXPORT|SSL_EXP40, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	40, +	128, +	}, +#endif	/* OPENSSL_NO_KRB5 */ + +/* New AES ciphersuites */ +/* Cipher 2F */ +	{ +	1, +	TLS1_TXT_RSA_WITH_AES_128_SHA, +	TLS1_CK_RSA_WITH_AES_128_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +/* Cipher 30 */ +	{ +	0, +	TLS1_TXT_DH_DSS_WITH_AES_128_SHA, +	TLS1_CK_DH_DSS_WITH_AES_128_SHA, +	SSL_kDHd, +	SSL_aDH, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +/* Cipher 31 */ +	{ +	0, +	TLS1_TXT_DH_RSA_WITH_AES_128_SHA, +	TLS1_CK_DH_RSA_WITH_AES_128_SHA, +	SSL_kDHr, +	SSL_aDH, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +/* Cipher 32 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_WITH_AES_128_SHA, +	TLS1_CK_DHE_DSS_WITH_AES_128_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +/* Cipher 33 */ +	{ +	1, +	TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, +	TLS1_CK_DHE_RSA_WITH_AES_128_SHA, +	SSL_kEDH, +	SSL_aRSA, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +/* Cipher 34 */ +	{ +	1, +	TLS1_TXT_ADH_WITH_AES_128_SHA, +	TLS1_CK_ADH_WITH_AES_128_SHA, +	SSL_kEDH, +	SSL_aNULL, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +/* Cipher 35 */ +	{ +	1, +	TLS1_TXT_RSA_WITH_AES_256_SHA, +	TLS1_CK_RSA_WITH_AES_256_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, +/* Cipher 36 */ +	{ +	0, +	TLS1_TXT_DH_DSS_WITH_AES_256_SHA, +	TLS1_CK_DH_DSS_WITH_AES_256_SHA, +	SSL_kDHd, +	SSL_aDH, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +/* Cipher 37 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_RSA_WITH_AES_256_SHA, +	TLS1_CK_DH_RSA_WITH_AES_256_SHA, +	SSL_kDHr, +	SSL_aDH, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +/* Cipher 38 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_WITH_AES_256_SHA, +	TLS1_CK_DHE_DSS_WITH_AES_256_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +/* Cipher 39 */ +	{ +	1, +	TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, +	TLS1_CK_DHE_RSA_WITH_AES_256_SHA, +	SSL_kEDH, +	SSL_aRSA, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher 3A */ +	{ +	1, +	TLS1_TXT_ADH_WITH_AES_256_SHA, +	TLS1_CK_ADH_WITH_AES_256_SHA, +	SSL_kEDH, +	SSL_aNULL, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +#ifndef OPENSSL_NO_CAMELLIA +	/* Camellia ciphersuites from RFC4132 (128-bit portion) */ + +	/* Cipher 41 */ +	{ +	1, +	TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA, +	TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_CAMELLIA128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 42 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, +	TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, +	SSL_kDHd, +	SSL_aDH, +	SSL_CAMELLIA128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 43 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, +	TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, +	SSL_kDHr, +	SSL_aDH, +	SSL_CAMELLIA128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 44 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, +	TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_CAMELLIA128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 45 */ +	{ +	1, +	TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, +	TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, +	SSL_kEDH, +	SSL_aRSA, +	SSL_CAMELLIA128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 46 */ +	{ +	1, +	TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA, +	TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA, +	SSL_kEDH, +	SSL_aNULL, +	SSL_CAMELLIA128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +#endif /* OPENSSL_NO_CAMELLIA */ + +#if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES +	/* New TLS Export CipherSuites from expired ID */ +#if 0 +	/* Cipher 60 */ +	{ +	1, +	TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5, +	TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC4, +	SSL_MD5, +	SSL_TLSV1, +	SSL_EXPORT|SSL_EXP56, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	128, +	}, + +	/* Cipher 61 */ +	{ +	1, +	TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, +	TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC2, +	SSL_MD5, +	SSL_TLSV1, +	SSL_EXPORT|SSL_EXP56, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	128, +	}, +#endif + +	/* Cipher 62 */ +	{ +	1, +	TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA, +	TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_EXPORT|SSL_EXP56, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +	/* Cipher 63 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, +	TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_EXPORT|SSL_EXP56, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	56, +	}, + +	/* Cipher 64 */ +	{ +	1, +	TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA, +	TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_EXPORT|SSL_EXP56, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	128, +	}, + +	/* Cipher 65 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, +	TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_EXPORT|SSL_EXP56, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	56, +	128, +	}, + +	/* Cipher 66 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA, +	TLS1_CK_DHE_DSS_WITH_RC4_128_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, +#endif +	{ +	1, +	"GOST94-GOST89-GOST89", +	0x3000080, +	SSL_kGOST, +	SSL_aGOST94, +	SSL_eGOST2814789CNT, +	SSL_GOST89MAC, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC, +	256, +	256 +	}, +	{ +	1, +	"GOST2001-GOST89-GOST89", +	0x3000081, +	SSL_kGOST, +	SSL_aGOST01, +	SSL_eGOST2814789CNT, +	SSL_GOST89MAC, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC, +	256, +	256 +	}, +	{ +	1, +	"GOST94-NULL-GOST94", +	0x3000082, +	SSL_kGOST, +	SSL_aGOST94, +	SSL_eNULL, +	SSL_GOST94, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94, +	0, +	0 +	}, +	{ +	1, +	"GOST2001-NULL-GOST94", +	0x3000083, +	SSL_kGOST, +	SSL_aGOST01, +	SSL_eNULL, +	SSL_GOST94, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94, +	0, +	0 +	}, + +#ifndef OPENSSL_NO_CAMELLIA +	/* Camellia ciphersuites from RFC4132 (256-bit portion) */ + +	/* Cipher 84 */ +	{ +	1, +	TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA, +	TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_CAMELLIA256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, +	/* Cipher 85 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, +	TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, +	SSL_kDHd, +	SSL_aDH, +	SSL_CAMELLIA256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher 86 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, +	TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, +	SSL_kDHr, +	SSL_aDH, +	SSL_CAMELLIA256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher 87 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, +	TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_CAMELLIA256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher 88 */ +	{ +	1, +	TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, +	TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, +	SSL_kEDH, +	SSL_aRSA, +	SSL_CAMELLIA256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher 89 */ +	{ +	1, +	TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA, +	TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA, +	SSL_kEDH, +	SSL_aNULL, +	SSL_CAMELLIA256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, +#endif /* OPENSSL_NO_CAMELLIA */ + +#ifndef OPENSSL_NO_PSK +	/* Cipher 8A */ +	{ +	1, +	TLS1_TXT_PSK_WITH_RC4_128_SHA, +	TLS1_CK_PSK_WITH_RC4_128_SHA, +	SSL_kPSK, +	SSL_aPSK, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 8B */ +	{ +	1, +	TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA, +	TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA, +	SSL_kPSK, +	SSL_aPSK, +	SSL_3DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +	/* Cipher 8C */ +	{ +	1, +	TLS1_TXT_PSK_WITH_AES_128_CBC_SHA, +	TLS1_CK_PSK_WITH_AES_128_CBC_SHA, +	SSL_kPSK, +	SSL_aPSK, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 8D */ +	{ +	1, +	TLS1_TXT_PSK_WITH_AES_256_CBC_SHA, +	TLS1_CK_PSK_WITH_AES_256_CBC_SHA, +	SSL_kPSK, +	SSL_aPSK, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, +#endif  /* OPENSSL_NO_PSK */ + +#ifndef OPENSSL_NO_SEED +	/* SEED ciphersuites from RFC4162 */ + +	/* Cipher 96 */ +	{ +	1, +	TLS1_TXT_RSA_WITH_SEED_SHA, +	TLS1_CK_RSA_WITH_SEED_SHA, +	SSL_kRSA, +	SSL_aRSA, +	SSL_SEED, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 97 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_DSS_WITH_SEED_SHA, +	TLS1_CK_DH_DSS_WITH_SEED_SHA, +	SSL_kDHd, +	SSL_aDH, +	SSL_SEED, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 98 */ +	{ +	0, /* not implemented (non-ephemeral DH) */ +	TLS1_TXT_DH_RSA_WITH_SEED_SHA, +	TLS1_CK_DH_RSA_WITH_SEED_SHA, +	SSL_kDHr, +	SSL_aDH, +	SSL_SEED, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 99 */ +	{ +	1, +	TLS1_TXT_DHE_DSS_WITH_SEED_SHA, +	TLS1_CK_DHE_DSS_WITH_SEED_SHA, +	SSL_kEDH, +	SSL_aDSS, +	SSL_SEED, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 9A */ +	{ +	1, +	TLS1_TXT_DHE_RSA_WITH_SEED_SHA, +	TLS1_CK_DHE_RSA_WITH_SEED_SHA, +	SSL_kEDH, +	SSL_aRSA, +	SSL_SEED, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher 9B */ +	{ +	1, +	TLS1_TXT_ADH_WITH_SEED_SHA, +	TLS1_CK_ADH_WITH_SEED_SHA, +	SSL_kEDH, +	SSL_aNULL, +	SSL_SEED, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +#endif /* OPENSSL_NO_SEED */ + +#ifndef OPENSSL_NO_ECDH +	/* Cipher C001 */ +	{ +	1, +	TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA, +	TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA, +	SSL_kECDHe, +	SSL_aECDH, +	SSL_eNULL, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +	/* Cipher C002 */ +	{ +	1, +	TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA, +	TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA, +	SSL_kECDHe, +	SSL_aECDH, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C003 */ +	{ +	1, +	TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA, +	TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA, +	SSL_kECDHe, +	SSL_aECDH, +	SSL_3DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +	/* Cipher C004 */ +	{ +	1, +	TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA, +	TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA, +	SSL_kECDHe, +	SSL_aECDH, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C005 */ +	{ +	1, +	TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA, +	TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA, +	SSL_kECDHe, +	SSL_aECDH, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher C006 */ +	{ +	1, +	TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA, +	TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA, +	SSL_kEECDH, +	SSL_aECDSA, +	SSL_eNULL, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +	/* Cipher C007 */ +	{ +	1, +	TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA, +	TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, +	SSL_kEECDH, +	SSL_aECDSA, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C008 */ +	{ +	1, +	TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, +	TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, +	SSL_kEECDH, +	SSL_aECDSA, +	SSL_3DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +	/* Cipher C009 */ +	{ +	1, +	TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, +	TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, +	SSL_kEECDH, +	SSL_aECDSA, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C00A */ +	{ +	1, +	TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, +	TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, +	SSL_kEECDH, +	SSL_aECDSA, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher C00B */ +	{ +	1, +	TLS1_TXT_ECDH_RSA_WITH_NULL_SHA, +	TLS1_CK_ECDH_RSA_WITH_NULL_SHA, +	SSL_kECDHr, +	SSL_aECDH, +	SSL_eNULL, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +	/* Cipher C00C */ +	{ +	1, +	TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA, +	TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA, +	SSL_kECDHr, +	SSL_aECDH, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C00D */ +	{ +	1, +	TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA, +	TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA, +	SSL_kECDHr, +	SSL_aECDH, +	SSL_3DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +	/* Cipher C00E */ +	{ +	1, +	TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA, +	TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA, +	SSL_kECDHr, +	SSL_aECDH, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C00F */ +	{ +	1, +	TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA, +	TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA, +	SSL_kECDHr, +	SSL_aECDH, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher C010 */ +	{ +	1, +	TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA, +	TLS1_CK_ECDHE_RSA_WITH_NULL_SHA, +	SSL_kEECDH, +	SSL_aRSA, +	SSL_eNULL, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +	/* Cipher C011 */ +	{ +	1, +	TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, +	TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, +	SSL_kEECDH, +	SSL_aRSA, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C012 */ +	{ +	1, +	TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA, +	TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA, +	SSL_kEECDH, +	SSL_aRSA, +	SSL_3DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +	/* Cipher C013 */ +	{ +	1, +	TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA, +	TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, +	SSL_kEECDH, +	SSL_aRSA, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C014 */ +	{ +	1, +	TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA, +	TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, +	SSL_kEECDH, +	SSL_aRSA, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, + +	/* Cipher C015 */ +	{ +	1, +	TLS1_TXT_ECDH_anon_WITH_NULL_SHA, +	TLS1_CK_ECDH_anon_WITH_NULL_SHA, +	SSL_kEECDH, +	SSL_aNULL, +	SSL_eNULL, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_STRONG_NONE, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	0, +	0, +	}, + +	/* Cipher C016 */ +	{ +	1, +	TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA, +	TLS1_CK_ECDH_anon_WITH_RC4_128_SHA, +	SSL_kEECDH, +	SSL_aNULL, +	SSL_RC4, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_MEDIUM, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C017 */ +	{ +	1, +	TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA, +	TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA, +	SSL_kEECDH, +	SSL_aNULL, +	SSL_3DES, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	168, +	168, +	}, + +	/* Cipher C018 */ +	{ +	1, +	TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA, +	TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA, +	SSL_kEECDH, +	SSL_aNULL, +	SSL_AES128, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	128, +	128, +	}, + +	/* Cipher C019 */ +	{ +	1, +	TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA, +	TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA, +	SSL_kEECDH, +	SSL_aNULL, +	SSL_AES256, +	SSL_SHA1, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, +#endif	/* OPENSSL_NO_ECDH */ + +#ifdef TEMP_GOST_TLS +/* Cipher FF00 */ +	{ +	1, +	"GOST-MD5", +	0x0300ff00, +	SSL_kRSA, +	SSL_aRSA, +	SSL_eGOST2814789CNT, +	SSL_MD5, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256, +	}, +	{ +	1, +	"GOST-GOST94", +	0x0300ff01, +	SSL_kRSA, +	SSL_aRSA, +	SSL_eGOST2814789CNT, +	SSL_GOST94, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256 +	}, +	{ +	1, +	"GOST-GOST89MAC", +	0x0300ff02, +	SSL_kRSA, +	SSL_aRSA, +	SSL_eGOST2814789CNT, +	SSL_GOST89MAC, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, +	256, +	256 +	}, +	{ +	1, +	"GOST-GOST89STREAM", +	0x0300ff03, +	SSL_kRSA, +	SSL_aRSA, +	SSL_eGOST2814789CNT, +	SSL_GOST89MAC, +	SSL_TLSV1, +	SSL_NOT_EXP|SSL_HIGH, +	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF|TLS1_STREAM_MAC, +	256, +	256 +	}, +#endif + +/* end of list */ +	}; + +SSL3_ENC_METHOD SSLv3_enc_data={ +	ssl3_enc, +	n_ssl3_mac, +	ssl3_setup_key_block, +	ssl3_generate_master_secret, +	ssl3_change_cipher_state, +	ssl3_final_finish_mac, +	MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, +	ssl3_cert_verify_mac, +	SSL3_MD_CLIENT_FINISHED_CONST,4, +	SSL3_MD_SERVER_FINISHED_CONST,4, +	ssl3_alert_code, +	}; + +long ssl3_default_timeout(void) +	{ +	/* 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); +	} + +int ssl3_num_ciphers(void) +	{ +	return(SSL3_NUM_CIPHERS); +	} + +const SSL_CIPHER *ssl3_get_cipher(unsigned int u) +	{ +	if (u < SSL3_NUM_CIPHERS) +		return(&(ssl3_ciphers[SSL3_NUM_CIPHERS-1-u])); +	else +		return(NULL); +	} + +int ssl3_pending(const SSL *s) +	{ +	if (s->rstate == SSL_ST_READ_BODY) +		return 0; +	 +	return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0; +	} + +int ssl3_new(SSL *s) +	{ +	SSL3_STATE *s3; + +	if ((s3=OPENSSL_malloc(sizeof *s3)) == NULL) goto err; +	memset(s3,0,sizeof *s3); +	memset(s3->rrec.seq_num,0,sizeof(s3->rrec.seq_num)); +	memset(s3->wrec.seq_num,0,sizeof(s3->wrec.seq_num)); + +	s->s3=s3; + +	s->method->ssl_clear(s); +	return(1); +err: +	return(0); +	} + +void ssl3_free(SSL *s) +	{ +	if(s == NULL) +	    return; + +#ifdef TLSEXT_TYPE_opaque_prf_input +	if (s->s3->client_opaque_prf_input != NULL) +		OPENSSL_free(s->s3->client_opaque_prf_input); +	if (s->s3->server_opaque_prf_input != NULL) +		OPENSSL_free(s->s3->server_opaque_prf_input); +#endif + +	ssl3_cleanup_key_block(s); +	if (s->s3->rbuf.buf != NULL) +		ssl3_release_read_buffer(s); +	if (s->s3->wbuf.buf != NULL) +		ssl3_release_write_buffer(s); +	if (s->s3->rrec.comp != NULL) +		OPENSSL_free(s->s3->rrec.comp); +#ifndef OPENSSL_NO_DH +	if (s->s3->tmp.dh != NULL) +		DH_free(s->s3->tmp.dh); +#endif +#ifndef OPENSSL_NO_ECDH +	if (s->s3->tmp.ecdh != NULL) +		EC_KEY_free(s->s3->tmp.ecdh); +#endif + +	if (s->s3->tmp.ca_names != NULL) +		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free); +	if (s->s3->handshake_buffer) { +		BIO_free(s->s3->handshake_buffer); +	} +	if (s->s3->handshake_dgst) ssl3_free_digest_list(s); +	OPENSSL_cleanse(s->s3,sizeof *s->s3); +	OPENSSL_free(s->s3); +	s->s3=NULL; +	} + +void ssl3_clear(SSL *s) +	{ +	unsigned char *rp,*wp; +	size_t rlen, wlen; + +#ifdef TLSEXT_TYPE_opaque_prf_input +	if (s->s3->client_opaque_prf_input != NULL) +		OPENSSL_free(s->s3->client_opaque_prf_input); +	s->s3->client_opaque_prf_input = NULL; +	if (s->s3->server_opaque_prf_input != NULL) +		OPENSSL_free(s->s3->server_opaque_prf_input); +	s->s3->server_opaque_prf_input = NULL; +#endif + +	ssl3_cleanup_key_block(s); +	if (s->s3->tmp.ca_names != NULL) +		sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + +	if (s->s3->rrec.comp != NULL) +		{ +		OPENSSL_free(s->s3->rrec.comp); +		s->s3->rrec.comp=NULL; +		} +#ifndef OPENSSL_NO_DH +	if (s->s3->tmp.dh != NULL) +		{ +		DH_free(s->s3->tmp.dh); +		s->s3->tmp.dh = NULL; +		} +#endif +#ifndef OPENSSL_NO_ECDH +	if (s->s3->tmp.ecdh != NULL) +		{ +		EC_KEY_free(s->s3->tmp.ecdh); +		s->s3->tmp.ecdh = NULL; +		} +#endif + +	rp = s->s3->rbuf.buf; +	wp = s->s3->wbuf.buf; +	rlen = s->s3->rbuf.len; + 	wlen = s->s3->wbuf.len; +	if (s->s3->handshake_buffer) { +		BIO_free(s->s3->handshake_buffer); +		s->s3->handshake_buffer = NULL; +	} +	if (s->s3->handshake_dgst) { +		ssl3_free_digest_list(s); +	}	 +	memset(s->s3,0,sizeof *s->s3); +	s->s3->rbuf.buf = rp; +	s->s3->wbuf.buf = wp; +	s->s3->rbuf.len = rlen; + 	s->s3->wbuf.len = wlen; + +	ssl_free_wbio_buffer(s); + +	s->packet_length=0; +	s->s3->renegotiate=0; +	s->s3->total_renegotiations=0; +	s->s3->num_renegotiations=0; +	s->s3->in_read_app_data=0; +	s->version=SSL3_VERSION; + +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +	if (s->next_proto_negotiated) +		{ +		OPENSSL_free(s->next_proto_negotiated); +		s->next_proto_negotiated = NULL; +		s->next_proto_negotiated_len = 0; +		} +#endif +	} + +long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) +	{ +	int ret=0; + +#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_RSA) +	if ( +#ifndef OPENSSL_NO_RSA +	    cmd == SSL_CTRL_SET_TMP_RSA || +	    cmd == SSL_CTRL_SET_TMP_RSA_CB || +#endif +#ifndef OPENSSL_NO_DSA +	    cmd == SSL_CTRL_SET_TMP_DH || +	    cmd == SSL_CTRL_SET_TMP_DH_CB || +#endif +		0) +		{ +		if (!ssl_cert_inst(&s->cert)) +		    	{ +			SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE); +			return(0); +			} +		} +#endif + +	switch (cmd) +		{ +	case SSL_CTRL_GET_SESSION_REUSED: +		ret=s->hit; +		break; +	case SSL_CTRL_GET_CLIENT_CERT_REQUEST: +		break; +	case SSL_CTRL_GET_NUM_RENEGOTIATIONS: +		ret=s->s3->num_renegotiations; +		break; +	case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS: +		ret=s->s3->num_renegotiations; +		s->s3->num_renegotiations=0; +		break; +	case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS: +		ret=s->s3->total_renegotiations; +		break; +	case SSL_CTRL_GET_FLAGS: +		ret=(int)(s->s3->flags); +		break; +#ifndef OPENSSL_NO_RSA +	case SSL_CTRL_NEED_TMP_RSA: +		if ((s->cert != NULL) && (s->cert->rsa_tmp == NULL) && +		    ((s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) || +		     (EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > (512/8)))) +			ret = 1; +		break; +	case SSL_CTRL_SET_TMP_RSA: +		{ +			RSA *rsa = (RSA *)parg; +			if (rsa == NULL) +				{ +				SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); +				return(ret); +				} +			if ((rsa = RSAPrivateKey_dup(rsa)) == NULL) +				{ +				SSLerr(SSL_F_SSL3_CTRL, ERR_R_RSA_LIB); +				return(ret); +				} +			if (s->cert->rsa_tmp != NULL) +				RSA_free(s->cert->rsa_tmp); +			s->cert->rsa_tmp = rsa; +			ret = 1; +		} +		break; +	case SSL_CTRL_SET_TMP_RSA_CB: +		{ +		SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		return(ret); +		} +		break; +#endif +#ifndef OPENSSL_NO_DH +	case SSL_CTRL_SET_TMP_DH: +		{ +			DH *dh = (DH *)parg; +			if (dh == NULL) +				{ +				SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); +				return(ret); +				} +			if ((dh = DHparams_dup(dh)) == NULL) +				{ +				SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); +				return(ret); +				} +			if (!(s->options & SSL_OP_SINGLE_DH_USE)) +				{ +				if (!DH_generate_key(dh)) +					{ +					DH_free(dh); +					SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); +					return(ret); +					} +				} +			if (s->cert->dh_tmp != NULL) +				DH_free(s->cert->dh_tmp); +			s->cert->dh_tmp = dh; +			ret = 1; +		} +		break; +	case SSL_CTRL_SET_TMP_DH_CB: +		{ +		SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		return(ret); +		} +		break; +#endif +#ifndef OPENSSL_NO_ECDH +	case SSL_CTRL_SET_TMP_ECDH: +		{ +		EC_KEY *ecdh = NULL; + 			 +		if (parg == NULL) +			{ +			SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); +			return(ret); +			} +		if (!EC_KEY_up_ref((EC_KEY *)parg)) +			{ +			SSLerr(SSL_F_SSL3_CTRL,ERR_R_ECDH_LIB); +			return(ret); +			} +		ecdh = (EC_KEY *)parg; +		if (!(s->options & SSL_OP_SINGLE_ECDH_USE)) +			{ +			if (!EC_KEY_generate_key(ecdh)) +				{ +				EC_KEY_free(ecdh); +				SSLerr(SSL_F_SSL3_CTRL,ERR_R_ECDH_LIB); +				return(ret); +				} +			} +		if (s->cert->ecdh_tmp != NULL) +			EC_KEY_free(s->cert->ecdh_tmp); +		s->cert->ecdh_tmp = ecdh; +		ret = 1; +		} +		break; +	case SSL_CTRL_SET_TMP_ECDH_CB: +		{ +		SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		return(ret); +		} +		break; +#endif /* !OPENSSL_NO_ECDH */ +#ifndef OPENSSL_NO_TLSEXT +	case SSL_CTRL_SET_TLSEXT_HOSTNAME: + 		if (larg == TLSEXT_NAMETYPE_host_name) +			{ +			if (s->tlsext_hostname != NULL)  +				OPENSSL_free(s->tlsext_hostname); +			s->tlsext_hostname = NULL; + +			ret = 1; +			if (parg == NULL)  +				break; +			if (strlen((char *)parg) > TLSEXT_MAXLEN_host_name) +				{ +				SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME); +				return 0; +				} +			if ((s->tlsext_hostname = BUF_strdup((char *)parg)) == NULL) +				{ +				SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR); +				return 0; +				} +			} +		else +			{ +			SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE); +			return 0; +			} + 		break; +	case SSL_CTRL_SET_TLSEXT_DEBUG_ARG: +		s->tlsext_debug_arg=parg; +		ret = 1; +		break; + +#ifdef TLSEXT_TYPE_opaque_prf_input +	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT: +		if (larg > 12288) /* actual internal limit is 2^16 for the complete hello message +		                   * (including the cert chain and everything) */ +			{ +			SSLerr(SSL_F_SSL3_CTRL, SSL_R_OPAQUE_PRF_INPUT_TOO_LONG); +			break; +			} +		if (s->tlsext_opaque_prf_input != NULL) +			OPENSSL_free(s->tlsext_opaque_prf_input); +		if ((size_t)larg == 0) +			s->tlsext_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */ +		else +			s->tlsext_opaque_prf_input = BUF_memdup(parg, (size_t)larg); +		if (s->tlsext_opaque_prf_input != NULL) +			{ +			s->tlsext_opaque_prf_input_len = (size_t)larg; +			ret = 1; +			} +		else +			s->tlsext_opaque_prf_input_len = 0; +		break; +#endif + +	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE: +		s->tlsext_status_type=larg; +		ret = 1; +		break; + +	case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS: +		*(STACK_OF(X509_EXTENSION) **)parg = s->tlsext_ocsp_exts; +		ret = 1; +		break; + +	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS: +		s->tlsext_ocsp_exts = parg; +		ret = 1; +		break; + +	case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS: +		*(STACK_OF(OCSP_RESPID) **)parg = s->tlsext_ocsp_ids; +		ret = 1; +		break; + +	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS: +		s->tlsext_ocsp_ids = parg; +		ret = 1; +		break; + +	case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP: +		*(unsigned char **)parg = s->tlsext_ocsp_resp; +		return s->tlsext_ocsp_resplen; +		 +	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP: +		if (s->tlsext_ocsp_resp) +			OPENSSL_free(s->tlsext_ocsp_resp); +		s->tlsext_ocsp_resp = parg; +		s->tlsext_ocsp_resplen = larg; +		ret = 1; +		break; + +#endif /* !OPENSSL_NO_TLSEXT */ +	default: +		break; +		} +	return(ret); +	} + +long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) +	{ +	int ret=0; + +#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_RSA) +	if ( +#ifndef OPENSSL_NO_RSA +	    cmd == SSL_CTRL_SET_TMP_RSA_CB || +#endif +#ifndef OPENSSL_NO_DSA +	    cmd == SSL_CTRL_SET_TMP_DH_CB || +#endif +		0) +		{ +		if (!ssl_cert_inst(&s->cert)) +			{ +			SSLerr(SSL_F_SSL3_CALLBACK_CTRL, ERR_R_MALLOC_FAILURE); +			return(0); +			} +		} +#endif + +	switch (cmd) +		{ +#ifndef OPENSSL_NO_RSA +	case SSL_CTRL_SET_TMP_RSA_CB: +		{ +		s->cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))fp; +		} +		break; +#endif +#ifndef OPENSSL_NO_DH +	case SSL_CTRL_SET_TMP_DH_CB: +		{ +		s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; +		} +		break; +#endif +#ifndef OPENSSL_NO_ECDH +	case SSL_CTRL_SET_TMP_ECDH_CB: +		{ +		s->cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp; +		} +		break; +#endif +#ifndef OPENSSL_NO_TLSEXT +	case SSL_CTRL_SET_TLSEXT_DEBUG_CB: +		s->tlsext_debug_cb=(void (*)(SSL *,int ,int, +					unsigned char *, int, void *))fp; +		break; +#endif +	default: +		break; +		} +	return(ret); +	} + +long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +	{ +	CERT *cert; + +	cert=ctx->cert; + +	switch (cmd) +		{ +#ifndef OPENSSL_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: +		{ +		SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		return(0); +		} +		break; +#endif +#ifndef OPENSSL_NO_DH +	case SSL_CTRL_SET_TMP_DH: +		{ +		DH *new=NULL,*dh; + +		dh=(DH *)parg; +		if ((new=DHparams_dup(dh)) == NULL) +			{ +			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB); +			return 0; +			} +		if (!(ctx->options & SSL_OP_SINGLE_DH_USE)) +			{ +			if (!DH_generate_key(new)) +				{ +				SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB); +				DH_free(new); +				return 0; +				} +			} +		if (cert->dh_tmp != NULL) +			DH_free(cert->dh_tmp); +		cert->dh_tmp=new; +		return 1; +		} +		/*break; */ +	case SSL_CTRL_SET_TMP_DH_CB: +		{ +		SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		return(0); +		} +		break; +#endif +#ifndef OPENSSL_NO_ECDH +	case SSL_CTRL_SET_TMP_ECDH: +		{ +		EC_KEY *ecdh = NULL; + 			 +		if (parg == NULL) +			{ +			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_ECDH_LIB); +			return 0; +			} +		ecdh = EC_KEY_dup((EC_KEY *)parg); +		if (ecdh == NULL) +			{ +			SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_EC_LIB); +			return 0; +			} +		if (!(ctx->options & SSL_OP_SINGLE_ECDH_USE)) +			{ +			if (!EC_KEY_generate_key(ecdh)) +				{ +				EC_KEY_free(ecdh); +				SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_ECDH_LIB); +				return 0; +				} +			} + +		if (cert->ecdh_tmp != NULL) +			{ +			EC_KEY_free(cert->ecdh_tmp); +			} +		cert->ecdh_tmp = ecdh; +		return 1; +		} +		/* break; */ +	case SSL_CTRL_SET_TMP_ECDH_CB: +		{ +		SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +		return(0); +		} +		break; +#endif /* !OPENSSL_NO_ECDH */ +#ifndef OPENSSL_NO_TLSEXT +	case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: +		ctx->tlsext_servername_arg=parg; +		break; +	case SSL_CTRL_SET_TLSEXT_TICKET_KEYS: +	case SSL_CTRL_GET_TLSEXT_TICKET_KEYS: +		{ +		unsigned char *keys = parg; +		if (!keys) +			return 48; +		if (larg != 48) +			{ +			SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH); +			return 0; +			} +		if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) +			{ +			memcpy(ctx->tlsext_tick_key_name, keys, 16); +			memcpy(ctx->tlsext_tick_hmac_key, keys + 16, 16); +			memcpy(ctx->tlsext_tick_aes_key, keys + 32, 16); +			} +		else +			{ +			memcpy(keys, ctx->tlsext_tick_key_name, 16); +			memcpy(keys + 16, ctx->tlsext_tick_hmac_key, 16); +			memcpy(keys + 32, ctx->tlsext_tick_aes_key, 16); +			} +		return 1; +		} + +#ifdef TLSEXT_TYPE_opaque_prf_input +	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG: +		ctx->tlsext_opaque_prf_input_callback_arg = parg; +		return 1; +#endif + +	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG: +		ctx->tlsext_status_arg=parg; +		return 1; +		break; + +#endif /* !OPENSSL_NO_TLSEXT */ + +	/* A Thawte special :-) */ +	case SSL_CTRL_EXTRA_CHAIN_CERT: +		if (ctx->extra_certs == NULL) +			{ +			if ((ctx->extra_certs=sk_X509_new_null()) == NULL) +				return(0); +			} +		sk_X509_push(ctx->extra_certs,(X509 *)parg); +		break; + +	default: +		return(0); +		} +	return(1); +	} + +long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) +	{ +	CERT *cert; + +	cert=ctx->cert; + +	switch (cmd) +		{ +#ifndef OPENSSL_NO_RSA +	case SSL_CTRL_SET_TMP_RSA_CB: +		{ +		cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))fp; +		} +		break; +#endif +#ifndef OPENSSL_NO_DH +	case SSL_CTRL_SET_TMP_DH_CB: +		{ +		cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; +		} +		break; +#endif +#ifndef OPENSSL_NO_ECDH +	case SSL_CTRL_SET_TMP_ECDH_CB: +		{ +		cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp; +		} +		break; +#endif +#ifndef OPENSSL_NO_TLSEXT +	case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: +		ctx->tlsext_servername_callback=(int (*)(SSL *,int *,void *))fp; +		break; + +#ifdef TLSEXT_TYPE_opaque_prf_input +	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB: +		ctx->tlsext_opaque_prf_input_callback = (int (*)(SSL *,void *, size_t, void *))fp; +		break; +#endif + +	case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB: +		ctx->tlsext_status_cb=(int (*)(SSL *,void *))fp; +		break; + +	case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB: +		ctx->tlsext_ticket_key_cb=(int (*)(SSL *,unsigned char  *, +						unsigned char *, +						EVP_CIPHER_CTX *, +						HMAC_CTX *, int))fp; +		break; + +#endif +	default: +		return(0); +		} +	return(1); +	} + +/* This function needs to check if the ciphers required are actually + * available */ +const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p) +	{ +	SSL_CIPHER c; +	const SSL_CIPHER *cp; +	unsigned long id; + +	id=0x03000000L|((unsigned long)p[0]<<8L)|(unsigned long)p[1]; +	c.id=id; +	cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS); +	if (cp == NULL || cp->valid == 0) +		return NULL; +	else +		return cp; +	} + +int ssl3_put_cipher_by_char(const 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); +	} + +SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, +	     STACK_OF(SSL_CIPHER) *srvr) +	{ +	SSL_CIPHER *c,*ret=NULL; +	STACK_OF(SSL_CIPHER) *prio, *allow; +	int i,ii,ok; +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_EC) +	unsigned int j; +	int ec_ok, ec_nid; +	unsigned char ec_search1 = 0, ec_search2 = 0; +#endif +	CERT *cert; +	unsigned long alg_k,alg_a,mask_k,mask_a,emask_k,emask_a; + +	/* Let's see which ciphers we can support */ +	cert=s->cert; + +#if 0 +	/* Do not set the compare functions, because this may lead to a +	 * reordering by "id". We want to keep the original ordering. +	 * We may pay a price in performance during sk_SSL_CIPHER_find(), +	 * but would have to pay with the price of sk_SSL_CIPHER_dup(). +	 */ +	sk_SSL_CIPHER_set_cmp_func(srvr, ssl_cipher_ptr_id_cmp); +	sk_SSL_CIPHER_set_cmp_func(clnt, ssl_cipher_ptr_id_cmp); +#endif + +#ifdef CIPHER_DEBUG +	printf("Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr), (void *)srvr); +	for(i=0 ; i < sk_SSL_CIPHER_num(srvr) ; ++i) +		{ +		c=sk_SSL_CIPHER_value(srvr,i); +		printf("%p:%s\n",(void *)c,c->name); +		} +	printf("Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt), (void *)clnt); +	for(i=0 ; i < sk_SSL_CIPHER_num(clnt) ; ++i) +	    { +	    c=sk_SSL_CIPHER_value(clnt,i); +	    printf("%p:%s\n",(void *)c,c->name); +	    } +#endif + +	if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) +		{ +		prio = srvr; +		allow = clnt; +		} +	else +		{ +		prio = clnt; +		allow = srvr; +		} + +	for (i=0; i<sk_SSL_CIPHER_num(prio); i++) +		{ +		c=sk_SSL_CIPHER_value(prio,i); + +		ssl_set_cert_masks(cert,c); +		mask_k = cert->mask_k; +		mask_a = cert->mask_a; +		emask_k = cert->export_mask_k; +		emask_a = cert->export_mask_a; +			 +#ifdef KSSL_DEBUG +/*		printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/ +#endif    /* KSSL_DEBUG */ + +		alg_k=c->algorithm_mkey; +		alg_a=c->algorithm_auth; + +#ifndef OPENSSL_NO_KRB5 +		if (alg_k & SSL_kKRB5) +			{ +			if ( !kssl_keytab_is_available(s->kssl_ctx) ) +			    continue; +			} +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_PSK +		/* with PSK there must be server callback set */ +		if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL) +			continue; +#endif /* OPENSSL_NO_PSK */ + +		if (SSL_C_IS_EXPORT(c)) +			{ +			ok = (alg_k & emask_k) && (alg_a & emask_a); +#ifdef CIPHER_DEBUG +			printf("%d:[%08lX:%08lX:%08lX:%08lX]%p:%s (export)\n",ok,alg_k,alg_a,emask_k,emask_a, +			       (void *)c,c->name); +#endif +			} +		else +			{ +			ok = (alg_k & mask_k) && (alg_a & mask_a); +#ifdef CIPHER_DEBUG +			printf("%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n",ok,alg_k,alg_a,mask_k,mask_a,(void *)c, +			       c->name); +#endif +			} + +#ifndef OPENSSL_NO_TLSEXT +#ifndef OPENSSL_NO_EC +		if ( +			/* if we are considering an ECC cipher suite that uses our certificate */ +			(alg_a & SSL_aECDSA || alg_a & SSL_aECDH) +			/* and we have an ECC certificate */ +			&& (s->cert->pkeys[SSL_PKEY_ECC].x509 != NULL) +			/* and the client specified a Supported Point Formats extension */ +			&& ((s->session->tlsext_ecpointformatlist_length > 0) && (s->session->tlsext_ecpointformatlist != NULL)) +			/* and our certificate's point is compressed */ +			&& ( +				(s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info != NULL) +				&& (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key != NULL) +				&& (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key != NULL) +				&& (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key->data != NULL) +				&& ( +					(*(s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key->data) == POINT_CONVERSION_COMPRESSED) +					|| (*(s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key->public_key->data) == POINT_CONVERSION_COMPRESSED + 1) +					) +				) +		) +			{ +			ec_ok = 0; +			/* if our certificate's curve is over a field type that the client does not support +			 * then do not allow this cipher suite to be negotiated */ +			if ( +				(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec != NULL) +				&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group != NULL) +				&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth != NULL) +				&& (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_prime_field) +			) +				{ +				for (j = 0; j < s->session->tlsext_ecpointformatlist_length; j++) +					{ +					if (s->session->tlsext_ecpointformatlist[j] == TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime) +						{ +						ec_ok = 1; +						break; +						} +					} +				} +			else if (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_characteristic_two_field) +				{ +				for (j = 0; j < s->session->tlsext_ecpointformatlist_length; j++) +					{ +					if (s->session->tlsext_ecpointformatlist[j] == TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2) +						{ +						ec_ok = 1; +						break; +						} +					} +				} +			ok = ok && ec_ok; +			} +		if ( +			/* if we are considering an ECC cipher suite that uses our certificate */ +			(alg_a & SSL_aECDSA || alg_a & SSL_aECDH) +			/* and we have an ECC certificate */ +			&& (s->cert->pkeys[SSL_PKEY_ECC].x509 != NULL) +			/* and the client specified an EllipticCurves extension */ +			&& ((s->session->tlsext_ellipticcurvelist_length > 0) && (s->session->tlsext_ellipticcurvelist != NULL)) +		) +			{ +			ec_ok = 0; +			if ( +				(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec != NULL) +				&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group != NULL) +			) +				{ +				ec_nid = EC_GROUP_get_curve_name(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group); +				if ((ec_nid == 0) +					&& (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth != NULL) +				) +					{ +					if (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_prime_field) +						{ +						ec_search1 = 0xFF; +						ec_search2 = 0x01; +						} +					else if (EC_METHOD_get_field_type(s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group->meth) == NID_X9_62_characteristic_two_field) +						{ +						ec_search1 = 0xFF; +						ec_search2 = 0x02; +						} +					} +				else +					{ +					ec_search1 = 0x00; +					ec_search2 = tls1_ec_nid2curve_id(ec_nid); +					} +				if ((ec_search1 != 0) || (ec_search2 != 0)) +					{ +					for (j = 0; j < s->session->tlsext_ellipticcurvelist_length / 2; j++) +						{ +						if ((s->session->tlsext_ellipticcurvelist[2*j] == ec_search1) && (s->session->tlsext_ellipticcurvelist[2*j+1] == ec_search2)) +							{ +							ec_ok = 1; +							break; +							} +						} +					} +				} +			ok = ok && ec_ok; +			} +		if ( +			/* if we are considering an ECC cipher suite that uses an ephemeral EC key */ +			(alg_k & SSL_kEECDH) +			/* and we have an ephemeral EC key */ +			&& (s->cert->ecdh_tmp != NULL) +			/* and the client specified an EllipticCurves extension */ +			&& ((s->session->tlsext_ellipticcurvelist_length > 0) && (s->session->tlsext_ellipticcurvelist != NULL)) +		) +			{ +			ec_ok = 0; +			if (s->cert->ecdh_tmp->group != NULL) +				{ +				ec_nid = EC_GROUP_get_curve_name(s->cert->ecdh_tmp->group); +				if ((ec_nid == 0) +					&& (s->cert->ecdh_tmp->group->meth != NULL) +				) +					{ +					if (EC_METHOD_get_field_type(s->cert->ecdh_tmp->group->meth) == NID_X9_62_prime_field) +						{ +						ec_search1 = 0xFF; +						ec_search2 = 0x01; +						} +					else if (EC_METHOD_get_field_type(s->cert->ecdh_tmp->group->meth) == NID_X9_62_characteristic_two_field) +						{ +						ec_search1 = 0xFF; +						ec_search2 = 0x02; +						} +					} +				else +					{ +					ec_search1 = 0x00; +					ec_search2 = tls1_ec_nid2curve_id(ec_nid); +					} +				if ((ec_search1 != 0) || (ec_search2 != 0)) +					{ +					for (j = 0; j < s->session->tlsext_ellipticcurvelist_length / 2; j++) +						{ +						if ((s->session->tlsext_ellipticcurvelist[2*j] == ec_search1) && (s->session->tlsext_ellipticcurvelist[2*j+1] == ec_search2)) +							{ +							ec_ok = 1; +							break; +							} +						} +					} +				} +			ok = ok && ec_ok; +			} +#endif /* OPENSSL_NO_EC */ +#endif /* OPENSSL_NO_TLSEXT */ + +		if (!ok) continue; +		ii=sk_SSL_CIPHER_find(allow,c); +		if (ii >= 0) +			{ +			ret=sk_SSL_CIPHER_value(allow,ii); +			break; +			} +		} +	return(ret); +	} + +int ssl3_get_req_cert_type(SSL *s, unsigned char *p) +	{ +	int ret=0; +	unsigned long alg_k; + +	alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + +#ifndef OPENSSL_NO_GOST +	if (s->version >= TLS1_VERSION) +		{ +		if (alg_k & SSL_kGOST) +			{ +			p[ret++]=TLS_CT_GOST94_SIGN; +			p[ret++]=TLS_CT_GOST01_SIGN; +			return(ret); +			} +		} +#endif + +#ifndef OPENSSL_NO_DH +	if (alg_k & (SSL_kDHr|SSL_kEDH)) +		{ +#  ifndef OPENSSL_NO_RSA +		p[ret++]=SSL3_CT_RSA_FIXED_DH; +#  endif +#  ifndef OPENSSL_NO_DSA +		p[ret++]=SSL3_CT_DSS_FIXED_DH; +#  endif +		} +	if ((s->version == SSL3_VERSION) && +		(alg_k & (SSL_kEDH|SSL_kDHd|SSL_kDHr))) +		{ +#  ifndef OPENSSL_NO_RSA +		p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH; +#  endif +#  ifndef OPENSSL_NO_DSA +		p[ret++]=SSL3_CT_DSS_EPHEMERAL_DH; +#  endif +		} +#endif /* !OPENSSL_NO_DH */ +#ifndef OPENSSL_NO_RSA +	p[ret++]=SSL3_CT_RSA_SIGN; +#endif +#ifndef OPENSSL_NO_DSA +	p[ret++]=SSL3_CT_DSS_SIGN; +#endif +#ifndef OPENSSL_NO_ECDH +	if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->version >= TLS1_VERSION)) +		{ +		p[ret++]=TLS_CT_RSA_FIXED_ECDH; +		p[ret++]=TLS_CT_ECDSA_FIXED_ECDH; +		} +#endif + +#ifndef OPENSSL_NO_ECDSA +	/* ECDSA certs can be used with RSA cipher suites as well  +	 * so we don't need to check for SSL_kECDH or SSL_kEECDH +	 */ +	if (s->version >= TLS1_VERSION) +		{ +		p[ret++]=TLS_CT_ECDSA_SIGN; +		} +#endif	 +	return(ret); +	} + +int ssl3_shutdown(SSL *s) +	{ +	int ret; + +	/* 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,SSL_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 */ +	 	if (s->s3->alert_dispatch) +	 		return(-1);	/* return WANT_WRITE */ +		} +	else if (s->s3->alert_dispatch) +		{ +		/* resend it if not sent */ +#if 1 +		ret=s->method->ssl_dispatch_alert(s); +		if(ret == -1) +			{ +			/* we only get to return -1 here the 2nd/Nth +			 * invocation, we must  have already signalled +			 * return 0 upon a previous invoation, +			 * return WANT_WRITE */ +			return(ret); +			} +#endif +		} +	else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) +		{ +		/* If we are waiting for a close from our peer, we are closed */ +		s->method->ssl_read_bytes(s,0,NULL,0,0); +		if(!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) +			{ +			return(-1);	/* return WANT_READ */ +			} +		} + +	if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) && +		!s->s3->alert_dispatch) +		return(1); +	else +		return(0); +	} + +int ssl3_write(SSL *s, const void *buf, int len) +	{ +	int ret,n; + +#if 0 +	if (s->shutdown & SSL_SEND_SHUTDOWN) +		{ +		s->rwstate=SSL_NOTHING; +		return(0); +		} +#endif +	clear_sys_error(); +	if (s->s3->renegotiate) ssl3_renegotiate_check(s); + +	/* 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, +					     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, so remove it */ +		ssl_free_wbio_buffer(s); +		s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER; + +		ret=s->s3->delay_buf_pop_ret; +		s->s3->delay_buf_pop_ret=0; +		} +	else +		{ +		ret=s->method->ssl_write_bytes(s,SSL3_RT_APPLICATION_DATA, +			buf,len); +		if (ret <= 0) return(ret); +		} + +	return(ret); +	} + +static int ssl3_read_internal(SSL *s, void *buf, int len, int peek) +	{ +	int n,ret; +	 +	clear_sys_error(); +	if ((s->s3->flags & SSL3_FLAGS_POP_BUFFER) && (s->wbio == s->bbio)) +		{ +		/* Deal with an application that calls SSL_read() when handshake data +		 * is yet to be written. +		 */ +		if (BIO_wpending(s->wbio) > 0) +			{ +			s->rwstate=SSL_WRITING; +			n=BIO_flush(s->wbio); +			if (n <= 0) return(n); +			s->rwstate=SSL_NOTHING; +			} +		} +	if (s->s3->renegotiate) ssl3_renegotiate_check(s); +	s->s3->in_read_app_data=1; +	ret=s->method->ssl_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek); +	if ((ret == -1) && (s->s3->in_read_app_data == 2)) +		{ +		/* ssl3_read_bytes decided to call s->handshake_func, which +		 * called ssl3_read_bytes to read handshake data. +		 * However, ssl3_read_bytes actually found application data +		 * and thinks that application data makes sense here; so disable +		 * handshake processing and try to read application data again. */ +		s->in_handshake++; +		ret=s->method->ssl_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek); +		s->in_handshake--; +		} +	else +		s->s3->in_read_app_data=0; + +	return(ret); +	} + +int ssl3_read(SSL *s, void *buf, int len) +	{ +	return ssl3_read_internal(s, buf, len, 0); +	} + +int ssl3_peek(SSL *s, void *buf, int len) +	{ +	return ssl3_read_internal(s, buf, len, 1); +	} + +int ssl3_renegotiate(SSL *s) +	{ +	if (s->handshake_func == NULL) +		return(1); + +	if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) +		return(0); + +	s->s3->renegotiate=1; +	return(1); +	} + +int ssl3_renegotiate_check(SSL *s) +	{ +	int ret=0; + +	if (s->s3->renegotiate) +		{ +		if (	(s->s3->rbuf.left == 0) && +			(s->s3->wbuf.left == 0) && +			!SSL_in_init(s)) +			{ +/* +if we are the server, and we have sent a 'RENEGOTIATE' message, we +need to go to SSL_ST_ACCEPT. +*/ +			/* SSL_ST_ACCEPT */ +			s->state=SSL_ST_RENEGOTIATE; +			s->s3->renegotiate=0; +			s->s3->num_renegotiations++; +			s->s3->total_renegotiations++; +			ret=1; +			} +		} +	return(ret); +	} + diff --git a/main/openssl/ssl/s3_meth.c b/main/openssl/ssl/s3_meth.c new file mode 100644 index 00000000..cdddb17b --- /dev/null +++ b/main/openssl/ssl/s3_meth.c @@ -0,0 +1,77 @@ +/* ssl/s3_meth.c */ +/* Copyright (C) 1995-1998 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 <openssl/objects.h> +#include "ssl_locl.h" + +static const SSL_METHOD *ssl3_get_method(int ver); +static const SSL_METHOD *ssl3_get_method(int ver) +	{ +	if (ver == SSL3_VERSION) +		return(SSLv3_method()); +	else  +		return(NULL); +	} + +IMPLEMENT_ssl3_meth_func(SSLv3_method, +			 ssl3_accept, +			 ssl3_connect, +			 ssl3_get_method) + + diff --git a/main/openssl/ssl/s3_pkt.c b/main/openssl/ssl/s3_pkt.c new file mode 100644 index 00000000..0d3874ae --- /dev/null +++ b/main/openssl/ssl/s3_pkt.c @@ -0,0 +1,1502 @@ +/* ssl/s3_pkt.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <errno.h> +#define USE_SOCKETS +#include "ssl_locl.h" +#include <openssl/evp.h> +#include <openssl/buffer.h> + +static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, +			 unsigned int len, int create_empty_fragment); +static int ssl3_get_record(SSL *s); + +int ssl3_read_n(SSL *s, int n, int max, int extend) +	{ +	/* If extend == 0, obtain new n-byte packet; if extend == 1, increase +	 * packet by another n bytes. +	 * The packet will be in the sub-array of s->s3->rbuf.buf specified +	 * by s->packet and s->packet_length. +	 * (If s->read_ahead is set, 'max' bytes may be stored in rbuf +	 * [plus s->packet_length bytes if extend == 1].) +	 */ +	int i,len,left; +	long align=0; +	unsigned char *pkt; +	SSL3_BUFFER *rb; + +	if (n <= 0) return n; + +	rb    = &(s->s3->rbuf); +	if (rb->buf == NULL) +		if (!ssl3_setup_read_buffer(s)) +			return -1; + +	left  = rb->left; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 +	align = (long)rb->buf + SSL3_RT_HEADER_LENGTH; +	align = (-align)&(SSL3_ALIGN_PAYLOAD-1); +#endif + +	if (!extend) +		{ +		/* start with empty packet ... */ +		if (left == 0) +			rb->offset = align; +		else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) +			{ +			/* check if next packet length is large +			 * enough to justify payload alignment... */ +			pkt = rb->buf + rb->offset; +			if (pkt[0] == SSL3_RT_APPLICATION_DATA +			    && (pkt[3]<<8|pkt[4]) >= 128) +				{ +				/* Note that even if packet is corrupted +				 * and its length field is insane, we can +				 * only be led to wrong decision about +				 * whether memmove will occur or not. +				 * Header values has no effect on memmove +				 * arguments and therefore no buffer +				 * overrun can be triggered. */ +				memmove (rb->buf+align,pkt,left); +				rb->offset = align; +				} +			} +		s->packet = rb->buf + rb->offset; +		s->packet_length = 0; +		/* ... now we can act as if 'extend' was set */ +		} + +	/* For DTLS/UDP reads should not span multiple packets +	 * because the read operation returns the whole packet +	 * at once (as long as it fits into the buffer). */ +	if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) +		{ +		if (left > 0 && n > left) +			n = left; +		} + +	/* if there is enough in the buffer from a previous read, take some */ +	if (left >= n) +		{ +		s->packet_length+=n; +		rb->left=left-n; +		rb->offset+=n; +		return(n); +		} + +	/* else we need to read more data */ + +	len = s->packet_length; +	pkt = rb->buf+align; +	/* Move any available bytes to front of buffer: +	 * 'len' bytes already pointed to by 'packet', +	 * 'left' extra ones at the end */ +	if (s->packet != pkt) /* len > 0 */ +		{ +		memmove(pkt, s->packet, len+left); +		s->packet = pkt; +		rb->offset = len + align; +		} + +	if (n > (int)(rb->len - rb->offset)) /* does not happen */ +		{ +		SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR); +		return -1; +		} + +	if (!s->read_ahead) +		/* ignore max parameter */ +		max = n; +	else +		{ +		if (max < n) +			max = n; +		if (max > (int)(rb->len - rb->offset)) +			max = rb->len - rb->offset; +		} + +	while (left < n) +		{ +		/* Now we have len+left bytes at the front of s->s3->rbuf.buf +		 * and need to read in more until we have len+n (up to +		 * len+max if possible) */ + +		clear_sys_error(); +		if (s->rbio != NULL) +			{ +			s->rwstate=SSL_READING; +			i=BIO_read(s->rbio,pkt+len+left, max-left); +			} +		else +			{ +			SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); +			i = -1; +			} + +		if (i <= 0) +			{ +			rb->left = left; +			if (s->mode & SSL_MODE_RELEASE_BUFFERS && +			    SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER) +				if (len+left == 0) +					ssl3_release_read_buffer(s); +			return(i); +			} +		left+=i; +		/* reads should *never* span multiple packets for DTLS because +		 * the underlying transport protocol is message oriented as opposed +		 * to byte oriented as in the TLS case. */ +		if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) +			{ +			if (n > left) +				n = left; /* makes the while condition false */ +			} +		} + +	/* done reading, now the book-keeping */ +	rb->offset += n; +	rb->left = left - n; +	s->packet_length += n; +	s->rwstate=SSL_NOTHING; +	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 + */ +/* used only by ssl3_read_bytes */ +static int ssl3_get_record(SSL *s) +	{ +	int ssl_major,ssl_minor,al; +	int enc_err,n,i,ret= -1; +	SSL3_RECORD *rr; +	SSL_SESSION *sess; +	unsigned char *p; +	unsigned char md[EVP_MAX_MD_SIZE]; +	short version; +	int mac_size; +	int clear=0; +	size_t extra; +	int decryption_failed_or_bad_record_mac = 0; +	unsigned char *mac = NULL; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 +	long align=SSL3_ALIGN_PAYLOAD; +#else +	long align=0; +#endif + +	rr= &(s->s3->rrec); +	sess=s->session; + +	if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) +		extra=SSL3_RT_MAX_EXTRA; +	else +		extra=0; +	if (!(SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) && +		extra && !s->s3->init_extra) +		{ +		/* An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER +		 * set after ssl3_setup_buffers() was done */ +		SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR); +		return -1; +		} + +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, s->s3->rbuf.len, 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); +#if 0 +fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); +#endif + +		/* Lets check version */ +		if (!s->first_packet) +			{ +			if (version != s->version) +				{ +				SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); +                                if ((s->version & 0xFF00) == (version & 0xFF00)) +                                	/* Send back error using their minor version number :-) */ +					s->version = (unsigned short)version; +				al=SSL_AD_PROTOCOL_VERSION; +				goto f_err; +				} +			} + +		if ((version>>8) != SSL3_VERSION_MAJOR) +			{ +			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); +			goto err; +			} + +		/* If we receive a valid record larger than the current buffer size, +		 * allocate some memory for it. +		 */ +		if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH - align) +			{ +			if ((p=OPENSSL_realloc(s->s3->rbuf.buf, rr->length + SSL3_RT_HEADER_LENGTH + align))==NULL) +				{ +				SSLerr(SSL_F_SSL3_GET_RECORD,ERR_R_MALLOC_FAILURE); +				goto err; +				} +			s->s3->rbuf.buf=p; +			s->s3->rbuf.len=rr->length + SSL3_RT_HEADER_LENGTH + align; +			s->packet= &(s->s3->rbuf.buf[0]); +			} + +		if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH) +			{ +			al=SSL_AD_RECORD_OVERFLOW; +			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG); +			goto f_err; +			} + +		/* now s->rstate == SSL_ST_READ_BODY */ +		} + +	/* s->rstate == SSL_ST_READ_BODY, get and decode the data */ + +	if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH) +		{ +		/* now s->packet_length == SSL3_RT_HEADER_LENGTH */ +		i=rr->length; +		n=ssl3_read_n(s,i,i,1); +		if (n <= 0) return(n); /* error or non-blocking io */ +		/* now n == rr->length, +		 * and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */ +		} + +	s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */ + +	/* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, +	 * and we have that many bytes in s->packet +	 */ +	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 */  + +	/* We now have - encrypted [ MAC [ compressed [ plain ] ] ] +	 * rr->length bytes of encrypted compressed stuff. */ + +	/* check is not needed I believe */ +	if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) +		{ +		al=SSL_AD_RECORD_OVERFLOW; +		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; + +	enc_err = s->method->ssl3_enc->enc(s,0); +	if (enc_err <= 0) +		{ +		if (enc_err == 0) +			/* SSLerr() and ssl3_send_alert() have been called */ +			goto err; + +		/* Otherwise enc_err == -1, which indicates bad padding +		 * (rec->length has not been changed in this case). +		 * To minimize information leaked via timing, we will perform +		 * the MAC computation anyway. */ +		decryption_failed_or_bad_record_mac = 1; +		} + +#ifdef TLS_DEBUG +printf("dec %d\n",rr->length); +{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } +printf("\n"); +#endif + +	/* r->length is now the compressed data plus mac */ +	if (	(sess == NULL) || +		(s->enc_read_ctx == NULL) || +		(EVP_MD_CTX_md(s->read_hash) == NULL)) +		clear=1; + +	if (!clear) +		{ +		/* !clear => s->read_hash != NULL => mac_size != -1 */ +		mac_size=EVP_MD_CTX_size(s->read_hash); +		OPENSSL_assert(mac_size >= 0); + +		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) +			{ +#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ +			al=SSL_AD_RECORD_OVERFLOW; +			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); +			goto f_err; +#else +			decryption_failed_or_bad_record_mac = 1; +#endif			 +			} +		/* check the MAC for rr->input (it's in mac_size bytes at the tail) */ +		if (rr->length >= (unsigned int)mac_size) +			{ +			rr->length -= mac_size; +			mac = &rr->data[rr->length]; +			} +		else +			{ +			/* record (minus padding) is too short to contain a MAC */ +#if 0 /* OK only for stream ciphers */ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); +			goto f_err; +#else +			decryption_failed_or_bad_record_mac = 1; +			rr->length = 0; +#endif +			} +		i=s->method->ssl3_enc->mac(s,md,0); +		if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0) +			{ +			decryption_failed_or_bad_record_mac = 1; +			} +		} + +	if (decryption_failed_or_bad_record_mac) +		{ +		/* A separate 'decryption_failed' alert was introduced with TLS 1.0, +		 * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption +		 * failure is directly visible from the ciphertext anyway, +		 * we should not reveal which kind of error occured -- this +		 * might become visible to an attacker (e.g. via a logfile) */ +		al=SSL_AD_BAD_RECORD_MAC; +		SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); +		goto f_err; +		} + +	/* r->length is now just compressed */ +	if (s->expand != NULL) +		{ +		if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) +			{ +			al=SSL_AD_RECORD_OVERFLOW; +			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG); +			goto f_err; +			} +		if (!ssl3_do_uncompress(s)) +			{ +			al=SSL_AD_DECOMPRESSION_FAILURE; +			SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION); +			goto f_err; +			} +		} + +	if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) +		{ +		al=SSL_AD_RECORD_OVERFLOW; +		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; + +#if 0 +fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, rr->length); +#endif + +	return(1); + +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	return(ret); +	} + +int ssl3_do_uncompress(SSL *ssl) +	{ +#ifndef OPENSSL_NO_COMP +	int i; +	SSL3_RECORD *rr; + +	rr= &(ssl->s3->rrec); +	i=COMP_expand_block(ssl->expand,rr->comp, +		SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length); +	if (i < 0) +		return(0); +	else +		rr->length=i; +	rr->data=rr->comp; +#endif +	return(1); +	} + +int ssl3_do_compress(SSL *ssl) +	{ +#ifndef OPENSSL_NO_COMP +	int i; +	SSL3_RECORD *wr; + +	wr= &(ssl->s3->wrec); +	i=COMP_compress_block(ssl->compress,wr->data, +		SSL3_RT_MAX_COMPRESSED_LENGTH, +		wr->input,(int)wr->length); +	if (i < 0) +		return(0); +	else +		wr->length=i; + +	wr->input=wr->data; +#endif +	return(1); +	} + +/* Call this to write data in records of type 'type' + * It will return <= 0 if not all data has been sent or non-blocking IO. + */ +int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) +	{ +	const unsigned char *buf=buf_; +	unsigned int tot,n,nw; +	int i; +	unsigned int max_plain_length; + +	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 (type == SSL3_RT_APPLICATION_DATA && (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS)) +			max_plain_length = SSL3_RT_DEFAULT_PLAIN_LENGTH; +		else +			max_plain_length = s->max_send_fragment; + +		if (n > max_plain_length) +			nw = max_plain_length; +		else +			nw=n; + +		i=do_ssl3_write(s, type, &(buf[tot]), nw, 0); +		if (i <= 0) +			{ +			s->s3->wnum=tot; +			return i; +			} + +		if ((i == (int)n) || +			(type == SSL3_RT_APPLICATION_DATA && +			 (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) +			{ +			/* next chunk of data should get another prepended empty fragment +			 * in ciphersuites with known-IV weakness: */ +			s->s3->empty_fragment_done = 0; +			 +			return tot+i; +			} + +		n-=i; +		tot+=i; +		} +	} + +static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, +			 unsigned int len, int create_empty_fragment) +	{ +	unsigned char *p,*plen; +	int i,mac_size,clear=0; +	int prefix_len=0; +	long align=0; +	SSL3_RECORD *wr; +	SSL3_BUFFER *wb=&(s->s3->wbuf); +	SSL_SESSION *sess; + + 	if (wb->buf == NULL) +		if (!ssl3_setup_write_buffer(s)) +			return -1; + +	/* first check if there is a SSL3_BUFFER still being written +	 * out.  This will happen with non blocking IO */ +	if (wb->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=s->method->ssl_dispatch_alert(s); +		if (i <= 0) +			return(i); +		/* if it went, fall through and send more stuff */ +		} + +	if (len == 0 && !create_empty_fragment) +		return 0; + +	wr= &(s->s3->wrec); +	sess=s->session; + +	if (	(sess == NULL) || +		(s->enc_write_ctx == NULL) || +		(EVP_MD_CTX_md(s->write_hash) == NULL)) +		clear=1; + +	if (clear) +		mac_size=0; +	else +		{ +		mac_size=EVP_MD_CTX_size(s->write_hash); +		if (mac_size < 0) +			goto err; +		} + +	/* 'create_empty_fragment' is true only when this function calls itself */ +	if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) +		{ +		/* countermeasure against known-IV weakness in CBC ciphersuites +		 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ + +		if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) +			{ +			/* recursive function call with 'create_empty_fragment' set; +			 * this prepares and buffers the data for an empty fragment +			 * (these 'prefix_len' bytes are sent out later +			 * together with the actual payload) */ +			prefix_len = do_ssl3_write(s, type, buf, 0, 1); +			if (prefix_len <= 0) +				goto err; + +			if (prefix_len > +		(SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) +				{ +				/* insufficient space */ +				SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR); +				goto err; +				} +			} +		 +		s->s3->empty_fragment_done = 1; +		} + +	/* resize if necessary to hold the data. */ +	if (len + SSL3_RT_DEFAULT_WRITE_OVERHEAD > wb->len) +		{ +		if ((p=OPENSSL_realloc(wb->buf, len + SSL3_RT_DEFAULT_WRITE_OVERHEAD))==NULL) +			{ +			SSLerr(SSL_F_DO_SSL3_WRITE,ERR_R_MALLOC_FAILURE); +			goto err; +			} +		wb->buf = p; +		wb->len = len + SSL3_RT_DEFAULT_WRITE_OVERHEAD; +		} + +	if (create_empty_fragment) +		{ +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 +		/* extra fragment would be couple of cipher blocks, +		 * which would be multiple of SSL3_ALIGN_PAYLOAD, so +		 * if we want to align the real payload, then we can +		 * just pretent we simply have two headers. */ +		align = (long)wb->buf + 2*SSL3_RT_HEADER_LENGTH; +		align = (-align)&(SSL3_ALIGN_PAYLOAD-1); +#endif +		p = wb->buf + align; +		wb->offset  = align; +		} +	else if (prefix_len) +		{ +		p = wb->buf + wb->offset + prefix_len; +		} +	else +		{ +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 +		align = (long)wb->buf + SSL3_RT_HEADER_LENGTH; +		align = (-align)&(SSL3_ALIGN_PAYLOAD-1); +#endif +		p = wb->buf + align; +		wb->offset  = align; +		} + +	/* write the header */ + +	*(p++)=type&0xff; +	wr->type=type; + +	*(p++)=(s->version>>8); +	*(p++)=s->version&0xff; + +	/* field 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 (s->compress != NULL) +		{ +		if (!ssl3_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) +		{ +		if (s->method->ssl3_enc->mac(s,&(p[wr->length]),1) < 0) +			goto err; +		wr->length+=mac_size; +		wr->input=p; +		wr->data=p; +		} + +	/* ssl3_enc can only have an error on read */ +	s->method->ssl3_enc->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; + +	if (create_empty_fragment) +		{ +		/* we are in a recursive call; +		 * just return the length, don't write out anything here +		 */ +		return wr->length; +		} + +	/* now let's set up wb */ +	wb->left = prefix_len + wr->length; + +	/* memorize arguments so that ssl3_write_pending can detect bad write retries later */ +	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 */ +int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, +	unsigned int len) +	{ +	int i; +	SSL3_BUFFER *wb=&(s->s3->wbuf); + +/* XXXX */ +	if ((s->s3->wpend_tot > (int)len) +		|| ((s->s3->wpend_buf != buf) && +			!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) +		|| (s->s3->wpend_type != type)) +		{ +		SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); +		return(-1); +		} + +	for (;;) +		{ +		clear_sys_error(); +		if (s->wbio != NULL) +			{ +			s->rwstate=SSL_WRITING; +			i=BIO_write(s->wbio, +				(char *)&(wb->buf[wb->offset]), +				(unsigned int)wb->left); +			} +		else +			{ +			SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET); +			i= -1; +			} +		if (i == wb->left) +			{ +			wb->left=0; +			wb->offset+=i; +			if (s->mode & SSL_MODE_RELEASE_BUFFERS && +			    SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER) +				ssl3_release_write_buffer(s); +			s->rwstate=SSL_NOTHING; +			return(s->s3->wpend_ret); +			} +		else if (i <= 0) { +			if (s->version == DTLS1_VERSION || +			    s->version == DTLS1_BAD_VER) { +				/* For DTLS, just drop it. That's kind of the whole +				   point in using a datagram service */ +				wb->left = 0; +			} +			return(i); +		} +		wb->offset+=i; +		wb->left-=i; +		} +	} + +/* Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + *   -  0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify), ChangeCipherSpec records (not really + * a surprise, but handled as if it were), or renegotiation requests. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + *     Change cipher spec protocol + *             just 1 byte needed, no need for keeping anything stored + *     Alert protocol + *             2 bytes needed (AlertLevel, AlertDescription) + *     Handshake protocol + *             4 bytes needed (HandshakeType, uint24 length) -- we just have + *             to detect unexpected Client Hello and Hello Request messages + *             here, anything else is handled by higher layers + *     Application data protocol + *             none of our business + */ +int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) +	{ +	int al,i,j,ret; +	unsigned int n; +	SSL3_RECORD *rr; +	void (*cb)(const SSL *ssl,int type2,int val)=NULL; + +	if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ +		if (!ssl3_setup_read_buffer(s)) +			return(-1); + +	if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) || +	    (peek && (type != SSL3_RT_APPLICATION_DATA))) +		{ +		SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR); +		return -1; +		} + +	if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0)) +		/* (partially) satisfy request from storage */ +		{ +		unsigned char *src = s->s3->handshake_fragment; +		unsigned char *dst = buf; +		unsigned int k; + +		/* peek == 0 */ +		n = 0; +		while ((len > 0) && (s->s3->handshake_fragment_len > 0)) +			{ +			*dst++ = *src++; +			len--; s->s3->handshake_fragment_len--; +			n++; +			} +		/* move any remaining fragment bytes: */ +		for (k = 0; k < s->s3->handshake_fragment_len; k++) +			s->s3->handshake_fragment[k] = *src++; +		return n; +	} + +	/* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */ + +	if (!s->in_handshake && SSL_in_init(s)) +		{ +		/* type == SSL3_RT_APPLICATION_DATA */ +		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,     - offset into 'data' for next read +	 * s->s3->rrec.length,  - number of bytes. */ +	rr = &(s->s3->rrec); + +	/* get new packet if necessary */ +	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 /* set when we receive ChangeCipherSpec, +	                               * reset by ssl3_get_finished */ +		&& (rr->type != SSL3_RT_HANDSHAKE)) +		{ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); +		goto f_err; +		} + +	/* If the other end has shut down, throw anything we read away +	 * (even in 'peek' mode) */ +	if (s->shutdown & SSL_RECEIVED_SHUTDOWN) +		{ +		rr->length=0; +		s->rwstate=SSL_NOTHING; +		return(0); +		} + + +	if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ +		{ +		/* 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=SSL_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 = (unsigned int)len; + +		memcpy(buf,&(rr->data[rr->off]),n); +		if (!peek) +			{ +			rr->length-=n; +			rr->off+=n; +			if (rr->length == 0) +				{ +				s->rstate=SSL_ST_READ_HEADER; +				rr->off=0; +				if (s->mode & SSL_MODE_RELEASE_BUFFERS) +					ssl3_release_read_buffer(s); +				} +			} +		return(n); +		} + + +	/* If we get here, then type != rr->type; if we have a handshake +	 * message, then it was unexpected (Hello Request or Client Hello). */ + +	/* In case of record types for which we have 'fragment' storage, +	 * fill that so that we can process the data at a fixed place. +	 */ +		{ +		unsigned int dest_maxlen = 0; +		unsigned char *dest = NULL; +		unsigned int *dest_len = NULL; + +		if (rr->type == SSL3_RT_HANDSHAKE) +			{ +			dest_maxlen = sizeof s->s3->handshake_fragment; +			dest = s->s3->handshake_fragment; +			dest_len = &s->s3->handshake_fragment_len; +			} +		else if (rr->type == SSL3_RT_ALERT) +			{ +			dest_maxlen = sizeof s->s3->alert_fragment; +			dest = s->s3->alert_fragment; +			dest_len = &s->s3->alert_fragment_len; +			} + +		if (dest_maxlen > 0) +			{ +			n = dest_maxlen - *dest_len; /* available space in 'dest' */ +			if (rr->length < n) +				n = rr->length; /* available bytes */ + +			/* now move 'n' bytes: */ +			while (n-- > 0) +				{ +				dest[(*dest_len)++] = rr->data[rr->off++]; +				rr->length--; +				} + +			if (*dest_len < dest_maxlen) +				goto start; /* fragment was too small */ +			} +		} + +	/* s->s3->handshake_fragment_len == 4  iff  rr->type == SSL3_RT_HANDSHAKE; +	 * s->s3->alert_fragment_len == 2      iff  rr->type == SSL3_RT_ALERT. +	 * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ + +	/* If we are a client, check for an incoming 'Hello Request': */ +	if ((!s->server) && +		(s->s3->handshake_fragment_len >= 4) && +		(s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && +		(s->session != NULL) && (s->session->cipher != NULL)) +		{ +		s->s3->handshake_fragment_len = 0; + +		if ((s->s3->handshake_fragment[1] != 0) || +			(s->s3->handshake_fragment[2] != 0) || +			(s->s3->handshake_fragment[3] != 0)) +			{ +			al=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); +			goto f_err; +			} + +		if (s->msg_callback) +			s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg); + +		if (SSL_is_init_finished(s) && +			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && +			!s->s3->renegotiate) +			{ +			ssl3_renegotiate(s); +			if (ssl3_renegotiate_check(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); +					} + +				if (!(s->mode & SSL_MODE_AUTO_RETRY)) +					{ +					if (s->s3->rbuf.left == 0) /* no read-ahead left? */ +						{ +						BIO *bio; +						/* In the case where we try to read application data, +						 * but we trigger an SSL handshake, we return -1 with +						 * the retry option set.  Otherwise renegotiation may +						 * cause nasty problems in the blocking world */ +						s->rwstate=SSL_READING; +						bio=SSL_get_rbio(s); +						BIO_clear_retry_flags(bio); +						BIO_set_retry_read(bio); +						return(-1); +						} +					} +				} +			} +		/* we either finished a handshake or ignored the request, +		 * now try again to obtain the (application) data we were asked for */ +		goto start; +		} +	/* If we are a server and get a client hello when renegotiation isn't +	 * allowed send back a no renegotiation alert and carry on. +	 * WARNING: experimental code, needs reviewing (steve) +	 */ +	if (s->server && +		SSL_is_init_finished(s) && +    		!s->s3->send_connection_binding && +		(s->version > SSL3_VERSION) && +		(s->s3->handshake_fragment_len >= 4) && +		(s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) && +		(s->session != NULL) && (s->session->cipher != NULL) && +		!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) +		 +		{ +		/*s->s3->handshake_fragment_len = 0;*/ +		rr->length = 0; +		ssl3_send_alert(s,SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); +		goto start; +		} +	if (s->s3->alert_fragment_len >= 2) +		{ +		int alert_level = s->s3->alert_fragment[0]; +		int alert_descr = s->s3->alert_fragment[1]; + +		s->s3->alert_fragment_len = 0; + +		if (s->msg_callback) +			s->msg_callback(0, s->version, SSL3_RT_ALERT, s->s3->alert_fragment, 2, s, s->msg_callback_arg); + +		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 = (alert_level << 8) | alert_descr; +			cb(s, SSL_CB_READ_ALERT, j); +			} + +		if (alert_level == 1) /* warning */ +			{ +			s->s3->warn_alert = alert_descr; +			if (alert_descr == SSL_AD_CLOSE_NOTIFY) +				{ +				s->shutdown |= SSL_RECEIVED_SHUTDOWN; +				return(0); +				} +			/* This is a warning but we receive it if we requested +			 * renegotiation and the peer denied it. Terminate with +			 * a fatal alert because if application tried to +			 * renegotiatie it presumably had a good reason and +			 * expects it to succeed. +			 * +			 * In future we might have a renegotiation where we +			 * don't care if the peer refused it where we carry on. +			 */ +			else if (alert_descr == SSL_AD_NO_RENEGOTIATION) +				{ +				al = SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_NO_RENEGOTIATION); +				goto f_err; +				} +			} +		else if (alert_level == 2) /* fatal */ +			{ +			char tmp[16]; + +			s->rwstate=SSL_NOTHING; +			s->s3->fatal_alert = alert_descr; +			SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr); +			BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr); +			ERR_add_error_data(2,"SSL alert number ",tmp); +			s->shutdown|=SSL_RECEIVED_SHUTDOWN; +			SSL_CTX_remove_session(s->ctx,s->session); +			return(0); +			} +		else +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE); +			goto f_err; +			} + +		goto start; +		} + +	if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */ +		{ +		s->rwstate=SSL_NOTHING; +		rr->length=0; +		return(0); +		} + +	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) +		{ +		/* 'Change Cipher Spec' is just a single byte, so we know +		 * exactly what the record payload has to look like */ +		if (	(rr->length != 1) || (rr->off != 0) || +			(rr->data[0] != SSL3_MT_CCS)) +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); +			goto f_err; +			} + +		/* Check we have a cipher to change to */ +		if (s->s3->tmp.new_cipher == NULL) +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_CCS_RECEIVED_EARLY); +			goto f_err; +			} + +		rr->length=0; + +		if (s->msg_callback) +			s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg); + +		s->s3->change_cipher_spec=1; +		if (!ssl3_do_change_cipher_spec(s)) +			goto err; +		else +			goto start; +		} + +	/* Unexpected handshake message (Client Hello, or protocol violation) */ +	if ((s->s3->handshake_fragment_len >= 4) &&	!s->in_handshake) +		{ +		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && +			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) +			{ +#if 0 /* worked only because C operator preferences are not as expected (and +       * because this is not really needed for clients except for detecting +       * protocol violations): */ +			s->state=SSL_ST_BEFORE|(s->server) +				?SSL_ST_ACCEPT +				:SSL_ST_CONNECT; +#else +			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; +#endif +			s->new_session=1; +			} +		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); +			} + +		if (!(s->mode & SSL_MODE_AUTO_RETRY)) +			{ +			if (s->s3->rbuf.left == 0) /* no read-ahead left? */ +				{ +				BIO *bio; +				/* In the case where we try to read application data, +				 * but we trigger an SSL handshake, we return -1 with +				 * the retry option set.  Otherwise renegotiation may +				 * cause nasty problems in the blocking world */ +				s->rwstate=SSL_READING; +				bio=SSL_get_rbio(s); +				BIO_clear_retry_flags(bio); +				BIO_set_retry_read(bio); +				return(-1); +				} +			} +		goto start; +		} + +	switch (rr->type) +		{ +	default: +#ifndef OPENSSL_NO_TLS +		/* TLS just ignores unknown message types */ +		if (s->version == TLS1_VERSION) +			{ +			rr->length = 0; +			goto start; +			} +#endif +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); +		goto f_err; +	case SSL3_RT_CHANGE_CIPHER_SPEC: +	case SSL3_RT_ALERT: +	case SSL3_RT_HANDSHAKE: +		/* we already handled all of these, with the possible exception +		 * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that +		 * should not happen when type != rr->type */ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_READ_BYTES,ERR_R_INTERNAL_ERROR); +		goto f_err; +	case SSL3_RT_APPLICATION_DATA: +		/* At this point, we were expecting handshake data, +		 * but have application data.  If the library was +		 * running inside ssl3_read() (i.e. in_read_app_data +		 * is set) and it makes sense to read application data +		 * at this point (session renegotiation not yet started), +		 * we will indulge it. +		 */ +		if (s->s3->in_read_app_data && +			(s->s3->total_renegotiations != 0) && +			(( +				(s->state & SSL_ST_CONNECT) && +				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) && +				(s->state <= SSL3_ST_CR_SRVR_HELLO_A) +				) || ( +					(s->state & SSL_ST_ACCEPT) && +					(s->state <= SSL3_ST_SW_HELLO_REQ_A) && +					(s->state >= SSL3_ST_SR_CLNT_HELLO_A) +					) +				)) +			{ +			s->s3->in_read_app_data=2; +			return(-1); +			} +		else +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); +			goto f_err; +			} +		} +	/* not reached */ + +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +	return(-1); +	} + +int ssl3_do_change_cipher_spec(SSL *s) +	{ +	int i; +#ifdef OPENSSL_NO_NEXTPROTONEG +	const char *sender; +	int slen; +#endif + +	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) +		{ +		if (s->session == NULL)  +			{ +			/* might happen if dtls1_read_bytes() calls this */ +			SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY); +			return (0); +			} + +		s->session->cipher=s->s3->tmp.new_cipher; +		if (!s->method->ssl3_enc->setup_key_block(s)) return(0); +		} + +	if (!s->method->ssl3_enc->change_cipher_state(s,i)) +		return(0); + +#ifdef OPENSSL_NO_NEXTPROTONEG +	/* we have to record the message digest at +	 * this point so we can get it before we read +	 * the finished message */ +	if (s->state & SSL_ST_CONNECT) +		{ +		sender=s->method->ssl3_enc->server_finished_label; +		slen=s->method->ssl3_enc->server_finished_label_len; +		} +	else +		{ +		sender=s->method->ssl3_enc->client_finished_label; +		slen=s->method->ssl3_enc->client_finished_label_len; +		} + +	s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, +		sender,slen,s->s3->tmp.peer_finish_md); +#endif + +	return(1); +	} + +int ssl3_send_alert(SSL *s, int level, int desc) +	{ +	/* Map tls/ssl alert value to correct one */ +	desc=s->method->ssl3_enc->alert_value(desc); +	if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) +		desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */ +	if (desc < 0) return -1; +	/* 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? */ +		return s->method->ssl_dispatch_alert(s); +	/* else data is still being written out, we will get written +	 * some time in the future */ +	return -1; +	} + +int ssl3_dispatch_alert(SSL *s) +	{ +	int i,j; +	void (*cb)(const SSL *ssl,int type,int val)=NULL; + +	s->s3->alert_dispatch=0; +	i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0); +	if (i <= 0) +		{ +		s->s3->alert_dispatch=1; +		} +	else +		{ +		/* Alert sent to BIO.  If it is important, flush 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) +			(void)BIO_flush(s->wbio); + +		if (s->msg_callback) +			s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s, s->msg_callback_arg); + +		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/main/openssl/ssl/s3_srvr.c b/main/openssl/ssl/s3_srvr.c new file mode 100644 index 00000000..60591622 --- /dev/null +++ b/main/openssl/ssl/s3_srvr.c @@ -0,0 +1,3314 @@ +/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by  + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#define REUSE_CIPHER_BUG +#define NETSCAPE_HANG_BUG + +#include <stdio.h> +#include "ssl_locl.h" +#include "kssl_lcl.h" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/x509.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif +#include <openssl/bn.h> +#ifndef OPENSSL_NO_KRB5 +#include <openssl/krb5_asn.h> +#endif +#include <openssl/md5.h> + +static const SSL_METHOD *ssl3_get_server_method(int ver); + +static const SSL_METHOD *ssl3_get_server_method(int ver) +	{ +	if (ver == SSL3_VERSION) +		return(SSLv3_server_method()); +	else +		return(NULL); +	} + +IMPLEMENT_ssl3_meth_func(SSLv3_server_method, +			ssl3_accept, +			ssl_undefined_function, +			ssl3_get_server_method) + +int ssl3_accept(SSL *s) +	{ +	BUF_MEM *buf; +	unsigned long alg_k,Time=(unsigned long)time(NULL); +	void (*cb)(const SSL *ssl,int type,int val)=NULL; +	int ret= -1; +	int new_state,state,skip=0; + +	RAND_add(&Time,sizeof(Time),0); +	ERR_clear_error(); +	clear_sys_error(); + +	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 */ +	s->in_handshake++; +	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); + +	if (s->cert == NULL) +		{ +		SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET); +		return(-1); +		} + +	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: + +			s->server=1; +			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); + +			if ((s->version>>8) != 3) +				{ +				SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); +				return -1; +				} +			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; +				} + +			s->init_num=0; + +			if (s->state != SSL_ST_RENEGOTIATE) +				{ +				/* Ok, we now need to push on a buffering BIO so that +				 * the output is sent in a way that TCP likes :-) +				 */ +				if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } +				 +				ssl3_init_finished_mac(s); +				s->state=SSL3_ST_SR_CLNT_HELLO_A; +				s->ctx->stats.sess_accept++; +				} +			else if (!s->s3->send_connection_binding && +				!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) +				{ +				/* Server attempting to renegotiate with +				 * client that doesn't support secure +				 * renegotiation. +				 */ +				SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +				ret = -1; +				goto end; +				} +			else +				{ +				/* s->state == SSL_ST_RENEGOTIATE, +				 * we will just send a HelloRequest */ +				s->ctx->stats.sess_accept_renegotiate++; +				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: +			s->state=SSL_ST_OK; +			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->new_session = 2; +			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; +#ifndef OPENSSL_NO_TLSEXT +			if (s->hit) +				{ +				if (s->tlsext_ticket_expected) +					s->state=SSL3_ST_SW_SESSION_TICKET_A; +				else +					s->state=SSL3_ST_SW_CHANGE_A; +				} +#else +			if (s->hit) +					s->state=SSL3_ST_SW_CHANGE_A; +#endif +			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 or anon ECDH, */ +			/* normal PSK or KRB5 */ +			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) +				&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) +				&& !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) +				{ +				ret=ssl3_send_server_certificate(s); +				if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT +				if (s->tlsext_status_expected) +					s->state=SSL3_ST_SW_CERT_STATUS_A; +				else +					s->state=SSL3_ST_SW_KEY_EXCH_A; +				} +			else +				{ +				skip = 1; +				s->state=SSL3_ST_SW_KEY_EXCH_A; +				} +#else +				} +			else +				skip=1; + +			s->state=SSL3_ST_SW_KEY_EXCH_A; +#endif +			s->init_num=0; +			break; + +		case SSL3_ST_SW_KEY_EXCH_A: +		case SSL3_ST_SW_KEY_EXCH_B: +			alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + +			/* clear this, it may get reset by +			 * send_server_key_exchange */ +			if ((s->options & SSL_OP_EPHEMERAL_RSA) +#ifndef OPENSSL_NO_KRB5 +				&& !(alg_k & SSL_kKRB5) +#endif /* OPENSSL_NO_KRB5 */ +				) +				/* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key +				 * even when forbidden by protocol specs +				 * (handshake may fail as clients are not required to +				 * be able to handle this) */ +				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 +			 * +			 * PSK: may send PSK identity hints +			 * +			 * For ECC ciphersuites, we send a serverKeyExchange +			 * message only if the cipher suite is either +			 * ECDH-anon or ECDHE. In other cases, the +			 * server certificate contains the server's +			 * public key for key exchange. +			 */ +			if (s->s3->tmp.use_rsa_tmp +			/* PSK: send ServerKeyExchange if PSK identity +			 * hint if provided */ +#ifndef OPENSSL_NO_PSK +			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) +#endif +			    || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH)) +			    || (alg_k & SSL_kEECDH) +			    || ((alg_k & SSL_kRSA) +				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL +				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) +					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) +					) +				    ) +				) +			    ) +				{ +				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 (/* don't request cert unless asked for it: */ +				!(s->verify_mode & SSL_VERIFY_PEER) || +				/* if SSL_VERIFY_CLIENT_ONCE is set, +				 * don't request cert during re-negotiation: */ +				((s->session->peer != NULL) && +				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || +				/* never request cert in anonymous ciphersuites +				 * (see section "Certificate request" in SSL 3 drafts +				 * and in RFC 2246): */ +				((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && +				 /* ... except when the application insists on verification +				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */ +				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || +				 /* never request cert in Kerberos ciphersuites */ +				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) +				/* With normal PSK Certificates and +				 * Certificate Requests are omitted */ +				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +				{ +				/* no cert request */ +				skip=1; +				s->s3->tmp.cert_request=0; +				s->state=SSL3_ST_SW_SRVR_DONE_A; +				} +			else +				{ +				s->s3->tmp.cert_request=1; +				ret=ssl3_send_certificate_request(s); +				if (ret <= 0) goto end; +#ifndef NETSCAPE_HANG_BUG +				s->state=SSL3_ST_SW_SRVR_DONE_A; +#else +				s->state=SSL3_ST_SW_FLUSH; +				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; +#endif +				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: + +			/* This code originally checked to see if +			 * any data was pending using BIO_CTRL_INFO +			 * and then flushed. This caused problems +			 * as documented in PR#1939. The proposed +			 * fix doesn't completely resolve this issue +			 * as buggy implementations of BIO_CTRL_PENDING +			 * still exist. So instead we just flush +			 * unconditionally. +			 */ + +			s->rwstate=SSL_WRITING; +			if (BIO_flush(s->wbio) <= 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: +			/* Check for second client hello (MS SGC) */ +			ret = ssl3_check_client_hello(s); +			if (ret <= 0) +				goto end; +			if (ret == 2) +				s->state = SSL3_ST_SR_CLNT_HELLO_C; +			else { +				if (s->s3->tmp.cert_request) +					{ +					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; +			if (ret == 2) +				{ +				/* For the ECDH ciphersuites when +				 * the client sends its ECDH pub key in +				 * a certificate, the CertificateVerify +				 * message is not sent. +				 * Also for GOST ciphersuites when +				 * the client uses its key from the certificate +				 * for key exchange. +				 */ +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) +				s->state=SSL3_ST_SR_FINISHED_A; +#else +				if (s->s3->next_proto_neg_seen) +					s->state=SSL3_ST_SR_NEXT_PROTO_A; +				else +					s->state=SSL3_ST_SR_FINISHED_A; +#endif +				s->init_num = 0; +				} +			else +				{ +				int offset=0; +				int dgst_num; + +				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 +				 * FIXME - digest processing for CertificateVerify +				 * should be generalized. But it is next step +				 */ +				if (s->s3->handshake_buffer) +					if (!ssl3_digest_cached_records(s)) +						return -1; +				for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)	 +					if (s->s3->handshake_dgst[dgst_num])  +						{ +						int dgst_size; + +						s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset])); +						dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]); +						if (dgst_size < 0) +							{ +							ret = -1; +							goto end; +							} +						offset+=dgst_size; +						}		 +				} +			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; + +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) +			s->state=SSL3_ST_SR_FINISHED_A; +#else +			if (s->s3->next_proto_neg_seen) +				s->state=SSL3_ST_SR_NEXT_PROTO_A; +			else +				s->state=SSL3_ST_SR_FINISHED_A; +#endif +			s->init_num=0; +			break; + +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +		case SSL3_ST_SR_NEXT_PROTO_A: +		case SSL3_ST_SR_NEXT_PROTO_B: +			ret=ssl3_get_next_proto(s); +			if (ret <= 0) goto end; +			s->init_num = 0; +			s->state=SSL3_ST_SR_FINISHED_A; +			break; +#endif + +		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); +			if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT +			if (s->tlsext_ticket_expected) +				s->state=SSL3_ST_SW_SESSION_TICKET_A; +			else if (s->hit) +				s->state=SSL_ST_OK; +#else +			if (s->hit) +				s->state=SSL_ST_OK; +#endif +			else +				s->state=SSL3_ST_SW_CHANGE_A; +			s->init_num=0; +			break; + +#ifndef OPENSSL_NO_TLSEXT +		case SSL3_ST_SW_SESSION_TICKET_A: +		case SSL3_ST_SW_SESSION_TICKET_B: +			ret=ssl3_send_newsession_ticket(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_SW_CHANGE_A; +			s->init_num=0; +			break; + +		case SSL3_ST_SW_CERT_STATUS_A: +		case SSL3_ST_SW_CERT_STATUS_B: +			ret=ssl3_send_cert_status(s); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_SW_KEY_EXCH_A; +			s->init_num=0; +			break; + +#endif + +		case SSL3_ST_SW_CHANGE_A: +		case SSL3_ST_SW_CHANGE_B: + +			s->session->cipher=s->s3->tmp.new_cipher; +			if (!s->method->ssl3_enc->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 (!s->method->ssl3_enc->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, +				s->method->ssl3_enc->server_finished_label, +				s->method->ssl3_enc->server_finished_label_len); +			if (ret <= 0) goto end; +			s->state=SSL3_ST_SW_FLUSH; +			if (s->hit) +				{ +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) +				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; +#else +				if (s->s3->next_proto_neg_seen) +					s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A; +				else +					s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; +#endif +				} +			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 */ +			ssl_free_wbio_buffer(s); + +			s->init_num=0; + +			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */ +				{ +				/* actually not necessarily a 'new' session unless +				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ +				 +				s->new_session=0; +				 +				ssl_update_cache(s,SSL_SESS_CACHE_SERVER); +				 +				s->ctx->stats.sess_accept_good++; +				/* s->server=1; */ +				s->handshake_func=ssl3_accept; + +				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); +				} +			 +			ret = 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) +				{ +				if ((ret=BIO_flush(s->wbio)) <= 0) +					goto end; +				} + + +			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); */ + +	s->in_handshake--; +	if (cb != NULL) +		cb(s,SSL_CB_ACCEPT_EXIT,ret); +	return(ret); +	} + +int ssl3_send_hello_request(SSL *s) +	{ +	unsigned char *p; + +	if (s->state == SSL3_ST_SW_HELLO_REQ_A) +		{ +		p=(unsigned char *)s->init_buf->data; +		*(p++)=SSL3_MT_HELLO_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)); +	} + +int ssl3_check_client_hello(SSL *s) +	{ +	int ok; +	long n; + +	/* this function is called when we really expect a Certificate message, +	 * so permit appropriate message length */ +	n=s->method->ssl_get_message(s, +		SSL3_ST_SR_CERT_A, +		SSL3_ST_SR_CERT_B, +		-1, +		s->max_cert_list, +		&ok); +	if (!ok) return((int)n); +	s->s3->tmp.reuse_message = 1; +	if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) +		{ +		/* Throw away what we have done so far in the current handshake, +		 * which will now be aborted. (A full SSL_clear would be too much.) */ +#ifndef OPENSSL_NO_DH +		if (s->s3->tmp.dh != NULL) +			{ +			DH_free(s->s3->tmp.dh); +			s->s3->tmp.dh = NULL; +			} +#endif +#ifndef OPENSSL_NO_ECDH +		if (s->s3->tmp.ecdh != NULL) +			{ +			EC_KEY_free(s->s3->tmp.ecdh); +			s->s3->tmp.ecdh = NULL; +			} +#endif +		return 2; +		} +	return 1; +} + +int ssl3_get_client_hello(SSL *s) +	{ +	int i,j,ok,al,ret= -1; +	unsigned int cookie_len; +	long n; +	unsigned long id; +	unsigned char *p,*d,*q; +	SSL_CIPHER *c; +#ifndef OPENSSL_NO_COMP +	SSL_COMP *comp=NULL; +#endif +	STACK_OF(SSL_CIPHER) *ciphers=NULL; + +	/* We do this so that we will respond with our native type. +	 * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, +	 * This down switching should be handled by a different method. +	 * If we are SSLv3, we will respond with SSLv3, even if prompted with +	 * TLSv1. +	 */ +	if (s->state == SSL3_ST_SR_CLNT_HELLO_A) +		{ +		s->state=SSL3_ST_SR_CLNT_HELLO_B; +		} +	s->first_packet=1; +	n=s->method->ssl_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); +	s->first_packet=0; +	d=p=(unsigned char *)s->init_msg; + +	/* use version from inside client hello, not from record header +	 * (may differ: see RFC 2246, Appendix E, second paragraph) */ +	s->client_version=(((int)p[0])<<8)|(int)p[1]; +	p+=2; + +	if ((s->version == DTLS1_VERSION && s->client_version > s->version) || +	    (s->version != DTLS1_VERSION && s->client_version < s->version)) +		{ +		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); +		if ((s->client_version>>8) == SSL3_VERSION_MAJOR) +			{ +			/* similar to ssl3_get_record, send alert using remote version number */ +			s->version = s->client_version; +			} +		al = SSL_AD_PROTOCOL_VERSION; +		goto f_err; +		} + +	/* If we require cookies and this ClientHello doesn't +	 * contain one, just return since we do not want to +	 * allocate any memory yet. So check cookie length... +	 */ +	if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) +		{ +		unsigned int session_length, cookie_length; +		 +		session_length = *(p + SSL3_RANDOM_SIZE); +		cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1); + +		if (cookie_length == 0) +			return 1; +		} + +	/* 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; +	/* Versions before 0.9.7 always allow session reuse during renegotiation +	 * (i.e. when s->new_session is true), option +	 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7. +	 * Maybe this optional behaviour should always have been the default, +	 * but we cannot safely change the default behaviour (or new applications +	 * might be written that become totally unsecure when compiled with +	 * an earlier library version) +	 */ +	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) +		{ +	        if (!s->session_creation_enabled) +			{ +			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); +			goto err; +		} +		if (!ssl_get_new_session(s,1)) +			goto err; +		} +	else +		{ +		i=ssl_get_prev_session(s, p, j, d + n); +		if (i == 1) +			{ /* previous session */ +			s->hit=1; +			} +		else if (i == -1) +			goto err; +		else /* i == 0 */ +			{ +		        if (!s->session_creation_enabled) +				{ +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); +				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); +				goto err; +				} +			if (!ssl_get_new_session(s,1)) +				goto err; +			} +		} + +	p+=j; + +	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) +		{ +		/* cookie stuff */ +		cookie_len = *(p++); + +		/*  +		 * The ClientHello may contain a cookie even if the +		 * HelloVerify message has not been sent--make sure that it +		 * does not cause an overflow. +		 */ +		if ( cookie_len > sizeof(s->d1->rcvd_cookie)) +			{ +			/* too much data */ +			al = SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); +			goto f_err; +			} + +		/* verify the cookie if appropriate option is set. */ +		if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && +			cookie_len > 0) +			{ +			memcpy(s->d1->rcvd_cookie, p, cookie_len); + +			if ( s->ctx->app_verify_cookie_cb != NULL) +				{ +				if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie, +					cookie_len) == 0) +					{ +					al=SSL_AD_HANDSHAKE_FAILURE; +					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,  +						SSL_R_COOKIE_MISMATCH); +					goto f_err; +					} +				/* else cookie verification succeeded */ +				} +			else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie,  +						  s->d1->cookie_len) != 0) /* default verification */ +				{ +					al=SSL_AD_HANDSHAKE_FAILURE; +					SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,  +						SSL_R_COOKIE_MISMATCH); +					goto f_err; +				} + +			ret = 2; +			} + +		p += cookie_len; +		} + +	n2s(p,i); +	if ((i == 0) && (j != 0)) +		{ +		/* we need a cipher if we are not resuming a session */ +		al=SSL_AD_ILLEGAL_PARAMETER; +		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED); +		goto f_err; +		} +	if ((p+i) >= (d+n)) +		{ +		/* not enough data */ +		al=SSL_AD_DECODE_ERROR; +		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; + +#ifdef CIPHER_DEBUG +		printf("client sent %d ciphers\n",sk_num(ciphers)); +#endif +		for (i=0; i<sk_SSL_CIPHER_num(ciphers); i++) +			{ +			c=sk_SSL_CIPHER_value(ciphers,i); +#ifdef CIPHER_DEBUG +			printf("client [%2d of %2d]:%s\n", +				i,sk_num(ciphers),SSL_CIPHER_get_name(c)); +#endif +			if (c->id == id) +				{ +				j=1; +				break; +				} +			} +/* Disabled because it can be used in a ciphersuite downgrade + * attack: CVE-2010-4180. + */ +#if 0 +		if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1)) +			{ +			/* Special case as client bug workaround: the previously used cipher may +			 * not be in the current list, the client instead might be trying to +			 * continue using a cipher that before wasn't chosen due to server +			 * preferences.  We'll have to reject the connection if the cipher is not +			 * enabled, though. */ +			c = sk_SSL_CIPHER_value(ciphers, 0); +			if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0) +				{ +				s->session->cipher = c; +				j = 1; +				} +			} +#endif +		if (j == 0) +			{ +			/* we need to have the cipher in the cipher +			 * list if we are asked to reuse it */ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING); +			goto f_err; +			} +		} + +	/* compression */ +	i= *(p++); +	if ((p+i) > (d+n)) +		{ +		/* not enough data */ +		al=SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); +		goto f_err; +		} +	q=p; +	for (j=0; j<i; j++) +		{ +		if (p[j] == 0) break; +		} + +	p+=i; +	if (j >= i) +		{ +		/* no compress */ +		al=SSL_AD_DECODE_ERROR; +		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED); +		goto f_err; +		} + +#ifndef OPENSSL_NO_TLSEXT +	/* TLS extensions*/ +	if (s->version >= SSL3_VERSION) +		{ +		if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al)) +			{ +			/* 'al' set by ssl_parse_clienthello_tlsext */ +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT); +			goto f_err; +			} +		} +		if (ssl_check_clienthello_tlsext(s) <= 0) { +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); +			goto err; +		} + +	/* Check if we want to use external pre-shared secret for this +	 * handshake for not reused session only. We need to generate +	 * server_random before calling tls_session_secret_cb in order to allow +	 * SessionTicket processing to use it in key derivation. */ +	{ +		unsigned long Time; +		unsigned char *pos; +		Time=(unsigned long)time(NULL);			/* Time */ +		pos=s->s3->server_random; +		l2n(Time,pos); +		if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) +			{ +			al=SSL_AD_INTERNAL_ERROR; +			goto f_err; +			} +	} + +	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) +		{ +		SSL_CIPHER *pref_cipher=NULL; + +		s->session->master_key_length=sizeof(s->session->master_key); +		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, +			ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) +			{ +			s->hit=1; +			s->session->ciphers=ciphers; +			s->session->verify_result=X509_V_OK; + +			ciphers=NULL; + +			/* check if some cipher was preferred by call back */ +			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); +			if (pref_cipher == NULL) +				{ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); +				goto f_err; +				} + +			s->session->cipher=pref_cipher; + +			if (s->cipher_list) +				sk_SSL_CIPHER_free(s->cipher_list); + +			if (s->cipher_list_by_id) +				sk_SSL_CIPHER_free(s->cipher_list_by_id); + +			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); +			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); +			} +		} +#endif + +	/* Worst case, we will use the NULL compression, but if we have other +	 * options, we will now look for them.  We have i-1 compression +	 * algorithms from the client, starting at q. */ +	s->s3->tmp.new_compression=NULL; +#ifndef OPENSSL_NO_COMP +	/* This only happens if we have a cache hit */ +	if (s->session->compress_meth != 0) +		{ +		int m, comp_id = s->session->compress_meth; +		/* Perform sanity checks on resumed compression algorithm */ +		/* Can't disable compression */ +		if (s->options & SSL_OP_NO_COMPRESSION) +			{ +			al=SSL_AD_INTERNAL_ERROR; +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); +			goto f_err; +			} +		/* Look for resumed compression method */ +		for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) +			{ +			comp=sk_SSL_COMP_value(s->ctx->comp_methods,m); +			if (comp_id == comp->id) +				{ +				s->s3->tmp.new_compression=comp; +				break; +				} +			} +		if (s->s3->tmp.new_compression == NULL) +			{ +			al=SSL_AD_INTERNAL_ERROR; +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INVALID_COMPRESSION_ALGORITHM); +			goto f_err; +			} +		/* Look for resumed method in compression list */ +		for (m = 0; m < i; m++) +			{ +			if (q[m] == comp_id) +				break; +			} +		if (m >= i) +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING); +			goto f_err; +			} +		} +	else if (s->hit) +		comp = NULL; +	else if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods) +		{ /* See if we have a match */ +		int m,nn,o,v,done=0; + +		nn=sk_SSL_COMP_num(s->ctx->comp_methods); +		for (m=0; m<nn; m++) +			{ +			comp=sk_SSL_COMP_value(s->ctx->comp_methods,m); +			v=comp->id; +			for (o=0; o<i; o++) +				{ +				if (v == q[o]) +					{ +					done=1; +					break; +					} +				} +			if (done) break; +			} +		if (done) +			s->s3->tmp.new_compression=comp; +		else +			comp=NULL; +		} +#else +	/* If compression is disabled we'd better not try to resume a session +	 * using compression. +	 */ +	if (s->session->compress_meth != 0) +		{ +		al=SSL_AD_INTERNAL_ERROR; +		SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); +		goto f_err; +		} +#endif + +	/* Given s->session->ciphers and SSL_get_ciphers, we must +	 * pick a cipher */ + +	if (!s->hit) +		{ +#ifdef OPENSSL_NO_COMP +		s->session->compress_meth=0; +#else +		s->session->compress_meth=(comp == NULL)?0:comp->id; +#endif +		if (s->session->ciphers != NULL) +			sk_SSL_CIPHER_free(s->session->ciphers); +		s->session->ciphers=ciphers; +		if (ciphers == NULL) +			{ +			al=SSL_AD_ILLEGAL_PARAMETER; +			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(s)); + +		if (c == NULL) +			{ +			al=SSL_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_OF(SSL_CIPHER) *sk; +		SSL_CIPHER *nc=NULL; +		SSL_CIPHER *ec=NULL; + +		if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) +			{ +			sk=s->session->ciphers; +			for (i=0; i<sk_SSL_CIPHER_num(sk); i++) +				{ +				c=sk_SSL_CIPHER_value(sk,i); +				if (c->algorithm_enc & SSL_eNULL) +					nc=c; +				if (SSL_C_IS_EXPORT(c)) +					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; +		} + +	if (!ssl3_digest_cached_records(s)) +		goto f_err; +	 +	/* 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		- session reuse flag +	 * s->tmp.new_cipher	- the new cipher to use. +	 */ + +	if (ret < 0) ret=1; +	if (0) +		{ +f_err: +		ssl3_send_alert(s,SSL3_AL_FATAL,al); +		} +err: +	if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); +	return(ret); +	} + +int ssl3_send_server_hello(SSL *s) +	{ +	unsigned char *buf; +	unsigned char *p,*d; +	int i,sl; +	unsigned long l; +#ifdef OPENSSL_NO_TLSEXT +	unsigned long Time; +#endif + +	if (s->state == SSL3_ST_SW_SRVR_HELLO_A) +		{ +		buf=(unsigned char *)s->init_buf->data; +#ifdef OPENSSL_NO_TLSEXT +		p=s->s3->server_random; +		/* Generate server_random if it was not needed previously */ +		Time=(unsigned long)time(NULL);			/* Time */ +		l2n(Time,p); +		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) +			return -1; +#endif +		/* Do the message type and length last */ +		d=p= &(buf[4]); + +		*(p++)=s->version>>8; +		*(p++)=s->version&0xff; + +		/* 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 +		 * 12-Jan-98 - I'll now support the '0' length stuff. +		 * +		 * We also have an additional case where stateless session +		 * resumption is successful: we always send back the old +		 * session id. In this case s->hit is non zero: this can +		 * only happen if stateless session resumption is succesful +		 * if session caching is disabled so existing functionality +		 * is unaffected. +		 */ +		if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) +			&& !s->hit) +			s->session->session_id_length=0; + +		sl=s->session->session_id_length; +		if (sl > (int)sizeof(s->session->session_id)) +			{ +			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); +			return -1; +			} +		*(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 */ +#ifdef OPENSSL_NO_COMP +			*(p++)=0; +#else +		if (s->s3->tmp.new_compression == NULL) +			*(p++)=0; +		else +			*(p++)=s->s3->tmp.new_compression->id; +#endif +#ifndef OPENSSL_NO_TLSEXT +		if (ssl_prepare_serverhello_tlsext(s) <= 0) +			{ +			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT); +			return -1; +			} +		if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) +			{ +			SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); +			return -1; +			} +#endif +		/* do the header */ +		l=(p-d); +		d=buf; +		*(d++)=SSL3_MT_SERVER_HELLO; +		l2n3(l,d); + +		s->state=SSL3_ST_SW_SRVR_HELLO_B; +		/* number of bytes to write */ +		s->init_num=p-buf; +		s->init_off=0; +		} + +	/* SSL3_ST_SW_SRVR_HELLO_B */ +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int ssl3_send_server_done(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_SW_SRVR_DONE_B */ +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int ssl3_send_server_key_exchange(SSL *s) +	{ +#ifndef OPENSSL_NO_RSA +	unsigned char *q; +	int j,num; +	RSA *rsa; +	unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; +	unsigned int u; +#endif +#ifndef OPENSSL_NO_DH +	DH *dh=NULL,*dhp; +#endif +#ifndef OPENSSL_NO_ECDH +	EC_KEY *ecdh=NULL, *ecdhp; +	unsigned char *encodedPoint = NULL; +	int encodedlen = 0; +	int curve_id = 0; +	BN_CTX *bn_ctx = NULL;  +#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; + +	EVP_MD_CTX_init(&md_ctx); +	if (s->state == SSL3_ST_SW_KEY_EXCH_A) +		{ +		type=s->s3->tmp.new_cipher->algorithm_mkey; +		cert=s->cert; + +		buf=s->init_buf; + +		r[0]=r[1]=r[2]=r[3]=NULL; +		n=0; +#ifndef OPENSSL_NO_RSA +		if (type & SSL_kRSA) +			{ +			rsa=cert->rsa_tmp; +			if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) +				{ +				rsa=s->cert->rsa_tmp_cb(s, +				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), +				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); +				if(rsa == NULL) +				{ +					al=SSL_AD_HANDSHAKE_FAILURE; +					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY); +					goto f_err; +				} +				RSA_up_ref(rsa); +				cert->rsa_tmp=rsa; +				} +			if (rsa == NULL) +				{ +				al=SSL_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 OPENSSL_NO_DH +			if (type & SSL_kEDH) +			{ +			dhp=cert->dh_tmp; +			if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) +				dhp=s->cert->dh_tmp_cb(s, +				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), +				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); +			if (dhp == NULL) +				{ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); +				goto f_err; +				} + +			if (s->s3->tmp.dh != NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); +				goto 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->options & SSL_OP_SINGLE_DH_USE))) +				{ +				if(!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 +#ifndef OPENSSL_NO_ECDH +			if (type & SSL_kEECDH) +			{ +			const EC_GROUP *group; + +			ecdhp=cert->ecdh_tmp; +			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) +				{ +				ecdhp=s->cert->ecdh_tmp_cb(s, +				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), +				      SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); +				} +			if (ecdhp == NULL) +				{ +				al=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY); +				goto f_err; +				} + +			if (s->s3->tmp.ecdh != NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); +				goto err; +				} + +			/* Duplicate the ECDH structure. */ +			if (ecdhp == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} +			if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} + +			s->s3->tmp.ecdh=ecdh; +			if ((EC_KEY_get0_public_key(ecdh) == NULL) || +			    (EC_KEY_get0_private_key(ecdh) == NULL) || +			    (s->options & SSL_OP_SINGLE_ECDH_USE)) +				{ +				if(!EC_KEY_generate_key(ecdh)) +				    { +				    SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				    goto err; +				    } +				} + +			if (((group = EC_KEY_get0_group(ecdh)) == NULL) || +			    (EC_KEY_get0_public_key(ecdh)  == NULL) || +			    (EC_KEY_get0_private_key(ecdh) == NULL)) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} + +			if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && +			    (EC_GROUP_get_degree(group) > 163))  +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); +				goto err; +				} + +			/* XXX: For now, we only support ephemeral ECDH +			 * keys over named (not generic) curves. For  +			 * supported named curves, curve_id is non-zero. +			 */ +			if ((curve_id =  +			    tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) +			    == 0) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); +				goto err; +				} + +			/* Encode the public key. +			 * First check the size of encoding and +			 * allocate memory accordingly. +			 */ +			encodedlen = EC_POINT_point2oct(group,  +			    EC_KEY_get0_public_key(ecdh), +			    POINT_CONVERSION_UNCOMPRESSED,  +			    NULL, 0, NULL); + +			encodedPoint = (unsigned char *)  +			    OPENSSL_malloc(encodedlen*sizeof(unsigned char));  +			bn_ctx = BN_CTX_new(); +			if ((encodedPoint == NULL) || (bn_ctx == NULL)) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); +				goto err; +				} + + +			encodedlen = EC_POINT_point2oct(group,  +			    EC_KEY_get0_public_key(ecdh),  +			    POINT_CONVERSION_UNCOMPRESSED,  +			    encodedPoint, encodedlen, bn_ctx); + +			if (encodedlen == 0)  +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); +				goto err; +				} + +			BN_CTX_free(bn_ctx);  bn_ctx=NULL; + +			/* XXX: For now, we only support named (not  +			 * generic) curves in ECDH ephemeral key exchanges. +			 * In this situation, we need four additional bytes +			 * to encode the entire ServerECDHParams +			 * structure.  +			 */ +			n = 4 + encodedlen; + +			/* We'll generate the serverKeyExchange message +			 * explicitly so we can set these to NULLs +			 */ +			r[0]=NULL; +			r[1]=NULL; +			r[2]=NULL; +			r[3]=NULL; +			} +		else  +#endif /* !OPENSSL_NO_ECDH */ +#ifndef OPENSSL_NO_PSK +			if (type & SSL_kPSK) +				{ +				/* reserve size for record length and PSK identity hint*/ +				n+=2+strlen(s->ctx->psk_identity_hint); +				} +			else +#endif /* !OPENSSL_NO_PSK */ +			{ +			al=SSL_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->algorithm_auth & SSL_aNULL) +			&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +			{ +			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) +				== NULL) +				{ +				al=SSL_AD_DECODE_ERROR; +				goto f_err; +				} +			kn=EVP_PKEY_size(pkey); +			} +		else +			{ +			pkey=NULL; +			kn=0; +			} + +		if (!BUF_MEM_grow_clean(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]; +			} + +#ifndef OPENSSL_NO_ECDH +		if (type & SSL_kEECDH)  +			{ +			/* XXX: For now, we only support named (not generic) curves. +			 * In this situation, the serverKeyExchange message has: +			 * [1 byte CurveType], [2 byte CurveName] +			 * [1 byte length of encoded point], followed by +			 * the actual encoded point itself +			 */ +			*p = NAMED_CURVE_TYPE; +			p += 1; +			*p = 0; +			p += 1; +			*p = curve_id; +			p += 1; +			*p = encodedlen; +			p += 1; +			memcpy((unsigned char*)p,  +			    (unsigned char *)encodedPoint,  +			    encodedlen); +			OPENSSL_free(encodedPoint); +			encodedPoint = NULL; +			p += encodedlen; +			} +#endif + +#ifndef OPENSSL_NO_PSK +		if (type & SSL_kPSK) +			{ +			/* copy PSK identity hint */ +			s2n(strlen(s->ctx->psk_identity_hint), p);  +			strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); +			p+=strlen(s->ctx->psk_identity_hint); +			} +#endif + +		/* 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 OPENSSL_NO_RSA +			if (pkey->type == EVP_PKEY_RSA) +				{ +				q=md_buf; +				j=0; +				for (num=2; num > 0; num--) +					{ +					EVP_DigestInit_ex(&md_ctx,(num == 2) +						?s->ctx->md5:s->ctx->sha1, NULL); +					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_ex(&md_ctx,q, +						(unsigned int *)&i); +					q+=i; +					j+=i; +					} +				if (RSA_sign(NID_md5_sha1, md_buf, j, +					&(p[2]), &u, pkey->pkey.rsa) <= 0) +					{ +					SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); +					goto err; +					} +				s2n(u,p); +				n+=u+2; +				} +			else +#endif +#if !defined(OPENSSL_NO_DSA) +				if (pkey->type == EVP_PKEY_DSA) +				{ +				/* lets do DSS */ +				EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL); +				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 +#if !defined(OPENSSL_NO_ECDSA) +				if (pkey->type == EVP_PKEY_EC) +				{ +				/* let's do ECDSA */ +				EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL); +				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_ECDSA); +					goto err; +					} +				s2n(i,p); +				n+=i+2; +				} +			else +#endif +				{ +				/* Is this error check actually needed? */ +				al=SSL_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; +		} + +	s->state = SSL3_ST_SW_KEY_EXCH_B; +	EVP_MD_CTX_cleanup(&md_ctx); +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +f_err: +	ssl3_send_alert(s,SSL3_AL_FATAL,al); +err: +#ifndef OPENSSL_NO_ECDH +	if (encodedPoint != NULL) OPENSSL_free(encodedPoint); +	BN_CTX_free(bn_ctx); +#endif +	EVP_MD_CTX_cleanup(&md_ctx); +	return(-1); +	} + +int ssl3_send_certificate_request(SSL *s) +	{ +	unsigned char *p,*d; +	int i,j,nl,off,n; +	STACK_OF(X509_NAME) *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_X509_NAME_num(sk); i++) +				{ +				name=sk_X509_NAME_value(sk,i); +				j=i2d_X509_NAME(name,NULL); +				if (!BUF_MEM_grow_clean(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->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; +#ifdef NETSCAPE_HANG_BUG +		p=(unsigned char *)s->init_buf->data + s->init_num; + +		/* do the header */ +		*(p++)=SSL3_MT_SERVER_DONE; +		*(p++)=0; +		*(p++)=0; +		*(p++)=0; +		s->init_num += 4; +#endif + +		s->state = SSL3_ST_SW_CERT_REQ_B; +		} + +	/* SSL3_ST_SW_CERT_REQ_B */ +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +err: +	return(-1); +	} + +int ssl3_get_client_key_exchange(SSL *s) +	{ +	int i,al,ok; +	long n; +	unsigned long alg_k; +	unsigned char *p; +#ifndef OPENSSL_NO_RSA +	RSA *rsa=NULL; +	EVP_PKEY *pkey=NULL; +#endif +#ifndef OPENSSL_NO_DH +	BIGNUM *pub=NULL; +	DH *dh_srvr; +#endif +#ifndef OPENSSL_NO_KRB5 +	KSSL_ERR kssl_err; +#endif /* OPENSSL_NO_KRB5 */ + +#ifndef OPENSSL_NO_ECDH +	EC_KEY *srvr_ecdh = NULL; +	EVP_PKEY *clnt_pub_pkey = NULL; +	EC_POINT *clnt_ecpoint = NULL; +	BN_CTX *bn_ctx = NULL;  +#endif + +	n=s->method->ssl_get_message(s, +		SSL3_ST_SR_KEY_EXCH_A, +		SSL3_ST_SR_KEY_EXCH_B, +		SSL3_MT_CLIENT_KEY_EXCHANGE, +		2048, /* ??? */ +		&ok); + +	if (!ok) return((int)n); +	p=(unsigned char *)s->init_msg; + +	alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + +#ifndef OPENSSL_NO_RSA +	if (alg_k & SSL_kRSA) +		{ +		/* FIX THIS UP EAY EAY EAY EAY */ +		if (s->s3->tmp.use_rsa_tmp) +			{ +			if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL)) +				rsa=s->cert->rsa_tmp; +			/* Don't do a callback because rsa_tmp should +			 * be sent already */ +			if (rsa == NULL) +				{ +				al=SSL_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=SSL_AD_HANDSHAKE_FAILURE; +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE); +				goto f_err; +				} +			rsa=pkey->pkey.rsa; +			} + +		/* TLS and [incidentally] DTLS{0xFEFF} */ +		if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER) +			{ +			n2s(p,i); +			if (n != i+2) +				{ +				if (!(s->options & SSL_OP_TLS_D5_BUG)) +					{ +					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); +					goto err; +					} +				else +					p-=2; +				} +			else +				n=i; +			} + +		i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); + +		al = -1; +		 +		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); */ +			} + +		if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff)))) +			{ +			/* The premaster secret must contain the same version number as the +			 * ClientHello to detect version rollback attacks (strangely, the +			 * protocol does not offer such protection for DH ciphersuites). +			 * However, buggy clients exist that send the negotiated protocol +			 * version instead if the server does not support the requested +			 * protocol version. +			 * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */ +			if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) && +				(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); */ + +				/* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack +				 * (http://eprint.iacr.org/2003/052/) exploits the version +				 * number check as a "bad version oracle" -- an alert would +				 * reveal that the plaintext corresponding to some ciphertext +				 * made up by the adversary is properly formatted except +				 * that the version number is wrong.  To avoid such attacks, +				 * we should treat this just like any other decryption error. */ +				} +			} + +		if (al != -1) +			{ +			/* Some decryption failure -- use random value instead as countermeasure +			 * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding +			 * (see RFC 2246, section 7.4.7.1). */ +			ERR_clear_error(); +			i = SSL_MAX_MASTER_KEY_LENGTH; +			p[0] = s->client_version >> 8; +			p[1] = s->client_version & 0xff; +			if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */ +				goto err; +			} +	 +		s->session->master_key_length= +			s->method->ssl3_enc->generate_master_secret(s, +				s->session->master_key, +				p,i); +		OPENSSL_cleanse(p,i); +		} +	else +#endif +#ifndef OPENSSL_NO_DH +		if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) +		{ +		n2s(p,i); +		if (n != i+2) +			{ +			if (!(s->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=SSL_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=SSL_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= +			s->method->ssl3_enc->generate_master_secret(s, +				s->session->master_key,p,i); +		OPENSSL_cleanse(p,i); +		} +	else +#endif +#ifndef OPENSSL_NO_KRB5 +	if (alg_k & SSL_kKRB5) +		{ +		krb5_error_code		krb5rc; +		krb5_data		enc_ticket; +		krb5_data		authenticator; +		krb5_data		enc_pms; +		KSSL_CTX		*kssl_ctx = s->kssl_ctx; +		EVP_CIPHER_CTX		ciph_ctx; +		const EVP_CIPHER	*enc = NULL; +		unsigned char		iv[EVP_MAX_IV_LENGTH]; +		unsigned char		pms[SSL_MAX_MASTER_KEY_LENGTH +					       + EVP_MAX_BLOCK_LENGTH]; +		int		     padl, outl; +		krb5_timestamp		authtime = 0; +		krb5_ticket_times	ttimes; + +		EVP_CIPHER_CTX_init(&ciph_ctx); + +		if (!kssl_ctx)  kssl_ctx = kssl_ctx_new(); + +		n2s(p,i); +		enc_ticket.length = i; + +		if (n < (long)(enc_ticket.length + 6)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DATA_LENGTH_TOO_LONG); +			goto err; +			} + +		enc_ticket.data = (char *)p; +		p+=enc_ticket.length; + +		n2s(p,i); +		authenticator.length = i; + +		if (n < (long)(enc_ticket.length + authenticator.length + 6)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DATA_LENGTH_TOO_LONG); +			goto err; +			} + +		authenticator.data = (char *)p; +		p+=authenticator.length; + +		n2s(p,i); +		enc_pms.length = i; +		enc_pms.data = (char *)p; +		p+=enc_pms.length; + +		/* Note that the length is checked again below, +		** after decryption +		*/ +		if(enc_pms.length > sizeof pms) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +			       SSL_R_DATA_LENGTH_TOO_LONG); +			goto err; +			} + +		if (n != (long)(enc_ticket.length + authenticator.length + +						enc_pms.length + 6)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DATA_LENGTH_TOO_LONG); +			goto err; +			} + +		if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes, +					&kssl_err)) != 0) +			{ +#ifdef KSSL_DEBUG +			printf("kssl_sget_tkt rtn %d [%d]\n", +				krb5rc, kssl_err.reason); +			if (kssl_err.text) +				printf("kssl_err text= %s\n", kssl_err.text); +#endif	/* KSSL_DEBUG */ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				kssl_err.reason); +			goto err; +			} + +		/*  Note: no authenticator is not considered an error, +		**  but will return authtime == 0. +		*/ +		if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator, +					&authtime, &kssl_err)) != 0) +			{ +#ifdef KSSL_DEBUG +			printf("kssl_check_authent rtn %d [%d]\n", +				krb5rc, kssl_err.reason); +			if (kssl_err.text) +				printf("kssl_err text= %s\n", kssl_err.text); +#endif	/* KSSL_DEBUG */ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				kssl_err.reason); +			goto err; +			} + +		if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc); +			goto err; +			} + +#ifdef KSSL_DEBUG +		kssl_ctx_show(kssl_ctx); +#endif	/* KSSL_DEBUG */ + +		enc = kssl_map_enc(kssl_ctx->enctype); +		if (enc == NULL) +		    goto err; + +		memset(iv, 0, sizeof iv);	/* per RFC 1510 */ + +		if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DECRYPTION_FAILED); +			goto err; +			} +		if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl, +					(unsigned char *)enc_pms.data, enc_pms.length)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DECRYPTION_FAILED); +			goto err; +			} +		if (outl > SSL_MAX_MASTER_KEY_LENGTH) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DATA_LENGTH_TOO_LONG); +			goto err; +			} +		if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DECRYPTION_FAILED); +			goto err; +			} +		outl += padl; +		if (outl > SSL_MAX_MASTER_KEY_LENGTH) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				SSL_R_DATA_LENGTH_TOO_LONG); +			goto err; +			} +		if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff)))) +		    { +		    /* The premaster secret must contain the same version number as the +		     * ClientHello to detect version rollback attacks (strangely, the +		     * protocol does not offer such protection for DH ciphersuites). +		     * However, buggy clients exist that send random bytes instead of +		     * the protocol version. +		     * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients.  +		     * (Perhaps we should have a separate BUG value for the Kerberos cipher) +		     */ +		    if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +			       SSL_AD_DECODE_ERROR); +			goto err; +			} +		    } + +		EVP_CIPHER_CTX_cleanup(&ciph_ctx); + +		s->session->master_key_length= +			s->method->ssl3_enc->generate_master_secret(s, +				s->session->master_key, pms, outl); + +		if (kssl_ctx->client_princ) +			{ +			size_t len = strlen(kssl_ctx->client_princ); +			if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH )  +				{ +				s->session->krb5_client_princ_len = len; +				memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len); +				} +			} + + +		/*  Was doing kssl_ctx_free() here, +		**  but it caused problems for apache. +		**  kssl_ctx = kssl_ctx_free(kssl_ctx); +		**  if (s->kssl_ctx)  s->kssl_ctx = NULL; +		*/ +		} +	else +#endif	/* OPENSSL_NO_KRB5 */ + +#ifndef OPENSSL_NO_ECDH +		if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) +		{ +		int ret = 1; +		int field_size = 0; +		const EC_KEY   *tkey; +		const EC_GROUP *group; +		const BIGNUM *priv_key; + +		/* initialize structures for server's ECDH key pair */ +		if ((srvr_ecdh = EC_KEY_new()) == NULL)  +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +			    ERR_R_MALLOC_FAILURE); +			goto err; +			} + +		/* Let's get server private key and group information */ +		if (alg_k & (SSL_kECDHr|SSL_kECDHe)) +			{  +			/* use the certificate */ +			tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec; +			} +		else +			{ +			/* use the ephermeral values we saved when +			 * generating the ServerKeyExchange msg. +			 */ +			tkey = s->s3->tmp.ecdh; +			} + +		group    = EC_KEY_get0_group(tkey); +		priv_key = EC_KEY_get0_private_key(tkey); + +		if (!EC_KEY_set_group(srvr_ecdh, group) || +		    !EC_KEY_set_private_key(srvr_ecdh, priv_key)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +			       ERR_R_EC_LIB); +			goto err; +			} + +		/* Let's get client's public key */ +		if ((clnt_ecpoint = EC_POINT_new(group)) == NULL) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +			    ERR_R_MALLOC_FAILURE); +			goto err; +			} + +		if (n == 0L)  +			{ +			/* Client Publickey was in Client Certificate */ + +			 if (alg_k & SSL_kEECDH) +				 { +				 al=SSL_AD_HANDSHAKE_FAILURE; +				 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY); +				 goto f_err; +				 } +			if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer)) +			    == NULL) ||  +			    (clnt_pub_pkey->type != EVP_PKEY_EC)) +				{ +				/* XXX: For now, we do not support client +				 * authentication using ECDH certificates +				 * so this branch (n == 0L) of the code is +				 * never executed. When that support is +				 * added, we ought to ensure the key  +				 * received in the certificate is  +				 * authorized for key agreement. +				 * ECDH_compute_key implicitly checks that +				 * the two ECDH shares are for the same +				 * group. +				 */ +			   	al=SSL_AD_HANDSHAKE_FAILURE; +			   	SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				    SSL_R_UNABLE_TO_DECODE_ECDH_CERTS); +			   	goto f_err; +			   	} + +			if (EC_POINT_copy(clnt_ecpoint, +			    EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +					ERR_R_EC_LIB); +				goto err; +				} +			ret = 2; /* Skip certificate verify processing */ +			} +		else +			{ +			/* Get client's public key from encoded point +			 * in the ClientKeyExchange message. +			 */ +			if ((bn_ctx = BN_CTX_new()) == NULL) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				    ERR_R_MALLOC_FAILURE); +				goto err; +				} + +			/* Get encoded point length */ +			i = *p;  +			p += 1; +			if (n != 1 + i) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				    ERR_R_EC_LIB); +				goto err; +				} +			if (EC_POINT_oct2point(group,  +			    clnt_ecpoint, p, i, bn_ctx) == 0) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				    ERR_R_EC_LIB); +				goto err; +				} +			/* p is pointing to somewhere in the buffer +			 * currently, so set it to the start  +			 */  +			p=(unsigned char *)s->init_buf->data; +			} + +		/* Compute the shared pre-master secret */ +		field_size = EC_GROUP_get_degree(group); +		if (field_size <= 0) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,  +			       ERR_R_ECDH_LIB); +			goto err; +			} +		i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL); +		if (i <= 0) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +			    ERR_R_ECDH_LIB); +			goto err; +			} + +		EVP_PKEY_free(clnt_pub_pkey); +		EC_POINT_free(clnt_ecpoint); +		EC_KEY_free(srvr_ecdh); +		BN_CTX_free(bn_ctx); +		EC_KEY_free(s->s3->tmp.ecdh); +		s->s3->tmp.ecdh = NULL;  + +		/* Compute the master secret */ +		s->session->master_key_length = s->method->ssl3_enc-> \ +		    generate_master_secret(s, s->session->master_key, p, i); +		 +		OPENSSL_cleanse(p, i); +		return (ret); +		} +	else +#endif +#ifndef OPENSSL_NO_PSK +		if (alg_k & SSL_kPSK) +			{ +			unsigned char *t = NULL; +			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; +			unsigned int pre_ms_len = 0, psk_len = 0; +			int psk_err = 1; +			char tmp_id[PSK_MAX_IDENTITY_LEN+1]; + +			al=SSL_AD_HANDSHAKE_FAILURE; + +			n2s(p,i); +			if (n != i+2) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +					SSL_R_LENGTH_MISMATCH); +				goto psk_err; +				} +			if (i > PSK_MAX_IDENTITY_LEN) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +					SSL_R_DATA_LENGTH_TOO_LONG); +				goto psk_err; +				} +			if (s->psk_server_callback == NULL) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				       SSL_R_PSK_NO_SERVER_CB); +				goto psk_err; +				} + +			/* Create guaranteed NULL-terminated identity +			 * string for the callback */ +			memcpy(tmp_id, p, i); +			memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i); +			psk_len = s->psk_server_callback(s, tmp_id, +				psk_or_pre_ms, sizeof(psk_or_pre_ms)); +			OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1); + +			if (psk_len > PSK_MAX_PSK_LEN) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +					ERR_R_INTERNAL_ERROR); +				goto psk_err; +				} +			else if (psk_len == 0) +				{ +				/* PSK related to the given identity not found */ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +				       SSL_R_PSK_IDENTITY_NOT_FOUND); +				al=SSL_AD_UNKNOWN_PSK_IDENTITY; +				goto psk_err; +				} + +			/* create PSK pre_master_secret */ +			pre_ms_len=2+psk_len+2+psk_len; +			t = psk_or_pre_ms; +			memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); +			s2n(psk_len, t); +			memset(t, 0, psk_len); +			t+=psk_len; +			s2n(psk_len, t); + +			if (s->session->psk_identity != NULL) +				OPENSSL_free(s->session->psk_identity); +			s->session->psk_identity = BUF_strdup((char *)p); +			if (s->session->psk_identity == NULL) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} + +			if (s->session->psk_identity_hint != NULL) +				OPENSSL_free(s->session->psk_identity_hint); +			s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); +			if (s->ctx->psk_identity_hint != NULL && +				s->session->psk_identity_hint == NULL) +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, +					ERR_R_MALLOC_FAILURE); +				goto psk_err; +				} + +			s->session->master_key_length= +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key, psk_or_pre_ms, pre_ms_len); +			psk_err = 0; +		psk_err: +			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); +			if (psk_err != 0) +				goto f_err; +			} +		else +#endif +		if (alg_k & SSL_kGOST)  +			{ +			int ret = 0; +			EVP_PKEY_CTX *pkey_ctx; +			EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; +			unsigned char premaster_secret[32], *start; +			size_t outlen=32, inlen; +			unsigned long alg_a; + +			/* Get our certificate private key*/ +			alg_a = s->s3->tmp.new_cipher->algorithm_auth; +			if (alg_a & SSL_aGOST94) +				pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey; +			else if (alg_a & SSL_aGOST01) +				pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + +			pkey_ctx = EVP_PKEY_CTX_new(pk,NULL); +			EVP_PKEY_decrypt_init(pkey_ctx); +			/* If client certificate is present and is of the same type, maybe +			 * use it for key exchange.  Don't mind errors from +			 * EVP_PKEY_derive_set_peer, because it is completely valid to use +			 * a client certificate for authorization only. */ +			client_pub_pkey = X509_get_pubkey(s->session->peer); +			if (client_pub_pkey) +				{ +				if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) +					ERR_clear_error(); +				} +			/* Decrypt session key */ +			if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)))  +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); +				goto gerr; +				} +			if (p[1] == 0x81) +				{ +				start = p+3; +				inlen = p[2]; +				} +			else if (p[1] < 0x80) +				{ +				start = p+2; +				inlen = p[1]; +				} +			else +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); +				goto gerr; +				} +			if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)  + +				{ +				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); +				goto gerr; +				} +			/* Generate master secret */ +			s->session->master_key_length= +				s->method->ssl3_enc->generate_master_secret(s, +					s->session->master_key,premaster_secret,32); +			/* Check if pubkey from client certificate was used */ +			if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) +				ret = 2; +			else +				ret = 1; +		gerr: +			EVP_PKEY_free(client_pub_pkey); +			EVP_PKEY_CTX_free(pkey_ctx); +			if (ret) +				return ret; +			else +				goto err; +			} +		else +		{ +		al=SSL_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); +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) +err: +#endif +#ifndef OPENSSL_NO_ECDH +	EVP_PKEY_free(clnt_pub_pkey); +	EC_POINT_free(clnt_ecpoint); +	if (srvr_ecdh != NULL)  +		EC_KEY_free(srvr_ecdh); +	BN_CTX_free(bn_ctx); +#endif +	return(-1); +	} + +int ssl3_get_cert_verify(SSL *s) +	{ +	EVP_PKEY *pkey=NULL; +	unsigned char *p; +	int al,ok,ret=0; +	long n; +	int type=0,i,j; +	X509 *peer; + +	n=s->method->ssl_get_message(s, +		SSL3_ST_SR_CERT_VRFY_A, +		SSL3_ST_SR_CERT_VRFY_B, +		-1, +		514, /* 514? */ +		&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)) +			{ +			al=SSL_AD_UNEXPECTED_MESSAGE; +			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_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=SSL_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=SSL_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=SSL_AD_UNEXPECTED_MESSAGE; +		goto f_err; +		} + +	/* we now have a signature that we need to verify */ +	p=(unsigned char *)s->init_msg; +	/* Check for broken implementations of GOST ciphersuites */ +	/* If key is GOST and n is exactly 64, it is bare +	 * signature without length field */ +	if (n==64 && (pkey->type==NID_id_GostR3410_94 || +		pkey->type == NID_id_GostR3410_2001) ) +		{ +		i=64; +		}  +	else  +		{	 +		n2s(p,i); +		n-=2; +		if (i > n) +			{ +			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH); +			al=SSL_AD_DECODE_ERROR; +			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=SSL_AD_DECODE_ERROR; +		goto f_err; +		} + +#ifndef OPENSSL_NO_RSA  +	if (pkey->type == EVP_PKEY_RSA) +		{ +		i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md, +			MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i,  +							pkey->pkey.rsa); +		if (i < 0) +			{ +			al=SSL_AD_DECRYPT_ERROR; +			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT); +			goto f_err; +			} +		if (i == 0) +			{ +			al=SSL_AD_DECRYPT_ERROR; +			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE); +			goto f_err; +			} +		} +	else +#endif +#ifndef OPENSSL_NO_DSA +		if (pkey->type == EVP_PKEY_DSA) +		{ +		j=DSA_verify(pkey->save_type, +			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), +			SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa); +		if (j <= 0) +			{ +			/* bad signature */ +			al=SSL_AD_DECRYPT_ERROR; +			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE); +			goto f_err; +			} +		} +	else +#endif +#ifndef OPENSSL_NO_ECDSA +		if (pkey->type == EVP_PKEY_EC) +		{ +		j=ECDSA_verify(pkey->save_type, +			&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), +			SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec); +		if (j <= 0) +			{ +			/* bad signature */ +			al=SSL_AD_DECRYPT_ERROR; +			SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, +			    SSL_R_BAD_ECDSA_SIGNATURE); +			goto f_err; +			} +		} +	else +#endif +	if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001) +		{   unsigned char signature[64]; +			int idx; +			EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL); +			EVP_PKEY_verify_init(pctx); +			if (i!=64) { +				fprintf(stderr,"GOST signature length is %d",i); +			}	 +			for (idx=0;idx<64;idx++) { +				signature[63-idx]=p[idx]; +			}	 +			j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32); +			EVP_PKEY_CTX_free(pctx); +			if (j<=0)  +				{ +				al=SSL_AD_DECRYPT_ERROR; +				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, +					SSL_R_BAD_ECDSA_SIGNATURE); +				goto f_err; +				}	 +		} +	else	 +		{ +		SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR); +		al=SSL_AD_UNSUPPORTED_CERTIFICATE; +		goto f_err; +		} + + +	ret=1; +	if (0) +		{ +f_err: +		ssl3_send_alert(s,SSL3_AL_FATAL,al); +		} +end: +	EVP_PKEY_free(pkey); +	return(ret); +	} + +int ssl3_get_client_certificate(SSL *s) +	{ +	int i,ok,al,ret= -1; +	X509 *x=NULL; +	unsigned long l,nc,llen,n; +	const unsigned char *p,*q; +	unsigned char *d; +	STACK_OF(X509) *sk=NULL; + +	n=s->method->ssl_get_message(s, +		SSL3_ST_SR_CERT_A, +		SSL3_ST_SR_CERT_B, +		-1, +		s->max_cert_list, +		&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=SSL_AD_HANDSHAKE_FAILURE; +			goto f_err; +			} +		/* If tls asked for a client cert, the client must return a 0 list */ +		if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); +			al=SSL_AD_UNEXPECTED_MESSAGE; +			goto f_err; +			} +		s->s3->tmp.reuse_message=1; +		return(1); +		} + +	if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) +		{ +		al=SSL_AD_UNEXPECTED_MESSAGE; +		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE); +		goto f_err; +		} +	p=d=(unsigned char *)s->init_msg; + +	if ((sk=sk_X509_new_null()) == NULL) +		{ +		SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); +		goto err; +		} + +	n2l3(p,llen); +	if (llen+3 != n) +		{ +		al=SSL_AD_DECODE_ERROR; +		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=SSL_AD_DECODE_ERROR; +			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=SSL_AD_DECODE_ERROR; +			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); +			goto f_err; +			} +		if (!sk_X509_push(sk,x)) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); +			goto err; +			} +		x=NULL; +		nc+=l+3; +		} + +	if (sk_X509_num(sk) <= 0) +		{ +		/* TLS does not mind 0 certs returned */ +		if (s->version == SSL3_VERSION) +			{ +			al=SSL_AD_HANDSHAKE_FAILURE; +			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED); +			goto f_err; +			} +		/* Fail for TLS only if we required a certificate */ +		else 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=SSL_AD_HANDSHAKE_FAILURE; +			goto f_err; +			} +		} +	else +		{ +		i=ssl_verify_cert_chain(s,sk); +		if (i <= 0) +			{ +			al=ssl_verify_alarm_type(s->verify_result); +			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED); +			goto f_err; +			} +		} + +	if (s->session->peer != NULL) /* This should not be needed */ +		X509_free(s->session->peer); +	s->session->peer=sk_X509_shift(sk); +	s->session->verify_result = s->verify_result; + +	/* With the current implementation, sess_cert will always be NULL +	 * when we arrive here. */ +	if (s->session->sess_cert == NULL) +		{ +		s->session->sess_cert = ssl_sess_cert_new(); +		if (s->session->sess_cert == NULL) +			{ +			SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE); +			goto err; +			} +		} +	if (s->session->sess_cert->cert_chain != NULL) +		sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); +	s->session->sess_cert->cert_chain=sk; +	/* Inconsistency alert: cert_chain does *not* include the +	 * peer's own certificate, while we do include it in s3_clnt.c */ + +	sk=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_X509_pop_free(sk,X509_free); +	return(ret); +	} + +int ssl3_send_server_certificate(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) +			{ +			/* VRS: allow null cert if auth == KRB5 */ +			if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) || +			    (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5)) +				{ +				SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_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)); +	} +#ifndef OPENSSL_NO_TLSEXT +int ssl3_send_newsession_ticket(SSL *s) +	{ +	if (s->state == SSL3_ST_SW_SESSION_TICKET_A) +		{ +		unsigned char *p, *senc, *macstart; +		int len, slen; +		unsigned int hlen; +		EVP_CIPHER_CTX ctx; +		HMAC_CTX hctx; +		SSL_CTX *tctx = s->initial_ctx; +		unsigned char iv[EVP_MAX_IV_LENGTH]; +		unsigned char key_name[16]; + +		/* get session encoding length */ +		slen = i2d_SSL_SESSION(s->session, NULL); +		/* Some length values are 16 bits, so forget it if session is + 		 * too long + 		 */ +		if (slen > 0xFF00) +			return -1; +		/* Grow buffer if need be: the length calculation is as + 		 * follows 1 (size of message name) + 3 (message length + 		 * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) + + 		 * 16 (key name) + max_iv_len (iv length) + + 		 * session_length + max_enc_block_size (max encrypted session + 		 * length) + max_md_size (HMAC). + 		 */ +		if (!BUF_MEM_grow(s->init_buf, +			26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + +			EVP_MAX_MD_SIZE + slen)) +			return -1; +		senc = OPENSSL_malloc(slen); +		if (!senc) +			return -1; +		p = senc; +		i2d_SSL_SESSION(s->session, &p); + +		p=(unsigned char *)s->init_buf->data; +		/* do the header */ +		*(p++)=SSL3_MT_NEWSESSION_TICKET; +		/* Skip message length for now */ +		p += 3; +		EVP_CIPHER_CTX_init(&ctx); +		HMAC_CTX_init(&hctx); +		/* Initialize HMAC and cipher contexts. If callback present +		 * it does all the work otherwise use generated values +		 * from parent ctx. +		 */ +		if (tctx->tlsext_ticket_key_cb) +			{ +			if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, +							 &hctx, 1) < 0) +				{ +				OPENSSL_free(senc); +				return -1; +				} +			} +		else +			{ +			RAND_pseudo_bytes(iv, 16); +			EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, +					tctx->tlsext_tick_aes_key, iv); +			HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, +					tlsext_tick_md(), NULL); +			memcpy(key_name, tctx->tlsext_tick_key_name, 16); +			} +		l2n(s->session->tlsext_tick_lifetime_hint, p); +		/* Skip ticket length for now */ +		p += 2; +		/* Output key name */ +		macstart = p; +		memcpy(p, key_name, 16); +		p += 16; +		/* output IV */ +		memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); +		p += EVP_CIPHER_CTX_iv_length(&ctx); +		/* Encrypt session data */ +		EVP_EncryptUpdate(&ctx, p, &len, senc, slen); +		p += len; +		EVP_EncryptFinal(&ctx, p, &len); +		p += len; +		EVP_CIPHER_CTX_cleanup(&ctx); + +		HMAC_Update(&hctx, macstart, p - macstart); +		HMAC_Final(&hctx, p, &hlen); +		HMAC_CTX_cleanup(&hctx); + +		p += hlen; +		/* Now write out lengths: p points to end of data written */ +		/* Total length */ +		len = p - (unsigned char *)s->init_buf->data; +		p=(unsigned char *)s->init_buf->data + 1; +		l2n3(len - 4, p); /* Message length */ +		p += 4; +		s2n(len - 10, p);  /* Ticket length */ + +		/* number of bytes to write */ +		s->init_num= len; +		s->state=SSL3_ST_SW_SESSION_TICKET_B; +		s->init_off=0; +		OPENSSL_free(senc); +		} + +	/* SSL3_ST_SW_SESSION_TICKET_B */ +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +int ssl3_send_cert_status(SSL *s) +	{ +	if (s->state == SSL3_ST_SW_CERT_STATUS_A) +		{ +		unsigned char *p; +		/* Grow buffer if need be: the length calculation is as + 		 * follows 1 (message type) + 3 (message length) + + 		 * 1 (ocsp response type) + 3 (ocsp response length) + 		 * + (ocsp response) + 		 */ +		if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) +			return -1; + +		p=(unsigned char *)s->init_buf->data; + +		/* do the header */ +		*(p++)=SSL3_MT_CERTIFICATE_STATUS; +		/* message length */ +		l2n3(s->tlsext_ocsp_resplen + 4, p); +		/* status type */ +		*(p++)= s->tlsext_status_type; +		/* length of OCSP response */ +		l2n3(s->tlsext_ocsp_resplen, p); +		/* actual response */ +		memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen); +		/* number of bytes to write */ +		s->init_num = 8 + s->tlsext_ocsp_resplen; +		s->state=SSL3_ST_SW_CERT_STATUS_B; +		s->init_off = 0; +		} + +	/* SSL3_ST_SW_CERT_STATUS_B */ +	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); +	} + +# ifndef OPENSSL_NO_NPN +/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It + * sets the next_proto member in s if found */ +int ssl3_get_next_proto(SSL *s) +	{ +	int ok; +	unsigned proto_len, padding_len; +	long n; +	const unsigned char *p; + +	/* Clients cannot send a NextProtocol message if we didn't see the +	 * extension in their ClientHello */ +	if (!s->s3->next_proto_neg_seen) +		{ +		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); +		return -1; +		} + +	n=s->method->ssl_get_message(s, +		SSL3_ST_SR_NEXT_PROTO_A, +		SSL3_ST_SR_NEXT_PROTO_B, +		SSL3_MT_NEXT_PROTO, +		514,  /* See the payload format below */ +		&ok); + +	if (!ok) +		return((int)n); + +	/* s->state doesn't reflect whether ChangeCipherSpec has been received +	 * in this handshake, but s->s3->change_cipher_spec does (will be reset +	 * by ssl3_get_finished). */ +	if (!s->s3->change_cipher_spec) +		{ +		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); +		return -1; +		} + +	if (n < 2) +		return 0;  /* The body must be > 1 bytes long */ + +	p=(unsigned char *)s->init_msg; + +	/* The payload looks like: +	 *   uint8 proto_len; +	 *   uint8 proto[proto_len]; +	 *   uint8 padding_len; +	 *   uint8 padding[padding_len]; +	 */ +	proto_len = p[0]; +	if (proto_len + 2 > s->init_num) +		return 0; +	padding_len = p[proto_len + 1]; +	if (proto_len + padding_len + 2 != s->init_num) +		return 0; + +	s->next_proto_negotiated = OPENSSL_malloc(proto_len); +	if (!s->next_proto_negotiated) +		{ +		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE); +		return 0; +		} +	memcpy(s->next_proto_negotiated, p + 1, proto_len); +	s->next_proto_negotiated_len = proto_len; + +	return 1; +	} +# endif +#endif diff --git a/main/openssl/ssl/ssl.h b/main/openssl/ssl/ssl.h new file mode 100644 index 00000000..9cb2bf93 --- /dev/null +++ b/main/openssl/ssl/ssl.h @@ -0,0 +1,2382 @@ +/* ssl/ssl.h */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_SSL_H  +#define HEADER_SSL_H  + +#include <openssl/e_os2.h> + +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#ifndef OPENSSL_NO_BIO +#include <openssl/bio.h> +#endif +#ifndef OPENSSL_NO_DEPRECATED +#ifndef OPENSSL_NO_X509 +#include <openssl/x509.h> +#endif +#include <openssl/crypto.h> +#include <openssl/lhash.h> +#include <openssl/buffer.h> +#endif +#include <openssl/pem.h> +#include <openssl/hmac.h> + +#include <openssl/kssl.h> +#include <openssl/safestack.h> +#include <openssl/symhacks.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	 + +/*    VRS Additional Kerberos5 entries + */ +#define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA +#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +#define SSL_TXT_KRB5_RC4_128_SHA      SSL3_TXT_KRB5_RC4_128_SHA +#define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA +#define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5        +#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5        +#define SSL_TXT_KRB5_RC4_128_MD5      SSL3_TXT_KRB5_RC4_128_MD5 +#define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5  + +#define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA  +#define SSL_TXT_KRB5_RC2_40_CBC_SHA   SSL3_TXT_KRB5_RC2_40_CBC_SHA  +#define SSL_TXT_KRB5_RC4_40_SHA	      SSL3_TXT_KRB5_RC4_40_SHA +#define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5  +#define SSL_TXT_KRB5_RC2_40_CBC_MD5   SSL3_TXT_KRB5_RC2_40_CBC_MD5  +#define SSL_TXT_KRB5_RC4_40_MD5	      SSL3_TXT_KRB5_RC4_40_MD5 + +#define SSL_TXT_KRB5_DES_40_CBC_SHA   SSL3_TXT_KRB5_DES_40_CBC_SHA +#define SSL_TXT_KRB5_DES_40_CBC_MD5   SSL3_TXT_KRB5_DES_40_CBC_MD5 +#define SSL_TXT_KRB5_DES_64_CBC_SHA   SSL3_TXT_KRB5_DES_64_CBC_SHA +#define SSL_TXT_KRB5_DES_64_CBC_MD5   SSL3_TXT_KRB5_DES_64_CBC_MD5 +#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +#define SSL_MAX_KRB5_PRINCIPAL_LENGTH  256 + +#define SSL_MAX_SSL_SESSION_ID_LENGTH		32 +#define SSL_MAX_SID_CTX_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_EXP40		"EXPORT40" +#define SSL_TXT_EXP56		"EXPORT56" +#define SSL_TXT_LOW		"LOW" +#define SSL_TXT_MEDIUM		"MEDIUM" +#define SSL_TXT_HIGH		"HIGH" +#define SSL_TXT_FIPS		"FIPS" + +#define SSL_TXT_kFZA		"kFZA" /* unused! */ +#define	SSL_TXT_aFZA		"aFZA" /* unused! */ +#define SSL_TXT_eFZA		"eFZA" /* unused! */ +#define SSL_TXT_FZA		"FZA"  /* unused! */ + +#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" /* no such ciphersuites supported! */ +#define SSL_TXT_kDHd		"kDHd" /* no such ciphersuites supported! */ +#define SSL_TXT_kDH 		"kDH"  /* no such ciphersuites supported! */ +#define SSL_TXT_kEDH		"kEDH" +#define SSL_TXT_kKRB5     	"kKRB5" +#define SSL_TXT_kECDHr		"kECDHr" +#define SSL_TXT_kECDHe		"kECDHe" +#define SSL_TXT_kECDH		"kECDH" +#define SSL_TXT_kEECDH		"kEECDH" +#define SSL_TXT_kPSK            "kPSK" +#define SSL_TXT_kGOST		"kGOST" + +#define	SSL_TXT_aRSA		"aRSA" +#define	SSL_TXT_aDSS		"aDSS" +#define	SSL_TXT_aDH		"aDH" /* no such ciphersuites supported! */ +#define	SSL_TXT_aECDH		"aECDH" +#define SSL_TXT_aKRB5     	"aKRB5" +#define SSL_TXT_aECDSA		"aECDSA" +#define SSL_TXT_aPSK            "aPSK" +#define SSL_TXT_aGOST94	"aGOST94" +#define SSL_TXT_aGOST01 "aGOST01" +#define SSL_TXT_aGOST  "aGOST" + +#define	SSL_TXT_DSS		"DSS" +#define SSL_TXT_DH		"DH" +#define SSL_TXT_EDH		"EDH" /* same as "kEDH:-ADH" */ +#define SSL_TXT_ADH		"ADH" +#define SSL_TXT_RSA		"RSA" +#define SSL_TXT_ECDH		"ECDH" +#define SSL_TXT_EECDH		"EECDH" /* same as "kEECDH:-AECDH" */ +#define SSL_TXT_AECDH		"AECDH" +#define SSL_TXT_ECDSA		"ECDSA" +#define SSL_TXT_KRB5      	"KRB5" +#define SSL_TXT_PSK             "PSK" + +#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_SEED		"SEED" +#define SSL_TXT_AES128		"AES128" +#define SSL_TXT_AES256		"AES256" +#define SSL_TXT_AES		"AES" +#define SSL_TXT_CAMELLIA128	"CAMELLIA128" +#define SSL_TXT_CAMELLIA256	"CAMELLIA256" +#define SSL_TXT_CAMELLIA	"CAMELLIA" + +#define SSL_TXT_MD5		"MD5" +#define SSL_TXT_SHA1		"SHA1" +#define SSL_TXT_SHA		"SHA" /* same as "SHA1" */ +#define SSL_TXT_GOST94		"GOST94"  +#define SSL_TXT_GOST89MAC		"GOST89MAC"  + +#define SSL_TXT_SSLV2		"SSLv2" +#define SSL_TXT_SSLV3		"SSLv3" +#define SSL_TXT_TLSV1		"TLSv1" + +#define SSL_TXT_EXP		"EXP" +#define SSL_TXT_EXPORT		"EXPORT" + +#define SSL_TXT_ALL		"ALL" + +/* + * COMPLEMENTOF* definitions. These identifiers are used to (de-select) + * ciphers normally not being used. + * Example: "RC4" will activate all ciphers using RC4 including ciphers + * without authentication, which would normally disabled by DEFAULT (due + * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" + * will make sure that it is also disabled in the specific selection. + * COMPLEMENTOF* identifiers are portable between version, as adjustments + * to the default cipher setup will also be included here. + * + * COMPLEMENTOFDEFAULT does not experience the same special treatment that + * DEFAULT gets, as only selection is being done and no sorting as needed + * for DEFAULT. + */ +#define SSL_TXT_CMPALL		"COMPLEMENTOFALL" +#define SSL_TXT_CMPDEF		"COMPLEMENTOFDEFAULT" + +/* The following cipher list is used by default. + * It also is substituted when an application-defined cipher list string + * starts with 'DEFAULT'. */ +#define SSL_DEFAULT_CIPHER_LIST	"ALL:!aNULL:!eNULL:!SSLv2" +/* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always + * starts with a reasonable order, and all we have to do for DEFAULT is + * throwing out anonymous and unencrypted ciphersuites! + * (The latter are not actually enabled by ALL, but "ALL:RSA" would enable + * some of them.) + */ + +/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ +#define SSL_SENT_SHUTDOWN	1 +#define SSL_RECEIVED_SHUTDOWN	2 + +#ifdef __cplusplus +} +#endif + +#ifdef  __cplusplus +extern "C" { +#endif + +#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2) +#define OPENSSL_NO_SSL2 +#endif + +#define SSL_FILETYPE_ASN1	X509_FILETYPE_ASN1 +#define SSL_FILETYPE_PEM	X509_FILETYPE_PEM + +/* This is needed to stop compilers complaining about the + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ +typedef struct ssl_st *ssl_crock_st; +typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; + +/* used to hold info on the particular ciphers used */ +typedef struct ssl_cipher_st +	{ +	int valid; +	const char *name;		/* text name */ +	unsigned long id;		/* id, 4 bytes, first is version */ + +	/* changed in 0.9.9: these four used to be portions of a single value 'algorithms' */ +	unsigned long algorithm_mkey;	/* key exchange algorithm */ +	unsigned long algorithm_auth;	/* server authentication */ +	unsigned long algorithm_enc;	/* symmetric encryption */ +	unsigned long algorithm_mac;	/* symmetric authentication */ +	unsigned long algorithm_ssl;	/* (major) protocol version */ + +	unsigned long algo_strength;	/* strength and export flags */ +	unsigned long algorithm2;	/* Extra flags */ +	int strength_bits;		/* Number of bits really used */ +	int alg_bits;			/* Number of bits for algorithm */ +	} SSL_CIPHER; + +DECLARE_STACK_OF(SSL_CIPHER) + +typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg); +typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); + +/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ +typedef struct ssl_method_st +	{ +	int version; +	int (*ssl_new)(SSL *s); +	void (*ssl_clear)(SSL *s); +	void (*ssl_free)(SSL *s); +	int (*ssl_accept)(SSL *s); +	int (*ssl_connect)(SSL *s); +	int (*ssl_read)(SSL *s,void *buf,int len); +	int (*ssl_peek)(SSL *s,void *buf,int len); +	int (*ssl_write)(SSL *s,const void *buf,int len); +	int (*ssl_shutdown)(SSL *s); +	int (*ssl_renegotiate)(SSL *s); +	int (*ssl_renegotiate_check)(SSL *s); +	long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long +		max, int *ok); +	int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,  +		int peek); +	int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len); +	int (*ssl_dispatch_alert)(SSL *s); +	long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg); +	long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg); +	const SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr); +	int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr); +	int (*ssl_pending)(const SSL *s); +	int (*num_ciphers)(void); +	const SSL_CIPHER *(*get_cipher)(unsigned ncipher); +	const struct ssl_method_st *(*get_ssl_method)(int version); +	long (*get_timeout)(void); +	struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */ +	int (*ssl_version)(void); +	long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void)); +	long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void)); +	} SSL_METHOD; + +/* 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 + *	KRB5_principal		OCTET STRING	-- optional Kerberos principal + *	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 + *	Session_ID_context [ 4 ] EXPLICIT OCTET STRING,   -- the Session ID context + *	Verify_result [ 5 ] EXPLICIT INTEGER,   -- X509_V_... code for `Peer' + *	HostName [ 6 ] EXPLICIT OCTET STRING,   -- optional HostName from servername TLS extension  + *	ECPointFormatList [ 7 ] OCTET STRING,     -- optional EC point format list from TLS extension + *	PSK_identity_hint [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity hint + *	PSK_identity [ 9 ] EXPLICIT OCTET STRING -- optional PSK identity + *	} + * 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]; +	/* this is used to determine whether the session is being reused in +	 * the appropriate context. It is up to the application to set this, +	 * via SSL_new */ +	unsigned int sid_ctx_length; +	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + +#ifndef OPENSSL_NO_KRB5 +        unsigned int krb5_client_princ_len; +        unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH]; +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_PSK +	char *psk_identity_hint; +	char *psk_identity; +#endif +	int not_resumable; + +	/* The cert is the certificate used to establish this connection */ +	struct sess_cert_st /* SESS_CERT */ *sess_cert; + +	/* This is the cert for the other end. +	 * On clients, it will be the same as sess_cert->peer_key->x509 +	 * (the latter is not enough as sess_cert is not retained +	 * in the external representation of sessions, see ssl_asn1.c). */ +	X509 *peer; +	/* when app_verify_callback accepts a session where the peer's certificate +	 * is not ok, we must remember the error for session reuse: */ +	long verify_result; /* only for servers */ + +	int references; +	long timeout; +	long time; + +	unsigned int compress_meth;	/* Need to lookup the method */ + +	const SSL_CIPHER *cipher; +	unsigned long cipher_id;	/* when ASN.1 loaded, this +					 * needs to be used to load +					 * the 'cipher' structure */ + +	STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */ + +	CRYPTO_EX_DATA ex_data; /* application specific data */ + +	/* These are used to make removal of session-ids more +	 * efficient and to implement a maximum cache size. */ +	struct ssl_session_st *prev,*next; +#ifndef OPENSSL_NO_TLSEXT +	char *tlsext_hostname; +#ifndef OPENSSL_NO_EC +	size_t tlsext_ecpointformatlist_length; +	unsigned char *tlsext_ecpointformatlist; /* peer's list */ +	size_t tlsext_ellipticcurvelist_length; +	unsigned char *tlsext_ellipticcurvelist; /* peer's list */ +#endif /* OPENSSL_NO_EC */ +	/* RFC4507 info */ +	unsigned char *tlsext_tick;	/* Session ticket */ +	size_t	tlsext_ticklen;		/* Session ticket length */	 +	long tlsext_tick_lifetime_hint;	/* Session lifetime hint in seconds */ +#endif +	} SSL_SESSION; + + +#define SSL_OP_MICROSOFT_SESS_ID_BUG			0x00000001L +#define SSL_OP_NETSCAPE_CHALLENGE_BUG			0x00000002L +/* Allow initial connection to servers that don't support RI */ +#define SSL_OP_LEGACY_SERVER_CONNECT			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 /* no effect since 0.9.7h and 0.9.8b */ +#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG			0x00000080L +#define SSL_OP_TLS_D5_BUG				0x00000100L +#define SSL_OP_TLS_BLOCK_PADDING_BUG			0x00000200L + +/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added + * in OpenSSL 0.9.6d.  Usually (depending on the application protocol) + * the workaround is not needed.  Unfortunately some broken SSL/TLS + * implementations cannot handle it at all, which is why we include + * it in SSL_OP_ALL. */ +#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L /* added in 0.9.6e */ + +/* SSL_OP_ALL: various bug workarounds that should be rather harmless. + *             This used to be 0x000FFFFFL before 0.9.7. */ +#define SSL_OP_ALL					0x80000FFFL + +/* DTLS options */ +#define SSL_OP_NO_QUERY_MTU                 0x00001000L +/* Turn on Cookie Exchange (on relevant for servers) */ +#define SSL_OP_COOKIE_EXCHANGE              0x00002000L +/* Don't use RFC4507 ticket extension */ +#define SSL_OP_NO_TICKET	            0x00004000L +/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client)  */ +#define SSL_OP_CISCO_ANYCONNECT		    0x00008000L + +/* As server, disallow session resumption on renegotiation */ +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION	0x00010000L +/* Don't use compression even if supported */ +#define SSL_OP_NO_COMPRESSION				0x00020000L +/* Permit unsafe legacy renegotiation */ +#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00040000L +/* If set, always create a new key when using tmp_ecdh parameters */ +#define SSL_OP_SINGLE_ECDH_USE				0x00080000L +/* If set, always create a new key when using tmp_dh parameters */ +#define SSL_OP_SINGLE_DH_USE				0x00100000L +/* Set to always use the tmp_rsa key when doing RSA operations, + * even when this violates protocol specs */ +#define SSL_OP_EPHEMERAL_RSA				0x00200000L +/* Set on servers to choose the cipher according to the server's + * preferences */ +#define SSL_OP_CIPHER_SERVER_PREFERENCE			0x00400000L +/* If set, a server will allow a client to issue a SSLv3.0 version number + * as latest version supported in the premaster secret, even when TLSv1.0 + * (version 3.1) was announced in the client hello. Normally this is + * forbidden to prevent version rollback attacks. */ +#define SSL_OP_TLS_ROLLBACK_BUG				0x00800000L + +#define SSL_OP_NO_SSLv2					0x01000000L +#define SSL_OP_NO_SSLv3					0x02000000L +#define SSL_OP_NO_TLSv1					0x04000000L + +/* The next flag deliberately changes the ciphertest, this is a check + * for the PKCS#1 attack */ +#define SSL_OP_PKCS1_CHECK_1				0x08000000L +#define SSL_OP_PKCS1_CHECK_2				0x10000000L +#define SSL_OP_NETSCAPE_CA_DN_BUG			0x20000000L +#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG		0x40000000L +/* Make server add server-hello extension from early version of + * cryptopro draft, when GOST ciphersuite is negotiated.  + * Required for interoperability with CryptoPro CSP 3.x  + */ +#define SSL_OP_CRYPTOPRO_TLSEXT_BUG			0x80000000L + +/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): */ +#define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L +/* Make it possible to retry SSL_write() with changed buffer location + * (buffer contents must stay the same!); this is not the default to avoid + * the misconception that non-blocking SSL_write() behaves like + * non-blocking write(): */ +#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L +/* Never bother the application with retries if the transport + * is blocking: */ +#define SSL_MODE_AUTO_RETRY 0x00000004L +/* Don't attempt to automatically build certificate chain */ +#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L +/* Save RAM by releasing read and write buffers when they're empty. (SSL3 and + * TLS only.)  "Released" buffers are put onto a free-list in the context + * or just freed (depending on the context's setting for freelist_max_len). */ +#define SSL_MODE_RELEASE_BUFFERS 0x00000010L +/* Use small read and write buffers: (a) lazy allocate read buffers for + * large incoming records, and (b) limit the size of outgoing records. */ +#define SSL_MODE_SMALL_BUFFERS 0x00000020L +/* When set, clients may send application data before receipt of CCS + * and Finished.  This mode enables full-handshakes to 'complete' in + * one RTT. */ +#define SSL_MODE_HANDSHAKE_CUTTHROUGH 0x00000040L + +/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, + * they cannot be used to clear bits. */ + +#define SSL_CTX_set_options(ctx,op) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_CTX_clear_options(ctx,op) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL) +#define SSL_CTX_get_options(ctx) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL) +#define SSL_set_options(ssl,op) \ +	SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_clear_options(ssl,op) \ +	SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL) +#define SSL_get_options(ssl) \ +        SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL) + +#define SSL_CTX_set_mode(ctx,op) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +#define SSL_CTX_clear_mode(ctx,op) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL) +#define SSL_CTX_get_mode(ctx) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +#define SSL_clear_mode(ssl,op) \ +	SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL) +#define SSL_set_mode(ssl,op) \ +	SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +#define SSL_get_mode(ssl) \ +        SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) +#define SSL_set_mtu(ssl, mtu) \ +        SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL) + +#define SSL_get_secure_renegotiation_support(ssl) \ +	SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL) + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) + + + +#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32) +#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */ +#else +#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */ +#endif + +#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT	(1024*20) + +/* This callback type is used inside SSL_CTX, SSL, and in the functions that set + * them. It is used to override the generation of SSL/TLS session IDs in a + * server. Return value should be zero on an error, non-zero to proceed. Also, + * callbacks should themselves check if the id they generate is unique otherwise + * the SSL handshake will fail with an error - callbacks can do this using the + * 'ssl' value they're passed by; + *      SSL_has_matching_session_id(ssl, id, *id_len) + * The length value passed in is set at the maximum size the session ID can be. + * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback + * can alter this length to be less if desired, but under SSLv2 session IDs are + * supposed to be fixed at 16 bytes so the id will be padded after the callback + * returns in this case. It is also an error for the callback to set the size to + * zero. */ +typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id, +				unsigned int *id_len); + +typedef struct ssl_comp_st +	{ +	int id; +	const char *name; +#ifndef OPENSSL_NO_COMP +	COMP_METHOD *method; +#else +	char *method; +#endif +	} SSL_COMP; + +DECLARE_STACK_OF(SSL_COMP) +DECLARE_LHASH_OF(SSL_SESSION); + +struct ssl_ctx_st +	{ +	const SSL_METHOD *method; + +	STACK_OF(SSL_CIPHER) *cipher_list; +	/* same as above but sorted for lookup */ +	STACK_OF(SSL_CIPHER) *cipher_list_by_id; + +	struct x509_store_st /* X509_STORE */ *cert_store; +	LHASH_OF(SSL_SESSION) *sessions; +	/* Most session-ids that will be cached, default is +	 * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */ +	unsigned long session_cache_size; +	struct ssl_session_st *session_cache_head; +	struct ssl_session_st *session_cache_tail; + +	/* 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.  After the call, +	 * OpenSSL will SSL_SESSION_free() it. */ +	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); + +	struct +		{ +		int sess_connect;	/* SSL new conn - started */ +		int sess_connect_renegotiate;/* SSL reneg - requested */ +		int sess_connect_good;	/* SSL new conne/reneg - finished */ +		int sess_accept;	/* SSL new accept - started */ +		int sess_accept_renegotiate;/* SSL reneg - requested */ +		int sess_accept_good;	/* SSL accept/reneg - finished */ +		int sess_miss;		/* session lookup misses  */ +		int sess_timeout;	/* reuse attempt on timeouted session */ +		int sess_cache_full;	/* session removed due to full cache */ +		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 :-) */ +		} stats; + +	int references; + +	/* if defined, these override the X509_verify_cert() calls */ +	int (*app_verify_callback)(X509_STORE_CTX *, void *); +	void *app_verify_arg; +	/* before OpenSSL 0.9.7, 'app_verify_arg' was ignored +	 * ('app_verify_callback' was called with just one argument) */ + +	/* Default password callback. */ +	pem_password_cb *default_passwd_callback; + +	/* Default password callback user data. */ +	void *default_passwd_callback_userdata; + +	/* get client cert callback */ +	int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey); + +    /* cookie generate callback */ +    int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie,  +        unsigned int *cookie_len); + +    /* verify cookie callback */ +    int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie,  +        unsigned int cookie_len); + +	CRYPTO_EX_DATA ex_data; + +	const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */ +	const EVP_MD *md5;	/* For SSLv3/TLSv1 'ssl3-md5' */ +	const EVP_MD *sha1;   /* For SSLv3/TLSv1 'ssl3->sha1' */ + +	STACK_OF(X509) *extra_certs; +	STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ + + +	/* Default values used when no per-SSL value is defined follow */ + +	void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */ + +	/* what we put in client cert requests */ +	STACK_OF(X509_NAME) *client_CA; + + +	/* Default values to use in SSL structures follow (these are copied by SSL_new) */ + +	unsigned long options; +	unsigned long mode; +	long max_cert_list; + +	struct cert_st /* CERT */ *cert; +	int read_ahead; + +	/* callback that allows applications to peek at protocol messages */ +	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); +	void *msg_callback_arg; + +	int verify_mode; +	unsigned int sid_ctx_length; +	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; +	int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */ + +	/* Default generate session ID callback. */ +	GEN_SESSION_CB generate_session_id; + +	X509_VERIFY_PARAM *param; + +#if 0 +	int purpose;		/* Purpose setting */ +	int trust;		/* Trust setting */ +#endif + +	int quiet_shutdown; + +	/* Maximum amount of data to send in one fragment. +	 * actual record size can be more than this due to +	 * padding and MAC overheads. +	 */ +	unsigned int max_send_fragment; + +#ifndef OPENSSL_ENGINE +	/* Engine to pass requests for client certs to +	 */ +	ENGINE *client_cert_engine; +#endif + +#ifndef OPENSSL_NO_TLSEXT +	/* TLS extensions servername callback */ +	int (*tlsext_servername_callback)(SSL*, int *, void *); +	void *tlsext_servername_arg; +	/* RFC 4507 session ticket keys */ +	unsigned char tlsext_tick_key_name[16]; +	unsigned char tlsext_tick_hmac_key[16]; +	unsigned char tlsext_tick_aes_key[16]; +	/* Callback to support customisation of ticket key setting */ +	int (*tlsext_ticket_key_cb)(SSL *ssl, +					unsigned char *name, unsigned char *iv, +					EVP_CIPHER_CTX *ectx, + 					HMAC_CTX *hctx, int enc); + +	/* certificate status request info */ +	/* Callback for status request */ +	int (*tlsext_status_cb)(SSL *ssl, void *arg); +	void *tlsext_status_arg; + +	/* draft-rescorla-tls-opaque-prf-input-00.txt information */ +	int (*tlsext_opaque_prf_input_callback)(SSL *, void *peerinput, size_t len, void *arg); +	void *tlsext_opaque_prf_input_callback_arg; + +# ifndef OPENSSL_NO_NEXTPROTONEG +	/* Next protocol negotiation information */ +	/* (for experimental NPN extension). */ + +	/* For a server, this contains a callback function by which the set of +	 * advertised protocols can be provided. */ +	int (*next_protos_advertised_cb)(SSL *s, const unsigned char **buf, +			                 unsigned int *len, void *arg); +	void *next_protos_advertised_cb_arg; +	/* For a client, this contains a callback function that selects the +	 * next protocol from the list provided by the server. */ +	int (*next_proto_select_cb)(SSL *s, unsigned char **out, +				    unsigned char *outlen, +				    const unsigned char *in, +				    unsigned int inlen, +				    void *arg); +	void *next_proto_select_cb_arg; +# endif +#endif + +#ifndef OPENSSL_NO_PSK +	char *psk_identity_hint; +	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity, +		unsigned int max_identity_len, unsigned char *psk, +		unsigned int max_psk_len); +	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity, +		unsigned char *psk, unsigned int max_psk_len); +#endif + +#ifndef OPENSSL_NO_BUF_FREELISTS +#define SSL_MAX_BUF_FREELIST_LEN_DEFAULT 32 +	unsigned int freelist_max_len; +	struct ssl3_buf_freelist_st *wbuf_freelist; +	struct ssl3_buf_freelist_st *rbuf_freelist; +#endif +	}; + +#define SSL_SESS_CACHE_OFF			0x0000 +#define SSL_SESS_CACHE_CLIENT			0x0001 +#define SSL_SESS_CACHE_SERVER			0x0002 +#define SSL_SESS_CACHE_BOTH	(SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER) +#define SSL_SESS_CACHE_NO_AUTO_CLEAR		0x0080 +/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */ +#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP	0x0100 +#define SSL_SESS_CACHE_NO_INTERNAL_STORE	0x0200 +#define SSL_SESS_CACHE_NO_INTERNAL \ +	(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE) + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx); +#define SSL_CTX_sess_number(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +#define SSL_CTX_sess_connect(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +#define SSL_CTX_sess_connect_good(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +#define SSL_CTX_sess_connect_renegotiate(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +#define SSL_CTX_sess_accept_renegotiate(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept_good(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +#define SSL_CTX_sess_hits(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +#define SSL_CTX_sess_cb_hits(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +#define SSL_CTX_sess_misses(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +#define SSL_CTX_sess_timeouts(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +#define SSL_CTX_sess_cache_full(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess)); +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess); +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess)); +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess); +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy)); +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy); +void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val)); +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val); +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)); +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey); +#ifndef OPENSSL_NO_ENGINE +int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e); +#endif +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)); +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len)); +#ifndef OPENSSL_NO_NEXTPROTONEG +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s, +					   int (*cb) (SSL *ssl, +						      const unsigned char **out, +						      unsigned int *outlen, +						      void *arg), void *arg); +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, +				      int (*cb) (SSL *ssl, unsigned char **out, +						 unsigned char *outlen, +						 const unsigned char *in, +						 unsigned int inlen, void *arg), +				      void *arg); + +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, +			  const unsigned char *in, unsigned int inlen, +			  const unsigned char *client, unsigned int client_len); +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, +				    unsigned *len); + +#define OPENSSL_NPN_UNSUPPORTED	0 +#define OPENSSL_NPN_NEGOTIATED	1 +#define OPENSSL_NPN_NO_OVERLAP	2 + +#endif + +#ifndef OPENSSL_NO_PSK +/* the maximum length of the buffer given to callbacks containing the + * resulting identity/psk */ +#define PSK_MAX_IDENTITY_LEN 128 +#define PSK_MAX_PSK_LEN 256 +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,  +	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,  +		char *identity, unsigned int max_identity_len, unsigned char *psk, +		unsigned int max_psk_len)); +void SSL_set_psk_client_callback(SSL *ssl,  +	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,  +		char *identity, unsigned int max_identity_len, unsigned char *psk, +		unsigned int max_psk_len)); +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,  +	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity, +		unsigned char *psk, unsigned int max_psk_len)); +void SSL_set_psk_server_callback(SSL *ssl, +	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity, +		unsigned char *psk, unsigned int max_psk_len)); +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint); +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint); +const char *SSL_get_psk_identity_hint(const SSL *s); +const char *SSL_get_psk_identity(const SSL *s); +#endif + +#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_nothing(s)	(SSL_want(s) == SSL_NOTHING) +#define SSL_want_read(s)	(SSL_want(s) == SSL_READING) +#define SSL_want_write(s)	(SSL_want(s) == SSL_WRITING) +#define SSL_want_x509_lookup(s)	(SSL_want(s) == SSL_X509_LOOKUP) + +#define SSL_MAC_FLAG_READ_MAC_STREAM 1 +#define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 + +struct ssl_st +	{ +	/* protocol version +	 * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION) +	 */ +	int version; +	int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */ + +	const 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 */ + +#ifndef OPENSSL_NO_BIO +	BIO *rbio; /* used by SSL_read */ +	BIO *wbio; /* used by SSL_write */ +	BIO *bbio; /* used during session-id reuse to concatenate +		    * 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)(SSL *); + +	/* Imagine that here's a boolean member "init" that is +	 * switched as soon as SSL_set_{accept/connect}_state +	 * is called for the first time, so that "state" and +	 * "handshake_func" are properly initialized.  But as +	 * handshake_func is == 0 until then, we use this +	 * test instead of an "init" member. +	 */ + +	int server;	/* are we the server side? - mostly used by SSL_clear*/ + +	int new_session;/* 1 if we are to use a new session. +	                 * 2 if we are a server and are inside a handshake +	                 *   (i.e. not just sending a HelloRequest) +	                 * NB: For servers, the 'new' session may actually be a previously +	                 * cached session or even the previous session unless +	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ +	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 */ +	void *init_msg;   	/* pointer to handshake message body, set by ssl3_get_message() */ +	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_state_st *s2; /* SSLv2 variables */ +	struct ssl3_state_st *s3; /* SSLv3 variables */ +	struct dtls1_state_st *d1; /* DTLSv1 variables */ + +	int read_ahead;		/* Read as many input bytes as possible +	               	 	 * (for non-blocking reads) */ + +	/* callback that allows applications to peek at protocol messages */ +	void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); +	void *msg_callback_arg; + +	int hit;		/* reusing a previous session */ + +	X509_VERIFY_PARAM *param; + +#if 0 +	int purpose;		/* Purpose setting */ +	int trust;		/* Trust setting */ +#endif + +	/* crypto */ +	STACK_OF(SSL_CIPHER) *cipher_list; +	STACK_OF(SSL_CIPHER) *cipher_list_by_id; + +	/* These are the ones being used, the ones in SSL_SESSION are +	 * the ones to be 'copied' into these ones */ +	int mac_flags;  +	EVP_CIPHER_CTX *enc_read_ctx;		/* cryptographic state */ +	EVP_MD_CTX *read_hash;		/* used for mac generation */ +#ifndef OPENSSL_NO_COMP +	COMP_CTX *expand;			/* uncompress */ +#else +	char *expand; +#endif + +	EVP_CIPHER_CTX *enc_write_ctx;		/* cryptographic state */ +	EVP_MD_CTX *write_hash;		/* used for mac generation */ +#ifndef OPENSSL_NO_COMP +	COMP_CTX *compress;			/* compression */ +#else +	char *compress;	 +#endif + +	/* session info */ + +	/* client cert? */ +	/* This is used to hold the server certificate used */ +	struct cert_st /* CERT */ *cert; + +	/* the session_id_context is used to ensure sessions are only reused +	 * in the appropriate context */ +	unsigned int sid_ctx_length; +	unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + +	/* This can also be in the session once a session is established */ +	SSL_SESSION *session; + +        /* This can be disabled to prevent the use of uncached sessions */ +	int session_creation_enabled; + +	/* Default generate session ID callback. */ +	GEN_SESSION_CB generate_session_id; + +	/* Used in SSL2 and SSL3 */ +	int verify_mode;	/* 0 don't care about verify failure. +				 * 1 fail if verify fails */ +	int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */ + +	void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */ + +	int error;		/* error bytes to be written */ +	int error_code;		/* actual code */ + +#ifndef OPENSSL_NO_KRB5 +	KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */ +#endif	/* OPENSSL_NO_KRB5 */ + +#ifndef OPENSSL_NO_PSK +	unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity, +		unsigned int max_identity_len, unsigned char *psk, +		unsigned int max_psk_len); +	unsigned int (*psk_server_callback)(SSL *ssl, const char *identity, +		unsigned char *psk, unsigned int max_psk_len); +#endif + +	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 */ +	long verify_result; +	CRYPTO_EX_DATA ex_data; + +	/* for server side, keep the list of CA_dn we can use */ +	STACK_OF(X509_NAME) *client_CA; + +	int references; +	unsigned long options; /* protocol behaviour */ +	unsigned long mode; /* API behaviour */ +	long max_cert_list; +	int first_packet; +	int client_version;	/* what was passed, used for +				 * SSLv3/TLS rollback check */ +	unsigned int max_send_fragment; +#ifndef OPENSSL_NO_TLSEXT +	/* TLS extension debug callback */ +	void (*tlsext_debug_cb)(SSL *s, int client_server, int type, +					unsigned char *data, int len, +					void *arg); +	void *tlsext_debug_arg; +	char *tlsext_hostname; +	int servername_done;   /* no further mod of servername  +	                          0 : call the servername extension callback. +	                          1 : prepare 2, allow last ack just after in server callback. +	                          2 : don't call servername callback, no ack in server hello +	                       */ +	/* certificate status request info */ +	/* Status type or -1 if no status type */ +	int tlsext_status_type; +	/* Expect OCSP CertificateStatus message */ +	int tlsext_status_expected; +	/* OCSP status request only */ +	STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids; +	X509_EXTENSIONS *tlsext_ocsp_exts; +	/* OCSP response received or to be sent */ +	unsigned char *tlsext_ocsp_resp; +	int tlsext_ocsp_resplen; + +	/* RFC4507 session ticket expected to be received or sent */ +	int tlsext_ticket_expected; +#ifndef OPENSSL_NO_EC +	size_t tlsext_ecpointformatlist_length; +	unsigned char *tlsext_ecpointformatlist; /* our list */ +	size_t tlsext_ellipticcurvelist_length; +	unsigned char *tlsext_ellipticcurvelist; /* our list */ +#endif /* OPENSSL_NO_EC */ + +	/* draft-rescorla-tls-opaque-prf-input-00.txt information to be used for handshakes */ +	void *tlsext_opaque_prf_input; +	size_t tlsext_opaque_prf_input_len; + +	/* TLS Session Ticket extension override */ +	TLS_SESSION_TICKET_EXT *tlsext_session_ticket; + +	/* TLS Session Ticket extension callback */ +	tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb; +	void *tls_session_ticket_ext_cb_arg; + +	/* TLS pre-shared secret session resumption */ +	tls_session_secret_cb_fn tls_session_secret_cb; +	void *tls_session_secret_cb_arg; + +	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ + +#ifndef OPENSSL_NO_NEXTPROTONEG +	/* Next protocol negotiation. For the client, this is the protocol that +	 * we sent in NextProtocol and is set when handling ServerHello +	 * extensions. +	 * +	 * For a server, this is the client's selected_protocol from +	 * NextProtocol and is set when handling the NextProtocol message, +	 * before the Finished message. */ +	unsigned char *next_proto_negotiated; +	unsigned char next_proto_negotiated_len; +#endif + +#define session_ctx initial_ctx +#else +#define session_ctx ctx +#endif /* OPENSSL_NO_TLSEXT */ +	}; + +#ifdef __cplusplus +} +#endif + +#include <openssl/ssl2.h> +#include <openssl/ssl3.h> +#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */ +#include <openssl/dtls1.h> /* Datagram TLS */ +#include <openssl/ssl23.h> + +#ifdef  __cplusplus +extern "C" { +#endif + +/* compatibility */ +#define SSL_set_app_data(s,arg)		(SSL_set_ex_data(s,0,(char *)arg)) +#define SSL_get_app_data(s)		(SSL_get_ex_data(s,0)) +#define SSL_SESSION_set_app_data(s,a)	(SSL_SESSION_set_ex_data(s,0,(char *)a)) +#define SSL_SESSION_get_app_data(s)	(SSL_SESSION_get_ex_data(s,0)) +#define SSL_CTX_get_app_data(ctx)	(SSL_CTX_get_ex_data(ctx,0)) +#define SSL_CTX_set_app_data(ctx,arg)	(SSL_CTX_set_ex_data(ctx,0,(char *)arg)) + +/* The following are the possible values for ssl->state are are + * used to indicate where we are up to 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_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) + +#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_get_state(a)		SSL_state(a) +#define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK) +#define SSL_in_init(a)			((SSL_state(a)&SSL_ST_INIT) && \ +                                  !SSL_cutthrough_complete(a)) +#define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE) +#define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT) +#define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT) +int SSL_cutthrough_complete(const SSL *s); + +/* 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 + +/* Obtain latest Finished message + *   -- that we sent (SSL_get_finished) + *   -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); + +/* 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 OpenSSL_add_ssl_algorithms()	SSL_library_init() +#define SSLeay_add_ssl_algorithms()	SSL_library_init() + +/* this is for backward compatibility */ +#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 compatibility */ +#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)) +#define SSL_get_time(a)		SSL_SESSION_get_time(a) +#define SSL_set_time(a,b)	SSL_SESSION_set_time((a),(b)) +#define SSL_get_timeout(a)	SSL_SESSION_get_timeout(a) +#define SSL_set_timeout(a,b)	SSL_SESSION_set_timeout((a),(b)) + +#define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id) +#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id) + +DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) + +#define SSL_AD_REASON_OFFSET		1000 /* offset to get SSL_R_... value from SSL_AD_... */ + +/* These alert types are for SSLv3 and TLSv1 */ +#define SSL_AD_CLOSE_NOTIFY		SSL3_AD_CLOSE_NOTIFY +#define SSL_AD_UNEXPECTED_MESSAGE	SSL3_AD_UNEXPECTED_MESSAGE /* fatal */ +#define SSL_AD_BAD_RECORD_MAC		SSL3_AD_BAD_RECORD_MAC     /* fatal */ +#define SSL_AD_DECRYPTION_FAILED	TLS1_AD_DECRYPTION_FAILED +#define SSL_AD_RECORD_OVERFLOW		TLS1_AD_RECORD_OVERFLOW +#define SSL_AD_DECOMPRESSION_FAILURE	SSL3_AD_DECOMPRESSION_FAILURE/* fatal */ +#define SSL_AD_HANDSHAKE_FAILURE	SSL3_AD_HANDSHAKE_FAILURE/* fatal */ +#define SSL_AD_NO_CERTIFICATE		SSL3_AD_NO_CERTIFICATE /* Not for TLS */ +#define SSL_AD_BAD_CERTIFICATE		SSL3_AD_BAD_CERTIFICATE +#define SSL_AD_UNSUPPORTED_CERTIFICATE	SSL3_AD_UNSUPPORTED_CERTIFICATE +#define SSL_AD_CERTIFICATE_REVOKED	SSL3_AD_CERTIFICATE_REVOKED +#define SSL_AD_CERTIFICATE_EXPIRED	SSL3_AD_CERTIFICATE_EXPIRED +#define SSL_AD_CERTIFICATE_UNKNOWN	SSL3_AD_CERTIFICATE_UNKNOWN +#define SSL_AD_ILLEGAL_PARAMETER	SSL3_AD_ILLEGAL_PARAMETER   /* fatal */ +#define SSL_AD_UNKNOWN_CA		TLS1_AD_UNKNOWN_CA	/* fatal */ +#define SSL_AD_ACCESS_DENIED		TLS1_AD_ACCESS_DENIED	/* fatal */ +#define SSL_AD_DECODE_ERROR		TLS1_AD_DECODE_ERROR	/* fatal */ +#define SSL_AD_DECRYPT_ERROR		TLS1_AD_DECRYPT_ERROR +#define SSL_AD_EXPORT_RESTRICTION	TLS1_AD_EXPORT_RESTRICTION/* fatal */ +#define SSL_AD_PROTOCOL_VERSION		TLS1_AD_PROTOCOL_VERSION /* fatal */ +#define SSL_AD_INSUFFICIENT_SECURITY	TLS1_AD_INSUFFICIENT_SECURITY/* fatal */ +#define SSL_AD_INTERNAL_ERROR		TLS1_AD_INTERNAL_ERROR	/* fatal */ +#define SSL_AD_USER_CANCELLED		TLS1_AD_USER_CANCELLED +#define SSL_AD_NO_RENEGOTIATION		TLS1_AD_NO_RENEGOTIATION +#define SSL_AD_UNSUPPORTED_EXTENSION	TLS1_AD_UNSUPPORTED_EXTENSION +#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE +#define SSL_AD_UNRECOGNIZED_NAME	TLS1_AD_UNRECOGNIZED_NAME +#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE +#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE +#define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */ + +#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 error stack/return value/errno */ +#define SSL_ERROR_ZERO_RETURN		6 +#define SSL_ERROR_WANT_CONNECT		7 +#define SSL_ERROR_WANT_ACCEPT		8 + +#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_ECDH			4 +#define SSL_CTRL_SET_TMP_RSA_CB			5 +#define SSL_CTRL_SET_TMP_DH_CB			6 +#define SSL_CTRL_SET_TMP_ECDH_CB		7 + +#define SSL_CTRL_GET_SESSION_REUSED		8 +#define SSL_CTRL_GET_CLIENT_CERT_REQUEST	9 +#define SSL_CTRL_GET_NUM_RENEGOTIATIONS		10 +#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS	11 +#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS	12 +#define SSL_CTRL_GET_FLAGS			13 +#define SSL_CTRL_EXTRA_CHAIN_CERT		14 + +#define SSL_CTRL_SET_MSG_CALLBACK               15 +#define SSL_CTRL_SET_MSG_CALLBACK_ARG           16 + +/* only applies to datagram connections */ +#define SSL_CTRL_SET_MTU                17 +/* Stats */ +#define SSL_CTRL_SESS_NUMBER			20 +#define SSL_CTRL_SESS_CONNECT			21 +#define SSL_CTRL_SESS_CONNECT_GOOD		22 +#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE	23 +#define SSL_CTRL_SESS_ACCEPT			24 +#define SSL_CTRL_SESS_ACCEPT_GOOD		25 +#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE	26 +#define SSL_CTRL_SESS_HIT			27 +#define SSL_CTRL_SESS_CB_HIT			28 +#define SSL_CTRL_SESS_MISSES			29 +#define SSL_CTRL_SESS_TIMEOUTS			30 +#define SSL_CTRL_SESS_CACHE_FULL		31 +#define SSL_CTRL_OPTIONS			32 +#define SSL_CTRL_MODE				33 + +#define SSL_CTRL_GET_READ_AHEAD			40 +#define SSL_CTRL_SET_READ_AHEAD			41 +#define SSL_CTRL_SET_SESS_CACHE_SIZE		42 +#define SSL_CTRL_GET_SESS_CACHE_SIZE		43 +#define SSL_CTRL_SET_SESS_CACHE_MODE		44 +#define SSL_CTRL_GET_SESS_CACHE_MODE		45 + +#define SSL_CTRL_GET_MAX_CERT_LIST		50 +#define SSL_CTRL_SET_MAX_CERT_LIST		51 + +#define SSL_CTRL_SET_MAX_SEND_FRAGMENT		52 + +/* see tls1.h for macros based on these */ +#ifndef OPENSSL_NO_TLSEXT +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB	53 +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG	54 +#define SSL_CTRL_SET_TLSEXT_HOSTNAME		55 +#define SSL_CTRL_SET_TLSEXT_DEBUG_CB		56 +#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG		57 +#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS		58 +#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS		59 +#define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT	60 +#define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB	61 +#define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB	63 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG	64 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE	65 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS	66 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS	67 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS	68 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS	69 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP	70 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP	71 + +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB	72 +#endif + +#define DTLS_CTRL_GET_TIMEOUT		73 +#define DTLS_CTRL_HANDLE_TIMEOUT	74 +#define DTLS_CTRL_LISTEN			75 + +#define SSL_CTRL_GET_RI_SUPPORT			76 +#define SSL_CTRL_CLEAR_OPTIONS			77 +#define SSL_CTRL_CLEAR_MODE			78 + +#define DTLSv1_get_timeout(ssl, arg) \ +	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) +#define DTLSv1_handle_timeout(ssl) \ +	SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +#define DTLSv1_listen(ssl, peer) \ +	SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer) + +#define SSL_session_reused(ssl) \ +	SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) +#define SSL_num_renegotiations(ssl) \ +	SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL) +#define SSL_clear_num_renegotiations(ssl) \ +	SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL) +#define SSL_total_renegotiations(ssl) \ +	SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL) + +#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) +#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) + +#define SSL_need_tmp_RSA(ssl) \ +	SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL) +#define SSL_set_tmp_rsa(ssl,rsa) \ +	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +#define SSL_set_tmp_dh(ssl,dh) \ +	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh) +#define SSL_set_tmp_ecdh(ssl,ecdh) \ +	SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) + +#define SSL_CTX_add_extra_chain_cert(ctx,x509) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) + +#ifndef OPENSSL_NO_BIO +BIO_METHOD *BIO_f_ssl(void); +BIO *BIO_new_ssl(SSL_CTX *ctx,int client); +BIO *BIO_new_ssl_connect(SSL_CTX *ctx); +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx); +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 *,const char *str); +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); +void	SSL_CTX_free(SSL_CTX *); +long SSL_CTX_set_timeout(SSL_CTX *ctx,long t); +long SSL_CTX_get_timeout(const SSL_CTX *ctx); +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *); +int SSL_want(const SSL *s); +int	SSL_clear(SSL *s); + +void	SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm); + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s); +int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits); +char *	SSL_CIPHER_get_version(const SSL_CIPHER *c); +const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c); +const char *	SSL_CIPHER_authentication_method(const SSL_CIPHER *c); + +int	SSL_get_fd(const SSL *s); +int	SSL_get_rfd(const SSL *s); +int	SSL_get_wfd(const SSL *s); +const char  * SSL_get_cipher_list(const SSL *s,int n); +char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len); +int	SSL_get_read_ahead(const SSL * s); +int	SSL_pending(const SSL *s); +const char *	SSL_authentication_method(const SSL *c); +#ifndef OPENSSL_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 +#ifndef OPENSSL_NO_BIO +void	SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio); +BIO *	SSL_get_rbio(const SSL *s); +BIO *	SSL_get_wbio(const SSL *s); +#endif +int	SSL_set_cipher_list(SSL *s, const char *str); +int	SSL_set_cipher_lists(SSL *s, STACK_OF(SSL_CIPHER) *sk); +void	SSL_set_read_ahead(SSL *s, int yes); +int	SSL_get_verify_mode(const SSL *s); +int	SSL_get_verify_depth(const SSL *s); +int	(*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *); +void	SSL_set_verify(SSL *s, int mode, +		       int (*callback)(int ok,X509_STORE_CTX *ctx)); +void	SSL_set_verify_depth(SSL *s, int depth); +#ifndef OPENSSL_NO_RSA +int	SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +#endif +int	SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); +int	SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len); +int	SSL_use_certificate(SSL *ssl, X509 *x); +int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); +int	SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain); +STACK_OF(X509) * SSL_get_certificate_chain(SSL *ssl, X509 *x); + +#ifndef OPENSSL_NO_STDIO +int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +int	SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +int	SSL_use_certificate_file(SSL *ssl, const char *file, int type); +int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); +int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +int	SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, +					    const char *file); +#ifndef OPENSSL_SYS_VMS +#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */ +int	SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, +					   const char *dir); +#endif +#endif + +#endif + +void	SSL_load_error_strings(void ); +const char *SSL_state_string(const SSL *s); +const char *SSL_rstate_string(const SSL *s); +const char *SSL_state_string_long(const SSL *s); +const char *SSL_rstate_string_long(const SSL *s); +long	SSL_SESSION_get_time(const SSL_SESSION *s); +long	SSL_SESSION_set_time(SSL_SESSION *s, long t); +long	SSL_SESSION_get_timeout(const SSL_SESSION *s); +long	SSL_SESSION_set_timeout(SSL_SESSION *s, long t); +void	SSL_copy_session_id(SSL *to,const SSL *from); + +SSL_SESSION *SSL_SESSION_new(void); +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, +					unsigned int *len); +const char *	SSL_SESSION_get_version(const SSL_SESSION *s); +#ifndef OPENSSL_NO_FP_API +int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses); +#endif +#ifndef OPENSSL_NO_BIO +int	SSL_SESSION_print(BIO *fp,const 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); +void	SSL_set_session_creation_enabled(SSL *, int); +int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c); +int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c); +int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB); +int	SSL_set_generate_session_id(SSL *, GEN_SESSION_CB); +int	SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, +					unsigned int id_len); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp, +			     long length); + +#ifdef HEADER_X509_H +X509 *	SSL_get_peer_certificate(const SSL *s); +#endif + +STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s); + +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx); +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *); +void SSL_CTX_set_verify(SSL_CTX *ctx,int mode, +			int (*callback)(int, X509_STORE_CTX *)); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg); +#ifndef OPENSSL_NO_RSA +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +#endif +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len); +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx, +	const unsigned char *d, long len); +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); + +int SSL_CTX_check_private_key(const SSL_CTX *ctx); +int SSL_check_private_key(const SSL *ctx); + +int	SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx, +				       unsigned int sid_ctx_len); + +SSL *	SSL_new(SSL_CTX *ctx); +int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx, +				   unsigned int sid_ctx_len); + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose); +int SSL_set_purpose(SSL *s, int purpose); +int SSL_CTX_set_trust(SSL_CTX *s, int trust); +int SSL_set_trust(SSL *s, int trust); + +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm); +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm); + +void	SSL_free(SSL *ssl); +int 	SSL_accept(SSL *ssl); +int 	SSL_connect(SSL *ssl); +int 	SSL_read(SSL *ssl,void *buf,int num); +int 	SSL_peek(SSL *ssl,void *buf,int num); +int 	SSL_write(SSL *ssl,const void *buf,int num); +long	SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg); +long	SSL_callback_ctrl(SSL *, int, void (*)(void)); +long	SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg); +long	SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void)); + +int	SSL_get_error(const SSL *s,int ret_code); +const char *SSL_get_version(const SSL *s); + +/* This sets the 'default' SSL version that SSL_new() will create */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth); + +#ifndef OPENSSL_NO_SSL2 +const SSL_METHOD *SSLv2_method(void);		/* SSLv2 */ +const SSL_METHOD *SSLv2_server_method(void);	/* SSLv2 */ +const SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */ +#endif + +const SSL_METHOD *SSLv3_method(void);		/* SSLv3 */ +const SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */ +const SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */ + +const SSL_METHOD *SSLv23_method(void);	/* SSLv3 but can rollback to v2 */ +const SSL_METHOD *SSLv23_server_method(void);	/* SSLv3 but can rollback to v2 */ +const SSL_METHOD *SSLv23_client_method(void);	/* SSLv3 but can rollback to v2 */ + +const SSL_METHOD *TLSv1_method(void);		/* TLSv1.0 */ +const SSL_METHOD *TLSv1_server_method(void);	/* TLSv1.0 */ +const SSL_METHOD *TLSv1_client_method(void);	/* TLSv1.0 */ + +const SSL_METHOD *DTLSv1_method(void);		/* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_server_method(void);	/* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_client_method(void);	/* DTLSv1.0 */ + +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); + +int SSL_do_handshake(SSL *s); +int SSL_renegotiate(SSL *s); +int SSL_renegotiate_pending(SSL *s); +int SSL_shutdown(SSL *s); + +const SSL_METHOD *SSL_get_ssl_method(SSL *s); +int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); +const char *SSL_alert_type_string_long(int value); +const char *SSL_alert_type_string(int value); +const char *SSL_alert_desc_string_long(int value); +const char *SSL_alert_desc_string(int value); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s); +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const 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(const SSL *s); + +int SSL_library_init(void ); + +char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size); +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk); + +SSL *SSL_dup(SSL *ssl); + +X509 *SSL_get_certificate(const SSL *ssl); +/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl); + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode); +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); +void SSL_set_quiet_shutdown(SSL *ssl,int mode); +int SSL_get_quiet_shutdown(const SSL *ssl); +void SSL_set_shutdown(SSL *ssl,int mode); +int SSL_get_shutdown(const SSL *ssl); +int SSL_version(const SSL *ssl); +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, +	const char *CApath); +#define SSL_get0_session SSL_get_session /* just peek at pointer */ +SSL_SESSION *SSL_get_session(const SSL *ssl); +SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx); +void SSL_set_info_callback(SSL *ssl, +			   void (*cb)(const SSL *ssl,int type,int val)); +void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val); +int SSL_state(const SSL *ssl); + +void SSL_set_verify_result(SSL *ssl,long v); +long SSL_get_verify_result(const SSL *ssl); + +int SSL_set_ex_data(SSL *ssl,int idx,void *data); +void *SSL_get_ex_data(const SSL *ssl,int idx); +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, +	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data); +void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, +	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data); +void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx); +int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, +	CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_get_ex_data_X509_STORE_CTX_idx(void ); + +#define SSL_CTX_sess_set_cache_size(ctx,t) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +#define SSL_CTX_sess_get_cache_size(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +#define SSL_CTX_set_session_cache_mode(ctx,m) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +#define SSL_CTX_get_session_cache_mode(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +#define SSL_CTX_get_read_ahead(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +#define SSL_CTX_set_read_ahead(ctx,m) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +#define SSL_CTX_get_max_cert_list(ctx) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_CTX_set_max_cert_list(ctx,m) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +#define SSL_get_max_cert_list(ssl) \ +	SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_set_max_cert_list(ssl,m) \ +	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + +#define SSL_CTX_set_max_send_fragment(ctx,m) \ +	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +#define SSL_set_max_send_fragment(ssl,m) \ +	SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) + +     /* NB: the keylength is only applicable when is_export is true */ +#ifndef OPENSSL_NO_RSA +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, +				  RSA *(*cb)(SSL *ssl,int is_export, +					     int keylength)); + +void SSL_set_tmp_rsa_callback(SSL *ssl, +				  RSA *(*cb)(SSL *ssl,int is_export, +					     int keylength)); +#endif +#ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, +				 DH *(*dh)(SSL *ssl,int is_export, +					   int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, +				 DH *(*dh)(SSL *ssl,int is_export, +					   int keylength)); +#endif +#ifndef OPENSSL_NO_ECDH +void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, +				 EC_KEY *(*ecdh)(SSL *ssl,int is_export, +					   int keylength)); +void SSL_set_tmp_ecdh_callback(SSL *ssl, +				 EC_KEY *(*ecdh)(SSL *ssl,int is_export, +					   int keylength)); +#endif + +#ifndef OPENSSL_NO_COMP +const COMP_METHOD *SSL_get_current_compression(SSL *s); +const COMP_METHOD *SSL_get_current_expansion(SSL *s); +const char *SSL_COMP_get_name(const COMP_METHOD *comp); +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm); +#else +const void *SSL_get_current_compression(SSL *s); +const void *SSL_get_current_expansion(SSL *s); +const char *SSL_COMP_get_name(const void *comp); +void *SSL_COMP_get_compression_methods(void); +int SSL_COMP_add_compression_method(int id,void *cm); +#endif + +/* TLS extensions functions */ +int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); + +int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, +				  void *arg); + +/* Pre-shared secret session resumption functions */ +int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_SSL_strings(void); + +/* Error codes for the SSL functions. */ + +/* Function codes. */ +#define SSL_F_CLIENT_CERTIFICATE			 100 +#define SSL_F_CLIENT_FINISHED				 167 +#define SSL_F_CLIENT_HELLO				 101 +#define SSL_F_CLIENT_MASTER_KEY				 102 +#define SSL_F_D2I_SSL_SESSION				 103 +#define SSL_F_DO_DTLS1_WRITE				 245 +#define SSL_F_DO_SSL3_WRITE				 104 +#define SSL_F_DTLS1_ACCEPT				 246 +#define SSL_F_DTLS1_ADD_CERT_TO_BUF			 295 +#define SSL_F_DTLS1_BUFFER_RECORD			 247 +#define SSL_F_DTLS1_CLIENT_HELLO			 248 +#define SSL_F_DTLS1_CONNECT				 249 +#define SSL_F_DTLS1_ENC					 250 +#define SSL_F_DTLS1_GET_HELLO_VERIFY			 251 +#define SSL_F_DTLS1_GET_MESSAGE				 252 +#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT		 253 +#define SSL_F_DTLS1_GET_RECORD				 254 +#define SSL_F_DTLS1_HANDLE_TIMEOUT			 297 +#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN			 255 +#define SSL_F_DTLS1_PREPROCESS_FRAGMENT			 288 +#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE		 256 +#define SSL_F_DTLS1_PROCESS_RECORD			 257 +#define SSL_F_DTLS1_READ_BYTES				 258 +#define SSL_F_DTLS1_READ_FAILED				 259 +#define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST		 260 +#define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE		 261 +#define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE		 262 +#define SSL_F_DTLS1_SEND_CLIENT_VERIFY			 263 +#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST		 264 +#define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE		 265 +#define SSL_F_DTLS1_SEND_SERVER_HELLO			 266 +#define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE		 267 +#define SSL_F_DTLS1_WRITE_APP_DATA_BYTES		 268 +#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_FINISH				 239 +#define SSL_F_SERVER_HELLO				 114 +#define SSL_F_SERVER_VERIFY				 240 +#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_PEEK				 237 +#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_GENERATE_KEY_MATERIAL		 241 +#define SSL_F_SSL2_PEEK					 234 +#define SSL_F_SSL2_READ					 125 +#define SSL_F_SSL2_READ_INTERNAL			 236 +#define SSL_F_SSL2_SET_CERTIFICATE			 126 +#define SSL_F_SSL2_WRITE				 127 +#define SSL_F_SSL3_ACCEPT				 128 +#define SSL_F_SSL3_ADD_CERT_TO_BUF			 296 +#define SSL_F_SSL3_CALLBACK_CTRL			 233 +#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_CTRL					 213 +#define SSL_F_SSL3_CTX_CTRL				 133 +#define SSL_F_SSL3_DIGEST_CACHED_RECORDS		 293 +#define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC		 292 +#define SSL_F_SSL3_ENC					 134 +#define SSL_F_SSL3_GENERATE_KEY_BLOCK			 238 +#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST		 135 +#define SSL_F_SSL3_GET_CERT_STATUS			 289 +#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_NEW_SESSION_TICKET		 283 +#define SSL_F_SSL3_GET_NEXT_PROTO			 304 +#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_HANDSHAKE_MAC			 285 +#define SSL_F_SSL3_NEW_SESSION_TICKET			 287 +#define SSL_F_SSL3_OUTPUT_CERT_CHAIN			 147 +#define SSL_F_SSL3_PEEK					 235 +#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_HELLO			 242 +#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE		 155 +#define SSL_F_SSL3_SETUP_KEY_BLOCK			 157 +#define SSL_F_SSL3_SETUP_READ_BUFFER			 156 +#define SSL_F_SSL3_SETUP_WRITE_BUFFER			 291 +#define SSL_F_SSL3_WRITE_BYTES				 158 +#define SSL_F_SSL3_WRITE_PENDING			 159 +#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT	 298 +#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT		 277 +#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK	 215 +#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK	 216 +#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT	 299 +#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT		 278 +#define SSL_F_SSL_BAD_METHOD				 160 +#define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161 +#define SSL_F_SSL_CERT_DUP				 221 +#define SSL_F_SSL_CERT_INST				 222 +#define SSL_F_SSL_CERT_INSTANTIATE			 214 +#define SSL_F_SSL_CERT_NEW				 162 +#define SSL_F_SSL_CHECK_PRIVATE_KEY			 163 +#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT		 280 +#define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG		 279 +#define SSL_F_SSL_CIPHER_PROCESS_RULESTR		 230 +#define SSL_F_SSL_CIPHER_STRENGTH_SORT			 231 +#define SSL_F_SSL_CLEAR					 164 +#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD		 165 +#define SSL_F_SSL_CREATE_CIPHER_LIST			 166 +#define SSL_F_SSL_CTRL					 232 +#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168 +#define SSL_F_SSL_CTX_NEW				 169 +#define SSL_F_SSL_CTX_SET_CIPHER_LIST			 269 +#define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE		 290 +#define SSL_F_SSL_CTX_SET_PURPOSE			 226 +#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219 +#define SSL_F_SSL_CTX_SET_SSL_VERSION			 170 +#define SSL_F_SSL_CTX_SET_TRUST				 229 +#define SSL_F_SSL_CTX_USE_CERTIFICATE			 171 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176 +#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT		 272 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179 +#define SSL_F_SSL_DO_HANDSHAKE				 180 +#define SSL_F_SSL_GET_NEW_SESSION			 181 +#define SSL_F_SSL_GET_PREV_SESSION			 217 +#define SSL_F_SSL_GET_SERVER_SEND_CERT			 182 +#define SSL_F_SSL_GET_SIGN_PKEY				 183 +#define SSL_F_SSL_INIT_WBIO_BUFFER			 184 +#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185 +#define SSL_F_SSL_NEW					 186 +#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 300 +#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 302 +#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 301 +#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 303 +#define SSL_F_SSL_PEEK					 270 +#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 281 +#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 282 +#define SSL_F_SSL_READ					 223 +#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187 +#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188 +#define SSL_F_SSL_SESSION_NEW				 189 +#define SSL_F_SSL_SESSION_PRINT_FP			 190 +#define SSL_F_SSL_SESS_CERT_NEW				 225 +#define SSL_F_SSL_SET_CERT				 191 +#define SSL_F_SSL_SET_CIPHER_LIST			 271 +#define SSL_F_SSL_SET_FD				 192 +#define SSL_F_SSL_SET_PKEY				 193 +#define SSL_F_SSL_SET_PURPOSE				 227 +#define SSL_F_SSL_SET_RFD				 194 +#define SSL_F_SSL_SET_SESSION				 195 +#define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218 +#define SSL_F_SSL_SET_SESSION_TICKET_EXT		 294 +#define SSL_F_SSL_SET_TRUST				 228 +#define SSL_F_SSL_SET_WFD				 196 +#define SSL_F_SSL_SHUTDOWN				 224 +#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243 +#define SSL_F_SSL_UNDEFINED_FUNCTION			 197 +#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244 +#define SSL_F_SSL_USE_CERTIFICATE			 198 +#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199 +#define SSL_F_SSL_USE_CERTIFICATE_CHAIN			 2000 +#define SSL_F_SSL_USE_CERTIFICATE_FILE			 200 +#define SSL_F_SSL_USE_PRIVATEKEY			 201 +#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202 +#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203 +#define SSL_F_SSL_USE_PSK_IDENTITY_HINT			 273 +#define SSL_F_SSL_USE_RSAPRIVATEKEY			 204 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206 +#define SSL_F_SSL_VERIFY_CERT_CHAIN			 207 +#define SSL_F_SSL_WRITE					 208 +#define SSL_F_TLS1_CERT_VERIFY_MAC			 286 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209 +#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274 +#define SSL_F_TLS1_ENC					 210 +#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT		 275 +#define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT		 276 +#define SSL_F_TLS1_PRF					 284 +#define SSL_F_TLS1_SETUP_KEY_BLOCK			 211 +#define SSL_F_WRITE_PENDING				 212 + +/* Reason codes. */ +#define SSL_R_APP_DATA_IN_HANDSHAKE			 100 +#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 +#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_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_ECC_CERT				 304 +#define SSL_R_BAD_ECDSA_SIGNATURE			 305 +#define SSL_R_BAD_ECPOINT				 306 +#define SSL_R_BAD_HANDSHAKE_LENGTH			 332 +#define SSL_R_BAD_HELLO_REQUEST				 105 +#define SSL_R_BAD_LENGTH				 271 +#define SSL_R_BAD_MAC_DECODE				 113 +#define SSL_R_BAD_MAC_LENGTH				 333 +#define SSL_R_BAD_MESSAGE_TYPE				 114 +#define SSL_R_BAD_PACKET_LENGTH				 115 +#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER		 116 +#define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH		 316 +#define SSL_R_BAD_RESPONSE_ARGUMENT			 117 +#define SSL_R_BAD_RSA_DECRYPT				 118 +#define SSL_R_BAD_RSA_ENCRYPT				 119 +#define SSL_R_BAD_RSA_E_LENGTH				 120 +#define SSL_R_BAD_RSA_MODULUS_LENGTH			 121 +#define SSL_R_BAD_RSA_SIGNATURE				 122 +#define SSL_R_BAD_SIGNATURE				 123 +#define SSL_R_BAD_SSL_FILETYPE				 124 +#define SSL_R_BAD_SSL_SESSION_ID_LENGTH			 125 +#define SSL_R_BAD_STATE					 126 +#define SSL_R_BAD_WRITE_RETRY				 127 +#define SSL_R_BIO_NOT_SET				 128 +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG			 129 +#define SSL_R_BN_LIB					 130 +#define SSL_R_CA_DN_LENGTH_MISMATCH			 131 +#define SSL_R_CA_DN_TOO_LONG				 132 +#define SSL_R_CCS_RECEIVED_EARLY			 133 +#define SSL_R_CERTIFICATE_VERIFY_FAILED			 134 +#define SSL_R_CERT_LENGTH_MISMATCH			 135 +#define SSL_R_CHALLENGE_IS_DIFFERENT			 136 +#define SSL_R_CIPHER_CODE_WRONG_LENGTH			 137 +#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE		 138 +#define SSL_R_CIPHER_TABLE_SRC_ERROR			 139 +#define SSL_R_CLIENTHELLO_TLSEXT			 226 +#define SSL_R_COMPRESSED_LENGTH_TOO_LONG		 140 +#define SSL_R_COMPRESSION_DISABLED			 343 +#define SSL_R_COMPRESSION_FAILURE			 141 +#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE	 307 +#define SSL_R_COMPRESSION_LIBRARY_ERROR			 142 +#define SSL_R_CONNECTION_ID_IS_DIFFERENT		 143 +#define SSL_R_CONNECTION_TYPE_NOT_SET			 144 +#define SSL_R_COOKIE_MISMATCH				 308 +#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED		 145 +#define SSL_R_DATA_LENGTH_TOO_LONG			 146 +#define SSL_R_DECRYPTION_FAILED				 147 +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC	 281 +#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG		 148 +#define SSL_R_DIGEST_CHECK_FAILED			 149 +#define SSL_R_DTLS_MESSAGE_TOO_BIG			 334 +#define SSL_R_DUPLICATE_COMPRESSION_ID			 309 +#define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT		 317 +#define SSL_R_ECC_CERT_NOT_FOR_SIGNING			 318 +#define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE	 322 +#define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE	 323 +#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER		 310 +#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG			 150 +#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY		 282 +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST		 151 +#define SSL_R_EXCESSIVE_MESSAGE_SIZE			 152 +#define SSL_R_EXTRA_DATA_IN_MESSAGE			 153 +#define SSL_R_GOT_A_FIN_BEFORE_A_CCS			 154 +#define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS		 346 +#define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION		 347 +#define SSL_R_HTTPS_PROXY_REQUEST			 155 +#define SSL_R_HTTP_REQUEST				 156 +#define SSL_R_ILLEGAL_PADDING				 283 +#define SSL_R_INCONSISTENT_COMPRESSION			 340 +#define SSL_R_INVALID_CHALLENGE_LENGTH			 158 +#define SSL_R_INVALID_COMMAND				 280 +#define SSL_R_INVALID_COMPRESSION_ALGORITHM		 341 +#define SSL_R_INVALID_PURPOSE				 278 +#define SSL_R_INVALID_STATUS_RESPONSE			 328 +#define SSL_R_INVALID_TICKET_KEYS_LENGTH		 325 +#define SSL_R_INVALID_TRUST				 279 +#define SSL_R_KEY_ARG_TOO_LONG				 284 +#define SSL_R_KRB5					 285 +#define SSL_R_KRB5_C_CC_PRINC				 286 +#define SSL_R_KRB5_C_GET_CRED				 287 +#define SSL_R_KRB5_C_INIT				 288 +#define SSL_R_KRB5_C_MK_REQ				 289 +#define SSL_R_KRB5_S_BAD_TICKET				 290 +#define SSL_R_KRB5_S_INIT				 291 +#define SSL_R_KRB5_S_RD_REQ				 292 +#define SSL_R_KRB5_S_TKT_EXPIRED			 293 +#define SSL_R_KRB5_S_TKT_NYV				 294 +#define SSL_R_KRB5_S_TKT_SKEW				 295 +#define SSL_R_LENGTH_MISMATCH				 159 +#define SSL_R_LENGTH_TOO_SHORT				 160 +#define SSL_R_LIBRARY_BUG				 274 +#define SSL_R_LIBRARY_HAS_NO_CIPHERS			 161 +#define SSL_R_MESSAGE_TOO_LONG				 296 +#define SSL_R_MISSING_DH_DSA_CERT			 162 +#define SSL_R_MISSING_DH_KEY				 163 +#define SSL_R_MISSING_DH_RSA_CERT			 164 +#define SSL_R_MISSING_DSA_SIGNING_CERT			 165 +#define SSL_R_MISSING_EXPORT_TMP_DH_KEY			 166 +#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY		 167 +#define SSL_R_MISSING_RSA_CERTIFICATE			 168 +#define SSL_R_MISSING_RSA_ENCRYPTING_CERT		 169 +#define SSL_R_MISSING_RSA_SIGNING_CERT			 170 +#define SSL_R_MISSING_TMP_DH_KEY			 171 +#define SSL_R_MISSING_TMP_ECDH_KEY			 311 +#define SSL_R_MISSING_TMP_RSA_KEY			 172 +#define SSL_R_MISSING_TMP_RSA_PKEY			 173 +#define SSL_R_MISSING_VERIFY_MESSAGE			 174 +#define SSL_R_NON_SSLV2_INITIAL_PACKET			 175 +#define SSL_R_NO_CERTIFICATES_RETURNED			 176 +#define SSL_R_NO_CERTIFICATE_ASSIGNED			 177 +#define SSL_R_NO_CERTIFICATE_RETURNED			 178 +#define SSL_R_NO_CERTIFICATE_SET			 179 +#define SSL_R_NO_CERTIFICATE_SPECIFIED			 180 +#define SSL_R_NO_CIPHERS_AVAILABLE			 181 +#define SSL_R_NO_CIPHERS_PASSED				 182 +#define SSL_R_NO_CIPHERS_SPECIFIED			 183 +#define SSL_R_NO_CIPHER_LIST				 184 +#define SSL_R_NO_CIPHER_MATCH				 185 +#define SSL_R_NO_CLIENT_CERT_METHOD			 331 +#define SSL_R_NO_CLIENT_CERT_RECEIVED			 186 +#define SSL_R_NO_COMPRESSION_SPECIFIED			 187 +#define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER		 330 +#define SSL_R_NO_METHOD_SPECIFIED			 188 +#define SSL_R_NO_PRIVATEKEY				 189 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED			 190 +#define SSL_R_NO_PROTOCOLS_AVAILABLE			 191 +#define SSL_R_NO_PUBLICKEY				 192 +#define SSL_R_NO_RENEGOTIATION				 339 +#define SSL_R_NO_REQUIRED_DIGEST			 324 +#define SSL_R_NO_SHARED_CIPHER				 193 +#define SSL_R_NO_VERIFY_CALLBACK			 194 +#define SSL_R_NULL_SSL_CTX				 195 +#define SSL_R_NULL_SSL_METHOD_PASSED			 196 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197 +#define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 +#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297 +#define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG			 327 +#define SSL_R_PACKET_LENGTH_TOO_LONG			 198 +#define SSL_R_PARSE_TLSEXT				 227 +#define SSL_R_PATH_TOO_LONG				 270 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE		 199 +#define SSL_R_PEER_ERROR				 200 +#define SSL_R_PEER_ERROR_CERTIFICATE			 201 +#define SSL_R_PEER_ERROR_NO_CERTIFICATE			 202 +#define SSL_R_PEER_ERROR_NO_CIPHER			 203 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE	 204 +#define SSL_R_PRE_MAC_LENGTH_TOO_LONG			 205 +#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS		 206 +#define SSL_R_PROTOCOL_IS_SHUTDOWN			 207 +#define SSL_R_PSK_IDENTITY_NOT_FOUND			 223 +#define SSL_R_PSK_NO_CLIENT_CB				 224 +#define SSL_R_PSK_NO_SERVER_CB				 225 +#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR			 208 +#define SSL_R_PUBLIC_KEY_IS_NOT_RSA			 209 +#define SSL_R_PUBLIC_KEY_NOT_RSA			 210 +#define SSL_R_READ_BIO_NOT_SET				 211 +#define SSL_R_READ_TIMEOUT_EXPIRED			 312 +#define SSL_R_READ_WRONG_PACKET_TYPE			 212 +#define SSL_R_RECORD_LENGTH_MISMATCH			 213 +#define SSL_R_RECORD_TOO_LARGE				 214 +#define SSL_R_RECORD_TOO_SMALL				 298 +#define SSL_R_RENEGOTIATE_EXT_TOO_LONG			 335 +#define SSL_R_RENEGOTIATION_ENCODING_ERR		 336 +#define SSL_R_RENEGOTIATION_MISMATCH			 337 +#define SSL_R_REQUIRED_CIPHER_MISSING			 215 +#define SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING	 342 +#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO		 216 +#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO			 217 +#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO		 218 +#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 345 +#define SSL_R_SERVERHELLO_TLSEXT			 275 +#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277 +#define SSL_R_SESSION_MAY_NOT_BE_CREATED		 2000 +#define SSL_R_SHORT_READ				 219 +#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220 +#define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221 +#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG		 299 +#define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT		 321 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME		 319 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE		 320 +#define SSL_R_SSL3_SESSION_ID_TOO_LONG			 300 +#define SSL_R_SSL3_SESSION_ID_TOO_SHORT			 222 +#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_UNEXPECTED_MESSAGE		 1010 +#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE	 1043 +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION	 228 +#define SSL_R_SSL_HANDSHAKE_FAILURE			 229 +#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS		 230 +#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED		 301 +#define SSL_R_SSL_SESSION_ID_CONFLICT			 302 +#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG		 273 +#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH		 303 +#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT		 231 +#define SSL_R_TLSV1_ALERT_ACCESS_DENIED			 1049 +#define SSL_R_TLSV1_ALERT_DECODE_ERROR			 1050 +#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED		 1021 +#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR			 1051 +#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION		 1060 +#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY		 1071 +#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR		 1080 +#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION		 1100 +#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION		 1070 +#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW		 1022 +#define SSL_R_TLSV1_ALERT_UNKNOWN_CA			 1048 +#define SSL_R_TLSV1_ALERT_USER_CANCELLED		 1090 +#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE		 1114 +#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE	 1113 +#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE		 1111 +#define SSL_R_TLSV1_UNRECOGNIZED_NAME			 1112 +#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION		 1110 +#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER	 232 +#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST		 157 +#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 +#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG	 234 +#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER		 235 +#define SSL_R_UNABLE_TO_DECODE_DH_CERTS			 236 +#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS		 313 +#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY		 237 +#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS		 238 +#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS		 314 +#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS	 239 +#define SSL_R_UNABLE_TO_FIND_SSL_METHOD			 240 +#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES		 241 +#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES		 242 +#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES		 243 +#define SSL_R_UNEXPECTED_MESSAGE			 244 +#define SSL_R_UNEXPECTED_RECORD				 245 +#define SSL_R_UNINITIALIZED				 276 +#define SSL_R_UNKNOWN_ALERT_TYPE			 246 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE			 247 +#define SSL_R_UNKNOWN_CIPHER_RETURNED			 248 +#define SSL_R_UNKNOWN_CIPHER_TYPE			 249 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE			 250 +#define SSL_R_UNKNOWN_PKEY_TYPE				 251 +#define SSL_R_UNKNOWN_PROTOCOL				 252 +#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE			 253 +#define SSL_R_UNKNOWN_SSL_VERSION			 254 +#define SSL_R_UNKNOWN_STATE				 255 +#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED	 338 +#define SSL_R_UNSUPPORTED_CIPHER			 256 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 257 +#define SSL_R_UNSUPPORTED_DIGEST_TYPE			 326 +#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE		 315 +#define SSL_R_UNSUPPORTED_PROTOCOL			 258 +#define SSL_R_UNSUPPORTED_SSL_VERSION			 259 +#define SSL_R_UNSUPPORTED_STATUS_TYPE			 329 +#define SSL_R_WRITE_BIO_NOT_SET				 260 +#define SSL_R_WRONG_CIPHER_RETURNED			 261 +#define SSL_R_WRONG_MESSAGE_TYPE			 262 +#define SSL_R_WRONG_NUMBER_OF_KEY_BITS			 263 +#define SSL_R_WRONG_SIGNATURE_LENGTH			 264 +#define SSL_R_WRONG_SIGNATURE_SIZE			 265 +#define SSL_R_WRONG_SSL_VERSION				 266 +#define SSL_R_WRONG_VERSION_NUMBER			 267 +#define SSL_R_X509_LIB					 268 +#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269 + +#ifdef  __cplusplus +} +#endif +#endif diff --git a/main/openssl/ssl/ssl2.h b/main/openssl/ssl/ssl2.h new file mode 100644 index 00000000..99a52ea0 --- /dev/null +++ b/main/openssl/ssl/ssl2.h @@ -0,0 +1,268 @@ +/* ssl/ssl2.h */ +/* Copyright (C) 1995-1998 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_VERSION		0x0002 +#define SSL2_VERSION_MAJOR	0x00 +#define SSL2_VERSION_MINOR	0x02 +/* #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 +#ifdef OPENSSL_SYS_MPE +#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	29998u +#else +#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER	32767u  /* 2^15-1 */ +#endif +#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER	16383 /* 2^14-1 */ + +#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_state_st +	{ +	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; +	const unsigned 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 *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; +		unsigned int csl;  +		unsigned int clear; +		unsigned int enc;  +		unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH]; +		unsigned int cipher_spec_length; +		unsigned int session_id_length; +		unsigned int clen; +		unsigned int rlen; +		} tmp; +	} SSL2_STATE; + +/* 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/main/openssl/ssl/ssl23.h b/main/openssl/ssl/ssl23.h new file mode 100644 index 00000000..d3228983 --- /dev/null +++ b/main/openssl/ssl/ssl23.h @@ -0,0 +1,83 @@ +/* ssl/ssl23.h */ +/* Copyright (C) 1995-1998 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/main/openssl/ssl/ssl3.h b/main/openssl/ssl/ssl3.h new file mode 100644 index 00000000..f9268c57 --- /dev/null +++ b/main/openssl/ssl/ssl3.h @@ -0,0 +1,664 @@ +/* ssl/ssl3.h */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_SSL3_H  +#define HEADER_SSL3_H  + +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#include <openssl/buffer.h> +#include <openssl/evp.h> +#include <openssl/ssl.h> + +#ifdef  __cplusplus +extern "C" { +#endif + +/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */ +#define SSL3_CK_SCSV				0x030000FF + +#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_192_CBC_SHA		0x0300001B + +#if 0 +	#define SSL3_CK_FZA_DMS_NULL_SHA		0x0300001C +	#define SSL3_CK_FZA_DMS_FZA_SHA			0x0300001D +	#if 0 /* Because it clashes with KRB5, is never used any more, and is safe +		 to remove according to David Hopwood <david.hopwood@zetnet.co.uk> +		 of the ietf-tls list */ +	#define SSL3_CK_FZA_DMS_RC4_SHA			0x0300001E +	#endif +#endif + +/*    VRS Additional Kerberos5 entries + */ +#define SSL3_CK_KRB5_DES_64_CBC_SHA		0x0300001E +#define SSL3_CK_KRB5_DES_192_CBC3_SHA		0x0300001F +#define SSL3_CK_KRB5_RC4_128_SHA		0x03000020 +#define SSL3_CK_KRB5_IDEA_128_CBC_SHA	       	0x03000021 +#define SSL3_CK_KRB5_DES_64_CBC_MD5       	0x03000022 +#define SSL3_CK_KRB5_DES_192_CBC3_MD5       	0x03000023 +#define SSL3_CK_KRB5_RC4_128_MD5	       	0x03000024 +#define SSL3_CK_KRB5_IDEA_128_CBC_MD5 		0x03000025 + +#define SSL3_CK_KRB5_DES_40_CBC_SHA 		0x03000026 +#define SSL3_CK_KRB5_RC2_40_CBC_SHA 		0x03000027 +#define SSL3_CK_KRB5_RC4_40_SHA	 		0x03000028 +#define SSL3_CK_KRB5_DES_40_CBC_MD5 		0x03000029 +#define SSL3_CK_KRB5_RC2_40_CBC_MD5 		0x0300002A +#define SSL3_CK_KRB5_RC4_40_MD5	 		0x0300002B + +#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-SHA" +#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-SHA" +#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_192_CBC_SHA		"ADH-DES-CBC3-SHA" + +#if 0 +	#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" +#endif + +#define SSL3_TXT_KRB5_DES_64_CBC_SHA		"KRB5-DES-CBC-SHA" +#define SSL3_TXT_KRB5_DES_192_CBC3_SHA		"KRB5-DES-CBC3-SHA" +#define SSL3_TXT_KRB5_RC4_128_SHA		"KRB5-RC4-SHA" +#define SSL3_TXT_KRB5_IDEA_128_CBC_SHA	       	"KRB5-IDEA-CBC-SHA" +#define SSL3_TXT_KRB5_DES_64_CBC_MD5       	"KRB5-DES-CBC-MD5" +#define SSL3_TXT_KRB5_DES_192_CBC3_MD5       	"KRB5-DES-CBC3-MD5" +#define SSL3_TXT_KRB5_RC4_128_MD5		"KRB5-RC4-MD5" +#define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 		"KRB5-IDEA-CBC-MD5" + +#define SSL3_TXT_KRB5_DES_40_CBC_SHA 		"EXP-KRB5-DES-CBC-SHA" +#define SSL3_TXT_KRB5_RC2_40_CBC_SHA 		"EXP-KRB5-RC2-CBC-SHA" +#define SSL3_TXT_KRB5_RC4_40_SHA	 	"EXP-KRB5-RC4-SHA" +#define SSL3_TXT_KRB5_DES_40_CBC_MD5 		"EXP-KRB5-DES-CBC-MD5" +#define SSL3_TXT_KRB5_RC2_40_CBC_MD5 		"EXP-KRB5-RC2-CBC-MD5" +#define SSL3_TXT_KRB5_RC4_40_MD5	 	"EXP-KRB5-RC4-MD5" + +#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 + +#ifndef SSL3_ALIGN_PAYLOAD + /* Some will argue that this increases memory footprint, but it's +  * not actually true. Point is that malloc has to return at least +  * 64-bit aligned pointers, meaning that allocating 5 bytes wastes +  * 3 bytes in either case. Suggested pre-gaping simply moves these +  * wasted bytes from the end of allocated region to its front, +  * but makes data payload aligned, which improves performance:-) */ +# define SSL3_ALIGN_PAYLOAD			8 +#else +# if (SSL3_ALIGN_PAYLOAD&(SSL3_ALIGN_PAYLOAD-1))!=0 +#  error "insane SSL3_ALIGN_PAYLOAD" +#  undef SSL3_ALIGN_PAYLOAD +# endif +#endif + +/* This is the maximum MAC (digest) size used by the SSL library. + * Currently maximum of 20 is used by SHA1, but we reserve for + * future extension for 512-bit hashes. + */ + +#define SSL3_RT_MAX_MD_SIZE			64 + +/* Maximum block size used in all ciphersuites. Currently 16 for AES. + */ + +#define	SSL_RT_MAX_CIPHER_BLOCK_SIZE		16 + +#define SSL3_RT_MAX_EXTRA			(16384) + +/* Default buffer length used for writen records.  Thus a generated record + * will contain plaintext no larger than this value. */ +#define SSL3_RT_DEFAULT_PLAIN_LENGTH	2048 +/* Maximum plaintext length: defined by SSL/TLS standards */ +#define SSL3_RT_MAX_PLAIN_LENGTH		16384 +/* Maximum compression overhead: defined by SSL/TLS standards */ +#define SSL3_RT_MAX_COMPRESSED_OVERHEAD		1024 + +/* The standards give a maximum encryption overhead of 1024 bytes. + * In practice the value is lower than this. The overhead is the maximum + * number of padding bytes (256) plus the mac size. + */ +#define SSL3_RT_MAX_ENCRYPTED_OVERHEAD	(256 + SSL3_RT_MAX_MD_SIZE) + +/* OpenSSL currently only uses a padding length of at most one block so + * the send overhead is smaller. + */ + +#define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ +			(SSL_RT_MAX_CIPHER_BLOCK_SIZE + SSL3_RT_MAX_MD_SIZE) + +/* If compression isn't used don't include the compression overhead */ + +#ifdef OPENSSL_NO_COMP +#define SSL3_RT_MAX_COMPRESSED_LENGTH		SSL3_RT_MAX_PLAIN_LENGTH +#else +#define SSL3_RT_MAX_COMPRESSED_LENGTH	\ +		(SSL3_RT_MAX_PLAIN_LENGTH+SSL3_RT_MAX_COMPRESSED_OVERHEAD) +#endif +#define SSL3_RT_MAX_ENCRYPTED_LENGTH	\ +		(SSL3_RT_MAX_ENCRYPTED_OVERHEAD+SSL3_RT_MAX_COMPRESSED_LENGTH) +#define SSL3_RT_MAX_PACKET_SIZE		\ +		(SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) + +/* Extra space for empty fragment, headers, MAC, and padding. */ +#define SSL3_RT_DEFAULT_WRITE_OVERHEAD  256 +#define SSL3_RT_DEFAULT_PACKET_SIZE     4096 - SSL3_RT_DEFAULT_WRITE_OVERHEAD +#if SSL3_RT_DEFAULT_PLAIN_LENGTH + SSL3_RT_DEFAULT_WRITE_OVERHEAD > SSL3_RT_DEFAULT_PACKET_SIZE +#error "Insufficient space allocated for write buffers." +#endif + +#define SSL3_MD_CLIENT_FINISHED_CONST	"\x43\x4C\x4E\x54" +#define SSL3_MD_SERVER_FINISHED_CONST	"\x53\x52\x56\x52" + +#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 */ +/*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 */ +/*r */	unsigned char *comp;    /* only used with decompression - malloc()ed */ +/*r */  unsigned long epoch;    /* epoch number, needed by DTLS1 */ +/*r */  unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */ +	} SSL3_RECORD; + +typedef struct ssl3_buffer_st +	{ +	unsigned char *buf;     /* at least SSL3_RT_MAX_PACKET_SIZE bytes, +	                         * see ssl3_setup_buffers() */ +	size_t len;             /* buffer size */ +	int offset;             /* where to 'copy from' */ +	int left;               /* how many bytes left */ +	} SSL3_BUFFER; + +#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 +/* SSL3_CT_NUMBER is used to size arrays and it must be large + * enough to contain all of the cert types defined either for + * SSLv3 and TLSv1. + */ +#define SSL3_CT_NUMBER			9 + + +#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS	0x0001 +#define SSL3_FLAGS_DELAY_CLIENT_FINISHED	0x0002 +#define SSL3_FLAGS_POP_BUFFER			0x0004 +#define TLS1_FLAGS_TLS_PADDING_BUG		0x0008 +#define TLS1_FLAGS_SKIP_CERT_VERIFY		0x0010 + +typedef struct ssl3_state_st +	{ +	long flags; +	int delay_buf_pop_ret; + +	unsigned char read_sequence[8]; +	int read_mac_secret_size; +	unsigned char read_mac_secret[EVP_MAX_MD_SIZE]; +	unsigned char write_sequence[8]; +	int write_mac_secret_size; +	unsigned char write_mac_secret[EVP_MAX_MD_SIZE]; + +	unsigned char server_random[SSL3_RANDOM_SIZE]; +	unsigned char client_random[SSL3_RANDOM_SIZE]; + +	/* flags for countermeasure against known-IV weakness */ +	int need_empty_fragments; +	int empty_fragment_done; + +	/* The value of 'extra' when the buffers were initialized */ +	int init_extra; + +	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 */ + +	/* storage for Alert/Handshake protocol data received but not +	 * yet processed by ssl3_read_bytes: */ +	unsigned char alert_fragment[2]; +	unsigned int alert_fragment_len; +	unsigned char handshake_fragment[4]; +	unsigned int handshake_fragment_len; + +	/* 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 */ +	const unsigned char *wpend_buf; + +	/* used during startup, digest all incoming/outgoing packets */ +	BIO *handshake_buffer; +	/* When set of handshake digests is determined, buffer is hashed +	 * and freed and MD_CTX-es for all required digests are stored in +	 * this array */ +	EVP_MD_CTX **handshake_dgst; +	/* 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 allow one fatal and one warning alert to be outstanding, +	 * send close alert via the warning alert */ +	int alert_dispatch; +	unsigned char send_alert[2]; + +	/* This flag is set when we should renegotiate ASAP, basically when +	 * there is no more data in the read or write buffers */ +	int renegotiate; +	int total_renegotiations; +	int num_renegotiations; + +	int in_read_app_data; + +	/* Opaque PRF input as used for the current handshake. +	 * These fields are used only if TLSEXT_TYPE_opaque_prf_input is defined +	 * (otherwise, they are merely present to improve binary compatibility) */ +	void *client_opaque_prf_input; +	size_t client_opaque_prf_input_len; +	void *server_opaque_prf_input; +	size_t server_opaque_prf_input_len; + +#ifndef OPENSSL_NO_NEXTPROTONEG +	/* Set if we saw the Next Protocol Negotiation extension from +	   our peer. */ +	int next_proto_neg_seen; +#endif + +	struct	{ +		/* actually only needs to be 16+20 */ +		unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2]; + +		/* actually only need to be 16+20 for SSLv3 and 12 for TLS */ +		unsigned char finish_md[EVP_MAX_MD_SIZE*2]; +		int finish_md_len; +		unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2]; +		int peer_finish_md_len; +		 +		unsigned long message_size; +		int message_type; + +		/* used to hold the new cipher we are going to use */ +		const SSL_CIPHER *new_cipher; +#ifndef OPENSSL_NO_DH +		DH *dh; +#endif + +#ifndef OPENSSL_NO_ECDH +		EC_KEY *ecdh; /* holds short lived ECDH key */ +#endif + +		/* 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_OF(X509_NAME) *ca_names; + +		int use_rsa_tmp; + +		int key_block_length; +		unsigned char *key_block; + +		const EVP_CIPHER *new_sym_enc; +		const EVP_MD *new_hash; +		int new_mac_pkey_type; +		int new_mac_secret_size; +#ifndef OPENSSL_NO_COMP +		const SSL_COMP *new_compression; +#else +		char *new_compression; +#endif +		int cert_request; +		} tmp; + +        /* Connection binding to prevent renegotiation attacks */ +        unsigned char previous_client_finished[EVP_MAX_MD_SIZE]; +        unsigned char previous_client_finished_len; +        unsigned char previous_server_finished[EVP_MAX_MD_SIZE]; +        unsigned char previous_server_finished_len; +        int send_connection_binding; /* TODOEKR */ +	} SSL3_STATE; + + +/* SSLv3 */ +/*client */ +/* extra state */ +#define SSL3_ST_CW_FLUSH		(0x100|SSL_ST_CONNECT) +#define SSL3_ST_CUTTHROUGH_COMPLETE	(0x101|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 DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT) +#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|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) +#ifndef OPENSSL_NO_NEXTPROTONEG +#define SSL3_ST_CW_NEXT_PROTO_A		(0x200|SSL_ST_CONNECT) +#define SSL3_ST_CW_NEXT_PROTO_B		(0x201|SSL_ST_CONNECT) +#endif +#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) +#define SSL3_ST_CR_SESSION_TICKET_A	(0x1E0|SSL_ST_CONNECT) +#define SSL3_ST_CR_SESSION_TICKET_B	(0x1E1|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_STATUS_A	(0x1F0|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_STATUS_B	(0x1F1|SSL_ST_CONNECT) + +/* server */ +/* extra state */ +#define SSL3_ST_SW_FLUSH		(0x100|SSL_ST_ACCEPT) +/* read from client */ +/* Do not change the number values, they do matter */ +#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 DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT) +#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT) +#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) +#ifndef OPENSSL_NO_NEXTPROTONEG +#define SSL3_ST_SR_NEXT_PROTO_A		(0x210|SSL_ST_ACCEPT) +#define SSL3_ST_SR_NEXT_PROTO_B		(0x211|SSL_ST_ACCEPT) +#endif +#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_ST_SW_SESSION_TICKET_A	(0x1F0|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SESSION_TICKET_B	(0x1F1|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_STATUS_A	(0x200|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_STATUS_B	(0x201|SSL_ST_ACCEPT) + +#define SSL3_MT_HELLO_REQUEST			0 +#define SSL3_MT_CLIENT_HELLO			1 +#define SSL3_MT_SERVER_HELLO			2 +#define	SSL3_MT_NEWSESSION_TICKET		4 +#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_CERTIFICATE_STATUS		22 +#ifndef OPENSSL_NO_NEXTPROTONEG +#define SSL3_MT_NEXT_PROTO			67 +#endif +#define DTLS1_MT_HELLO_VERIFY_REQUEST    3 + + +#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/main/openssl/ssl/ssl_algs.c b/main/openssl/ssl/ssl_algs.c new file mode 100644 index 00000000..0967b2df --- /dev/null +++ b/main/openssl/ssl/ssl_algs.c @@ -0,0 +1,140 @@ +/* ssl/ssl_algs.c */ +/* Copyright (C) 1995-1998 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 <openssl/objects.h> +#include <openssl/lhash.h> +#include "ssl_locl.h" + +int SSL_library_init(void) +	{ + +#ifndef OPENSSL_NO_DES +	EVP_add_cipher(EVP_des_cbc()); +	EVP_add_cipher(EVP_des_ede3_cbc()); +#endif +#ifndef OPENSSL_NO_IDEA +	EVP_add_cipher(EVP_idea_cbc()); +#endif +#ifndef OPENSSL_NO_RC4 +	EVP_add_cipher(EVP_rc4()); +#endif   +#ifndef OPENSSL_NO_RC2 +	EVP_add_cipher(EVP_rc2_cbc()); +	/* Not actually used for SSL/TLS but this makes PKCS#12 work +	 * if an application only calls SSL_library_init(). +	 */ +	EVP_add_cipher(EVP_rc2_40_cbc()); +#endif +#ifndef OPENSSL_NO_AES +	EVP_add_cipher(EVP_aes_128_cbc()); +	EVP_add_cipher(EVP_aes_192_cbc()); +	EVP_add_cipher(EVP_aes_256_cbc()); +#endif +#ifndef OPENSSL_NO_CAMELLIA +	EVP_add_cipher(EVP_camellia_128_cbc()); +	EVP_add_cipher(EVP_camellia_256_cbc()); +#endif + +#ifndef OPENSSL_NO_SEED +	EVP_add_cipher(EVP_seed_cbc()); +#endif +   +#ifndef OPENSSL_NO_MD5 +	EVP_add_digest(EVP_md5()); +	EVP_add_digest_alias(SN_md5,"ssl2-md5"); +	EVP_add_digest_alias(SN_md5,"ssl3-md5"); +#endif +#ifndef OPENSSL_NO_SHA +	EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ +	EVP_add_digest_alias(SN_sha1,"ssl3-sha1"); +	EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA); +#endif +#ifndef OPENSSL_NO_SHA256 +	EVP_add_digest(EVP_sha224()); +	EVP_add_digest(EVP_sha256()); +#endif +#ifndef OPENSSL_NO_SHA512 +	EVP_add_digest(EVP_sha384()); +	EVP_add_digest(EVP_sha512()); +#endif +#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_DSA) +	EVP_add_digest(EVP_dss1()); /* DSA with sha1 */ +	EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2); +	EVP_add_digest_alias(SN_dsaWithSHA1,"DSS1"); +	EVP_add_digest_alias(SN_dsaWithSHA1,"dss1"); +#endif +#ifndef OPENSSL_NO_ECDSA +	EVP_add_digest(EVP_ecdsa()); +#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 +#ifndef OPENSSL_NO_COMP +	/* This will initialise the built-in compression algorithms. +	   The value returned is a STACK_OF(SSL_COMP), but that can +	   be discarded safely */ +	(void)SSL_COMP_get_compression_methods(); +#endif +	/* initialize cipher/digest methods table */ +	ssl_load_ciphers(); +	return(1); +	} + diff --git a/main/openssl/ssl/ssl_asn1.c b/main/openssl/ssl/ssl_asn1.c new file mode 100644 index 00000000..d7f4c608 --- /dev/null +++ b/main/openssl/ssl/ssl_asn1.c @@ -0,0 +1,592 @@ +/* ssl/ssl_asn1.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "ssl_locl.h" +#include <openssl/asn1_mac.h> +#include <openssl/objects.h> +#include <openssl/x509.h> + +typedef struct ssl_session_asn1_st +	{ +	ASN1_INTEGER version; +	ASN1_INTEGER ssl_version; +	ASN1_OCTET_STRING cipher; +	ASN1_OCTET_STRING comp_id; +	ASN1_OCTET_STRING master_key; +	ASN1_OCTET_STRING session_id; +	ASN1_OCTET_STRING session_id_context; +	ASN1_OCTET_STRING key_arg; +#ifndef OPENSSL_NO_KRB5 +        ASN1_OCTET_STRING krb5_princ; +#endif /* OPENSSL_NO_KRB5 */ +	ASN1_INTEGER time; +	ASN1_INTEGER timeout; +	ASN1_INTEGER verify_result; +#ifndef OPENSSL_NO_TLSEXT +	ASN1_OCTET_STRING tlsext_hostname; +	ASN1_INTEGER tlsext_tick_lifetime; +	ASN1_OCTET_STRING tlsext_tick; +#endif /* OPENSSL_NO_TLSEXT */ +#ifndef OPENSSL_NO_PSK +	ASN1_OCTET_STRING psk_identity_hint; +	ASN1_OCTET_STRING psk_identity; +#endif /* OPENSSL_NO_PSK */ +	} SSL_SESSION_ASN1; + +int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) +	{ +#define LSIZE2 (sizeof(long)*2) +	int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0; +	unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2]; +	unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2]; +#ifndef OPENSSL_NO_TLSEXT +	int v6=0,v9=0,v10=0; +	unsigned char ibuf6[LSIZE2]; +#endif +#ifndef OPENSSL_NO_COMP +	unsigned char cbuf; +	int v11=0; +#endif +	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_INTEGER passed to ASN1_INTEGER_set +	 * is > sizeof(long)+1, the buffer will not be re-OPENSSL_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 == SSL2_VERSION) +		{ +		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; +		} + +#ifndef OPENSSL_NO_COMP +	if (in->compress_meth) +		{ +		cbuf = (unsigned char)in->compress_meth; +		a.comp_id.length = 1; +		a.comp_id.type = V_ASN1_OCTET_STRING; +		a.comp_id.data = &cbuf; +		} +#endif + +	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.session_id_context.length=in->sid_ctx_length; +	a.session_id_context.type=V_ASN1_OCTET_STRING; +	a.session_id_context.data=in->sid_ctx; + +	a.key_arg.length=in->key_arg_length; +	a.key_arg.type=V_ASN1_OCTET_STRING; +	a.key_arg.data=in->key_arg; + +#ifndef OPENSSL_NO_KRB5 +	if (in->krb5_client_princ_len) +		{ +		a.krb5_princ.length=in->krb5_client_princ_len; +		a.krb5_princ.type=V_ASN1_OCTET_STRING; +		a.krb5_princ.data=in->krb5_client_princ; +		} +#endif /* OPENSSL_NO_KRB5 */ + +	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); +		} + +	if (in->verify_result != X509_V_OK) +		{ +		a.verify_result.length=LSIZE2; +		a.verify_result.type=V_ASN1_INTEGER; +		a.verify_result.data=ibuf5; +		ASN1_INTEGER_set(&a.verify_result,in->verify_result); +		} + +#ifndef OPENSSL_NO_TLSEXT +	if (in->tlsext_hostname) +                { +                a.tlsext_hostname.length=strlen(in->tlsext_hostname); +                a.tlsext_hostname.type=V_ASN1_OCTET_STRING; +                a.tlsext_hostname.data=(unsigned char *)in->tlsext_hostname; +                } +	if (in->tlsext_tick) +                { +                a.tlsext_tick.length= in->tlsext_ticklen; +                a.tlsext_tick.type=V_ASN1_OCTET_STRING; +                a.tlsext_tick.data=(unsigned char *)in->tlsext_tick; +                } +	if (in->tlsext_tick_lifetime_hint > 0) +		{ +		a.tlsext_tick_lifetime.length=LSIZE2; +		a.tlsext_tick_lifetime.type=V_ASN1_INTEGER; +		a.tlsext_tick_lifetime.data=ibuf6; +		ASN1_INTEGER_set(&a.tlsext_tick_lifetime,in->tlsext_tick_lifetime_hint); +		} +#endif /* OPENSSL_NO_TLSEXT */ +#ifndef OPENSSL_NO_PSK +	if (in->psk_identity_hint) +		{ +		a.psk_identity_hint.length=strlen(in->psk_identity_hint); +		a.psk_identity_hint.type=V_ASN1_OCTET_STRING; +		a.psk_identity_hint.data=(unsigned char *)(in->psk_identity_hint); +		} +	if (in->psk_identity) +		{ +		a.psk_identity.length=strlen(in->psk_identity); +		a.psk_identity.type=V_ASN1_OCTET_STRING; +		a.psk_identity.data=(unsigned char *)(in->psk_identity); +		} +#endif /* OPENSSL_NO_PSK */ + +	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); +#ifndef OPENSSL_NO_KRB5 +	if (in->krb5_client_princ_len) +        	M_ASN1_I2D_len(&(a.krb5_princ),	i2d_ASN1_OCTET_STRING); +#endif /* OPENSSL_NO_KRB5 */ +	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_len_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4,v4); +	if (in->verify_result != X509_V_OK) +		M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5); + +#ifndef OPENSSL_NO_TLSEXT +	if (in->tlsext_tick_lifetime_hint > 0) +      	 	M_ASN1_I2D_len_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9); +	if (in->tlsext_tick) +        	M_ASN1_I2D_len_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10); +	if (in->tlsext_hostname) +        	M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6); +#ifndef OPENSSL_NO_COMP +	if (in->compress_meth) +        	M_ASN1_I2D_len_EXP_opt(&(a.comp_id), i2d_ASN1_OCTET_STRING,11,v11); +#endif +#endif /* OPENSSL_NO_TLSEXT */ +#ifndef OPENSSL_NO_PSK +	if (in->psk_identity_hint) +        	M_ASN1_I2D_len_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,7,v7); +	if (in->psk_identity) +        	M_ASN1_I2D_len_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,8,v8); +#endif /* OPENSSL_NO_PSK */ + +	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); +#ifndef OPENSSL_NO_KRB5 +	if (in->krb5_client_princ_len) +        	M_ASN1_I2D_put(&(a.krb5_princ),	i2d_ASN1_OCTET_STRING); +#endif /* OPENSSL_NO_KRB5 */ +	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_put_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4, +			       v4); +	if (in->verify_result != X509_V_OK) +		M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5); +#ifndef OPENSSL_NO_TLSEXT +	if (in->tlsext_hostname) +        	M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6); +#endif /* OPENSSL_NO_TLSEXT */ +#ifndef OPENSSL_NO_PSK +	if (in->psk_identity_hint) +		M_ASN1_I2D_put_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,7,v7); +	if (in->psk_identity) +		M_ASN1_I2D_put_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,8,v8); +#endif /* OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_TLSEXT +	if (in->tlsext_tick_lifetime_hint > 0) +      	 	M_ASN1_I2D_put_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9); +	if (in->tlsext_tick) +        	M_ASN1_I2D_put_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10); +#endif /* OPENSSL_NO_TLSEXT */ +#ifndef OPENSSL_NO_COMP +	if (in->compress_meth) +        	M_ASN1_I2D_put_EXP_opt(&(a.comp_id), i2d_ASN1_OCTET_STRING,11,v11); +#endif +	M_ASN1_I2D_finish(); +	} + +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, +			     long length) +	{ +	int 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_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER); +	if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; } + +	/* we don't care about the version right now :-) */ +	M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER); +	ssl_version=(int)ASN1_INTEGER_get(aip); +	ret->ssl_version=ssl_version; +	if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; } + +	os.data=NULL; os.length=0; +	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING); +	if (ssl_version == SSL2_VERSION) +		{ +		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>>8) >= SSL3_VERSION_MAJOR) +		{ +		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 +		{ +		c.error=SSL_R_UNKNOWN_SSL_VERSION; +		goto err; +		} +	 +	ret->cipher=NULL; +	ret->cipher_id=id; + +	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING); +	if ((ssl_version>>8) >= SSL3_VERSION_MAJOR) +		i=SSL3_MAX_SSL_SESSION_ID_LENGTH; +	else /* if (ssl_version>>8 == SSL2_VERSION_MAJOR) */ +		i=SSL2_MAX_SSL_SESSION_ID_LENGTH; + +	if (os.length > i) +		os.length = i; +	if (os.length > (int)sizeof(ret->session_id)) /* can't happen */ +		os.length = sizeof(ret->session_id); + +	ret->session_id_length=os.length; +	OPENSSL_assert(os.length <= (int)sizeof(ret->session_id)); +	memcpy(ret->session_id,os.data,os.length); + +	M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING); +	if (os.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; + +#ifndef OPENSSL_NO_KRB5 +	os.length=0; +	M_ASN1_D2I_get_opt(osp,d2i_ASN1_OCTET_STRING,V_ASN1_OCTET_STRING); +	if (os.data) +		{ +        	if (os.length > SSL_MAX_KRB5_PRINCIPAL_LENGTH) +            		ret->krb5_client_princ_len=0; +		else +			ret->krb5_client_princ_len=os.length; +		memcpy(ret->krb5_client_princ,os.data,ret->krb5_client_princ_len); +		OPENSSL_free(os.data); +		os.data = NULL; +		os.length = 0; +		} +	else +		ret->krb5_client_princ_len=0; +#endif /* OPENSSL_NO_KRB5 */ + +	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) OPENSSL_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); +		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; +		} +	else +		ret->time=(unsigned long)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); +		OPENSSL_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); + +	os.length=0; +	os.data=NULL; +	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,4); + +	if(os.data != NULL) +	    { +	    if (os.length > SSL_MAX_SID_CTX_LENGTH) +		{ +		c.error=SSL_R_BAD_LENGTH; +		goto err; +		} +	    else +		{ +		ret->sid_ctx_length=os.length; +		memcpy(ret->sid_ctx,os.data,os.length); +		} +	    OPENSSL_free(os.data); os.data=NULL; os.length=0; +	    } +	else +	    ret->sid_ctx_length=0; + +	ai.length=0; +	M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,5); +	if (ai.data != NULL) +		{ +		ret->verify_result=ASN1_INTEGER_get(aip); +		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; +		} +	else +		ret->verify_result=X509_V_OK; + +#ifndef OPENSSL_NO_TLSEXT +	os.length=0; +	os.data=NULL; +	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6); +	if (os.data) +		{ +		ret->tlsext_hostname = BUF_strndup((char *)os.data, os.length); +		OPENSSL_free(os.data); +		os.data = NULL; +		os.length = 0; +		} +	else +		ret->tlsext_hostname=NULL; +#endif /* OPENSSL_NO_TLSEXT */ + +#ifndef OPENSSL_NO_PSK +	os.length=0; +	os.data=NULL; +	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,7); +	if (os.data) +		{ +		ret->psk_identity_hint = BUF_strndup((char *)os.data, os.length); +		OPENSSL_free(os.data); +		os.data = NULL; +		os.length = 0; +		} +	else +		ret->psk_identity_hint=NULL; +#endif /* OPENSSL_NO_PSK */ + +#ifndef OPENSSL_NO_TLSEXT +	ai.length=0; +	M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,9); +	if (ai.data != NULL) +		{ +		ret->tlsext_tick_lifetime_hint=ASN1_INTEGER_get(aip); +		OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; +		} +	else if (ret->tlsext_ticklen && ret->session_id_length) +		ret->tlsext_tick_lifetime_hint = -1; +	else +		ret->tlsext_tick_lifetime_hint=0; +	os.length=0; +	os.data=NULL; +	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,10); +	if (os.data) +		{ +		ret->tlsext_tick = os.data; +		ret->tlsext_ticklen = os.length; +		os.data = NULL; +		os.length = 0; +		} +	else +		ret->tlsext_tick=NULL; +#endif /* OPENSSL_NO_TLSEXT */ +#ifndef OPENSSL_NO_COMP +	os.length=0; +	os.data=NULL; +	M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,11); +	if (os.data) +		{ +		ret->compress_meth = os.data[0]; +		OPENSSL_free(os.data); +		os.data = NULL; +		} +#endif + +	M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION); +	} diff --git a/main/openssl/ssl/ssl_cert.c b/main/openssl/ssl/ssl_cert.c new file mode 100644 index 00000000..27256eea --- /dev/null +++ b/main/openssl/ssl/ssl_cert.c @@ -0,0 +1,834 @@ +/*! \file ssl/ssl_cert.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#include <stdio.h> + +#include "e_os.h" +#ifndef NO_SYS_TYPES_H +# include <sys/types.h> +#endif + +#include "o_dir.h" +#include <openssl/objects.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif +#include <openssl/bn.h> +#include "ssl_locl.h" + +int SSL_get_ex_data_X509_STORE_CTX_idx(void) +	{ +	static volatile int ssl_x509_store_ctx_idx= -1; +	int got_write_lock = 0; + +	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + +	if (ssl_x509_store_ctx_idx < 0) +		{ +		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); +		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +		got_write_lock = 1; +		 +		if (ssl_x509_store_ctx_idx < 0) +			{ +			ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( +				0,"SSL for verify callback",NULL,NULL,NULL); +			} +		} + +	if (got_write_lock) +		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +	else +		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); +	 +	return ssl_x509_store_ctx_idx; +	} + +CERT *ssl_cert_new(void) +	{ +	CERT *ret; + +	ret=(CERT *)OPENSSL_malloc(sizeof(CERT)); +	if (ret == NULL) +		{ +		SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE); +		return(NULL); +		} +	memset(ret,0,sizeof(CERT)); + +	ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]); +	ret->references=1; + +	return(ret); +	} + +CERT *ssl_cert_dup(CERT *cert) +	{ +	CERT *ret; +	int i; + +	ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); +	if (ret == NULL) +		{ +		SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); +		return(NULL); +		} + +	memset(ret, 0, sizeof(CERT)); + +	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; +	/* or ret->key = ret->pkeys + (cert->key - cert->pkeys), +	 * if you find that more readable */ + +	ret->valid = cert->valid; +	ret->mask_k = cert->mask_k; +	ret->mask_a = cert->mask_a; +	ret->export_mask_k = cert->export_mask_k; +	ret->export_mask_a = cert->export_mask_a; + +#ifndef OPENSSL_NO_RSA +	if (cert->rsa_tmp != NULL) +		{ +		RSA_up_ref(cert->rsa_tmp); +		ret->rsa_tmp = cert->rsa_tmp; +		} +	ret->rsa_tmp_cb = cert->rsa_tmp_cb; +#endif + +#ifndef OPENSSL_NO_DH +	if (cert->dh_tmp != NULL) +		{ +		ret->dh_tmp = DHparams_dup(cert->dh_tmp); +		if (ret->dh_tmp == NULL) +			{ +			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB); +			goto err; +			} +		if (cert->dh_tmp->priv_key) +			{ +			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); +			if (!b) +				{ +				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); +				goto err; +				} +			ret->dh_tmp->priv_key = b; +			} +		if (cert->dh_tmp->pub_key) +			{ +			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); +			if (!b) +				{ +				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); +				goto err; +				} +			ret->dh_tmp->pub_key = b; +			} +		} +	ret->dh_tmp_cb = cert->dh_tmp_cb; +#endif + +#ifndef OPENSSL_NO_ECDH +	if (cert->ecdh_tmp) +		{ +		ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); +		if (ret->ecdh_tmp == NULL) +			{ +			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB); +			goto err; +			} +		} +	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; +#endif + +	for (i = 0; i < SSL_PKEY_NUM; i++) +		{ +		if (cert->pkeys[i].x509 != NULL) +			{ +			ret->pkeys[i].x509 = cert->pkeys[i].x509; +			CRYPTO_add(&ret->pkeys[i].x509->references, 1, +				CRYPTO_LOCK_X509); +			} +		 +		if (cert->pkeys[i].privatekey != NULL) +			{ +			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; +			CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, +				CRYPTO_LOCK_EVP_PKEY); + +			switch(i)  +				{ +				/* If there was anything special to do for +				 * certain types of keys, we'd do it here. +				 * (Nothing at the moment, I think.) */ + +			case SSL_PKEY_RSA_ENC: +			case SSL_PKEY_RSA_SIGN: +				/* We have an RSA key. */ +				break; +				 +			case SSL_PKEY_DSA_SIGN: +				/* We have a DSA key. */ +				break; +				 +			case SSL_PKEY_DH_RSA: +			case SSL_PKEY_DH_DSA: +				/* We have a DH key. */ +				break; + +			case SSL_PKEY_ECC: +				/* We have an ECC key */ +				break; + +			default: +				/* Can't happen. */ +				SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG); +				} +			} +		} +	 +	/* ret->extra_certs *should* exist, but currently the own certificate +	 * chain is held inside SSL_CTX */ + +	ret->references=1; + +	return(ret); +	 +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH) +err: +#endif +#ifndef OPENSSL_NO_RSA +	if (ret->rsa_tmp != NULL) +		RSA_free(ret->rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH +	if (ret->dh_tmp != NULL) +		DH_free(ret->dh_tmp); +#endif +#ifndef OPENSSL_NO_ECDH +	if (ret->ecdh_tmp != NULL) +		EC_KEY_free(ret->ecdh_tmp); +#endif + +	for (i = 0; i < SSL_PKEY_NUM; i++) +		{ +		if (ret->pkeys[i].x509 != NULL) +			X509_free(ret->pkeys[i].x509); +		if (ret->pkeys[i].privatekey != NULL) +			EVP_PKEY_free(ret->pkeys[i].privatekey); +		} + +	return NULL; +	} + + +void ssl_cert_free(CERT *c) +	{ +	int i; + +	if(c == NULL) +	    return; + +	i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT); +#ifdef REF_PRINT +	REF_PRINT("CERT",c); +#endif +	if (i > 0) return; +#ifdef REF_CHECK +	if (i < 0) +		{ +		fprintf(stderr,"ssl_cert_free, bad reference count\n"); +		abort(); /* ok */ +		} +#endif + +#ifndef OPENSSL_NO_RSA +	if (c->rsa_tmp) RSA_free(c->rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH +	if (c->dh_tmp) DH_free(c->dh_tmp); +#endif +#ifndef OPENSSL_NO_ECDH +	if (c->ecdh_tmp) EC_KEY_free(c->ecdh_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 +		} +	OPENSSL_free(c); +	} + +int ssl_cert_inst(CERT **o) +	{ +	/* Create a CERT if there isn't already one +	 * (which cannot really happen, as it is initially created in +	 * SSL_CTX_new; but the earlier code usually allows for that one +	 * being non-existant, so we follow that behaviour, as it might +	 * turn out that there actually is a reason for it -- but I'm +	 * not sure that *all* of the existing code could cope with +	 * s->cert being NULL, otherwise we could do without the +	 * initialization in SSL_CTX_new). +	 */ +	 +	if (o == NULL)  +		{ +		SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (*o == NULL) +		{ +		if ((*o = ssl_cert_new()) == NULL) +			{ +			SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE); +			return(0); +			} +		} +	return(1); +	} + + +SESS_CERT *ssl_sess_cert_new(void) +	{ +	SESS_CERT *ret; + +	ret = OPENSSL_malloc(sizeof *ret); +	if (ret == NULL) +		{ +		SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE); +		return NULL; +		} + +	memset(ret, 0 ,sizeof *ret); +	ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); +	ret->references = 1; + +	return ret; +	} + +void ssl_sess_cert_free(SESS_CERT *sc) +	{ +	int i; + +	if (sc == NULL) +		return; + +	i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); +#ifdef REF_PRINT +	REF_PRINT("SESS_CERT", sc); +#endif +	if (i > 0) +		return; +#ifdef REF_CHECK +	if (i < 0) +		{ +		fprintf(stderr,"ssl_sess_cert_free, bad reference count\n"); +		abort(); /* ok */ +		} +#endif + +	/* i == 0 */ +	if (sc->cert_chain != NULL) +		sk_X509_pop_free(sc->cert_chain, X509_free); +	for (i = 0; i < SSL_PKEY_NUM; i++) +		{ +		if (sc->peer_pkeys[i].x509 != NULL) +			X509_free(sc->peer_pkeys[i].x509); +#if 0 /* We don't have the peer's private key.  These lines are just +	   * here as a reminder that we're still using a not-quite-appropriate +	   * data structure. */ +		if (sc->peer_pkeys[i].privatekey != NULL) +			EVP_PKEY_free(sc->peer_pkeys[i].privatekey); +#endif +		} + +#ifndef OPENSSL_NO_RSA +	if (sc->peer_rsa_tmp != NULL) +		RSA_free(sc->peer_rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH +	if (sc->peer_dh_tmp != NULL) +		DH_free(sc->peer_dh_tmp); +#endif +#ifndef OPENSSL_NO_ECDH +	if (sc->peer_ecdh_tmp != NULL) +		EC_KEY_free(sc->peer_ecdh_tmp); +#endif + +	OPENSSL_free(sc); +	} + +int ssl_set_peer_cert_type(SESS_CERT *sc,int type) +	{ +	sc->peer_cert_type = type; +	return(1); +	} + +int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) +	{ +	X509 *x; +	int i; +	X509_STORE_CTX ctx; + +	if ((sk == NULL) || (sk_X509_num(sk) == 0)) +		return(0); + +	x=sk_X509_value(sk,0); +	if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) +		{ +		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); +		return(0); +		} +#if 0 +	if (SSL_get_verify_depth(s) >= 0) +		X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); +#endif +	X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); + +	/* We need to inherit the verify parameters. These can be determined by +	 * the context: if its a server it will verify SSL client certificates +	 * or vice versa. +	 */ + +	X509_STORE_CTX_set_default(&ctx, +				s->server ? "ssl_client" : "ssl_server"); +	/* Anything non-default in "param" should overwrite anything in the +	 * ctx. +	 */ +	X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); + +	if (s->verify_callback) +		X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); + +	if (s->ctx->app_verify_callback != NULL) +#if 1 /* new with OpenSSL 0.9.7 */ +		i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);  +#else +		i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ +#endif +	else +		{ +#ifndef OPENSSL_NO_X509_VERIFY +		i=X509_verify_cert(&ctx); +#else +		i=0; +		ctx.error=X509_V_ERR_APPLICATION_VERIFICATION; +		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK); +#endif +		} + +	s->verify_result=ctx.error; +	X509_STORE_CTX_cleanup(&ctx); + +	return(i); +	} + +static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list) +	{ +	if (*ca_list != NULL) +		sk_X509_NAME_pop_free(*ca_list,X509_NAME_free); + +	*ca_list=name_list; +	} + +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) +	{ +	int i; +	STACK_OF(X509_NAME) *ret; +	X509_NAME *name; + +	ret=sk_X509_NAME_new_null(); +	for (i=0; i<sk_X509_NAME_num(sk); i++) +		{ +		name=X509_NAME_dup(sk_X509_NAME_value(sk,i)); +		if ((name == NULL) || !sk_X509_NAME_push(ret,name)) +			{ +			sk_X509_NAME_pop_free(ret,X509_NAME_free); +			return(NULL); +			} +		} +	return(ret); +	} + +void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list) +	{ +	set_client_CA_list(&(s->client_CA),name_list); +	} + +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list) +	{ +	set_client_CA_list(&(ctx->client_CA),name_list); +	} + +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) +	{ +	return(ctx->client_CA); +	} + +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) +	{ +	if (s->type == SSL_ST_CONNECT) +		{ /* we are in the client */ +		if (((s->version>>8) == SSL3_VERSION_MAJOR) && +			(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(STACK_OF(X509_NAME) **sk,X509 *x) +	{ +	X509_NAME *name; + +	if (x == NULL) return(0); +	if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL)) +		return(0); +		 +	if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL) +		return(0); + +	if (!sk_X509_NAME_push(*sk,name)) +		{ +		X509_NAME_free(name); +		return(0); +		} +	return(1); +	} + +int SSL_add_client_CA(SSL *ssl,X509 *x) +	{ +	return(add_client_CA(&(ssl->client_CA),x)); +	} + +int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x) +	{ +	return(add_client_CA(&(ctx->client_CA),x)); +	} + +static int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) +	{ +	return(X509_NAME_cmp(*a,*b)); +	} + +#ifndef OPENSSL_NO_STDIO +/*! + * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; + * it doesn't really have anything to do with clients (except that a common use + * for a stack of CAs is to send it to the client). Actually, it doesn't have + * much to do with CAs, either, since it will load any old cert. + * \param file the file containing one or more certs. + * \return a ::STACK containing the certs. + */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) +	{ +	BIO *in; +	X509 *x=NULL; +	X509_NAME *xn=NULL; +	STACK_OF(X509_NAME) *ret = NULL,*sk; + +	sk=sk_X509_NAME_new(xname_cmp); + +	in=BIO_new(BIO_s_file_internal()); + +	if ((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) == NULL) +			break; +		if (ret == NULL) +			{ +			ret = sk_X509_NAME_new_null(); +			if (ret == NULL) +				{ +				SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE); +				goto err; +				} +			} +		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_X509_NAME_find(sk,xn) >= 0) +			X509_NAME_free(xn); +		else +			{ +			sk_X509_NAME_push(sk,xn); +			sk_X509_NAME_push(ret,xn); +			} +		} + +	if (0) +		{ +err: +		if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free); +		ret=NULL; +		} +	if (sk != NULL) sk_X509_NAME_free(sk); +	if (in != NULL) BIO_free(in); +	if (x != NULL) X509_free(x); +	if (ret != NULL) +		ERR_clear_error(); +	return(ret); +	} +#endif + +/*! + * Add a file of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, +					const char *file) +	{ +	BIO *in; +	X509 *x=NULL; +	X509_NAME *xn=NULL; +	int ret=1; +	int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); +	 +	oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp); +	 +	in=BIO_new(BIO_s_file_internal()); +	 +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE); +		goto err; +		} +	 +	if (!BIO_read_filename(in,file)) +		goto err; +	 +	for (;;) +		{ +		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) +			break; +		if ((xn=X509_get_subject_name(x)) == NULL) goto err; +		xn=X509_NAME_dup(xn); +		if (xn == NULL) goto err; +		if (sk_X509_NAME_find(stack,xn) >= 0) +			X509_NAME_free(xn); +		else +			sk_X509_NAME_push(stack,xn); +		} + +	ERR_clear_error(); + +	if (0) +		{ +err: +		ret=0; +		} +	if(in != NULL) +		BIO_free(in); +	if(x != NULL) +		X509_free(x); +	 +	(void)sk_X509_NAME_set_cmp_func(stack,oldcmp); + +	return ret; +	} + +/*! + * Add a directory of certs to a stack. + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be + * included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, +				       const char *dir) +	{ +	OPENSSL_DIR_CTX *d = NULL; +	const char *filename; +	int ret = 0; + +	CRYPTO_w_lock(CRYPTO_LOCK_READDIR); + +	/* Note that a side effect is that the CAs will be sorted by name */ + +	while((filename = OPENSSL_DIR_read(&d, dir))) +		{ +		char buf[1024]; +		int r; + +		if(strlen(dir)+strlen(filename)+2 > sizeof buf) +			{ +			SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); +			goto err; +			} + +#ifdef OPENSSL_SYS_VMS +		r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename); +#else +		r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename); +#endif +		if (r <= 0 || r >= (int)sizeof(buf)) +			goto err; +		if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) +			goto err; +		} + +	if (errno) +		{ +		SYSerr(SYS_F_OPENDIR, get_last_sys_error()); +		ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); +		SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); +		goto err; +		} + +	ret = 1; + +err: +	if (d) OPENSSL_DIR_end(&d); +	CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); +	return ret; +	} + diff --git a/main/openssl/ssl/ssl_ciph.c b/main/openssl/ssl/ssl_ciph.c new file mode 100644 index 00000000..e523a8f2 --- /dev/null +++ b/main/openssl/ssl/ssl_ciph.c @@ -0,0 +1,1792 @@ +/* ssl/ssl_ciph.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include <openssl/objects.h> +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#ifndef OPENSSL_NO_ENGINE +#include <openssl/engine.h> +#endif +#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_NULL_IDX	5 +#define SSL_ENC_AES128_IDX	6 +#define SSL_ENC_AES256_IDX	7 +#define SSL_ENC_CAMELLIA128_IDX	8 +#define SSL_ENC_CAMELLIA256_IDX	9 +#define SSL_ENC_GOST89_IDX	10 +#define SSL_ENC_SEED_IDX    	11 +#define SSL_ENC_NUM_IDX		12 + + +static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={ +	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, +	}; + +#define SSL_COMP_NULL_IDX	0 +#define SSL_COMP_ZLIB_IDX	1 +#define SSL_COMP_NUM_IDX	2 + +static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL; + +#define SSL_MD_MD5_IDX	0 +#define SSL_MD_SHA1_IDX	1 +#define SSL_MD_GOST94_IDX 2 +#define SSL_MD_GOST89MAC_IDX 3 +/*Constant SSL_MAX_DIGEST equal to size of digests array should be  + * defined in the + * ssl_locl.h */ +#define SSL_MD_NUM_IDX	SSL_MAX_DIGEST  +static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={ +	NULL,NULL,NULL,NULL +	}; +/* PKEY_TYPE for GOST89MAC is known in advance, but, because + * implementation is engine-provided, we'll fill it only if + * corresponding EVP_PKEY_METHOD is found  + */ +static int  ssl_mac_pkey_id[SSL_MD_NUM_IDX]={ +	EVP_PKEY_HMAC,EVP_PKEY_HMAC,EVP_PKEY_HMAC,NID_undef +	}; + +static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={ +	0,0,0,0 +	}; + +static int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={ +	SSL_HANDSHAKE_MAC_MD5,SSL_HANDSHAKE_MAC_SHA, +	SSL_HANDSHAKE_MAC_GOST94,0 +	}; + +#define CIPHER_ADD	1 +#define CIPHER_KILL	2 +#define CIPHER_DEL	3 +#define CIPHER_ORD	4 +#define CIPHER_SPECIAL	5 + +typedef struct cipher_order_st +	{ +	const SSL_CIPHER *cipher; +	int active; +	int dead; +	struct cipher_order_st *next,*prev; +	} CIPHER_ORDER; + +static const SSL_CIPHER cipher_aliases[]={ +	/* "ALL" doesn't include eNULL (must be specifically enabled) */ +	{0,SSL_TXT_ALL,0,     0,0,~SSL_eNULL,0,0,0,0,0,0}, +	/* "COMPLEMENTOFALL" */ +	{0,SSL_TXT_CMPALL,0,  0,0,SSL_eNULL,0,0,0,0,0,0}, + +	/* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in ALL!) */ +	{0,SSL_TXT_CMPDEF,0,  SSL_kEDH|SSL_kEECDH,SSL_aNULL,~SSL_eNULL,0,0,0,0,0,0}, + +	/* key exchange aliases +	 * (some of those using only a single bit here combine +	 * multiple key exchange algs according to the RFCs, +	 * e.g. kEDH combines DHE_DSS and DHE_RSA) */ +	{0,SSL_TXT_kRSA,0,    SSL_kRSA,  0,0,0,0,0,0,0,0}, + +	{0,SSL_TXT_kDHr,0,    SSL_kDHr,  0,0,0,0,0,0,0,0}, /* no such ciphersuites supported! */ +	{0,SSL_TXT_kDHd,0,    SSL_kDHd,  0,0,0,0,0,0,0,0}, /* no such ciphersuites supported! */ +	{0,SSL_TXT_kDH,0,     SSL_kDHr|SSL_kDHd,0,0,0,0,0,0,0,0}, /* no such ciphersuites supported! */ +	{0,SSL_TXT_kEDH,0,    SSL_kEDH,  0,0,0,0,0,0,0,0}, +	{0,SSL_TXT_DH,0,      SSL_kDHr|SSL_kDHd|SSL_kEDH,0,0,0,0,0,0,0,0}, + +	{0,SSL_TXT_kKRB5,0,   SSL_kKRB5, 0,0,0,0,0,0,0,0}, + +	{0,SSL_TXT_kECDHr,0,  SSL_kECDHr,0,0,0,0,0,0,0,0}, +	{0,SSL_TXT_kECDHe,0,  SSL_kECDHe,0,0,0,0,0,0,0,0}, +	{0,SSL_TXT_kECDH,0,   SSL_kECDHr|SSL_kECDHe,0,0,0,0,0,0,0,0}, +	{0,SSL_TXT_kEECDH,0,  SSL_kEECDH,0,0,0,0,0,0,0,0}, +	{0,SSL_TXT_ECDH,0,    SSL_kECDHr|SSL_kECDHe|SSL_kEECDH,0,0,0,0,0,0,0,0}, + +        {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0}, +	{0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0}, + +	/* server authentication aliases */ +	{0,SSL_TXT_aRSA,0,    0,SSL_aRSA,  0,0,0,0,0,0,0}, +	{0,SSL_TXT_aDSS,0,    0,SSL_aDSS,  0,0,0,0,0,0,0}, +	{0,SSL_TXT_DSS,0,     0,SSL_aDSS,   0,0,0,0,0,0,0}, +	{0,SSL_TXT_aKRB5,0,   0,SSL_aKRB5, 0,0,0,0,0,0,0}, +	{0,SSL_TXT_aNULL,0,   0,SSL_aNULL, 0,0,0,0,0,0,0}, +	{0,SSL_TXT_aDH,0,     0,SSL_aDH,   0,0,0,0,0,0,0}, /* no such ciphersuites supported! */ +	{0,SSL_TXT_aECDH,0,   0,SSL_aECDH, 0,0,0,0,0,0,0}, +	{0,SSL_TXT_aECDSA,0,  0,SSL_aECDSA,0,0,0,0,0,0,0}, +	{0,SSL_TXT_ECDSA,0,   0,SSL_aECDSA, 0,0,0,0,0,0,0}, +        {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0}, +	{0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0}, +	{0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0}, +	{0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0}, + +	/* aliases combining key exchange and server authentication */ +	{0,SSL_TXT_EDH,0,     SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0}, +	{0,SSL_TXT_EECDH,0,   SSL_kEECDH,~SSL_aNULL,0,0,0,0,0,0,0}, +	{0,SSL_TXT_NULL,0,    0,0,SSL_eNULL, 0,0,0,0,0,0}, +	{0,SSL_TXT_KRB5,0,    SSL_kKRB5,SSL_aKRB5,0,0,0,0,0,0,0}, +	{0,SSL_TXT_RSA,0,     SSL_kRSA,SSL_aRSA,0,0,0,0,0,0,0}, +	{0,SSL_TXT_ADH,0,     SSL_kEDH,SSL_aNULL,0,0,0,0,0,0,0}, +	{0,SSL_TXT_AECDH,0,   SSL_kEECDH,SSL_aNULL,0,0,0,0,0,0,0}, +        {0,SSL_TXT_PSK,0,     SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0}, + + +	/* symmetric encryption aliases */ +	{0,SSL_TXT_DES,0,     0,0,SSL_DES,   0,0,0,0,0,0}, +	{0,SSL_TXT_3DES,0,    0,0,SSL_3DES,  0,0,0,0,0,0}, +	{0,SSL_TXT_RC4,0,     0,0,SSL_RC4,   0,0,0,0,0,0}, +	{0,SSL_TXT_RC2,0,     0,0,SSL_RC2,   0,0,0,0,0,0}, +	{0,SSL_TXT_IDEA,0,    0,0,SSL_IDEA,  0,0,0,0,0,0}, +	{0,SSL_TXT_SEED,0,    0,0,SSL_SEED,  0,0,0,0,0,0}, +	{0,SSL_TXT_eNULL,0,   0,0,SSL_eNULL, 0,0,0,0,0,0}, +	{0,SSL_TXT_AES128,0,  0,0,SSL_AES128,0,0,0,0,0,0}, +	{0,SSL_TXT_AES256,0,  0,0,SSL_AES256,0,0,0,0,0,0}, +	{0,SSL_TXT_AES,0,     0,0,SSL_AES128|SSL_AES256,0,0,0,0,0,0}, +	{0,SSL_TXT_CAMELLIA128,0,0,0,SSL_CAMELLIA128,0,0,0,0,0,0}, +	{0,SSL_TXT_CAMELLIA256,0,0,0,SSL_CAMELLIA256,0,0,0,0,0,0}, +	{0,SSL_TXT_CAMELLIA   ,0,0,0,SSL_CAMELLIA128|SSL_CAMELLIA256,0,0,0,0,0,0}, + +	/* MAC aliases */	 +	{0,SSL_TXT_MD5,0,     0,0,0,SSL_MD5,   0,0,0,0,0}, +	{0,SSL_TXT_SHA1,0,    0,0,0,SSL_SHA1,  0,0,0,0,0}, +	{0,SSL_TXT_SHA,0,     0,0,0,SSL_SHA1,  0,0,0,0,0}, +	{0,SSL_TXT_GOST94,0,     0,0,0,SSL_GOST94,  0,0,0,0,0}, +	{0,SSL_TXT_GOST89MAC,0,     0,0,0,SSL_GOST89MAC,  0,0,0,0,0}, + +	/* protocol version aliases */ +	{0,SSL_TXT_SSLV2,0,   0,0,0,0,SSL_SSLV2, 0,0,0,0}, +	{0,SSL_TXT_SSLV3,0,   0,0,0,0,SSL_SSLV3, 0,0,0,0}, +	{0,SSL_TXT_TLSV1,0,   0,0,0,0,SSL_TLSV1, 0,0,0,0}, + +	/* export flag */ +	{0,SSL_TXT_EXP,0,     0,0,0,0,0,SSL_EXPORT,0,0,0}, +	{0,SSL_TXT_EXPORT,0,  0,0,0,0,0,SSL_EXPORT,0,0,0}, + +	/* strength classes */ +	{0,SSL_TXT_EXP40,0,   0,0,0,0,0,SSL_EXP40, 0,0,0}, +	{0,SSL_TXT_EXP56,0,   0,0,0,0,0,SSL_EXP56, 0,0,0}, +	{0,SSL_TXT_LOW,0,     0,0,0,0,0,SSL_LOW,   0,0,0}, +	{0,SSL_TXT_MEDIUM,0,  0,0,0,0,0,SSL_MEDIUM,0,0,0}, +	{0,SSL_TXT_HIGH,0,    0,0,0,0,0,SSL_HIGH,  0,0,0}, +	/* FIPS 140-2 approved ciphersuite */ +	{0,SSL_TXT_FIPS,0,    0,0,~SSL_eNULL,0,0,SSL_FIPS,  0,0,0}, +	}; +/* Search for public key algorithm with given name and  + * return its pkey_id if it is available. Otherwise return 0 + */ +#ifdef OPENSSL_NO_ENGINE + +static int get_optional_pkey_id(const char *pkey_name) +	{ +	const EVP_PKEY_ASN1_METHOD *ameth; +	int pkey_id=0; +	ameth = EVP_PKEY_asn1_find_str(NULL,pkey_name,-1); +	if (ameth)  +		{ +		EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth); +		}		 +	return pkey_id; +	} + +#else + +static int get_optional_pkey_id(const char *pkey_name) +	{ +	const EVP_PKEY_ASN1_METHOD *ameth; +	ENGINE *tmpeng = NULL; +	int pkey_id=0; +	ameth = EVP_PKEY_asn1_find_str(&tmpeng,pkey_name,-1); +	if (ameth) +		{ +		EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth); +		} +	if (tmpeng) ENGINE_finish(tmpeng); +	return pkey_id; +	} + +#endif + +void ssl_load_ciphers(void) +	{ +	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); +#ifndef OPENSSL_NO_IDEA +	ssl_cipher_methods[SSL_ENC_IDEA_IDX]=  +		EVP_get_cipherbyname(SN_idea_cbc); +#else +	ssl_cipher_methods[SSL_ENC_IDEA_IDX]= NULL; +#endif +	ssl_cipher_methods[SSL_ENC_AES128_IDX]= +	  EVP_get_cipherbyname(SN_aes_128_cbc); +	ssl_cipher_methods[SSL_ENC_AES256_IDX]= +	  EVP_get_cipherbyname(SN_aes_256_cbc); +	ssl_cipher_methods[SSL_ENC_CAMELLIA128_IDX]= +	  EVP_get_cipherbyname(SN_camellia_128_cbc); +	ssl_cipher_methods[SSL_ENC_CAMELLIA256_IDX]= +	  EVP_get_cipherbyname(SN_camellia_256_cbc); +	ssl_cipher_methods[SSL_ENC_GOST89_IDX]= +	  EVP_get_cipherbyname(SN_gost89_cnt); +	ssl_cipher_methods[SSL_ENC_SEED_IDX]= +	  EVP_get_cipherbyname(SN_seed_cbc); + +	ssl_digest_methods[SSL_MD_MD5_IDX]= +		EVP_get_digestbyname(SN_md5); +	ssl_mac_secret_size[SSL_MD_MD5_IDX]= +		EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]); +	OPENSSL_assert(ssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0); +	ssl_digest_methods[SSL_MD_SHA1_IDX]= +		EVP_get_digestbyname(SN_sha1); +	ssl_mac_secret_size[SSL_MD_SHA1_IDX]= +		EVP_MD_size(ssl_digest_methods[SSL_MD_SHA1_IDX]); +	OPENSSL_assert(ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0); +	ssl_digest_methods[SSL_MD_GOST94_IDX]= +		EVP_get_digestbyname(SN_id_GostR3411_94); +	if (ssl_digest_methods[SSL_MD_GOST94_IDX]) +		{	 +		ssl_mac_secret_size[SSL_MD_GOST94_IDX]= +			EVP_MD_size(ssl_digest_methods[SSL_MD_GOST94_IDX]); +		OPENSSL_assert(ssl_mac_secret_size[SSL_MD_GOST94_IDX] >= 0); +		} +	ssl_digest_methods[SSL_MD_GOST89MAC_IDX]= +		EVP_get_digestbyname(SN_id_Gost28147_89_MAC); +		ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac"); +		if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) { +			ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX]=32; +		}		 + +	} +#ifndef OPENSSL_NO_COMP + +static int sk_comp_cmp(const SSL_COMP * const *a, +			const SSL_COMP * const *b) +	{ +	return((*a)->id-(*b)->id); +	} + +static void load_builtin_compressions(void) +	{ +	int got_write_lock = 0; + +	CRYPTO_r_lock(CRYPTO_LOCK_SSL); +	if (ssl_comp_methods == NULL) +		{ +		CRYPTO_r_unlock(CRYPTO_LOCK_SSL); +		CRYPTO_w_lock(CRYPTO_LOCK_SSL); +		got_write_lock = 1; +		 +		if (ssl_comp_methods == NULL) +			{ +			SSL_COMP *comp = NULL; + +			MemCheck_off(); +			ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp); +			if (ssl_comp_methods != NULL) +				{ +				comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP)); +				if (comp != NULL) +					{ +					comp->method=COMP_zlib(); +					if (comp->method +						&& comp->method->type == NID_undef) +						OPENSSL_free(comp); +					else +						{ +						comp->id=SSL_COMP_ZLIB_IDX; +						comp->name=comp->method->name; +						sk_SSL_COMP_push(ssl_comp_methods,comp); +						} +					} +				} +			MemCheck_on(); +			} +		} +	 +	if (got_write_lock) +		CRYPTO_w_unlock(CRYPTO_LOCK_SSL); +	else +		CRYPTO_r_unlock(CRYPTO_LOCK_SSL); +	} +#endif + +int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, +	     const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size,SSL_COMP **comp) +	{ +	int i; +	const SSL_CIPHER *c; + +	c=s->cipher; +	if (c == NULL) return(0); +	if (comp != NULL) +		{ +		SSL_COMP ctmp; +#ifndef OPENSSL_NO_COMP +		load_builtin_compressions(); +#endif + +		*comp=NULL; +		ctmp.id=s->compress_meth; +		if (ssl_comp_methods != NULL) +			{ +			i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp); +			if (i >= 0) +				*comp=sk_SSL_COMP_value(ssl_comp_methods,i); +			else +				*comp=NULL; +			} +		} + +	if ((enc == NULL) || (md == NULL)) return(0); + +	switch (c->algorithm_enc) +		{ +	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; +	case SSL_AES128: +		i=SSL_ENC_AES128_IDX; +		break; +	case SSL_AES256: +		i=SSL_ENC_AES256_IDX; +		break; +	case SSL_CAMELLIA128: +		i=SSL_ENC_CAMELLIA128_IDX; +		break; +	case SSL_CAMELLIA256: +		i=SSL_ENC_CAMELLIA256_IDX; +		break; +	case SSL_eGOST2814789CNT: +		i=SSL_ENC_GOST89_IDX; +		break; +	case SSL_SEED: +		i=SSL_ENC_SEED_IDX; +		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->algorithm_mac) +		{ +	case SSL_MD5: +		i=SSL_MD_MD5_IDX; +		break; +	case SSL_SHA1: +		i=SSL_MD_SHA1_IDX; +		break; +	case SSL_GOST94: +		i = SSL_MD_GOST94_IDX; +		break; +	case SSL_GOST89MAC: +		i = SSL_MD_GOST89MAC_IDX; +		break; +	default: +		i= -1; +		break; +		} +	if ((i < 0) || (i > SSL_MD_NUM_IDX)) +	{ +		*md=NULL;  +		if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef; +		if (mac_secret_size!=NULL) *mac_secret_size = 0; + +	} +	else +	{ +		*md=ssl_digest_methods[i]; +		if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i]; +		if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i]; +	}	 + +	if ((*enc != NULL) && (*md != NULL) && (!mac_pkey_type||*mac_pkey_type != NID_undef)) +		return(1); +	else +		return(0); +	} + +int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md)  +{ +	if (idx <0||idx>=SSL_MD_NUM_IDX)  +		{ +		return 0; +		} +	if (ssl_handshake_digest_flag[idx]==0) return 0; +	*mask = ssl_handshake_digest_flag[idx]; +	*md = ssl_digest_methods[idx]; +	return 1; +} + +#define ITEM_SEP(a) \ +	(((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) + +static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr, +	     CIPHER_ORDER **tail) +	{ +	if (curr == *tail) return; +	if (curr == *head) +		*head=curr->next; +	if (curr->prev != NULL) +		curr->prev->next=curr->next; +	if (curr->next != NULL) +		curr->next->prev=curr->prev; +	(*tail)->next=curr; +	curr->prev= *tail; +	curr->next=NULL; +	*tail=curr; +	} + +static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr, +	     CIPHER_ORDER **tail) +	{ +	if (curr == *head) return; +	if (curr == *tail) +		*tail=curr->prev; +	if (curr->next != NULL) +		curr->next->prev=curr->prev; +	if (curr->prev != NULL) +		curr->prev->next=curr->next; +	(*head)->prev=curr; +	curr->next= *head; +	curr->prev=NULL; +	*head=curr; +	} + +static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, unsigned long *enc, unsigned long *mac, unsigned long *ssl) +	{ +	*mkey = 0; +	*auth = 0; +	*enc = 0; +	*mac = 0; +	*ssl = 0; + +#ifdef OPENSSL_NO_RSA +	*mkey |= SSL_kRSA; +	*auth |= SSL_aRSA; +#endif +#ifdef OPENSSL_NO_DSA +	*auth |= SSL_aDSS; +#endif +	*mkey |= SSL_kDHr|SSL_kDHd; /* no such ciphersuites supported! */ +	*auth |= SSL_aDH; +#ifdef OPENSSL_NO_DH +	*mkey |= SSL_kDHr|SSL_kDHd|SSL_kEDH; +	*auth |= SSL_aDH; +#endif +#ifdef OPENSSL_NO_KRB5 +	*mkey |= SSL_kKRB5; +	*auth |= SSL_aKRB5; +#endif +#ifdef OPENSSL_NO_ECDSA +	*auth |= SSL_aECDSA; +#endif +#ifdef OPENSSL_NO_ECDH +	*mkey |= SSL_kECDHe|SSL_kECDHr; +	*auth |= SSL_aECDH; +#endif +#ifdef OPENSSL_NO_PSK +	*mkey |= SSL_kPSK; +	*auth |= SSL_aPSK; +#endif +	/* Check for presence of GOST 34.10 algorithms, and if they +	 * do not present, disable  appropriate auth and key exchange */ +	if (!get_optional_pkey_id("gost94")) { +		*auth |= SSL_aGOST94; +	} +	if (!get_optional_pkey_id("gost2001")) { +		*auth |= SSL_aGOST01; +	} +	/* Disable GOST key exchange if no GOST signature algs are available * */ +	if ((*auth & (SSL_aGOST94|SSL_aGOST01)) == (SSL_aGOST94|SSL_aGOST01)) { +		*mkey |= SSL_kGOST; +	}	 +#ifdef SSL_FORBID_ENULL +	*enc |= SSL_eNULL; +#endif +		 + + +	*enc |= (ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL) ? SSL_DES :0; +	*enc |= (ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL) ? SSL_3DES:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL) ? SSL_RC4 :0; +	*enc |= (ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL) ? SSL_RC2 :0; +	*enc |= (ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL) ? SSL_IDEA:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES128:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_AES256_IDX] == NULL) ? SSL_AES256:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_CAMELLIA128_IDX] == NULL) ? SSL_CAMELLIA128:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_CAMELLIA256_IDX] == NULL) ? SSL_CAMELLIA256:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_GOST89_IDX] == NULL) ? SSL_eGOST2814789CNT:0; +	*enc |= (ssl_cipher_methods[SSL_ENC_SEED_IDX] == NULL) ? SSL_SEED:0; + +	*mac |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0; +	*mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0; +	*mac |= (ssl_digest_methods[SSL_MD_GOST94_IDX] == NULL) ? SSL_GOST94:0; +	*mac |= (ssl_digest_methods[SSL_MD_GOST89MAC_IDX] == NULL || ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]==NID_undef)? SSL_GOST89MAC:0; + +	} + +static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, +                int num_of_ciphers, +                unsigned long disabled_mkey, unsigned long disabled_auth, +                unsigned long disabled_enc, unsigned long disabled_mac, +                unsigned long disabled_ssl, +                CIPHER_ORDER *co_list, +                CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) +	{ +	int i, co_list_num; +	const SSL_CIPHER *c; + +	/* +	 * We have num_of_ciphers descriptions compiled in, depending on the +	 * method selected (SSLv2 and/or SSLv3, TLSv1 etc). +	 * These will later be sorted in a linked list with at most num +	 * entries. +	 */ + +	/* Get the initial list of ciphers */ +	co_list_num = 0;	/* actual count of ciphers */ +	for (i = 0; i < num_of_ciphers; i++) +		{ +		c = ssl_method->get_cipher(i); +		/* drop those that use any of that is not available */ +		if ((c != NULL) && c->valid && +		    !(c->algorithm_mkey & disabled_mkey) && +		    !(c->algorithm_auth & disabled_auth) && +		    !(c->algorithm_enc & disabled_enc) && +		    !(c->algorithm_mac & disabled_mac) && +		    !(c->algorithm_ssl & disabled_ssl)) +			{ +			co_list[co_list_num].cipher = c; +			co_list[co_list_num].next = NULL; +			co_list[co_list_num].prev = NULL; +			co_list[co_list_num].active = 0; +			co_list_num++; +#ifdef KSSL_DEBUG +			printf("\t%d: %s %lx %lx %lx\n",i,c->name,c->id,c->algorithm_mkey,c->algorithm_auth); +#endif	/* KSSL_DEBUG */ +			/* +			if (!sk_push(ca_list,(char *)c)) goto err; +			*/ +			} +		} + +	/* +	 * Prepare linked list from list entries +	 */	 +	if (co_list_num > 0) +		{ +		co_list[0].prev = NULL; + +		if (co_list_num > 1) +			{ +			co_list[0].next = &co_list[1]; +			 +			for (i = 1; i < co_list_num - 1; i++) +				{ +				co_list[i].prev = &co_list[i - 1]; +				co_list[i].next = &co_list[i + 1]; +				} + +			co_list[co_list_num - 1].prev = &co_list[co_list_num - 2]; +			} +		 +		co_list[co_list_num - 1].next = NULL; + +		*head_p = &co_list[0]; +		*tail_p = &co_list[co_list_num - 1]; +		} +	} + +static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list, +                        int num_of_group_aliases, +                        unsigned long disabled_mkey, unsigned long disabled_auth, +                        unsigned long disabled_enc, unsigned long disabled_mac, +                        unsigned long disabled_ssl, +			CIPHER_ORDER *head) +	{ +	CIPHER_ORDER *ciph_curr; +	const SSL_CIPHER **ca_curr; +	int i; +	unsigned long mask_mkey = ~disabled_mkey; +	unsigned long mask_auth = ~disabled_auth; +	unsigned long mask_enc = ~disabled_enc; +	unsigned long mask_mac = ~disabled_mac; +	unsigned long mask_ssl = ~disabled_ssl; + +	/* +	 * First, add the real ciphers as already collected +	 */ +	ciph_curr = head; +	ca_curr = ca_list; +	while (ciph_curr != NULL) +		{ +		*ca_curr = ciph_curr->cipher; +		ca_curr++; +		ciph_curr = ciph_curr->next; +		} + +	/* +	 * Now we add the available ones from the cipher_aliases[] table. +	 * They represent either one or more algorithms, some of which +	 * in any affected category must be supported (set in enabled_mask), +	 * or represent a cipher strength value (will be added in any case because algorithms=0). +	 */ +	for (i = 0; i < num_of_group_aliases; i++) +		{ +		unsigned long algorithm_mkey = cipher_aliases[i].algorithm_mkey; +		unsigned long algorithm_auth = cipher_aliases[i].algorithm_auth; +		unsigned long algorithm_enc = cipher_aliases[i].algorithm_enc; +		unsigned long algorithm_mac = cipher_aliases[i].algorithm_mac; +		unsigned long algorithm_ssl = cipher_aliases[i].algorithm_ssl; + +		if (algorithm_mkey) +			if ((algorithm_mkey & mask_mkey) == 0) +				continue; +	 +		if (algorithm_auth) +			if ((algorithm_auth & mask_auth) == 0) +				continue; +		 +		if (algorithm_enc) +			if ((algorithm_enc & mask_enc) == 0) +				continue; +		 +		if (algorithm_mac) +			if ((algorithm_mac & mask_mac) == 0) +				continue; +		 +		if (algorithm_ssl) +			if ((algorithm_ssl & mask_ssl) == 0) +				continue; +		 +		*ca_curr = (SSL_CIPHER *)(cipher_aliases + i); +		ca_curr++; +		} + +	*ca_curr = NULL;	/* end of list */ +	} + +static void ssl_cipher_apply_rule(unsigned long cipher_id, +                unsigned long alg_mkey, unsigned long alg_auth, +                unsigned long alg_enc, unsigned long alg_mac, +                unsigned long alg_ssl, +		unsigned long algo_strength, +		int rule, int strength_bits, +		CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) +	{ +	CIPHER_ORDER *head, *tail, *curr, *curr2, *last; +	const SSL_CIPHER *cp; +	int reverse = 0; + +#ifdef CIPHER_DEBUG +	printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d)\n", +		rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits); +#endif + +	if (rule == CIPHER_DEL) +		reverse = 1; /* needed to maintain sorting between currently deleted ciphers */ + +	head = *head_p; +	tail = *tail_p; + +	if (reverse) +		{ +		curr = tail; +		last = head; +		} +	else +		{ +		curr = head; +		last = tail; +		} + +	curr2 = curr; +	for (;;) +		{ +		if ((curr == NULL) || (curr == last)) break; +		curr = curr2; +		curr2 = reverse ? curr->prev : curr->next; + +		cp = curr->cipher; + +		/* +		 * Selection criteria is either the value of strength_bits +		 * or the algorithms used. +		 */ +		if (strength_bits >= 0) +			{ +			if (strength_bits != cp->strength_bits) +				continue; +			} +		else +			{ +#ifdef CIPHER_DEBUG +			printf("\nName: %s:\nAlgo = %08lx/%08lx/%08lx/%08lx/%08lx Algo_strength = %08lx\n", cp->name, cp->algorithm_mkey, cp->algorithm_auth, cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl, cp->algo_strength); +#endif + +			if (alg_mkey && !(alg_mkey & cp->algorithm_mkey)) +				continue; +			if (alg_auth && !(alg_auth & cp->algorithm_auth)) +				continue; +			if (alg_enc && !(alg_enc & cp->algorithm_enc)) +				continue; +			if (alg_mac && !(alg_mac & cp->algorithm_mac)) +				continue; +			if (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) +				continue; +			if ((algo_strength & SSL_EXP_MASK) && !(algo_strength & SSL_EXP_MASK & cp->algo_strength)) +				continue; +			if ((algo_strength & SSL_STRONG_MASK) && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength)) +				continue; +			} + +#ifdef CIPHER_DEBUG +		printf("Action = %d\n", rule); +#endif + +		/* add the cipher if it has not been added yet. */ +		if (rule == CIPHER_ADD) +			{ +			/* reverse == 0 */ +			if (!curr->active) +				{ +				ll_append_tail(&head, curr, &tail); +				curr->active = 1; +				} +			} +		/* Move the added cipher to this location */ +		else if (rule == CIPHER_ORD) +			{ +			/* reverse == 0 */ +			if (curr->active) +				{ +				ll_append_tail(&head, curr, &tail); +				} +			} +		else if	(rule == CIPHER_DEL) +			{ +			/* reverse == 1 */ +			if (curr->active) +				{ +				/* most recently deleted ciphersuites get best positions +				 * for any future CIPHER_ADD (note that the CIPHER_DEL loop +				 * works in reverse to maintain the order) */ +				ll_append_head(&head, curr, &tail); +				curr->active = 0; +				} +			} +		else if (rule == CIPHER_KILL) +			{ +			/* reverse == 0 */ +			if (head == curr) +				head = curr->next; +			else +				curr->prev->next = curr->next; +			if (tail == curr) +				tail = curr->prev; +			curr->active = 0; +			if (curr->next != NULL) +				curr->next->prev = curr->prev; +			if (curr->prev != NULL) +				curr->prev->next = curr->next; +			curr->next = NULL; +			curr->prev = NULL; +			} +		} + +	*head_p = head; +	*tail_p = tail; +	} + +static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p, +				    CIPHER_ORDER **tail_p) +	{ +	int max_strength_bits, i, *number_uses; +	CIPHER_ORDER *curr; + +	/* +	 * This routine sorts the ciphers with descending strength. The sorting +	 * must keep the pre-sorted sequence, so we apply the normal sorting +	 * routine as '+' movement to the end of the list. +	 */ +	max_strength_bits = 0; +	curr = *head_p; +	while (curr != NULL) +		{ +		if (curr->active && +		    (curr->cipher->strength_bits > max_strength_bits)) +		    max_strength_bits = curr->cipher->strength_bits; +		curr = curr->next; +		} + +	number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); +	if (!number_uses) +		{ +		SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int)); + +	/* +	 * Now find the strength_bits values actually used +	 */ +	curr = *head_p; +	while (curr != NULL) +		{ +		if (curr->active) +			number_uses[curr->cipher->strength_bits]++; +		curr = curr->next; +		} +	/* +	 * Go through the list of used strength_bits values in descending +	 * order. +	 */ +	for (i = max_strength_bits; i >= 0; i--) +		if (number_uses[i] > 0) +			ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p, tail_p); + +	OPENSSL_free(number_uses); +	return(1); +	} + +static int ssl_cipher_process_rulestr(const char *rule_str, +                CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p, +                const SSL_CIPHER **ca_list) +	{ +	unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength; +	const char *l, *buf; +	int j, multi, found, rule, retval, ok, buflen; +	unsigned long cipher_id = 0; +	char ch; + +	retval = 1; +	l = rule_str; +	for (;;) +		{ +		ch = *l; + +		if (ch == '\0') +			break;		/* done */ +		if (ch == '-') +			{ rule = CIPHER_DEL; l++; } +		else if (ch == '+') +			{ rule = CIPHER_ORD; l++; } +		else if (ch == '!') +			{ rule = CIPHER_KILL; l++; } +		else if (ch == '@') +			{ rule = CIPHER_SPECIAL; l++; } +		else +			{ rule = CIPHER_ADD; } + +		if (ITEM_SEP(ch)) +			{ +			l++; +			continue; +			} + +		alg_mkey = 0; +		alg_auth = 0; +		alg_enc = 0; +		alg_mac = 0; +		alg_ssl = 0; +		algo_strength = 0; + +		for (;;) +			{ +			ch = *l; +			buf = l; +			buflen = 0; +#ifndef CHARSET_EBCDIC +			while (	((ch >= 'A') && (ch <= 'Z')) || +				((ch >= '0') && (ch <= '9')) || +				((ch >= 'a') && (ch <= 'z')) || +				 (ch == '-')) +#else +			while (	isalnum(ch) || (ch == '-')) +#endif +				 { +				 ch = *(++l); +				 buflen++; +				 } + +			if (buflen == 0) +				{ +				/* +				 * We hit something we cannot deal with, +				 * it is no command or separator nor +				 * alphanumeric, so we call this an error. +				 */ +				SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, +				       SSL_R_INVALID_COMMAND); +				retval = found = 0; +				l++; +				break; +				} + +			if (rule == CIPHER_SPECIAL) +				{ +				found = 0; /* unused -- avoid compiler warning */ +				break;	/* special treatment */ +				} + +			/* check for multi-part specification */ +			if (ch == '+') +				{ +				multi=1; +				l++; +				} +			else +				multi=0; + +			/* +			 * Now search for the cipher alias in the ca_list. Be careful +			 * with the strncmp, because the "buflen" limitation +			 * will make the rule "ADH:SOME" and the cipher +			 * "ADH-MY-CIPHER" look like a match for buflen=3. +			 * So additionally check whether the cipher name found +			 * has the correct length. We can save a strlen() call: +			 * just checking for the '\0' at the right place is +			 * sufficient, we have to strncmp() anyway. (We cannot +			 * use strcmp(), because buf is not '\0' terminated.) +			 */ +			j = found = 0; +			cipher_id = 0; +			while (ca_list[j]) +				{ +				if (!strncmp(buf, ca_list[j]->name, buflen) && +				    (ca_list[j]->name[buflen] == '\0')) +					{ +					found = 1; +					break; +					} +				else +					j++; +				} + +			if (!found) +				break;	/* ignore this entry */ + +			if (ca_list[j]->algorithm_mkey) +				{ +				if (alg_mkey) +					{ +					alg_mkey &= ca_list[j]->algorithm_mkey; +					if (!alg_mkey) { found = 0; break; } +					} +				else +					alg_mkey = ca_list[j]->algorithm_mkey; +				} + +			if (ca_list[j]->algorithm_auth) +				{ +				if (alg_auth) +					{ +					alg_auth &= ca_list[j]->algorithm_auth; +					if (!alg_auth) { found = 0; break; } +					} +				else +					alg_auth = ca_list[j]->algorithm_auth; +				} +			 +			if (ca_list[j]->algorithm_enc) +				{ +				if (alg_enc) +					{ +					alg_enc &= ca_list[j]->algorithm_enc; +					if (!alg_enc) { found = 0; break; } +					} +				else +					alg_enc = ca_list[j]->algorithm_enc; +				} +						 +			if (ca_list[j]->algorithm_mac) +				{ +				if (alg_mac) +					{ +					alg_mac &= ca_list[j]->algorithm_mac; +					if (!alg_mac) { found = 0; break; } +					} +				else +					alg_mac = ca_list[j]->algorithm_mac; +				} +			 +			if (ca_list[j]->algo_strength & SSL_EXP_MASK) +				{ +				if (algo_strength & SSL_EXP_MASK) +					{ +					algo_strength &= (ca_list[j]->algo_strength & SSL_EXP_MASK) | ~SSL_EXP_MASK; +					if (!(algo_strength & SSL_EXP_MASK)) { found = 0; break; } +					} +				else +					algo_strength |= ca_list[j]->algo_strength & SSL_EXP_MASK; +				} + +			if (ca_list[j]->algo_strength & SSL_STRONG_MASK) +				{ +				if (algo_strength & SSL_STRONG_MASK) +					{ +					algo_strength &= (ca_list[j]->algo_strength & SSL_STRONG_MASK) | ~SSL_STRONG_MASK; +					if (!(algo_strength & SSL_STRONG_MASK)) { found = 0; break; } +					} +				else +					algo_strength |= ca_list[j]->algo_strength & SSL_STRONG_MASK; +				} +			 +			if (ca_list[j]->valid) +				{ +				/* explicit ciphersuite found; its protocol version +				 * does not become part of the search pattern!*/ + +				cipher_id = ca_list[j]->id; +				} +			else +				{ +				/* not an explicit ciphersuite; only in this case, the +				 * protocol version is considered part of the search pattern */ + +				if (ca_list[j]->algorithm_ssl) +					{ +					if (alg_ssl) +						{ +						alg_ssl &= ca_list[j]->algorithm_ssl; +						if (!alg_ssl) { found = 0; break; } +						} +					else +						alg_ssl = ca_list[j]->algorithm_ssl; +					} +				} +			 +			if (!multi) break; +			} + +		/* +		 * Ok, we have the rule, now apply it +		 */ +		if (rule == CIPHER_SPECIAL) +			{	/* special command */ +			ok = 0; +			if ((buflen == 8) && +				!strncmp(buf, "STRENGTH", 8)) +				ok = ssl_cipher_strength_sort(head_p, tail_p); +			else +				SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, +					SSL_R_INVALID_COMMAND); +			if (ok == 0) +				retval = 0; +			/* +			 * We do not support any "multi" options +			 * together with "@", so throw away the +			 * rest of the command, if any left, until +			 * end or ':' is found. +			 */ +			while ((*l != '\0') && !ITEM_SEP(*l)) +				l++; +			} +		else if (found) +			{ +			ssl_cipher_apply_rule(cipher_id, +				alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, +				rule, -1, head_p, tail_p); +			} +		else +			{ +			while ((*l != '\0') && !ITEM_SEP(*l)) +				l++; +			} +		if (*l == '\0') break; /* done */ +		} + +	return(retval); +	} + +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, +		STACK_OF(SSL_CIPHER) **cipher_list, +		STACK_OF(SSL_CIPHER) **cipher_list_by_id, +		const char *rule_str) +	{ +	int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; +	unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl; +	STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list; +	const char *rule_p; +	CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; +	const SSL_CIPHER **ca_list = NULL; + +	/* +	 * Return with error if nothing to do. +	 */ +	if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL) +		return NULL; + +	/* +	 * To reduce the work to do we only want to process the compiled +	 * in algorithms, so we first get the mask of disabled ciphers. +	 */ +	ssl_cipher_get_disabled(&disabled_mkey, &disabled_auth, &disabled_enc, &disabled_mac, &disabled_ssl); + +	/* +	 * Now we have to collect the available ciphers from the compiled +	 * in ciphers. We cannot get more than the number compiled in, so +	 * it is used for allocation. +	 */ +	num_of_ciphers = ssl_method->num_ciphers(); +#ifdef KSSL_DEBUG +	printf("ssl_create_cipher_list() for %d ciphers\n", num_of_ciphers); +#endif    /* KSSL_DEBUG */ +	co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers); +	if (co_list == NULL) +		{ +		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); +		return(NULL);	/* Failure */ +		} + +	ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, +	                           disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl, +	                           co_list, &head, &tail); + + +	/* Now arrange all ciphers by preference: */ + +	/* Everything else being equal, prefer ephemeral ECDH over other key exchange mechanisms */ +	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); +	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); + +	/* AES is our preferred symmetric cipher */ +	ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + +	/* Temporarily enable everything else for sorting */ +	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + +	/* Low priority for MD5 */ +	ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head, &tail); + +	/* Move anonymous ciphers to the end.  Usually, these will remain disabled. +	 * (For applications that allow them, they aren't too bad, but we prefer +	 * authenticated ciphers.) */ +	ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + +	/* Move ciphers without forward secrecy to the end */ +	ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); +	/* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); */ +	ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); +	ssl_cipher_apply_rule(0, SSL_kPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); +	ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + +	/* RC4 is sort-of broken -- move the the end */ +	ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + +	/* Now sort by symmetric encryption strength.  The above ordering remains +	 * in force within each class */ +	if (!ssl_cipher_strength_sort(&head, &tail)) +		{ +		OPENSSL_free(co_list); +		return NULL; +		} + +	/* Now disable everything (maintaining the ordering!) */ +	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); + + +	/* +	 * We also need cipher aliases for selecting based on the rule_str. +	 * There might be two types of entries in the rule_str: 1) names +	 * of ciphers themselves 2) aliases for groups of ciphers. +	 * For 1) we need the available ciphers and for 2) the cipher +	 * groups of cipher_aliases added together in one list (otherwise +	 * we would be happy with just the cipher_aliases table). +	 */ +	num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER); +	num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1; +	ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max); +	if (ca_list == NULL) +		{ +		OPENSSL_free(co_list); +		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); +		return(NULL);	/* Failure */ +		} +	ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, +	                           disabled_mkey, disabled_auth, disabled_enc, +				   disabled_mac, disabled_ssl, head); + +	/* +	 * If the rule_string begins with DEFAULT, apply the default rule +	 * before using the (possibly available) additional rules. +	 */ +	ok = 1; +	rule_p = rule_str; +	if (strncmp(rule_str,"DEFAULT",7) == 0) +		{ +		ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, +			&head, &tail, ca_list); +		rule_p += 7; +		if (*rule_p == ':') +			rule_p++; +		} + +	if (ok && (strlen(rule_p) > 0)) +		ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list); + +	OPENSSL_free((void *)ca_list);	/* Not needed anymore */ + +	if (!ok) +		{	/* Rule processing failure */ +		OPENSSL_free(co_list); +		return(NULL); +		} +	 +	/* +	 * Allocate new "cipherstack" for the result, return with error +	 * if we cannot get one. +	 */ +	if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) +		{ +		OPENSSL_free(co_list); +		return(NULL); +		} + +	/* +	 * The cipher selection for the list is done. The ciphers are added +	 * to the resulting precedence to the STACK_OF(SSL_CIPHER). +	 */ +	for (curr = head; curr != NULL; curr = curr->next) +		{ +		if (curr->active) +			{ +			sk_SSL_CIPHER_push(cipherstack, curr->cipher); +#ifdef CIPHER_DEBUG +			printf("<%s>\n",curr->cipher->name); +#endif +			} +		} +	OPENSSL_free(co_list);	/* Not needed any longer */ + +	tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); +	if (tmp_cipher_list == NULL) +		{ +		sk_SSL_CIPHER_free(cipherstack); +		return NULL; +		} +	if (*cipher_list != NULL) +		sk_SSL_CIPHER_free(*cipher_list); +	*cipher_list = cipherstack; +	if (*cipher_list_by_id != NULL) +		sk_SSL_CIPHER_free(*cipher_list_by_id); +	*cipher_list_by_id = tmp_cipher_list; +	(void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp); + +	sk_SSL_CIPHER_sort(*cipher_list_by_id); +	return(cipherstack); +	} + +char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) +	{ +	int is_export,pkl,kl; +	const char *ver,*exp_str; +	const char *kx,*au,*enc,*mac; +	unsigned long alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl,alg2; +#ifdef KSSL_DEBUG +	static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s AL=%lx/%lx/%lx/%lx/%lx\n"; +#else +	static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n"; +#endif /* KSSL_DEBUG */ + +	alg_mkey = cipher->algorithm_mkey; +	alg_auth = cipher->algorithm_auth; +	alg_enc = cipher->algorithm_enc; +	alg_mac = cipher->algorithm_mac; +	alg_ssl = cipher->algorithm_ssl; + +	alg2=cipher->algorithm2; + +	is_export=SSL_C_IS_EXPORT(cipher); +	pkl=SSL_C_EXPORT_PKEYLENGTH(cipher); +	kl=SSL_C_EXPORT_KEYLENGTH(cipher); +	exp_str=is_export?" export":""; +	 +	if (alg_ssl & SSL_SSLV2) +		ver="SSLv2"; +	else if (alg_ssl & SSL_SSLV3) +		ver="SSLv3"; +	else +		ver="unknown"; + +	switch (alg_mkey) +		{ +	case SSL_kRSA: +		kx=is_export?(pkl == 512 ? "RSA(512)" : "RSA(1024)"):"RSA"; +		break; +	case SSL_kDHr: +		kx="DH/RSA"; +		break; +	case SSL_kDHd: +		kx="DH/DSS"; +		break; +        case SSL_kKRB5: +		kx="KRB5"; +		break; +	case SSL_kEDH: +		kx=is_export?(pkl == 512 ? "DH(512)" : "DH(1024)"):"DH"; +		break; +	case SSL_kECDHr: +		kx="ECDH/RSA"; +		break; +	case SSL_kECDHe: +		kx="ECDH/ECDSA"; +		break; +	case SSL_kEECDH: +		kx="ECDH"; +		break; +	case SSL_kPSK: +		kx="PSK"; +		break; +	default: +		kx="unknown"; +		} + +	switch (alg_auth) +		{ +	case SSL_aRSA: +		au="RSA"; +		break; +	case SSL_aDSS: +		au="DSS"; +		break; +	case SSL_aDH: +		au="DH"; +		break; +        case SSL_aKRB5: +		au="KRB5"; +		break; +        case SSL_aECDH: +		au="ECDH"; +		break; +	case SSL_aNULL: +		au="None"; +		break; +	case SSL_aECDSA: +		au="ECDSA"; +		break; +	case SSL_aPSK: +		au="PSK"; +		break; +	default: +		au="unknown"; +		break; +		} + +	switch (alg_enc) +		{ +	case SSL_DES: +		enc=(is_export && kl == 5)?"DES(40)":"DES(56)"; +		break; +	case SSL_3DES: +		enc="3DES(168)"; +		break; +	case SSL_RC4: +		enc=is_export?(kl == 5 ? "RC4(40)" : "RC4(56)") +		  :((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)"); +		break; +	case SSL_RC2: +		enc=is_export?(kl == 5 ? "RC2(40)" : "RC2(56)"):"RC2(128)"; +		break; +	case SSL_IDEA: +		enc="IDEA(128)"; +		break; +	case SSL_eNULL: +		enc="None"; +		break; +	case SSL_AES128: +		enc="AES(128)"; +		break; +	case SSL_AES256: +		enc="AES(256)"; +		break; +	case SSL_CAMELLIA128: +		enc="Camellia(128)"; +		break; +	case SSL_CAMELLIA256: +		enc="Camellia(256)"; +		break; +	case SSL_SEED: +		enc="SEED(128)"; +		break; +	default: +		enc="unknown"; +		break; +		} + +	switch (alg_mac) +		{ +	case SSL_MD5: +		mac="MD5"; +		break; +	case SSL_SHA1: +		mac="SHA1"; +		break; +	default: +		mac="unknown"; +		break; +		} + +	if (buf == NULL) +		{ +		len=128; +		buf=OPENSSL_malloc(len); +		if (buf == NULL) return("OPENSSL_malloc Error"); +		} +	else if (len < 128) +		return("Buffer too small"); + +#ifdef KSSL_DEBUG +	BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp_str,alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl); +#else +	BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp_str); +#endif /* KSSL_DEBUG */ +	return(buf); +	} + +char *SSL_CIPHER_get_version(const SSL_CIPHER *c) +	{ +	int i; + +	if (c == NULL) return("(NONE)"); +	i=(int)(c->id>>24L); +	if (i == 3) +		return("TLSv1/SSLv3"); +	else if (i == 2) +		return("SSLv2"); +	else +		return("unknown"); +	} + +/* return the actual cipher being used */ +const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) +	{ +	if (c != NULL) +		return(c->name); +	return("(NONE)"); +	} + +/* number of bits for symmetric cipher */ +int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits) +	{ +	int ret=0; + +	if (c != NULL) +		{ +		if (alg_bits != NULL) *alg_bits = c->alg_bits; +		ret = c->strength_bits; +		} +	return(ret); +	} + +/* return string version of key exchange algorithm */ +const char* SSL_CIPHER_authentication_method(const SSL_CIPHER* cipher) +	{ +	switch (cipher->algorithm_mkey) +		{ +	case SSL_kRSA: +		return SSL_TXT_RSA; +	case SSL_kDHr: +		return SSL_TXT_DH "_" SSL_TXT_RSA; +	case SSL_kDHd: +		return SSL_TXT_DH "_" SSL_TXT_DSS; +	case SSL_kEDH: +		switch (cipher->algorithm_auth) +			{ +		case SSL_aDSS: +			return "DHE_" SSL_TXT_DSS; +		case SSL_aRSA: +			return "DHE_" SSL_TXT_RSA; +		case SSL_aNULL: +			return SSL_TXT_DH "_anon"; +		default: +			return "UNKNOWN"; +                        } +	case SSL_kKRB5: +		return SSL_TXT_KRB5; +	case SSL_kECDHr: +		return SSL_TXT_ECDH "_" SSL_TXT_RSA; +	case SSL_kECDHe: +		return SSL_TXT_ECDH "_" SSL_TXT_ECDSA; +	case SSL_kEECDH: +		switch (cipher->algorithm_auth) +			{ +		case SSL_aECDSA: +			return "ECDHE_" SSL_TXT_ECDSA; +		case SSL_aRSA: +			return "ECDHE_" SSL_TXT_RSA; +		case SSL_aNULL: +			return SSL_TXT_ECDH "_anon"; +		default: +			return "UNKNOWN"; +                        } +        default: +		return "UNKNOWN"; +		} +	} + +SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n) +	{ +	SSL_COMP *ctmp; +	int i,nn; + +	if ((n == 0) || (sk == NULL)) return(NULL); +	nn=sk_SSL_COMP_num(sk); +	for (i=0; i<nn; i++) +		{ +		ctmp=sk_SSL_COMP_value(sk,i); +		if (ctmp->id == n) +			return(ctmp); +		} +	return(NULL); +	} + +#ifdef OPENSSL_NO_COMP +void *SSL_COMP_get_compression_methods(void) +	{ +	return NULL; +	} +int SSL_COMP_add_compression_method(int id, void *cm) +	{ +	return 1; +	} + +const char *SSL_COMP_get_name(const void *comp) +	{ +	return NULL; +	} +#else +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +	{ +	load_builtin_compressions(); +	return(ssl_comp_methods); +	} + +int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) +	{ +	SSL_COMP *comp; + +        if (cm == NULL || cm->type == NID_undef) +                return 1; + +	/* According to draft-ietf-tls-compression-04.txt, the +	   compression number ranges should be the following: + +	   0 to 63:    methods defined by the IETF +	   64 to 192:  external party methods assigned by IANA +	   193 to 255: reserved for private use */ +	if (id < 193 || id > 255) +		{ +		SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE); +		return 0; +		} + +	MemCheck_off(); +	comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP)); +	comp->id=id; +	comp->method=cm; +	load_builtin_compressions(); +	if (ssl_comp_methods +		&& sk_SSL_COMP_find(ssl_comp_methods,comp) >= 0) +		{ +		OPENSSL_free(comp); +		MemCheck_on(); +		SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,SSL_R_DUPLICATE_COMPRESSION_ID); +		return(1); +		} +	else if ((ssl_comp_methods == NULL) +		|| !sk_SSL_COMP_push(ssl_comp_methods,comp)) +		{ +		OPENSSL_free(comp); +		MemCheck_on(); +		SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,ERR_R_MALLOC_FAILURE); +		return(1); +		} +	else +		{ +		MemCheck_on(); +		return(0); +		} +	} + +const char *SSL_COMP_get_name(const COMP_METHOD *comp) +	{ +	if (comp) +		return comp->name; +	return NULL; +	} + +#endif diff --git a/main/openssl/ssl/ssl_err.c b/main/openssl/ssl/ssl_err.c new file mode 100644 index 00000000..8bff5905 --- /dev/null +++ b/main/openssl/ssl/ssl_err.c @@ -0,0 +1,575 @@ +/* ssl/ssl_err.c */ +/* ==================================================================== + * Copyright (c) 1999-2009 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include <stdio.h> +#include <openssl/err.h> +#include <openssl/ssl.h> + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +#define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0) +#define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason) + +static ERR_STRING_DATA SSL_str_functs[]= +	{ +{ERR_FUNC(SSL_F_CLIENT_CERTIFICATE),	"CLIENT_CERTIFICATE"}, +{ERR_FUNC(SSL_F_CLIENT_FINISHED),	"CLIENT_FINISHED"}, +{ERR_FUNC(SSL_F_CLIENT_HELLO),	"CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_CLIENT_MASTER_KEY),	"CLIENT_MASTER_KEY"}, +{ERR_FUNC(SSL_F_D2I_SSL_SESSION),	"d2i_SSL_SESSION"}, +{ERR_FUNC(SSL_F_DO_DTLS1_WRITE),	"DO_DTLS1_WRITE"}, +{ERR_FUNC(SSL_F_DO_SSL3_WRITE),	"DO_SSL3_WRITE"}, +{ERR_FUNC(SSL_F_DTLS1_ACCEPT),	"DTLS1_ACCEPT"}, +{ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF),	"DTLS1_ADD_CERT_TO_BUF"}, +{ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD),	"DTLS1_BUFFER_RECORD"}, +{ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO),	"DTLS1_CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_DTLS1_CONNECT),	"DTLS1_CONNECT"}, +{ERR_FUNC(SSL_F_DTLS1_ENC),	"DTLS1_ENC"}, +{ERR_FUNC(SSL_F_DTLS1_GET_HELLO_VERIFY),	"DTLS1_GET_HELLO_VERIFY"}, +{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE),	"DTLS1_GET_MESSAGE"}, +{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),	"DTLS1_GET_MESSAGE_FRAGMENT"}, +{ERR_FUNC(SSL_F_DTLS1_GET_RECORD),	"DTLS1_GET_RECORD"}, +{ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT),	"DTLS1_HANDLE_TIMEOUT"}, +{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),	"DTLS1_OUTPUT_CERT_CHAIN"}, +{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),	"DTLS1_PREPROCESS_FRAGMENT"}, +{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),	"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"}, +{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD),	"DTLS1_PROCESS_RECORD"}, +{ERR_FUNC(SSL_F_DTLS1_READ_BYTES),	"DTLS1_READ_BYTES"}, +{ERR_FUNC(SSL_F_DTLS1_READ_FAILED),	"DTLS1_READ_FAILED"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST),	"DTLS1_SEND_CERTIFICATE_REQUEST"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE),	"DTLS1_SEND_CLIENT_CERTIFICATE"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE),	"DTLS1_SEND_CLIENT_KEY_EXCHANGE"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY),	"DTLS1_SEND_CLIENT_VERIFY"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST),	"DTLS1_SEND_HELLO_VERIFY_REQUEST"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE),	"DTLS1_SEND_SERVER_CERTIFICATE"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO),	"DTLS1_SEND_SERVER_HELLO"}, +{ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE),	"DTLS1_SEND_SERVER_KEY_EXCHANGE"}, +{ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES),	"DTLS1_WRITE_APP_DATA_BYTES"}, +{ERR_FUNC(SSL_F_GET_CLIENT_FINISHED),	"GET_CLIENT_FINISHED"}, +{ERR_FUNC(SSL_F_GET_CLIENT_HELLO),	"GET_CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_GET_CLIENT_MASTER_KEY),	"GET_CLIENT_MASTER_KEY"}, +{ERR_FUNC(SSL_F_GET_SERVER_FINISHED),	"GET_SERVER_FINISHED"}, +{ERR_FUNC(SSL_F_GET_SERVER_HELLO),	"GET_SERVER_HELLO"}, +{ERR_FUNC(SSL_F_GET_SERVER_VERIFY),	"GET_SERVER_VERIFY"}, +{ERR_FUNC(SSL_F_I2D_SSL_SESSION),	"i2d_SSL_SESSION"}, +{ERR_FUNC(SSL_F_READ_N),	"READ_N"}, +{ERR_FUNC(SSL_F_REQUEST_CERTIFICATE),	"REQUEST_CERTIFICATE"}, +{ERR_FUNC(SSL_F_SERVER_FINISH),	"SERVER_FINISH"}, +{ERR_FUNC(SSL_F_SERVER_HELLO),	"SERVER_HELLO"}, +{ERR_FUNC(SSL_F_SERVER_VERIFY),	"SERVER_VERIFY"}, +{ERR_FUNC(SSL_F_SSL23_ACCEPT),	"SSL23_ACCEPT"}, +{ERR_FUNC(SSL_F_SSL23_CLIENT_HELLO),	"SSL23_CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_SSL23_CONNECT),	"SSL23_CONNECT"}, +{ERR_FUNC(SSL_F_SSL23_GET_CLIENT_HELLO),	"SSL23_GET_CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_SSL23_GET_SERVER_HELLO),	"SSL23_GET_SERVER_HELLO"}, +{ERR_FUNC(SSL_F_SSL23_PEEK),	"SSL23_PEEK"}, +{ERR_FUNC(SSL_F_SSL23_READ),	"SSL23_READ"}, +{ERR_FUNC(SSL_F_SSL23_WRITE),	"SSL23_WRITE"}, +{ERR_FUNC(SSL_F_SSL2_ACCEPT),	"SSL2_ACCEPT"}, +{ERR_FUNC(SSL_F_SSL2_CONNECT),	"SSL2_CONNECT"}, +{ERR_FUNC(SSL_F_SSL2_ENC_INIT),	"SSL2_ENC_INIT"}, +{ERR_FUNC(SSL_F_SSL2_GENERATE_KEY_MATERIAL),	"SSL2_GENERATE_KEY_MATERIAL"}, +{ERR_FUNC(SSL_F_SSL2_PEEK),	"SSL2_PEEK"}, +{ERR_FUNC(SSL_F_SSL2_READ),	"SSL2_READ"}, +{ERR_FUNC(SSL_F_SSL2_READ_INTERNAL),	"SSL2_READ_INTERNAL"}, +{ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE),	"SSL2_SET_CERTIFICATE"}, +{ERR_FUNC(SSL_F_SSL2_WRITE),	"SSL2_WRITE"}, +{ERR_FUNC(SSL_F_SSL3_ACCEPT),	"SSL3_ACCEPT"}, +{ERR_FUNC(SSL_F_SSL3_ADD_CERT_TO_BUF),	"SSL3_ADD_CERT_TO_BUF"}, +{ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL),	"SSL3_CALLBACK_CTRL"}, +{ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE),	"SSL3_CHANGE_CIPHER_STATE"}, +{ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),	"SSL3_CHECK_CERT_AND_ALGORITHM"}, +{ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO),	"SSL3_CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_SSL3_CONNECT),	"SSL3_CONNECT"}, +{ERR_FUNC(SSL_F_SSL3_CTRL),	"SSL3_CTRL"}, +{ERR_FUNC(SSL_F_SSL3_CTX_CTRL),	"SSL3_CTX_CTRL"}, +{ERR_FUNC(SSL_F_SSL3_DIGEST_CACHED_RECORDS),	"SSL3_DIGEST_CACHED_RECORDS"}, +{ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),	"SSL3_DO_CHANGE_CIPHER_SPEC"}, +{ERR_FUNC(SSL_F_SSL3_ENC),	"SSL3_ENC"}, +{ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),	"SSL3_GENERATE_KEY_BLOCK"}, +{ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),	"SSL3_GET_CERTIFICATE_REQUEST"}, +{ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS),	"SSL3_GET_CERT_STATUS"}, +{ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY),	"SSL3_GET_CERT_VERIFY"}, +{ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE),	"SSL3_GET_CLIENT_CERTIFICATE"}, +{ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO),	"SSL3_GET_CLIENT_HELLO"}, +{ERR_FUNC(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE),	"SSL3_GET_CLIENT_KEY_EXCHANGE"}, +{ERR_FUNC(SSL_F_SSL3_GET_FINISHED),	"SSL3_GET_FINISHED"}, +{ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE),	"SSL3_GET_KEY_EXCHANGE"}, +{ERR_FUNC(SSL_F_SSL3_GET_MESSAGE),	"SSL3_GET_MESSAGE"}, +{ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET),	"SSL3_GET_NEW_SESSION_TICKET"}, +{ERR_FUNC(SSL_F_SSL3_GET_NEXT_PROTO),	"SSL3_GET_NEXT_PROTO"}, +{ERR_FUNC(SSL_F_SSL3_GET_RECORD),	"SSL3_GET_RECORD"}, +{ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE),	"SSL3_GET_SERVER_CERTIFICATE"}, +{ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE),	"SSL3_GET_SERVER_DONE"}, +{ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO),	"SSL3_GET_SERVER_HELLO"}, +{ERR_FUNC(SSL_F_SSL3_HANDSHAKE_MAC),	"ssl3_handshake_mac"}, +{ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET),	"SSL3_NEW_SESSION_TICKET"}, +{ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN),	"SSL3_OUTPUT_CERT_CHAIN"}, +{ERR_FUNC(SSL_F_SSL3_PEEK),	"SSL3_PEEK"}, +{ERR_FUNC(SSL_F_SSL3_READ_BYTES),	"SSL3_READ_BYTES"}, +{ERR_FUNC(SSL_F_SSL3_READ_N),	"SSL3_READ_N"}, +{ERR_FUNC(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST),	"SSL3_SEND_CERTIFICATE_REQUEST"}, +{ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE),	"SSL3_SEND_CLIENT_CERTIFICATE"}, +{ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE),	"SSL3_SEND_CLIENT_KEY_EXCHANGE"}, +{ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY),	"SSL3_SEND_CLIENT_VERIFY"}, +{ERR_FUNC(SSL_F_SSL3_SEND_SERVER_CERTIFICATE),	"SSL3_SEND_SERVER_CERTIFICATE"}, +{ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO),	"SSL3_SEND_SERVER_HELLO"}, +{ERR_FUNC(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE),	"SSL3_SEND_SERVER_KEY_EXCHANGE"}, +{ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK),	"SSL3_SETUP_KEY_BLOCK"}, +{ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER),	"SSL3_SETUP_READ_BUFFER"}, +{ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER),	"SSL3_SETUP_WRITE_BUFFER"}, +{ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),	"SSL3_WRITE_BYTES"}, +{ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),	"SSL3_WRITE_PENDING"}, +{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"}, +{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),	"SSL_ADD_CLIENTHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),	"SSL_add_dir_cert_subjects_to_stack"}, +{ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),	"SSL_add_file_cert_subjects_to_stack"}, +{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"}, +{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),	"SSL_ADD_SERVERHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_BAD_METHOD),	"SSL_BAD_METHOD"}, +{ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),	"SSL_BYTES_TO_CIPHER_LIST"}, +{ERR_FUNC(SSL_F_SSL_CERT_DUP),	"SSL_CERT_DUP"}, +{ERR_FUNC(SSL_F_SSL_CERT_INST),	"SSL_CERT_INST"}, +{ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE),	"SSL_CERT_INSTANTIATE"}, +{ERR_FUNC(SSL_F_SSL_CERT_NEW),	"SSL_CERT_NEW"}, +{ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),	"SSL_check_private_key"}, +{ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),	"SSL_CHECK_SERVERHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG),	"SSL_CHECK_SRVR_ECC_CERT_AND_ALG"}, +{ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),	"SSL_CIPHER_PROCESS_RULESTR"}, +{ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT),	"SSL_CIPHER_STRENGTH_SORT"}, +{ERR_FUNC(SSL_F_SSL_CLEAR),	"SSL_clear"}, +{ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD),	"SSL_COMP_add_compression_method"}, +{ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST),	"SSL_CREATE_CIPHER_LIST"}, +{ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"}, +{ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"}, +{ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"}, +{ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"}, +{ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"}, +{ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"}, +{ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"}, +{ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"}, +{ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),	"SSL_CTX_use_psk_identity_hint"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"}, +{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"}, +{ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"}, +{ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"}, +{ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"}, +{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"}, +{ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"}, +{ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"}, +{ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"}, +{ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"}, +{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"}, +{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"}, +{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"}, +{ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"}, +{ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"}, +{ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"}, +{ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"}, +{ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"}, +{ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),	"SSL_SESS_CERT_NEW"}, +{ERR_FUNC(SSL_F_SSL_SET_CERT),	"SSL_SET_CERT"}, +{ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST),	"SSL_set_cipher_list"}, +{ERR_FUNC(SSL_F_SSL_SET_FD),	"SSL_set_fd"}, +{ERR_FUNC(SSL_F_SSL_SET_PKEY),	"SSL_SET_PKEY"}, +{ERR_FUNC(SSL_F_SSL_SET_PURPOSE),	"SSL_set_purpose"}, +{ERR_FUNC(SSL_F_SSL_SET_RFD),	"SSL_set_rfd"}, +{ERR_FUNC(SSL_F_SSL_SET_SESSION),	"SSL_set_session"}, +{ERR_FUNC(SSL_F_SSL_SET_SESSION_ID_CONTEXT),	"SSL_set_session_id_context"}, +{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT),	"SSL_set_session_ticket_ext"}, +{ERR_FUNC(SSL_F_SSL_SET_TRUST),	"SSL_set_trust"}, +{ERR_FUNC(SSL_F_SSL_SET_WFD),	"SSL_set_wfd"}, +{ERR_FUNC(SSL_F_SSL_SHUTDOWN),	"SSL_shutdown"}, +{ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION),	"SSL_UNDEFINED_CONST_FUNCTION"}, +{ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION),	"SSL_UNDEFINED_FUNCTION"}, +{ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION),	"SSL_UNDEFINED_VOID_FUNCTION"}, +{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE),	"SSL_use_certificate"}, +{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1),	"SSL_use_certificate_ASN1"}, +{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE),	"SSL_use_certificate_file"}, +{ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY),	"SSL_use_PrivateKey"}, +{ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1),	"SSL_use_PrivateKey_ASN1"}, +{ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE),	"SSL_use_PrivateKey_file"}, +{ERR_FUNC(SSL_F_SSL_USE_PSK_IDENTITY_HINT),	"SSL_use_psk_identity_hint"}, +{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY),	"SSL_use_RSAPrivateKey"}, +{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),	"SSL_use_RSAPrivateKey_ASN1"}, +{ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),	"SSL_use_RSAPrivateKey_file"}, +{ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN),	"SSL_VERIFY_CERT_CHAIN"}, +{ERR_FUNC(SSL_F_SSL_WRITE),	"SSL_write"}, +{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC),	"tls1_cert_verify_mac"}, +{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"TLS1_CHANGE_CIPHER_STATE"}, +{ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT),	"TLS1_CHECK_SERVERHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"}, +{ERR_FUNC(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT),	"TLS1_PREPARE_CLIENTHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT),	"TLS1_PREPARE_SERVERHELLO_TLSEXT"}, +{ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"}, +{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"}, +{ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"}, +{0,NULL} +	}; + +static ERR_STRING_DATA SSL_str_reasons[]= +	{ +{ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) ,"app data in handshake"}, +{ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),"attempt to reuse session in different context"}, +{ERR_REASON(SSL_R_BAD_ALERT_RECORD)      ,"bad alert record"}, +{ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE),"bad authentication type"}, +{ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC),"bad change cipher spec"}, +{ERR_REASON(SSL_R_BAD_CHECKSUM)          ,"bad checksum"}, +{ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK),"bad data returned by callback"}, +{ERR_REASON(SSL_R_BAD_DECOMPRESSION)     ,"bad decompression"}, +{ERR_REASON(SSL_R_BAD_DH_G_LENGTH)       ,"bad dh g length"}, +{ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH) ,"bad dh pub key length"}, +{ERR_REASON(SSL_R_BAD_DH_P_LENGTH)       ,"bad dh p length"}, +{ERR_REASON(SSL_R_BAD_DIGEST_LENGTH)     ,"bad digest length"}, +{ERR_REASON(SSL_R_BAD_DSA_SIGNATURE)     ,"bad dsa signature"}, +{ERR_REASON(SSL_R_BAD_ECC_CERT)          ,"bad ecc cert"}, +{ERR_REASON(SSL_R_BAD_ECDSA_SIGNATURE)   ,"bad ecdsa signature"}, +{ERR_REASON(SSL_R_BAD_ECPOINT)           ,"bad ecpoint"}, +{ERR_REASON(SSL_R_BAD_HANDSHAKE_LENGTH)  ,"bad handshake length"}, +{ERR_REASON(SSL_R_BAD_HELLO_REQUEST)     ,"bad hello request"}, +{ERR_REASON(SSL_R_BAD_LENGTH)            ,"bad length"}, +{ERR_REASON(SSL_R_BAD_MAC_DECODE)        ,"bad mac decode"}, +{ERR_REASON(SSL_R_BAD_MAC_LENGTH)        ,"bad mac length"}, +{ERR_REASON(SSL_R_BAD_MESSAGE_TYPE)      ,"bad message type"}, +{ERR_REASON(SSL_R_BAD_PACKET_LENGTH)     ,"bad packet length"}, +{ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),"bad protocol version number"}, +{ERR_REASON(SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH),"bad psk identity hint length"}, +{ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) ,"bad response argument"}, +{ERR_REASON(SSL_R_BAD_RSA_DECRYPT)       ,"bad rsa decrypt"}, +{ERR_REASON(SSL_R_BAD_RSA_ENCRYPT)       ,"bad rsa encrypt"}, +{ERR_REASON(SSL_R_BAD_RSA_E_LENGTH)      ,"bad rsa e length"}, +{ERR_REASON(SSL_R_BAD_RSA_MODULUS_LENGTH),"bad rsa modulus length"}, +{ERR_REASON(SSL_R_BAD_RSA_SIGNATURE)     ,"bad rsa signature"}, +{ERR_REASON(SSL_R_BAD_SIGNATURE)         ,"bad signature"}, +{ERR_REASON(SSL_R_BAD_SSL_FILETYPE)      ,"bad ssl filetype"}, +{ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH),"bad ssl session id length"}, +{ERR_REASON(SSL_R_BAD_STATE)             ,"bad state"}, +{ERR_REASON(SSL_R_BAD_WRITE_RETRY)       ,"bad write retry"}, +{ERR_REASON(SSL_R_BIO_NOT_SET)           ,"bio not set"}, +{ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),"block cipher pad is wrong"}, +{ERR_REASON(SSL_R_BN_LIB)                ,"bn lib"}, +{ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH) ,"ca dn length mismatch"}, +{ERR_REASON(SSL_R_CA_DN_TOO_LONG)        ,"ca dn too long"}, +{ERR_REASON(SSL_R_CCS_RECEIVED_EARLY)    ,"ccs received early"}, +{ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),"certificate verify failed"}, +{ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH)  ,"cert length mismatch"}, +{ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT),"challenge is different"}, +{ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"}, +{ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"}, +{ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"}, +{ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)    ,"clienthello tlsext"}, +{ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"}, +{ERR_REASON(SSL_R_COMPRESSION_DISABLED)  ,"compression disabled"}, +{ERR_REASON(SSL_R_COMPRESSION_FAILURE)   ,"compression failure"}, +{ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"}, +{ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),"compression library error"}, +{ERR_REASON(SSL_R_CONNECTION_ID_IS_DIFFERENT),"connection id is different"}, +{ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET),"connection type not set"}, +{ERR_REASON(SSL_R_COOKIE_MISMATCH)       ,"cookie mismatch"}, +{ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),"data between ccs and finished"}, +{ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG)  ,"data length too long"}, +{ERR_REASON(SSL_R_DECRYPTION_FAILED)     ,"decryption failed"}, +{ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"}, +{ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"}, +{ERR_REASON(SSL_R_DIGEST_CHECK_FAILED)   ,"digest check failed"}, +{ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG)  ,"dtls message too big"}, +{ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID),"duplicate compression id"}, +{ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT),"ecc cert not for key agreement"}, +{ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_SIGNING),"ecc cert not for signing"}, +{ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE),"ecc cert should have rsa signature"}, +{ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE),"ecc cert should have sha1 signature"}, +{ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER),"ecgroup too large for cipher"}, +{ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG),"encrypted length too long"}, +{ERR_REASON(SSL_R_ERROR_GENERATING_TMP_RSA_KEY),"error generating tmp rsa key"}, +{ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),"error in received cipher list"}, +{ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE),"excessive message size"}, +{ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) ,"extra data in message"}, +{ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS),"got a fin before a ccs"}, +{ERR_REASON(SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS),"got next proto before a ccs"}, +{ERR_REASON(SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION),"got next proto without seeing extension"}, +{ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST)   ,"https proxy request"}, +{ERR_REASON(SSL_R_HTTP_REQUEST)          ,"http request"}, +{ERR_REASON(SSL_R_ILLEGAL_PADDING)       ,"illegal padding"}, +{ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"}, +{ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"}, +{ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"}, +{ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM),"invalid compression algorithm"}, +{ERR_REASON(SSL_R_INVALID_PURPOSE)       ,"invalid purpose"}, +{ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE),"invalid status response"}, +{ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),"invalid ticket keys length"}, +{ERR_REASON(SSL_R_INVALID_TRUST)         ,"invalid trust"}, +{ERR_REASON(SSL_R_KEY_ARG_TOO_LONG)      ,"key arg too long"}, +{ERR_REASON(SSL_R_KRB5)                  ,"krb5"}, +{ERR_REASON(SSL_R_KRB5_C_CC_PRINC)       ,"krb5 client cc principal (no tkt?)"}, +{ERR_REASON(SSL_R_KRB5_C_GET_CRED)       ,"krb5 client get cred"}, +{ERR_REASON(SSL_R_KRB5_C_INIT)           ,"krb5 client init"}, +{ERR_REASON(SSL_R_KRB5_C_MK_REQ)         ,"krb5 client mk_req (expired tkt?)"}, +{ERR_REASON(SSL_R_KRB5_S_BAD_TICKET)     ,"krb5 server bad ticket"}, +{ERR_REASON(SSL_R_KRB5_S_INIT)           ,"krb5 server init"}, +{ERR_REASON(SSL_R_KRB5_S_RD_REQ)         ,"krb5 server rd_req (keytab perms?)"}, +{ERR_REASON(SSL_R_KRB5_S_TKT_EXPIRED)    ,"krb5 server tkt expired"}, +{ERR_REASON(SSL_R_KRB5_S_TKT_NYV)        ,"krb5 server tkt not yet valid"}, +{ERR_REASON(SSL_R_KRB5_S_TKT_SKEW)       ,"krb5 server tkt skew"}, +{ERR_REASON(SSL_R_LENGTH_MISMATCH)       ,"length mismatch"}, +{ERR_REASON(SSL_R_LENGTH_TOO_SHORT)      ,"length too short"}, +{ERR_REASON(SSL_R_LIBRARY_BUG)           ,"library bug"}, +{ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS),"library has no ciphers"}, +{ERR_REASON(SSL_R_MESSAGE_TOO_LONG)      ,"message too long"}, +{ERR_REASON(SSL_R_MISSING_DH_DSA_CERT)   ,"missing dh dsa cert"}, +{ERR_REASON(SSL_R_MISSING_DH_KEY)        ,"missing dh key"}, +{ERR_REASON(SSL_R_MISSING_DH_RSA_CERT)   ,"missing dh rsa cert"}, +{ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT),"missing dsa signing cert"}, +{ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY),"missing export tmp dh key"}, +{ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY),"missing export tmp rsa key"}, +{ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE),"missing rsa certificate"}, +{ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),"missing rsa encrypting cert"}, +{ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT),"missing rsa signing cert"}, +{ERR_REASON(SSL_R_MISSING_TMP_DH_KEY)    ,"missing tmp dh key"}, +{ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY)  ,"missing tmp ecdh key"}, +{ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY)   ,"missing tmp rsa key"}, +{ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY)  ,"missing tmp rsa pkey"}, +{ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"}, +{ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"}, +{ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"}, +{ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"}, +{ERR_REASON(SSL_R_NO_CERTIFICATE_RETURNED),"no certificate returned"}, +{ERR_REASON(SSL_R_NO_CERTIFICATE_SET)    ,"no certificate set"}, +{ERR_REASON(SSL_R_NO_CERTIFICATE_SPECIFIED),"no certificate specified"}, +{ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE)  ,"no ciphers available"}, +{ERR_REASON(SSL_R_NO_CIPHERS_PASSED)     ,"no ciphers passed"}, +{ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED)  ,"no ciphers specified"}, +{ERR_REASON(SSL_R_NO_CIPHER_LIST)        ,"no cipher list"}, +{ERR_REASON(SSL_R_NO_CIPHER_MATCH)       ,"no cipher match"}, +{ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) ,"no client cert method"}, +{ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED),"no client cert received"}, +{ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED),"no compression specified"}, +{ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER),"Peer haven't sent GOST certificate, required for selected ciphersuite"}, +{ERR_REASON(SSL_R_NO_METHOD_SPECIFIED)   ,"no method specified"}, +{ERR_REASON(SSL_R_NO_PRIVATEKEY)         ,"no privatekey"}, +{ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED),"no private key assigned"}, +{ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE),"no protocols available"}, +{ERR_REASON(SSL_R_NO_PUBLICKEY)          ,"no publickey"}, +{ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"}, +{ERR_REASON(SSL_R_NO_REQUIRED_DIGEST)    ,"digest requred for handshake isn't computed"}, +{ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"}, +{ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"}, +{ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"}, +{ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"}, +{ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"}, +{ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),"old session compression algorithm not returned"}, +{ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"}, +{ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),"opaque PRF input too long"}, +{ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"}, +{ERR_REASON(SSL_R_PARSE_TLSEXT)          ,"parse tlsext"}, +{ERR_REASON(SSL_R_PATH_TOO_LONG)         ,"path too long"}, +{ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"}, +{ERR_REASON(SSL_R_PEER_ERROR)            ,"peer error"}, +{ERR_REASON(SSL_R_PEER_ERROR_CERTIFICATE),"peer error certificate"}, +{ERR_REASON(SSL_R_PEER_ERROR_NO_CERTIFICATE),"peer error no certificate"}, +{ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER)  ,"peer error no cipher"}, +{ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE),"peer error unsupported certificate type"}, +{ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG),"pre mac length too long"}, +{ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS),"problems mapping cipher functions"}, +{ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN)  ,"protocol is shutdown"}, +{ERR_REASON(SSL_R_PSK_IDENTITY_NOT_FOUND),"psk identity not found"}, +{ERR_REASON(SSL_R_PSK_NO_CLIENT_CB)      ,"psk no client cb"}, +{ERR_REASON(SSL_R_PSK_NO_SERVER_CB)      ,"psk no server cb"}, +{ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR),"public key encrypt error"}, +{ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) ,"public key is not rsa"}, +{ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"}, +{ERR_REASON(SSL_R_READ_BIO_NOT_SET)      ,"read bio not set"}, +{ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED)  ,"read timeout expired"}, +{ERR_REASON(SSL_R_READ_WRONG_PACKET_TYPE),"read wrong packet type"}, +{ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH),"record length mismatch"}, +{ERR_REASON(SSL_R_RECORD_TOO_LARGE)      ,"record too large"}, +{ERR_REASON(SSL_R_RECORD_TOO_SMALL)      ,"record too small"}, +{ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG),"renegotiate ext too long"}, +{ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),"renegotiation encoding err"}, +{ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH),"renegotiation mismatch"}, +{ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING),"required cipher missing"}, +{ERR_REASON(SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING),"required compresssion algorithm missing"}, +{ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"}, +{ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"}, +{ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"}, +{ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"}, +{ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"}, +{ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"}, +{ERR_REASON(SSL_R_SESSION_MAY_NOT_BE_CREATED),"session may not be created"}, +{ERR_REASON(SSL_R_SHORT_READ)            ,"short read"}, +{ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"}, +{ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"}, +{ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"}, +{ERR_REASON(SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT),"ssl3 ext invalid ecpointformat"}, +{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"}, +{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"}, +{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"}, +{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC),"sslv3 alert bad record mac"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED),"sslv3 alert certificate expired"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED),"sslv3 alert certificate revoked"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN),"sslv3 alert certificate unknown"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE),"sslv3 alert decompression failure"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE),"sslv3 alert handshake failure"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER),"sslv3 alert illegal parameter"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE),"sslv3 alert no certificate"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE),"sslv3 alert unexpected message"}, +{ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE),"sslv3 alert unsupported certificate"}, +{ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION),"ssl ctx has no default ssl version"}, +{ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE) ,"ssl handshake failure"}, +{ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS),"ssl library has no ciphers"}, +{ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED),"ssl session id callback failed"}, +{ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT),"ssl session id conflict"}, +{ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG),"ssl session id context too long"}, +{ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH),"ssl session id has bad length"}, +{ERR_REASON(SSL_R_SSL_SESSION_ID_IS_DIFFERENT),"ssl session id is different"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED),"tlsv1 alert access denied"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR),"tlsv1 alert decode error"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),"tlsv1 alert decryption failed"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),"tlsv1 alert decrypt error"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),"tlsv1 alert export restriction"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),"tlsv1 alert insufficient security"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),"tlsv1 alert internal error"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),"tlsv1 alert no renegotiation"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION),"tlsv1 alert protocol version"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"}, +{ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"}, +{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"}, +{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"}, +{ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"}, +{ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"}, +{ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"}, +{ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"}, +{ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"}, +{ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"}, +{ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"}, +{ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"}, +{ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS),"unable to decode dh certs"}, +{ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS),"unable to decode ecdh certs"}, +{ERR_REASON(SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY),"unable to extract public key"}, +{ERR_REASON(SSL_R_UNABLE_TO_FIND_DH_PARAMETERS),"unable to find dh parameters"}, +{ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),"unable to find ecdh parameters"}, +{ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),"unable to find public key parameters"}, +{ERR_REASON(SSL_R_UNABLE_TO_FIND_SSL_METHOD),"unable to find ssl method"}, +{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES),"unable to load ssl2 md5 routines"}, +{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES),"unable to load ssl3 md5 routines"}, +{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),"unable to load ssl3 sha1 routines"}, +{ERR_REASON(SSL_R_UNEXPECTED_MESSAGE)    ,"unexpected message"}, +{ERR_REASON(SSL_R_UNEXPECTED_RECORD)     ,"unexpected record"}, +{ERR_REASON(SSL_R_UNINITIALIZED)         ,"uninitialized"}, +{ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE)    ,"unknown alert type"}, +{ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"}, +{ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"}, +{ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE)   ,"unknown cipher type"}, +{ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),"unknown key exchange type"}, +{ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE)     ,"unknown pkey type"}, +{ERR_REASON(SSL_R_UNKNOWN_PROTOCOL)      ,"unknown protocol"}, +{ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE),"unknown remote error type"}, +{ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION)   ,"unknown ssl version"}, +{ERR_REASON(SSL_R_UNKNOWN_STATE)         ,"unknown state"}, +{ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),"unsafe legacy renegotiation disabled"}, +{ERR_REASON(SSL_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"}, +{ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"}, +{ERR_REASON(SSL_R_UNSUPPORTED_DIGEST_TYPE),"unsupported digest type"}, +{ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),"unsupported elliptic curve"}, +{ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL)  ,"unsupported protocol"}, +{ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION),"unsupported ssl version"}, +{ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"}, +{ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"}, +{ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"}, +{ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"}, +{ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS),"wrong number of key bits"}, +{ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"}, +{ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE)  ,"wrong signature size"}, +{ERR_REASON(SSL_R_WRONG_SSL_VERSION)     ,"wrong ssl version"}, +{ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"}, +{ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"}, +{ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"}, +{0,NULL} +	}; + +#endif + +void ERR_load_SSL_strings(void) +	{ +#ifndef OPENSSL_NO_ERR + +	if (ERR_func_error_string(SSL_str_functs[0].error) == NULL) +		{ +		ERR_load_strings(0,SSL_str_functs); +		ERR_load_strings(0,SSL_str_reasons); +		} +#endif +	} diff --git a/main/openssl/ssl/ssl_err2.c b/main/openssl/ssl/ssl_err2.c new file mode 100644 index 00000000..ea95a5f9 --- /dev/null +++ b/main/openssl/ssl/ssl_err2.c @@ -0,0 +1,70 @@ +/* ssl/ssl_err2.c */ +/* Copyright (C) 1995-1998 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 <openssl/err.h> +#include <openssl/ssl.h> + +void SSL_load_error_strings(void) +	{ +#ifndef OPENSSL_NO_ERR +	ERR_load_crypto_strings(); +	ERR_load_SSL_strings(); +#endif +	} + diff --git a/main/openssl/ssl/ssl_lib.c b/main/openssl/ssl/ssl_lib.c new file mode 100644 index 00000000..b169ba93 --- /dev/null +++ b/main/openssl/ssl/ssl_lib.c @@ -0,0 +1,3242 @@ +/*! \file ssl/ssl_lib.c + *  \brief Version independent SSL functions. + */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifdef REF_CHECK +#  include <assert.h> +#endif +#include <stdio.h> +#include "ssl_locl.h" +#include "kssl_lcl.h" +#include <openssl/objects.h> +#include <openssl/lhash.h> +#include <openssl/x509v3.h> +#include <openssl/rand.h> +#include <openssl/ocsp.h> +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif +#ifndef OPENSSL_NO_ENGINE +#include <openssl/engine.h> +#endif + +const char *SSL_version_str=OPENSSL_VERSION_TEXT; + +SSL3_ENC_METHOD ssl3_undef_enc_method={ +	/* evil casts, but these functions are only called if there's a library bug */ +	(int (*)(SSL *,int))ssl_undefined_function, +	(int (*)(SSL *, unsigned char *, int))ssl_undefined_function, +	ssl_undefined_function, +	(int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function, +	(int (*)(SSL*, int))ssl_undefined_function, +	(int (*)(SSL *,  const char*, int, unsigned char *))ssl_undefined_function, +	0,	/* finish_mac_length */ +	(int (*)(SSL *, int, unsigned char *))ssl_undefined_function, +	NULL,	/* client_finished_label */ +	0,	/* client_finished_label_len */ +	NULL,	/* server_finished_label */ +	0,	/* server_finished_label_len */ +	(int (*)(int))ssl_undefined_function +	}; + +int SSL_clear(SSL *s) +	{ + +	if (s->method == NULL) +		{ +		SSLerr(SSL_F_SSL_CLEAR,SSL_R_NO_METHOD_SPECIFIED); +		return(0); +		} + +	if (ssl_clear_bad_session(s)) +		{ +		SSL_SESSION_free(s->session); +		s->session=NULL; +		} + +	s->error=0; +	s->hit=0; +	s->shutdown=0; + +#if 0 /* Disabled since version 1.10 of this file (early return not +       * needed because SSL_clear is not called when doing renegotiation) */ +	/* 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(1); +#else +	if (s->new_session) +		{ +		SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR); +		return 0; +		} +#endif + +	s->type=0; + +	s->state=SSL_ST_BEFORE|((s->server)?SSL_ST_ACCEPT:SSL_ST_CONNECT); + +	s->version=s->method->version; +	s->client_version=s->version; +	s->rwstate=SSL_NOTHING; +	s->rstate=SSL_ST_READ_HEADER; +#if 0 +	s->read_ahead=s->ctx->read_ahead; +#endif + +	if (s->init_buf != NULL) +		{ +		BUF_MEM_free(s->init_buf); +		s->init_buf=NULL; +		} + +	ssl_clear_cipher_ctx(s); +	ssl_clear_hash_ctx(&s->read_hash); +	ssl_clear_hash_ctx(&s->write_hash); + +	s->first_packet=0; + +#if 1 +	/* Check to see if we were changed into a different method, if +	 * so, revert back if we are not doing session-id reuse. */ +	if (!s->in_handshake && (s->session == NULL) && (s->method != s->ctx->method)) +		{ +		s->method->ssl_free(s); +		s->method=s->ctx->method; +		if (!s->method->ssl_new(s)) +			return(0); +		} +	else +#endif +		s->method->ssl_clear(s); +	return(1); +	} + +/** Used to change an SSL_CTXs default SSL method type */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth) +	{ +	STACK_OF(SSL_CIPHER) *sk; + +	ctx->method=meth; + +	sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list), +		&(ctx->cipher_list_by_id), +		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); +	if ((sk == NULL) || (sk_SSL_CIPHER_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(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 *)OPENSSL_malloc(sizeof(SSL)); +	if (s == NULL) goto err; +	memset(s,0,sizeof(SSL)); + +#ifndef	OPENSSL_NO_KRB5 +	s->kssl_ctx = kssl_ctx_new(); +#endif	/* OPENSSL_NO_KRB5 */ + +	s->options=ctx->options; +	s->mode=ctx->mode; +	s->max_cert_list=ctx->max_cert_list; + +	if (ctx->cert != NULL) +		{ +		/* Earlier library versions used to copy the pointer to +		 * the CERT, not its contents; only when setting new +		 * parameters for the per-SSL copy, ssl_cert_new would be +		 * called (and the direct reference to the per-SSL_CTX +		 * settings would be lost, but those still were indirectly +		 * accessed for various purposes, and for that reason they +		 * used to be known as s->ctx->default_cert). +		 * Now we don't look at the SSL_CTX's CERT after having +		 * duplicated it once. */ + +		s->cert = ssl_cert_dup(ctx->cert); +		if (s->cert == NULL) +			goto err; +		} +	else +		s->cert=NULL; /* Cannot really happen (see SSL_CTX_new) */ + +	s->read_ahead=ctx->read_ahead; +	s->msg_callback=ctx->msg_callback; +	s->msg_callback_arg=ctx->msg_callback_arg; +	s->verify_mode=ctx->verify_mode; +#if 0 +	s->verify_depth=ctx->verify_depth; +#endif +	s->sid_ctx_length=ctx->sid_ctx_length; +	OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx); +	memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx)); +	s->verify_callback=ctx->default_verify_callback; +	s->session_creation_enabled=1; +	s->generate_session_id=ctx->generate_session_id; + +	s->param = X509_VERIFY_PARAM_new(); +	if (!s->param) +		goto err; +	X509_VERIFY_PARAM_inherit(s->param, ctx->param); +#if 0 +	s->purpose = ctx->purpose; +	s->trust = ctx->trust; +#endif +	s->quiet_shutdown=ctx->quiet_shutdown; +	s->max_send_fragment = ctx->max_send_fragment; + +	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); +	s->ctx=ctx; +#ifndef OPENSSL_NO_TLSEXT +	s->tlsext_debug_cb = 0; +	s->tlsext_debug_arg = NULL; +	s->tlsext_ticket_expected = 0; +	s->tlsext_status_type = -1; +	s->tlsext_status_expected = 0; +	s->tlsext_ocsp_ids = NULL; +	s->tlsext_ocsp_exts = NULL; +	s->tlsext_ocsp_resp = NULL; +	s->tlsext_ocsp_resplen = -1; +	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); +	s->initial_ctx=ctx; +# ifndef OPENSSL_NO_NEXTPROTONEG +	s->next_proto_negotiated = NULL; +# endif +#endif + +	s->verify_result=X509_V_OK; + +	s->method=ctx->method; + +	if (!s->method->ssl_new(s)) +		goto err; + +	s->references=1; +	s->server=(ctx->method->ssl_accept == ssl_undefined_function)?0:1; + +	SSL_clear(s); + +	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + +#ifndef OPENSSL_NO_PSK +	s->psk_client_callback=ctx->psk_client_callback; +	s->psk_server_callback=ctx->psk_server_callback; +#endif + +	return(s); +err: +	if (s != NULL) +		{ +		if (s->cert != NULL) +			ssl_cert_free(s->cert); +		if (s->ctx != NULL) +			SSL_CTX_free(s->ctx); /* decrement reference count */ +		OPENSSL_free(s); +		} +	SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE); +	return(NULL); +	} + +int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx, +				   unsigned int sid_ctx_len) +    { +    if(sid_ctx_len > sizeof ctx->sid_ctx) +	{ +	SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); +	return 0; +	} +    ctx->sid_ctx_length=sid_ctx_len; +    memcpy(ctx->sid_ctx,sid_ctx,sid_ctx_len); + +    return 1; +    } + +int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx, +			       unsigned int sid_ctx_len) +    { +    if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) +	{ +	SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); +	return 0; +	} +    ssl->sid_ctx_length=sid_ctx_len; +    memcpy(ssl->sid_ctx,sid_ctx,sid_ctx_len); + +    return 1; +    } + +int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) +	{ +	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +	ctx->generate_session_id = cb; +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +	return 1; +	} + +int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) +	{ +	CRYPTO_w_lock(CRYPTO_LOCK_SSL); +	ssl->generate_session_id = cb; +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL); +	return 1; +	} + +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, +				unsigned int id_len) +	{ +	/* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how +	 * we can "construct" a session to give us the desired check - ie. to +	 * find if there's a session in the hash table that would conflict with +	 * any new session built out of this id/id_len and the ssl_version in +	 * use by this SSL. */ +	SSL_SESSION r, *p; + +	if(id_len > sizeof r.session_id) +		return 0; + +	r.ssl_version = ssl->version; +	r.session_id_length = id_len; +	memcpy(r.session_id, id, id_len); +	/* NB: SSLv2 always uses a fixed 16-byte session ID, so even if a +	 * callback is calling us to check the uniqueness of a shorter ID, it +	 * must be compared as a padded-out ID because that is what it will be +	 * converted to when the callback has finished choosing it. */ +	if((r.ssl_version == SSL2_VERSION) && +			(id_len < SSL2_SSL_SESSION_ID_LENGTH)) +		{ +		memset(r.session_id + id_len, 0, +			SSL2_SSL_SESSION_ID_LENGTH - id_len); +		r.session_id_length = SSL2_SSL_SESSION_ID_LENGTH; +		} + +	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); +	p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r); +	CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); +	return (p != NULL); +	} + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) +	{ +	return X509_VERIFY_PARAM_set_purpose(s->param, purpose); +	} + +int SSL_set_purpose(SSL *s, int purpose) +	{ +	return X509_VERIFY_PARAM_set_purpose(s->param, purpose); +	} + +int SSL_CTX_set_trust(SSL_CTX *s, int trust) +	{ +	return X509_VERIFY_PARAM_set_trust(s->param, trust); +	} + +int SSL_set_trust(SSL *s, int trust) +	{ +	return X509_VERIFY_PARAM_set_trust(s->param, trust); +	} + +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) +	{ +	return X509_VERIFY_PARAM_set1(ctx->param, vpm); +	} + +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) +	{ +	return X509_VERIFY_PARAM_set1(ssl->param, vpm); +	} + +void SSL_free(SSL *s) +	{ +	int i; + +	if(s == NULL) +	    return; + +	i=CRYPTO_add(&s->references,-1,CRYPTO_LOCK_SSL); +#ifdef REF_PRINT +	REF_PRINT("SSL",s); +#endif +	if (i > 0) return; +#ifdef REF_CHECK +	if (i < 0) +		{ +		fprintf(stderr,"SSL_free, bad reference count\n"); +		abort(); /* ok */ +		} +#endif + +	if (s->param) +		X509_VERIFY_PARAM_free(s->param); + +	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + +	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); +		s->bbio=NULL; +		} +	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_SSL_CIPHER_free(s->cipher_list); +	if (s->cipher_list_by_id != NULL) sk_SSL_CIPHER_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); +	ssl_clear_hash_ctx(&s->read_hash); +	ssl_clear_hash_ctx(&s->write_hash); + +	if (s->cert != NULL) ssl_cert_free(s->cert); +	/* Free up if allocated */ + +#ifndef OPENSSL_NO_TLSEXT +	if (s->tlsext_hostname) +		OPENSSL_free(s->tlsext_hostname); +	if (s->initial_ctx) SSL_CTX_free(s->initial_ctx); +#ifndef OPENSSL_NO_EC +	if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist); +	if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist); +#endif /* OPENSSL_NO_EC */ +	if (s->tlsext_opaque_prf_input) OPENSSL_free(s->tlsext_opaque_prf_input); +	if (s->tlsext_ocsp_exts) +		sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, +						X509_EXTENSION_free); +	if (s->tlsext_ocsp_ids) +		sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free); +	if (s->tlsext_ocsp_resp) +		OPENSSL_free(s->tlsext_ocsp_resp); +#endif + +	if (s->client_CA != NULL) +		sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free); + +	if (s->method != NULL) s->method->ssl_free(s); + +	if (s->ctx) SSL_CTX_free(s->ctx); + +#ifndef	OPENSSL_NO_KRB5 +	if (s->kssl_ctx != NULL) +		kssl_ctx_free(s->kssl_ctx); +#endif	/* OPENSSL_NO_KRB5 */ + +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +	if (s->next_proto_negotiated) +		OPENSSL_free(s->next_proto_negotiated); +#endif + +	OPENSSL_free(s); +	} + +void SSL_set_bio(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(const SSL *s) +	{ return(s->rbio); } + +BIO *SSL_get_wbio(const SSL *s) +	{ return(s->wbio); } + +int SSL_get_fd(const SSL *s) +	{ +	return(SSL_get_rfd(s)); +	} + +int SSL_get_rfd(const 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); +	} + +int SSL_get_wfd(const SSL *s) +	{ +	int ret= -1; +	BIO *b,*r; + +	b=SSL_get_wbio(s); +	r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR); +	if (r != NULL) +		BIO_get_fd(r,&ret); +	return(ret); +	} + +#ifndef OPENSSL_NO_SOCK +int SSL_set_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(SSL *s,int fd) +	{ +	int ret=0; +	BIO *bio=NULL; + +	if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_SOCKET) +		|| ((int)BIO_get_fd(s->rbio,NULL) != fd)) +		{ +		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); +		} +	else +		SSL_set_bio(s,SSL_get_rbio(s),SSL_get_rbio(s)); +	ret=1; +err: +	return(ret); +	} + +int SSL_set_rfd(SSL *s,int fd) +	{ +	int ret=0; +	BIO *bio=NULL; + +	if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_SOCKET) +		|| ((int)BIO_get_fd(s->wbio,NULL) != fd)) +		{ +		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)); +		} +	else +		SSL_set_bio(s,SSL_get_wbio(s),SSL_get_wbio(s)); +	ret=1; +err: +	return(ret); +	} +#endif + + +/* return length of latest Finished message we sent, copy to 'buf' */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count) +	{ +	size_t ret = 0; +	 +	if (s->s3 != NULL) +		{ +		ret = s->s3->tmp.finish_md_len; +		if (count > ret) +			count = ret; +		memcpy(buf, s->s3->tmp.finish_md, count); +		} +	return ret; +	} + +/* return length of latest Finished message we expected, copy to 'buf' */ +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count) +	{ +	size_t ret = 0; +	 +	if (s->s3 != NULL) +		{ +		ret = s->s3->tmp.peer_finish_md_len; +		if (count > ret) +			count = ret; +		memcpy(buf, s->s3->tmp.peer_finish_md, count); +		} +	return ret; +	} + + +int SSL_get_verify_mode(const SSL *s) +	{ +	return(s->verify_mode); +	} + +int SSL_get_verify_depth(const SSL *s) +	{ +	return X509_VERIFY_PARAM_get_depth(s->param); +	} + +int (*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *) +	{ +	return(s->verify_callback); +	} + +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) +	{ +	return(ctx->verify_mode); +	} + +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) +	{ +	return X509_VERIFY_PARAM_get_depth(ctx->param); +	} + +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *) +	{ +	return(ctx->default_verify_callback); +	} + +void SSL_set_verify(SSL *s,int mode, +		    int (*callback)(int ok,X509_STORE_CTX *ctx)) +	{ +	s->verify_mode=mode; +	if (callback != NULL) +		s->verify_callback=callback; +	} + +void SSL_set_verify_depth(SSL *s,int depth) +	{ +	X509_VERIFY_PARAM_set_depth(s->param, depth); +	} + +void SSL_set_read_ahead(SSL *s,int yes) +	{ +	s->read_ahead=yes; +	} + +int SSL_get_read_ahead(const SSL *s) +	{ +	return(s->read_ahead); +	} + +int SSL_pending(const SSL *s) +	{ +	/* SSL_pending cannot work properly if read-ahead is enabled +	 * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), +	 * and it is impossible to fix since SSL_pending cannot report +	 * errors that may be observed while scanning the new data. +	 * (Note that SSL_pending() is often used as a boolean value, +	 * so we'd better not return -1.) +	 */ +	return(s->method->ssl_pending(s)); +	} + +X509 *SSL_get_peer_certificate(const 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_OF(X509) *SSL_get_peer_cert_chain(const SSL *s) +	{ +	STACK_OF(X509) *r; +	 +	if ((s == NULL) || (s->session == NULL) || (s->session->sess_cert == NULL)) +		r=NULL; +	else +		r=s->session->sess_cert->cert_chain; + +	/* If we are a client, cert_chain includes the peer's own +	 * certificate; if we are a server, it does not. */ +	 +	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(SSL *t,const SSL *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); +	SSL_set_session_id_context(t,f->sid_ctx,f->sid_ctx_length); +	} + +/* Fix this so it checks all the valid key/cert options */ +int SSL_CTX_check_private_key(const SSL_CTX *ctx) +	{ +	if (	(ctx == NULL) || +		(ctx->cert == NULL) || +		(ctx->cert->key->x509 == NULL)) +		{ +		SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); +		return(0); +		} +	if 	(ctx->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->cert->key->x509, ctx->cert->key->privatekey)); +	} + +/* Fix this function so that it takes an optional type parameter */ +int SSL_check_private_key(const SSL *ssl) +	{ +	if (ssl == NULL) +		{ +		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (ssl->cert == NULL) +		{ +		SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); +		return 0; +		} +	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(SSL *s) +	{ +	if (s->handshake_func == 0) +		/* Not properly initialized yet */ +		SSL_set_accept_state(s); + +	return(s->method->ssl_accept(s)); +	} + +int SSL_connect(SSL *s) +	{ +	if (s->handshake_func == 0) +		/* Not properly initialized yet */ +		SSL_set_connect_state(s); + +	return(s->method->ssl_connect(s)); +	} + +long SSL_get_default_timeout(const SSL *s) +	{ +	return(s->method->get_timeout()); +	} + +int SSL_read(SSL *s,void *buf,int num) +	{ +	if (s->handshake_func == 0) +		{ +		SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED); +		return -1; +		} + +	if (s->shutdown & SSL_RECEIVED_SHUTDOWN) +		{ +		s->rwstate=SSL_NOTHING; +		return(0); +		} +	return(s->method->ssl_read(s,buf,num)); +	} + +int SSL_peek(SSL *s,void *buf,int num) +	{ +	if (s->handshake_func == 0) +		{ +		SSLerr(SSL_F_SSL_PEEK, SSL_R_UNINITIALIZED); +		return -1; +		} + +	if (s->shutdown & SSL_RECEIVED_SHUTDOWN) +		{ +		return(0); +		} +	return(s->method->ssl_peek(s,buf,num)); +	} + +int SSL_write(SSL *s,const void *buf,int num) +	{ +	if (s->handshake_func == 0) +		{ +		SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED); +		return -1; +		} + +	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(SSL *s) +	{ +	/* Note that this function behaves differently from what one might +	 * expect.  Return values are 0 for no success (yet), +	 * 1 for success; but calling it once is usually not enough, +	 * even if blocking I/O is used (see ssl3_shutdown). +	 */ + +	if (s->handshake_func == 0) +		{ +		SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED); +		return -1; +		} + +	if ((s != NULL) && !SSL_in_init(s)) +		return(s->method->ssl_shutdown(s)); +	else +		return(1); +	} + +int SSL_renegotiate(SSL *s) +	{ +	if (s->new_session == 0) +		{ +		s->new_session=1; +		} +	return(s->method->ssl_renegotiate(s)); +	} + +int SSL_renegotiate_pending(SSL *s) +	{ +	/* becomes true when negotiation is requested; +	 * false again once a handshake has finished */ +	return (s->new_session != 0); +	} + +long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) +	{ +	long l; + +	switch (cmd) +		{ +	case SSL_CTRL_GET_READ_AHEAD: +		return(s->read_ahead); +	case SSL_CTRL_SET_READ_AHEAD: +		l=s->read_ahead; +		s->read_ahead=larg; +		return(l); + +	case SSL_CTRL_SET_MSG_CALLBACK_ARG: +		s->msg_callback_arg = parg; +		return 1; + +	case SSL_CTRL_OPTIONS: +		return(s->options|=larg); +	case SSL_CTRL_CLEAR_OPTIONS: +		return(s->options&=~larg); +	case SSL_CTRL_MODE: +		return(s->mode|=larg); +	case SSL_CTRL_CLEAR_MODE: +		return(s->mode &=~larg); +	case SSL_CTRL_GET_MAX_CERT_LIST: +		return(s->max_cert_list); +	case SSL_CTRL_SET_MAX_CERT_LIST: +		l=s->max_cert_list; +		s->max_cert_list=larg; +		return(l); +	case SSL_CTRL_SET_MTU: +		if (SSL_version(s) == DTLS1_VERSION || +		    SSL_version(s) == DTLS1_BAD_VER) +			{ +			s->d1->mtu = larg; +			return larg; +			} +		return 0; +	case SSL_CTRL_SET_MAX_SEND_FRAGMENT: +		if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) +			return 0; +		s->max_send_fragment = larg; +		return 1; +	case SSL_CTRL_GET_RI_SUPPORT: +		if (s->s3) +			return s->s3->send_connection_binding; +		else return 0; +	default: +		return(s->method->ssl_ctrl(s,cmd,larg,parg)); +		} +	} + +long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) +	{ +	switch(cmd) +		{ +	case SSL_CTRL_SET_MSG_CALLBACK: +		s->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); +		return 1; +		 +	default: +		return(s->method->ssl_callback_ctrl(s,cmd,fp)); +		} +	} + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) +	{ +	return ctx->sessions; +	} + +long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) +	{ +	long l; + +	switch (cmd) +		{ +	case SSL_CTRL_GET_READ_AHEAD: +		return(ctx->read_ahead); +	case SSL_CTRL_SET_READ_AHEAD: +		l=ctx->read_ahead; +		ctx->read_ahead=larg; +		return(l); +		 +	case SSL_CTRL_SET_MSG_CALLBACK_ARG: +		ctx->msg_callback_arg = parg; +		return 1; + +	case SSL_CTRL_GET_MAX_CERT_LIST: +		return(ctx->max_cert_list); +	case SSL_CTRL_SET_MAX_CERT_LIST: +		l=ctx->max_cert_list; +		ctx->max_cert_list=larg; +		return(l); + +	case SSL_CTRL_SET_SESS_CACHE_SIZE: +		l=ctx->session_cache_size; +		ctx->session_cache_size=larg; +		return(l); +	case SSL_CTRL_GET_SESS_CACHE_SIZE: +		return(ctx->session_cache_size); +	case SSL_CTRL_SET_SESS_CACHE_MODE: +		l=ctx->session_cache_mode; +		ctx->session_cache_mode=larg; +		return(l); +	case SSL_CTRL_GET_SESS_CACHE_MODE: +		return(ctx->session_cache_mode); + +	case SSL_CTRL_SESS_NUMBER: +		return(lh_SSL_SESSION_num_items(ctx->sessions)); +	case SSL_CTRL_SESS_CONNECT: +		return(ctx->stats.sess_connect); +	case SSL_CTRL_SESS_CONNECT_GOOD: +		return(ctx->stats.sess_connect_good); +	case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: +		return(ctx->stats.sess_connect_renegotiate); +	case SSL_CTRL_SESS_ACCEPT: +		return(ctx->stats.sess_accept); +	case SSL_CTRL_SESS_ACCEPT_GOOD: +		return(ctx->stats.sess_accept_good); +	case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: +		return(ctx->stats.sess_accept_renegotiate); +	case SSL_CTRL_SESS_HIT: +		return(ctx->stats.sess_hit); +	case SSL_CTRL_SESS_CB_HIT: +		return(ctx->stats.sess_cb_hit); +	case SSL_CTRL_SESS_MISSES: +		return(ctx->stats.sess_miss); +	case SSL_CTRL_SESS_TIMEOUTS: +		return(ctx->stats.sess_timeout); +	case SSL_CTRL_SESS_CACHE_FULL: +		return(ctx->stats.sess_cache_full); +	case SSL_CTRL_OPTIONS: +		return(ctx->options|=larg); +	case SSL_CTRL_CLEAR_OPTIONS: +		return(ctx->options&=~larg); +	case SSL_CTRL_MODE: +		return(ctx->mode|=larg); +	case SSL_CTRL_CLEAR_MODE: +		return(ctx->mode&=~larg); +	case SSL_CTRL_SET_MAX_SEND_FRAGMENT: +		if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) +			return 0; +		ctx->max_send_fragment = larg; +		return 1; +	default: +		return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); +		} +	} + +long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) +	{ +	switch(cmd) +		{ +	case SSL_CTRL_SET_MSG_CALLBACK: +		ctx->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); +		return 1; + +	default: +		return(ctx->method->ssl_ctx_callback_ctrl(ctx,cmd,fp)); +		} +	} + +int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *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(const SSL_CIPHER * const *ap, +			const SSL_CIPHER * const *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_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) +	{ +	if (s != NULL) +		{ +		if (s->cipher_list != NULL) +			{ +			return(s->cipher_list); +			} +		else if ((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_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) +	{ +	if (s != NULL) +		{ +		if (s->cipher_list_by_id != NULL) +			{ +			return(s->cipher_list_by_id); +			} +		else if ((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() */ +const char *SSL_get_cipher_list(const SSL *s,int n) +	{ +	SSL_CIPHER *c; +	STACK_OF(SSL_CIPHER) *sk; + +	if (s == NULL) return(NULL); +	sk=SSL_get_ciphers(s); +	if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n)) +		return(NULL); +	c=sk_SSL_CIPHER_value(sk,n); +	if (c == NULL) return(NULL); +	return(c->name); +	} + +/** specify the ciphers to be used by default by the SSL_CTX */ +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) +	{ +	STACK_OF(SSL_CIPHER) *sk; +	 +	sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, +		&ctx->cipher_list_by_id,str); +	/* ssl_create_cipher_list may return an empty stack if it +	 * was unable to find a cipher matching the given rule string +	 * (for example if the rule string specifies a cipher which +	 * has been disabled). This is not an error as far as +	 * ssl_create_cipher_list is concerned, and hence +	 * ctx->cipher_list and ctx->cipher_list_by_id has been +	 * updated. */ +	if (sk == NULL) +		return 0; +	else if (sk_SSL_CIPHER_num(sk) == 0) +		{ +		SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); +		return 0; +		} +	return 1; +	} + +/** specify the ciphers to be used by the SSL */ +int SSL_set_cipher_list(SSL *s,const char *str) +	{ +	STACK_OF(SSL_CIPHER) *sk; +	 +	sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, +		&s->cipher_list_by_id,str); +	/* see comment in SSL_CTX_set_cipher_list */ +	if (sk == NULL) +		return 0; +	else if (sk_SSL_CIPHER_num(sk) == 0) +		{ +		SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); +		return 0; +		} +	return 1; +	} + +/** specify the ciphers to be used by the SSL */ +int SSL_set_cipher_lists(SSL *s,STACK_OF(SSL_CIPHER) *sk) +	{ +	STACK_OF(SSL_CIPHER) *tmp_cipher_list; + +	if (sk == NULL) +		return 0; + +        /* Based on end of ssl_create_cipher_list */ +	tmp_cipher_list = sk_SSL_CIPHER_dup(sk); +	if (tmp_cipher_list == NULL) +		{ +		return 0; +		} +	if (s->cipher_list != NULL) +		sk_SSL_CIPHER_free(s->cipher_list); +	s->cipher_list = sk; +	if (s->cipher_list_by_id != NULL) +		sk_SSL_CIPHER_free(s->cipher_list_by_id); +	s->cipher_list_by_id = tmp_cipher_list; +	(void)sk_SSL_CIPHER_set_cmp_func(s->cipher_list_by_id,ssl_cipher_ptr_id_cmp); + +	sk_SSL_CIPHER_sort(s->cipher_list_by_id); +	return 1; +	} + +/* works well for SSLv2, not so good for SSLv3 */ +char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len) +	{ +	char *p; +	STACK_OF(SSL_CIPHER) *sk; +	SSL_CIPHER *c; +	int i; + +	if ((s->session == NULL) || (s->session->ciphers == NULL) || +		(len < 2)) +		return(NULL); + +	p=buf; +	sk=s->session->ciphers; +	for (i=0; i<sk_SSL_CIPHER_num(sk); i++) +		{ +		int n; + +		c=sk_SSL_CIPHER_value(sk,i); +		n=strlen(c->name); +		if (n+1 > len) +			{ +			if (p != buf) +				--p; +			*p='\0'; +			return buf; +			} +		strcpy(p,c->name); +		p+=n; +		*(p++)=':'; +		len-=n+1; +		} +	p[-1]='\0'; +	return(buf); +	} + +int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, +			     int (*put_cb)(const SSL_CIPHER *, unsigned char *)) +	{ +	int i,j=0; +	SSL_CIPHER *c; +	unsigned char *q; +#ifndef OPENSSL_NO_KRB5 +	int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx); +#endif /* OPENSSL_NO_KRB5 */ + +	if (sk == NULL) return(0); +	q=p; + +	for (i=0; i<sk_SSL_CIPHER_num(sk); i++) +		{ +		c=sk_SSL_CIPHER_value(sk,i); +#ifndef OPENSSL_NO_KRB5 +		if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) && +		    nokrb5) +		    continue; +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_PSK +		/* with PSK there must be client callback set */ +		if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) && +		    s->psk_client_callback == NULL) +			continue; +#endif /* OPENSSL_NO_PSK */ +		j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p); +		p+=j; +		} +	/* If p == q, no ciphers and caller indicates an error. Otherwise +	 * add SCSV if not renegotiating. +	 */ +	if (p != q && !s->new_session) +		{ +		static SSL_CIPHER scsv = +			{ +			0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 +			}; +		j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p); +		p+=j; +#ifdef OPENSSL_RI_DEBUG +		fprintf(stderr, "SCSV sent by client\n"); +#endif +		} + +	return(p-q); +	} + +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, +					       STACK_OF(SSL_CIPHER) **skp) +	{ +	const SSL_CIPHER *c; +	STACK_OF(SSL_CIPHER) *sk; +	int i,n; +	if (s->s3) +		s->s3->send_connection_binding = 0; + +	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_SSL_CIPHER_new_null(); /* change perhaps later */ +	else +		{ +		sk= *skp; +		sk_SSL_CIPHER_zero(sk); +		} + +	for (i=0; i<num; i+=n) +		{ +		/* Check for SCSV */ +		if (s->s3 && (n != 3 || !p[0]) && +			(p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) && +			(p[n-1] == (SSL3_CK_SCSV & 0xff))) +			{ +			/* SCSV fatal if renegotiating */ +			if (s->new_session) +				{ +				SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);  +				goto err; +				} +			s->s3->send_connection_binding = 1; +			p += n; +#ifdef OPENSSL_RI_DEBUG +			fprintf(stderr, "SCSV received by server\n"); +#endif +			continue; +			} + +		c=ssl_get_cipher_by_char(s,p); +		p+=n; +		if (c != NULL) +			{ +			if (!sk_SSL_CIPHER_push(sk,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_SSL_CIPHER_free(sk); +	return(NULL); +	} + + +#ifndef OPENSSL_NO_TLSEXT +/** return a servername extension value if provided in Client Hello, or NULL. + * So far, only host_name types are defined (RFC 3546). + */ + +const char *SSL_get_servername(const SSL *s, const int type) +	{ +	if (type != TLSEXT_NAMETYPE_host_name) +		return NULL; + +	return s->session && !s->tlsext_hostname ? +		s->session->tlsext_hostname : +		s->tlsext_hostname; +	} + +int SSL_get_servername_type(const SSL *s) +	{ +	if (s->session && (!s->tlsext_hostname ? s->session->tlsext_hostname : s->tlsext_hostname)) +		return TLSEXT_NAMETYPE_host_name; +	return -1; +	} + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* SSL_select_next_proto implements the standard protocol selection. It is + * expected that this function is called from the callback set by + * SSL_CTX_set_next_proto_select_cb. + * + * The protocol data is assumed to be a vector of 8-bit, length prefixed byte + * strings. The length byte itself is not included in the length. A byte + * string of length 0 is invalid. No byte string may be truncated. + * + * The current, but experimental algorithm for selecting the protocol is: + * + * 1) If the server doesn't support NPN then this is indicated to the + * callback. In this case, the client application has to abort the connection + * or have a default application level protocol. + * + * 2) If the server supports NPN, but advertises an empty list then the + * client selects the first protcol in its list, but indicates via the + * API that this fallback case was enacted. + * + * 3) Otherwise, the client finds the first protocol in the server's list + * that it supports and selects this protocol. This is because it's + * assumed that the server has better information about which protocol + * a client should use. + * + * 4) If the client doesn't support any of the server's advertised + * protocols, then this is treated the same as case 2. + * + * It returns either + * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or + * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. + */ +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len) +	{ +	unsigned int i, j; +	const unsigned char *result; +	int status = OPENSSL_NPN_UNSUPPORTED; + +	/* For each protocol in server preference order, see if we support it. */ +	for (i = 0; i < server_len; ) +		{ +		for (j = 0; j < client_len; ) +			{ +			if (server[i] == client[j] && +			    memcmp(&server[i+1], &client[j+1], server[i]) == 0) +				{ +				/* We found a match */ +				result = &server[i]; +				status = OPENSSL_NPN_NEGOTIATED; +				goto found; +				} +			j += client[j]; +			j++; +			} +		i += server[i]; +		i++; +		} + +	/* There's no overlap between our protocols and the server's list. */ +	result = client; +	status = OPENSSL_NPN_NO_OVERLAP; + +	found: +	*out = (unsigned char *) result + 1; +	*outlen = result[0]; +	return status; +	} + +/* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's + * requested protocol for this connection and returns 0. If the client didn't + * request any protocol, then *data is set to NULL. + * + * Note that the client can request any protocol it chooses. The value returned + * from this function need not be a member of the list of supported protocols + * provided by the callback. + */ +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len) +	{ +	*data = s->next_proto_negotiated; +	if (!*data) { +		*len = 0; +	} else { +		*len = s->next_proto_negotiated_len; +	} +} + +/* SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a + * TLS server needs a list of supported protocols for Next Protocol + * Negotiation. The returned list must be in wire format.  The list is returned + * by setting |out| to point to it and |outlen| to its length. This memory will + * not be modified, but one should assume that the SSL* keeps a reference to + * it. + * + * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise. Otherwise, no + * such extension will be included in the ServerHello. */ +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg) +	{ +	ctx->next_protos_advertised_cb = cb; +	ctx->next_protos_advertised_cb_arg = arg; +	} + +/* SSL_CTX_set_next_proto_select_cb sets a callback that is called when a + * client needs to select a protocol from the server's provided list. |out| + * must be set to point to the selected protocol (which may be within |in|). + * The length of the protocol name must be written into |outlen|. The server's + * advertised protocols are provided in |in| and |inlen|. The callback can + * assume that |in| is syntactically valid. + * + * The client must select a protocol. It is fatal to the connection if this + * callback returns a value other than SSL_TLSEXT_ERR_OK. + */ +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg) +	{ +	ctx->next_proto_select_cb = cb; +	ctx->next_proto_select_cb_arg = arg; +	} + +# endif +#endif + +static unsigned long ssl_session_hash(const SSL_SESSION *a) +	{ +	unsigned long l; + +	l=(unsigned long) +		((unsigned int) a->session_id[0]     )| +		((unsigned int) a->session_id[1]<< 8L)| +		((unsigned long)a->session_id[2]<<16L)| +		((unsigned long)a->session_id[3]<<24L); +	return(l); +	} + +/* NB: If this function (or indeed the hash function which uses a sort of + * coarser function than this one) is changed, ensure + * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being + * able to construct an SSL_SESSION that will collide with any existing session + * with a matching session ID. */ +static int ssl_session_cmp(const SSL_SESSION *a,const SSL_SESSION *b) +	{ +	if (a->ssl_version != b->ssl_version) +		return(1); +	if (a->session_id_length != b->session_id_length) +		return(1); +	return(memcmp(a->session_id,b->session_id,a->session_id_length)); +	} + +/* These wrapper functions should remain rather than redeclaring + * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each + * variable. The reason is that the functions aren't static, they're exposed via + * ssl.h. */ +static IMPLEMENT_LHASH_HASH_FN(ssl_session, SSL_SESSION) +static IMPLEMENT_LHASH_COMP_FN(ssl_session, SSL_SESSION) + +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) +	{ +	SSL_CTX *ret=NULL; + +	if (meth == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED); +		return(NULL); +		} + +	if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) +		{ +		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); +		goto err; +		} +	ret=(SSL_CTX *)OPENSSL_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; +	ret->session_cache_size=SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; +	ret->session_cache_head=NULL; +	ret->session_cache_tail=NULL; + +	/* We take the system default */ +	ret->session_timeout=meth->get_timeout(); + +	ret->new_session_cb=0; +	ret->remove_session_cb=0; +	ret->get_session_cb=0; +	ret->generate_session_id=0; + +	memset((char *)&ret->stats,0,sizeof(ret->stats)); + +	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=0; +	ret->app_verify_arg=NULL; + +	ret->max_cert_list=SSL_MAX_CERT_LIST_DEFAULT; +	ret->read_ahead=0; +	ret->msg_callback=0; +	ret->msg_callback_arg=NULL; +	ret->verify_mode=SSL_VERIFY_NONE; +#if 0 +	ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */ +#endif +	ret->sid_ctx_length=0; +	ret->default_verify_callback=NULL; +	if ((ret->cert=ssl_cert_new()) == NULL) +		goto err; + +	ret->default_passwd_callback=0; +	ret->default_passwd_callback_userdata=NULL; +	ret->client_cert_cb=0; +	ret->app_gen_cookie_cb=0; +	ret->app_verify_cookie_cb=0; + +	ret->sessions=lh_SSL_SESSION_new(); +	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, +		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); +	if (ret->cipher_list == NULL +	    || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) +		{ +		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS); +		goto err2; +		} + +	ret->param = X509_VERIFY_PARAM_new(); +	if (!ret->param) +		goto err; + +	if ((ret->rsa_md5=EVP_get_digestbyname("ssl2-md5")) == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES); +		goto err2; +		} +	if ((ret->md5=EVP_get_digestbyname("ssl3-md5")) == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES); +		goto err2; +		} +	if ((ret->sha1=EVP_get_digestbyname("ssl3-sha1")) == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES); +		goto err2; +		} + +	if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL) +		goto err; + +	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); + +	ret->extra_certs=NULL; +	ret->comp_methods=SSL_COMP_get_compression_methods(); + +	ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + +#ifndef OPENSSL_NO_TLSEXT +	ret->tlsext_servername_callback = 0; +	ret->tlsext_servername_arg = NULL; +	/* Setup RFC4507 ticket keys */ +	if ((RAND_pseudo_bytes(ret->tlsext_tick_key_name, 16) <= 0) +		|| (RAND_bytes(ret->tlsext_tick_hmac_key, 16) <= 0) +		|| (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0)) +		ret->options |= SSL_OP_NO_TICKET; + +	ret->tlsext_status_cb = 0; +	ret->tlsext_status_arg = NULL; + +# ifndef OPENSSL_NO_NEXTPROTONEG +	ret->next_protos_advertised_cb = 0; +	ret->next_proto_select_cb = 0; +# endif +#endif +#ifndef OPENSSL_NO_PSK +	ret->psk_identity_hint=NULL; +	ret->psk_client_callback=NULL; +	ret->psk_server_callback=NULL; +#endif +#ifndef OPENSSL_NO_BUF_FREELISTS +	ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT; +	ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); +	if (!ret->rbuf_freelist) +		goto err; +	ret->rbuf_freelist->chunklen = 0; +	ret->rbuf_freelist->len = 0; +	ret->rbuf_freelist->head = NULL; +	ret->wbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); +	if (!ret->wbuf_freelist) +		{ +		OPENSSL_free(ret->rbuf_freelist); +		goto err; +		} +	ret->wbuf_freelist->chunklen = 0; +	ret->wbuf_freelist->len = 0; +	ret->wbuf_freelist->head = NULL; +#endif +#ifndef OPENSSL_NO_ENGINE +	ret->client_cert_engine = NULL; +#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO +#define eng_strx(x)	#x +#define eng_str(x)	eng_strx(x) +	/* Use specific client engine automatically... ignore errors */ +	{ +	ENGINE *eng; +	eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); +	if (!eng) +		{ +		ERR_clear_error(); +		ENGINE_load_builtin_engines(); +		eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); +		} +	if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng)) +		ERR_clear_error(); +	} +#endif +#endif +	/* Default is to connect to non-RI servers. When RI is more widely +	 * deployed might change this. +	 */ +	ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + +	return(ret); +err: +	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE); +err2: +	if (ret != NULL) SSL_CTX_free(ret); +	return(NULL); +	} + +#if 0 +static void SSL_COMP_free(SSL_COMP *comp) +    { OPENSSL_free(comp); } +#endif + +#ifndef OPENSSL_NO_BUF_FREELISTS +static void +ssl_buf_freelist_free(SSL3_BUF_FREELIST *list) +	{ +	SSL3_BUF_FREELIST_ENTRY *ent, *next; +	for (ent = list->head; ent; ent = next) +		{ +		next = ent->next; +		OPENSSL_free(ent); +		} +	OPENSSL_free(list); +	} +#endif + +void SSL_CTX_free(SSL_CTX *a) +	{ +	int i; + +	if (a == NULL) return; + +	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX); +#ifdef REF_PRINT +	REF_PRINT("SSL_CTX",a); +#endif +	if (i > 0) return; +#ifdef REF_CHECK +	if (i < 0) +		{ +		fprintf(stderr,"SSL_CTX_free, bad reference count\n"); +		abort(); /* ok */ +		} +#endif + +	if (a->param) +		X509_VERIFY_PARAM_free(a->param); + +	/* +	 * Free internal session cache. However: the remove_cb() may reference +	 * the ex_data of SSL_CTX, thus the ex_data store can only be removed +	 * after the sessions were flushed. +	 * As the ex_data handling routines might also touch the session cache, +	 * the most secure solution seems to be: empty (flush) the cache, then +	 * free ex_data, then finally free the cache. +	 * (See ticket [openssl.org #212].) +	 */ +	if (a->sessions != NULL) +		SSL_CTX_flush_sessions(a,0); + +	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); + +	if (a->sessions != NULL) +		lh_SSL_SESSION_free(a->sessions); + +	if (a->cert_store != NULL) +		X509_STORE_free(a->cert_store); +	if (a->cipher_list != NULL) +		sk_SSL_CIPHER_free(a->cipher_list); +	if (a->cipher_list_by_id != NULL) +		sk_SSL_CIPHER_free(a->cipher_list_by_id); +	if (a->cert != NULL) +		ssl_cert_free(a->cert); +	if (a->client_CA != NULL) +		sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free); +	if (a->extra_certs != NULL) +		sk_X509_pop_free(a->extra_certs,X509_free); +#if 0 /* This should never be done, since it removes a global database */ +	if (a->comp_methods != NULL) +		sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free); +#else +	a->comp_methods = NULL; +#endif + +#ifndef OPENSSL_NO_PSK +	if (a->psk_identity_hint) +		OPENSSL_free(a->psk_identity_hint); +#endif +#ifndef OPENSSL_NO_ENGINE +	if (a->client_cert_engine) +		ENGINE_finish(a->client_cert_engine); +#endif + +#ifndef OPENSSL_NO_BUF_FREELISTS +	if (a->wbuf_freelist) +		ssl_buf_freelist_free(a->wbuf_freelist); +	if (a->rbuf_freelist) +		ssl_buf_freelist_free(a->rbuf_freelist); +#endif + +	OPENSSL_free(a); +	} + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) +	{ +	ctx->default_passwd_callback=cb; +	} + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u) +	{ +	ctx->default_passwd_callback_userdata=u; +	} + +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg) +	{ +	ctx->app_verify_callback=cb; +	ctx->app_verify_arg=arg; +	} + +void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *)) +	{ +	ctx->verify_mode=mode; +	ctx->default_verify_callback=cb; +	} + +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) +	{ +	X509_VERIFY_PARAM_set_depth(ctx->param, depth); +	} + +void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) +	{ +	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,kl; +	unsigned long mask_k,mask_a,emask_k,emask_a; +	int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size; +#ifndef OPENSSL_NO_ECDH +	int have_ecdh_tmp; +#endif +	X509 *x = NULL; +	EVP_PKEY *ecc_pkey = NULL; +	int signature_nid = 0, pk_nid = 0, md_nid = 0; + +	if (c == NULL) return; + +	kl=SSL_C_EXPORT_PKEYLENGTH(cipher); + +#ifndef OPENSSL_NO_RSA +	rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL); +	rsa_tmp_export=(c->rsa_tmp_cb != NULL || +		(rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl)); +#else +	rsa_tmp=rsa_tmp_export=0; +#endif +#ifndef OPENSSL_NO_DH +	dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL); +	dh_tmp_export=(c->dh_tmp_cb != NULL || +		(dh_tmp && DH_size(c->dh_tmp)*8 <= kl)); +#else +	dh_tmp=dh_tmp_export=0; +#endif + +#ifndef OPENSSL_NO_ECDH +	have_ecdh_tmp=(c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL); +#endif +	cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); +	rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL); +	rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl); +	cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]); +	rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); +	cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); +	dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); +	cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); +	dh_rsa=  (cpk->x509 != NULL && cpk->privatekey != NULL); +	dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); +	cpk= &(c->pkeys[SSL_PKEY_DH_DSA]); +/* FIX THIS EAY EAY EAY */ +	dh_dsa=  (cpk->x509 != NULL && cpk->privatekey != NULL); +	dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); +	cpk= &(c->pkeys[SSL_PKEY_ECC]); +	have_ecc_cert= (cpk->x509 != NULL && cpk->privatekey != NULL); +	mask_k=0; +	mask_a=0; +	emask_k=0; +	emask_a=0; + +	 + +#ifdef CIPHER_DEBUG +	printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", +	        rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp, +		rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa); +#endif +	 +	cpk = &(c->pkeys[SSL_PKEY_GOST01]); +	if (cpk->x509 != NULL && cpk->privatekey !=NULL) { +		mask_k |= SSL_kGOST; +		mask_a |= SSL_aGOST01; +	} +	cpk = &(c->pkeys[SSL_PKEY_GOST94]); +	if (cpk->x509 != NULL && cpk->privatekey !=NULL) { +		mask_k |= SSL_kGOST; +		mask_a |= SSL_aGOST94; +	} + +	if (rsa_enc || (rsa_tmp && rsa_sign)) +		mask_k|=SSL_kRSA; +	if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc))) +		emask_k|=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_k|=SSL_kEDH; +	if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) && +		(rsa_enc || rsa_sign || dsa_sign)) +		emask_k|=SSL_kEDH; +#endif + +	if (dh_tmp_export) +		emask_k|=SSL_kEDH; + +	if (dh_tmp) +		mask_k|=SSL_kEDH; + +	if (dh_rsa) mask_k|=SSL_kDHr; +	if (dh_rsa_export) emask_k|=SSL_kDHr; + +	if (dh_dsa) mask_k|=SSL_kDHd; +	if (dh_dsa_export) emask_k|=SSL_kDHd; + +	if (rsa_enc || rsa_sign) +		{ +		mask_a|=SSL_aRSA; +		emask_a|=SSL_aRSA; +		} + +	if (dsa_sign) +		{ +		mask_a|=SSL_aDSS; +		emask_a|=SSL_aDSS; +		} + +	mask_a|=SSL_aNULL; +	emask_a|=SSL_aNULL; + +#ifndef OPENSSL_NO_KRB5 +	mask_k|=SSL_kKRB5; +	mask_a|=SSL_aKRB5; +	emask_k|=SSL_kKRB5; +	emask_a|=SSL_aKRB5; +#endif + +	/* An ECC certificate may be usable for ECDH and/or +	 * ECDSA cipher suites depending on the key usage extension. +	 */ +	if (have_ecc_cert) +		{ +		/* This call populates extension flags (ex_flags) */ +		x = (c->pkeys[SSL_PKEY_ECC]).x509; +		X509_check_purpose(x, -1, 0); +		ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ? +		    (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1; +		ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? +		    (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; +		ecc_pkey = X509_get_pubkey(x); +		ecc_pkey_size = (ecc_pkey != NULL) ? +		    EVP_PKEY_bits(ecc_pkey) : 0; +		EVP_PKEY_free(ecc_pkey); +		if ((x->sig_alg) && (x->sig_alg->algorithm)) +			{ +			signature_nid = OBJ_obj2nid(x->sig_alg->algorithm); +			OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid); +			} +#ifndef OPENSSL_NO_ECDH +		if (ecdh_ok) +			{ + +			if (pk_nid == NID_rsaEncryption || pk_nid == NID_rsa) +				{ +				mask_k|=SSL_kECDHr; +				mask_a|=SSL_aECDH; +				if (ecc_pkey_size <= 163) +					{ +					emask_k|=SSL_kECDHr; +					emask_a|=SSL_aECDH; +					} +				} + +			if (pk_nid == NID_X9_62_id_ecPublicKey) +				{ +				mask_k|=SSL_kECDHe; +				mask_a|=SSL_aECDH; +				if (ecc_pkey_size <= 163) +					{ +					emask_k|=SSL_kECDHe; +					emask_a|=SSL_aECDH; +					} +				} +			} +#endif +#ifndef OPENSSL_NO_ECDSA +		if (ecdsa_ok) +			{ +			mask_a|=SSL_aECDSA; +			emask_a|=SSL_aECDSA; +			} +#endif +		} + +#ifndef OPENSSL_NO_ECDH +	if (have_ecdh_tmp) +		{ +		mask_k|=SSL_kEECDH; +		emask_k|=SSL_kEECDH; +		} +#endif + +#ifndef OPENSSL_NO_PSK +	mask_k |= SSL_kPSK; +	mask_a |= SSL_aPSK; +	emask_k |= SSL_kPSK; +	emask_a |= SSL_aPSK; +#endif + +	c->mask_k=mask_k; +	c->mask_a=mask_a; +	c->export_mask_k=emask_k; +	c->export_mask_a=emask_a; +	c->valid=1; +	} + +/* This handy macro borrowed from crypto/x509v3/v3_purp.c */ +#define ku_reject(x, usage) \ +	(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) + +#ifndef OPENSSL_NO_EC + +int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs) +	{ +	unsigned long alg_k, alg_a; +	EVP_PKEY *pkey = NULL; +	int keysize = 0; +	int signature_nid = 0, md_nid = 0, pk_nid = 0; + +	alg_k = cs->algorithm_mkey; +	alg_a = cs->algorithm_auth; + +	if (SSL_C_IS_EXPORT(cs)) +		{ +		/* ECDH key length in export ciphers must be <= 163 bits */ +		pkey = X509_get_pubkey(x); +		if (pkey == NULL) return 0; +		keysize = EVP_PKEY_bits(pkey); +		EVP_PKEY_free(pkey); +		if (keysize > 163) return 0; +		} + +	/* This call populates the ex_flags field correctly */ +	X509_check_purpose(x, -1, 0); +	if ((x->sig_alg) && (x->sig_alg->algorithm)) +		{ +		signature_nid = OBJ_obj2nid(x->sig_alg->algorithm); +		OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid); +		} +	if (alg_k & SSL_kECDHe || alg_k & SSL_kECDHr) +		{ +		/* key usage, if present, must allow key agreement */ +		if (ku_reject(x, X509v3_KU_KEY_AGREEMENT)) +			{ +			SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT); +			return 0; +			} +		if (alg_k & SSL_kECDHe) +			{ +			/* signature alg must be ECDSA */ +			if (pk_nid != NID_X9_62_id_ecPublicKey) +				{ +				SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE); +				return 0; +				} +			} +		if (alg_k & SSL_kECDHr) +			{ +			/* signature alg must be RSA */ + +			if (pk_nid != NID_rsaEncryption && pk_nid != NID_rsa) +				{ +				SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE); +				return 0; +				} +			} +		} +	if (alg_a & SSL_aECDSA) +		{ +		/* key usage, if present, must allow signing */ +		if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) +			{ +			SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_SIGNING); +			return 0; +			} +		} + +	return 1;  /* all checks are ok */ +	} + +#endif + +/* THIS NEEDS CLEANING UP */ +X509 *ssl_get_server_send_cert(SSL *s) +	{ +	unsigned long alg_k,alg_a; +	CERT *c; +	int i; + +	c=s->cert; +	ssl_set_cert_masks(c, s->s3->tmp.new_cipher); +	 +	alg_k = s->s3->tmp.new_cipher->algorithm_mkey; +	alg_a = s->s3->tmp.new_cipher->algorithm_auth; + +	if (alg_k & (SSL_kECDHr|SSL_kECDHe)) +		{ +		/* we don't need to look at SSL_kEECDH +		 * since no certificate is needed for +		 * anon ECDH and for authenticated +		 * EECDH, the check for the auth +		 * algorithm will set i correctly +		 * NOTE: For ECDH-RSA, we need an ECC +		 * not an RSA cert but for EECDH-RSA +		 * we need an RSA cert. Placing the +		 * checks for SSL_kECDH before RSA +		 * checks ensures the correct cert is chosen. +		 */ +		i=SSL_PKEY_ECC; +		} +	else if (alg_a & SSL_aECDSA) +		{ +		i=SSL_PKEY_ECC; +		} +	else if (alg_k & SSL_kDHr) +		i=SSL_PKEY_DH_RSA; +	else if (alg_k & SSL_kDHd) +		i=SSL_PKEY_DH_DSA; +	else if (alg_a & SSL_aDSS) +		i=SSL_PKEY_DSA_SIGN; +	else if (alg_a & SSL_aRSA) +		{ +		if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) +			i=SSL_PKEY_RSA_SIGN; +		else +			i=SSL_PKEY_RSA_ENC; +		} +	else if (alg_a & SSL_aKRB5) +		{ +		/* VRS something else here? */ +		return(NULL); +		} +	else if (alg_a & SSL_aGOST94)  +		i=SSL_PKEY_GOST94; +	else if (alg_a & SSL_aGOST01) +		i=SSL_PKEY_GOST01; +	else /* if (alg_a & SSL_aNULL) */ +		{ +		SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR); +		return(NULL); +		} +	if (c->pkeys[i].x509 == NULL) return(NULL); + +	return(c->pkeys[i].x509); +	} + +EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher) +	{ +	unsigned long alg_a; +	CERT *c; + +	alg_a = cipher->algorithm_auth; +	c=s->cert; + +	if ((alg_a & SSL_aDSS) && +		(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) +		return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey); +	else if (alg_a & 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_a & SSL_aECDSA) && +	         (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) +		return(c->pkeys[SSL_PKEY_ECC].privatekey); +	else /* if (alg_a & SSL_aNULL) */ +		{ +		SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR); +		return(NULL); +		} +	} + +void ssl_update_cache(SSL *s,int mode) +	{ +	int i; + +	/* If the session_id_length is 0, we are not supposed to cache it, +	 * and it would be rather hard to do anyway :-) */ +	if (s->session->session_id_length == 0) return; + +	i=s->session_ctx->session_cache_mode; +	if ((i & mode) && (!s->hit) +		&& ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) +		    || SSL_CTX_add_session(s->session_ctx,s->session)) +		&& (s->session_ctx->new_session_cb != NULL)) +		{ +		CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION); +		if (!s->session_ctx->new_session_cb(s,s->session)) +			SSL_SESSION_free(s->session); +		} + +	/* auto flush every 255 connections */ +	if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && +		((i & mode) == mode)) +		{ +		if (  (((mode & SSL_SESS_CACHE_CLIENT) +			?s->session_ctx->stats.sess_connect_good +			:s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff) +			{ +			SSL_CTX_flush_sessions(s->session_ctx,(unsigned long)time(NULL)); +			} +		} +	} + +const SSL_METHOD *SSL_get_ssl_method(SSL *s) +	{ +	return(s->method); +	} + +int SSL_set_ssl_method(SSL *s, const 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(const SSL *s,int i) +	{ +	int reason; +	unsigned long l; +	BIO *bio; + +	if (i > 0) return(SSL_ERROR_NONE); + +	/* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake +	 * etc, where we do encode the error */ +	if ((l=ERR_peek_error()) != 0) +		{ +		if (ERR_GET_LIB(l) == ERR_LIB_SYS) +			return(SSL_ERROR_SYSCALL); +		else +			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)) +			/* This one doesn't make too much sense ... We never try +			 * to write to the rbio, and an application program where +			 * rbio and wbio are separate couldn't even know what it +			 * should wait for. +			 * However if we ever set s->rwstate incorrectly +			 * (so that we have SSL_want_read(s) instead of +			 * SSL_want_write(s)) and rbio and wbio *are* the same, +			 * this test works around that bug; so it might be safer +			 * to keep it. */ +			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 if (reason == BIO_RR_ACCEPT) +				return(SSL_ERROR_WANT_ACCEPT); +			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)) +			/* See above (SSL_want_read(s) with BIO_should_write(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 if (reason == BIO_RR_ACCEPT) +				return(SSL_ERROR_WANT_ACCEPT); +			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 == SSL2_VERSION) +			{ +			/* assume it is the socket being closed */ +			return(SSL_ERROR_ZERO_RETURN); +			} +		else +			{ +			if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && +				(s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) +				return(SSL_ERROR_ZERO_RETURN); +			} +		} +	return(SSL_ERROR_SYSCALL); +	} + +int SSL_do_handshake(SSL *s) +	{ +	int ret=1; + +	if (s->handshake_func == NULL) +		{ +		SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_CONNECTION_TYPE_NOT_SET); +		return(-1); +		} + +	s->method->ssl_renegotiate_check(s); + +	if (SSL_in_init(s) || SSL_in_before(s)) +		{ +		ret=s->handshake_func(s); +		} +	return(ret); +	} + +/* For the next 2 functions, SSL_clear() sets shutdown and so + * one of these calls will reset it */ +void SSL_set_accept_state(SSL *s) +	{ +	s->server=1; +	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); +	ssl_clear_hash_ctx(&s->read_hash); +	ssl_clear_hash_ctx(&s->write_hash); +	} + +void SSL_set_connect_state(SSL *s) +	{ +	s->server=0; +	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); +	ssl_clear_hash_ctx(&s->read_hash); +	ssl_clear_hash_ctx(&s->write_hash); +	} + +int ssl_undefined_function(SSL *s) +	{ +	SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +	return(0); +	} + +int ssl_undefined_void_function(void) +	{ +	SSLerr(SSL_F_SSL_UNDEFINED_VOID_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +	return(0); +	} + +int ssl_undefined_const_function(const SSL *s) +	{ +	SSLerr(SSL_F_SSL_UNDEFINED_CONST_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +	return(0); +	} + +SSL_METHOD *ssl_bad_method(int ver) +	{ +	SSLerr(SSL_F_SSL_BAD_METHOD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); +	return(NULL); +	} + +static const char *ssl_get_version(int version) +	{ +	if (version == TLS1_VERSION) +		return("TLSv1"); +	else if (version == SSL3_VERSION) +		return("SSLv3"); +	else if (version == SSL2_VERSION) +		return("SSLv2"); +	else +		return("unknown"); +	} + +const char *SSL_get_version(const SSL *s) +	{ +		return ssl_get_version(s->version); +	} + +const char *SSL_SESSION_get_version(const SSL_SESSION *s) +	{ +		return ssl_get_version(s->ssl_version); +	} + +const char* SSL_authentication_method(const SSL* ssl) +	{ +	if (ssl->cert != NULL && ssl->cert->rsa_tmp != NULL) +		return SSL_TXT_RSA "_" SSL_TXT_EXPORT; +	switch (ssl->version) +		{ +	case SSL2_VERSION: +		return SSL_TXT_RSA; +	case SSL3_VERSION: +	case TLS1_VERSION: +	case DTLS1_VERSION: +		return SSL_CIPHER_authentication_method(ssl->s3->tmp.new_cipher); +	default: +		return "UNKNOWN"; +		} +	} + +SSL *SSL_dup(SSL *s) +	{ +	STACK_OF(X509_NAME) *sk; +	X509_NAME *xn; +	SSL *ret; +	int i; +	 +	if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL) +	    return(NULL); + +	ret->version = s->version; +	ret->type = s->type; +	ret->method = s->method; + +	if (s->session != NULL) +		{ +		/* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */ +		SSL_copy_session_id(ret,s); +		} +	else +		{ +		/* No session has been established yet, so we have to expect +		 * that s->cert or ret->cert will be changed later -- +		 * they should not both point to the same object, +		 * and thus we can't use SSL_copy_session_id. */ + +		ret->method->ssl_free(ret); +		ret->method = s->method; +		ret->method->ssl_new(ret); + +		if (s->cert != NULL) +			{ +			if (ret->cert != NULL) +				{ +				ssl_cert_free(ret->cert); +				} +			ret->cert = ssl_cert_dup(s->cert); +			if (ret->cert == NULL) +				goto err; +			} +				 +		SSL_set_session_id_context(ret, +			s->sid_ctx, s->sid_ctx_length); +		} + +	ret->options=s->options; +	ret->mode=s->mode; +	SSL_set_max_cert_list(ret,SSL_get_max_cert_list(s)); +	SSL_set_read_ahead(ret,SSL_get_read_ahead(s)); +	ret->msg_callback = s->msg_callback; +	ret->msg_callback_arg = s->msg_callback_arg; +	SSL_set_verify(ret,SSL_get_verify_mode(s), +		SSL_get_verify_callback(s)); +	SSL_set_verify_depth(ret,SSL_get_verify_depth(s)); +	ret->generate_session_id = s->generate_session_id; + +	SSL_set_info_callback(ret,SSL_get_info_callback(s)); +	 +	ret->debug=s->debug; + +	/* copy app data, a little dangerous perhaps */ +	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data)) +		goto err; + +	/* 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->wbio)) +				goto err; +			} +		else +			ret->wbio=ret->rbio; +		} +	ret->rwstate = s->rwstate; +	ret->in_handshake = s->in_handshake; +	ret->handshake_func = s->handshake_func; +	ret->server = s->server; +	ret->new_session = s->new_session; +	ret->quiet_shutdown = s->quiet_shutdown; +	ret->shutdown=s->shutdown; +	ret->state=s->state; /* SSL_dup does not really work at any state, though */ +	ret->rstate=s->rstate; +	ret->init_num = 0; /* would have to copy ret->init_buf, ret->init_msg, ret->init_num, ret->init_off */ +	ret->hit=s->hit; + +	X509_VERIFY_PARAM_inherit(ret->param, s->param); + +	/* dup the cipher_list and cipher_list_by_id stacks */ +	if (s->cipher_list != NULL) +		{ +		if ((ret->cipher_list=sk_SSL_CIPHER_dup(s->cipher_list)) == NULL) +			goto err; +		} +	if (s->cipher_list_by_id != NULL) +		if ((ret->cipher_list_by_id=sk_SSL_CIPHER_dup(s->cipher_list_by_id)) +			== NULL) +			goto err; + +	/* Dup the client_CA list */ +	if (s->client_CA != NULL) +		{ +		if ((sk=sk_X509_NAME_dup(s->client_CA)) == NULL) goto err; +		ret->client_CA=sk; +		for (i=0; i<sk_X509_NAME_num(sk); i++) +			{ +			xn=sk_X509_NAME_value(sk,i); +			if (sk_X509_NAME_set(sk,i,X509_NAME_dup(xn)) == NULL) +				{ +				X509_NAME_free(xn); +				goto err; +				} +			} +		} + +	if (0) +		{ +err: +		if (ret != NULL) SSL_free(ret); +		ret=NULL; +		} +	return(ret); +	} + +void ssl_clear_cipher_ctx(SSL *s) +	{ +	if (s->enc_read_ctx != NULL) +		{ +		EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); +		OPENSSL_free(s->enc_read_ctx); +		s->enc_read_ctx=NULL; +		} +	if (s->enc_write_ctx != NULL) +		{ +		EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); +		OPENSSL_free(s->enc_write_ctx); +		s->enc_write_ctx=NULL; +		} +#ifndef OPENSSL_NO_COMP +	if (s->expand != NULL) +		{ +		COMP_CTX_free(s->expand); +		s->expand=NULL; +		} +	if (s->compress != NULL) +		{ +		COMP_CTX_free(s->compress); +		s->compress=NULL; +		} +#endif +	} + +/* Fix this function so that it takes an optional type parameter */ +X509 *SSL_get_certificate(const SSL *s) +	{ +	if (s->cert != NULL) +		return(s->cert->key->x509); +	else +		return(NULL); +	} + +/* Fix this function so that it takes an optional type parameter */ +EVP_PKEY *SSL_get_privatekey(SSL *s) +	{ +	if (s->cert != NULL) +		return(s->cert->key->privatekey); +	else +		return(NULL); +	} + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) +	{ +	if ((s->session != NULL) && (s->session->cipher != NULL)) +		return(s->session->cipher); +	return(NULL); +	} +#ifdef OPENSSL_NO_COMP +const void *SSL_get_current_compression(SSL *s) +	{ +	return NULL; +	} +const void *SSL_get_current_expansion(SSL *s) +	{ +	return NULL; +	} +#else + +const COMP_METHOD *SSL_get_current_compression(SSL *s) +	{ +	if (s->compress != NULL) +		return(s->compress->meth); +	return(NULL); +	} + +const COMP_METHOD *SSL_get_current_expansion(SSL *s) +	{ +	if (s->expand != NULL) +		return(s->expand->meth); +	return(NULL); +	} +#endif + +int ssl_init_wbio_buffer(SSL *s,int push) +	{ +	BIO *bbio; + +	if (s->bbio == NULL) +		{ +		bbio=BIO_new(BIO_f_buffer()); +		if (bbio == NULL) return(0); +		s->bbio=bbio; +		} +	else +		{ +		bbio=s->bbio; +		if (s->bbio == s->wbio) +			s->wbio=BIO_pop(s->wbio); +		} +	(void)BIO_reset(bbio); +/*	if (!BIO_set_write_buffer_size(bbio,16*1024)) */ +	if (!BIO_set_read_buffer_size(bbio,1)) +		{ +		SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER,ERR_R_BUF_LIB); +		return(0); +		} +	if (push) +		{ +		if (s->wbio != bbio) +			s->wbio=BIO_push(bbio,s->wbio); +		} +	else +		{ +		if (s->wbio == bbio) +			s->wbio=BIO_pop(bbio); +		} +	return(1); +	} + +void ssl_free_wbio_buffer(SSL *s) +	{ +	if (s->bbio == NULL) return; + +	if (s->bbio == s->wbio) +		{ +		/* remove buffering */ +		s->wbio=BIO_pop(s->wbio); +#ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */ +		assert(s->wbio != NULL); +#endif +	} +	BIO_free(s->bbio); +	s->bbio=NULL; +	} +	 +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode) +	{ +	ctx->quiet_shutdown=mode; +	} + +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) +	{ +	return(ctx->quiet_shutdown); +	} + +void SSL_set_quiet_shutdown(SSL *s,int mode) +	{ +	s->quiet_shutdown=mode; +	} + +int SSL_get_quiet_shutdown(const SSL *s) +	{ +	return(s->quiet_shutdown); +	} + +void SSL_set_shutdown(SSL *s,int mode) +	{ +	s->shutdown=mode; +	} + +int SSL_get_shutdown(const SSL *s) +	{ +	return(s->shutdown); +	} + +int SSL_version(const SSL *s) +	{ +	return(s->version); +	} + +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) +	{ +	return(ssl->ctx); +	} + +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) +	{ +	if (ssl->ctx == ctx) +		return ssl->ctx; +#ifndef OPENSSL_NO_TLSEXT +	if (ctx == NULL) +		ctx = ssl->initial_ctx; +#endif +	if (ssl->cert != NULL) +		ssl_cert_free(ssl->cert); +	ssl->cert = ssl_cert_dup(ctx->cert); +	CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); +	if (ssl->ctx != NULL) +		SSL_CTX_free(ssl->ctx); /* decrement reference count */ +	ssl->ctx = ctx; +	return(ssl->ctx); +	} + +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) +	{ +	return(X509_STORE_set_default_paths(ctx->cert_store)); +	} + +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, +		const char *CApath) +	{ +	return(X509_STORE_load_locations(ctx->cert_store,CAfile,CApath)); +	} +#endif + +void SSL_set_info_callback(SSL *ssl, +	void (*cb)(const SSL *ssl,int type,int val)) +	{ +	ssl->info_callback=cb; +	} + +/* One compiler (Diab DCC) doesn't like argument names in returned +   function pointer.  */ +void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/) +	{ +	return ssl->info_callback; +	} + +int SSL_state(const SSL *ssl) +	{ +	return(ssl->state); +	} + +void SSL_set_verify_result(SSL *ssl,long arg) +	{ +	ssl->verify_result=arg; +	} + +long SSL_get_verify_result(const SSL *ssl) +	{ +	return(ssl->verify_result); +	} + +int SSL_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func, +			 CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func) +	{ +	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, +				new_func, dup_func, free_func); +	} + +int SSL_set_ex_data(SSL *s,int idx,void *arg) +	{ +	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); +	} + +void *SSL_get_ex_data(const SSL *s,int idx) +	{ +	return(CRYPTO_get_ex_data(&s->ex_data,idx)); +	} + +int SSL_CTX_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func, +			     CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func) +	{ +	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, +				new_func, dup_func, free_func); +	} + +int SSL_CTX_set_ex_data(SSL_CTX *s,int idx,void *arg) +	{ +	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); +	} + +void *SSL_CTX_get_ex_data(const SSL_CTX *s,int idx) +	{ +	return(CRYPTO_get_ex_data(&s->ex_data,idx)); +	} + +int ssl_ok(SSL *s) +	{ +	return(1); +	} + +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) +	{ +	return(ctx->cert_store); +	} + +void SSL_CTX_set_cert_store(SSL_CTX *ctx,X509_STORE *store) +	{ +	if (ctx->cert_store != NULL) +		X509_STORE_free(ctx->cert_store); +	ctx->cert_store=store; +	} + +int SSL_want(const SSL *s) +	{ +	return(s->rwstate); +	} + +/*! + * \brief Set the callback for generating temporary RSA keys. + * \param ctx the SSL context. + * \param cb the callback + */ + +#ifndef OPENSSL_NO_RSA +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,RSA *(*cb)(SSL *ssl, +							  int is_export, +							  int keylength)) +    { +    SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb); +    } + +void SSL_set_tmp_rsa_callback(SSL *ssl,RSA *(*cb)(SSL *ssl, +						  int is_export, +						  int keylength)) +    { +    SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb); +    } +#endif + +#ifdef DOXYGEN +/*! + * \brief The RSA temporary key callback function. + * \param ssl the SSL session. + * \param is_export \c TRUE if the temp RSA key is for an export ciphersuite. + * \param keylength if \c is_export is \c TRUE, then \c keylength is the size + * of the required key in bits. + * \return the temporary RSA key. + * \sa SSL_CTX_set_tmp_rsa_callback, SSL_set_tmp_rsa_callback + */ + +RSA *cb(SSL *ssl,int is_export,int keylength) +    {} +#endif + +/*! + * \brief Set the callback for generating temporary DH keys. + * \param ctx the SSL context. + * \param dh the callback + */ + +#ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export, +                                                        int keylength)) +	{ +	SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); +	} + +void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export, +                                                int keylength)) +	{ +	SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); +	} +#endif + +#ifndef OPENSSL_NO_ECDH +void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export, +                                                                int keylength)) +	{ +	SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); +	} + +void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export, +                                                        int keylength)) +	{ +	SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); +	} +#endif + +#ifndef OPENSSL_NO_PSK +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) +	{ +	if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); +		return 0; +		} +	if (ctx->psk_identity_hint != NULL) +		OPENSSL_free(ctx->psk_identity_hint); +	if (identity_hint != NULL) +		{ +		ctx->psk_identity_hint = BUF_strdup(identity_hint); +		if (ctx->psk_identity_hint == NULL) +			return 0; +		} +	else +		ctx->psk_identity_hint = NULL; +	return 1; +	} + +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) +	{ +	if (s == NULL) +		return 0; + +	if (s->session == NULL) +		return 1; /* session not created yet, ignored */ + +	if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) +		{ +		SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); +		return 0; +		} +	if (s->session->psk_identity_hint != NULL) +		OPENSSL_free(s->session->psk_identity_hint); +	if (identity_hint != NULL) +		{ +		s->session->psk_identity_hint = BUF_strdup(identity_hint); +		if (s->session->psk_identity_hint == NULL) +			return 0; +		} +	else +		s->session->psk_identity_hint = NULL; +	return 1; +	} + +const char *SSL_get_psk_identity_hint(const SSL *s) +	{ +	if (s == NULL || s->session == NULL) +		return NULL; +	return(s->session->psk_identity_hint); +	} + +const char *SSL_get_psk_identity(const SSL *s) +	{ +	if (s == NULL || s->session == NULL) +		return NULL; +	return(s->session->psk_identity); +	} + +void SSL_set_psk_client_callback(SSL *s, +    unsigned int (*cb)(SSL *ssl, const char *hint, +                       char *identity, unsigned int max_identity_len, unsigned char *psk, +                       unsigned int max_psk_len)) +	{ +	s->psk_client_callback = cb; +	} + +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, +    unsigned int (*cb)(SSL *ssl, const char *hint, +                       char *identity, unsigned int max_identity_len, unsigned char *psk, +                       unsigned int max_psk_len)) +	{ +	ctx->psk_client_callback = cb; +	} + +void SSL_set_psk_server_callback(SSL *s, +    unsigned int (*cb)(SSL *ssl, const char *identity, +                       unsigned char *psk, unsigned int max_psk_len)) +	{ +	s->psk_server_callback = cb; +	} + +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, +    unsigned int (*cb)(SSL *ssl, const char *identity, +                       unsigned char *psk, unsigned int max_psk_len)) +	{ +	ctx->psk_server_callback = cb; +	} +#endif + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) +	{ +	SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +	} +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) +	{ +	SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +	} + +int SSL_cutthrough_complete(const SSL *s) +	{ +	return (!s->server &&                 /* cutthrough only applies to clients */ +		!s->hit &&                        /* full-handshake */ +		s->version >= SSL3_VERSION && +		s->s3->in_read_app_data == 0 &&   /* cutthrough only applies to write() */ +		(SSL_get_mode((SSL*)s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) &&  /* cutthrough enabled */ +		SSL_get_cipher_bits(s, NULL) >= 128 &&                      /* strong cipher choosen */ +		s->s3->previous_server_finished_len == 0 &&                 /* not a renegotiation handshake */ +		(s->state == SSL3_ST_CR_SESSION_TICKET_A ||                 /* ready to write app-data*/ +			s->state == SSL3_ST_CR_FINISHED_A)); +	} + +/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer + * vairable, freeing  EVP_MD_CTX previously stored in that variable, if + * any. If EVP_MD pointer is passed, initializes ctx with this md + * Returns newly allocated ctx; + */ + +EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md)  +{ +	ssl_clear_hash_ctx(hash); +	*hash = EVP_MD_CTX_create(); +	if (md) EVP_DigestInit_ex(*hash,md,NULL); +	return *hash; +} +void ssl_clear_hash_ctx(EVP_MD_CTX **hash)  +{ + +	if (*hash) EVP_MD_CTX_destroy(*hash); +	*hash=NULL; +} + +#if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) +#include "../crypto/bio/bss_file.c" +#endif + +IMPLEMENT_STACK_OF(SSL_CIPHER) +IMPLEMENT_STACK_OF(SSL_COMP) +IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, +				    ssl_cipher_id); + diff --git a/main/openssl/ssl/ssl_locl.h b/main/openssl/ssl/ssl_locl.h new file mode 100644 index 00000000..25f8e16c --- /dev/null +++ b/main/openssl/ssl/ssl_locl.h @@ -0,0 +1,1085 @@ +/* ssl/ssl_locl.h */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_SSL_LOCL_H +#define HEADER_SSL_LOCL_H +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <errno.h> + +#include "e_os.h" + +#include <openssl/buffer.h> +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#include <openssl/bio.h> +#include <openssl/stack.h> +#ifndef OPENSSL_NO_RSA +#include <openssl/rsa.h> +#endif +#ifndef OPENSSL_NO_DSA +#include <openssl/dsa.h> +#endif +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <openssl/symhacks.h> + +#ifdef OPENSSL_BUILD_SHLIBSSL +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + +#define PKCS1_CHECK + +#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)) + +#define l2n6(l,c)	(*((c)++)=(unsigned char)(((l)>>40)&0xff), \ +			 *((c)++)=(unsigned char)(((l)>>32)&0xff), \ +			 *((c)++)=(unsigned char)(((l)>>24)&0xff), \ +			 *((c)++)=(unsigned char)(((l)>>16)&0xff), \ +			 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ +			 *((c)++)=(unsigned char)(((l)    )&0xff)) + +#define n2l6(c,l)	(l =((BN_ULLONG)(*((c)++)))<<40, \ +			 l|=((BN_ULLONG)(*((c)++)))<<32, \ +			 l|=((BN_ULLONG)(*((c)++)))<<24, \ +			 l|=((BN_ULLONG)(*((c)++)))<<16, \ +			 l|=((BN_ULLONG)(*((c)++)))<< 8, \ +			 l|=((BN_ULLONG)(*((c)++)))) + +/* 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[0]))<< 8)| \ +			    (((unsigned int)(c[1]))    )),c+=2) +#define s2n(s,c)	((c[0]=(unsigned char)(((s)>> 8)&0xff), \ +			  c[1]=(unsigned char)(((s)    )&0xff)),c+=2) + +#define n2l3(c,l)	((l =(((unsigned long)(c[0]))<<16)| \ +			     (((unsigned long)(c[1]))<< 8)| \ +			     (((unsigned long)(c[2]))    )),c+=3) + +#define l2n3(l,c)	((c[0]=(unsigned char)(((l)>>16)&0xff), \ +			  c[1]=(unsigned char)(((l)>> 8)&0xff), \ +			  c[2]=(unsigned char)(((l)    )&0xff)),c+=3) + +/* 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 the Bitmasks for SSL_CIPHER.algorithms. + * This bits are used packed as dense as possible. If new methods/ciphers + * etc will be added, the bits a likely to change, so this information + * is for internal library use only, even though SSL_CIPHER.algorithms + * can be publicly accessed. + * Use the according functions for cipher management instead. + * + * The bit mask handling in the selection and sorting scheme in + * ssl_create_cipher_list() has only limited capabilities, reflecting + * that the different entities within are mutually exclusive: + * ONLY ONE BIT PER MASK CAN BE SET AT A TIME. + */ + +/* Bits for algorithm_mkey (key exchange algorithm) */ +#define SSL_kRSA		0x00000001L /* RSA key exchange */ +#define SSL_kDHr		0x00000002L /* DH cert, RSA CA cert */ /* no such ciphersuites supported! */ +#define SSL_kDHd		0x00000004L /* DH cert, DSA CA cert */ /* no such ciphersuite supported! */ +#define SSL_kEDH		0x00000008L /* tmp DH key no DH cert */ +#define SSL_kKRB5		0x00000010L /* Kerberos5 key exchange */ +#define SSL_kECDHr		0x00000020L /* ECDH cert, RSA CA cert */ +#define SSL_kECDHe		0x00000040L /* ECDH cert, ECDSA CA cert */ +#define SSL_kEECDH		0x00000080L /* ephemeral ECDH */ +#define SSL_kPSK		0x00000100L /* PSK */ +#define SSL_kGOST       0x00000200L /* GOST key exchange */ + +/* Bits for algorithm_auth (server authentication) */ +#define SSL_aRSA		0x00000001L /* RSA auth */ +#define SSL_aDSS 		0x00000002L /* DSS auth */ +#define SSL_aNULL 		0x00000004L /* no auth (i.e. use ADH or AECDH) */ +#define SSL_aDH 		0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no such ciphersuites supported! */ +#define SSL_aECDH 		0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */ +#define SSL_aKRB5               0x00000020L /* KRB5 auth */ +#define SSL_aECDSA              0x00000040L /* ECDSA auth*/ +#define SSL_aPSK                0x00000080L /* PSK auth */ +#define SSL_aGOST94				0x00000100L /* GOST R 34.10-94 signature auth */ +#define SSL_aGOST01 			0x00000200L /* GOST R 34.10-2001 signature auth */ + + +/* Bits for algorithm_enc (symmetric encryption) */ +#define SSL_DES			0x00000001L +#define SSL_3DES		0x00000002L +#define SSL_RC4			0x00000004L +#define SSL_RC2			0x00000008L +#define SSL_IDEA		0x00000010L +#define SSL_eNULL		0x00000020L +#define SSL_AES128		0x00000040L +#define SSL_AES256		0x00000080L +#define SSL_CAMELLIA128		0x00000100L +#define SSL_CAMELLIA256		0x00000200L +#define SSL_eGOST2814789CNT	0x00000400L +#define SSL_SEED		0x00000800L + +#define SSL_AES        		(SSL_AES128|SSL_AES256) +#define SSL_CAMELLIA		(SSL_CAMELLIA128|SSL_CAMELLIA256) + + +/* Bits for algorithm_mac (symmetric authentication) */ +#define SSL_MD5			0x00000001L +#define SSL_SHA1		0x00000002L +#define SSL_GOST94      0x00000004L +#define SSL_GOST89MAC   0x00000008L + +/* Bits for algorithm_ssl (protocol version) */ +#define SSL_SSLV2		0x00000001L +#define SSL_SSLV3		0x00000002L +#define SSL_TLSV1		SSL_SSLV3	/* for now */ + + +/* Bits for algorithm2 (handshake digests and other extra flags) */ + +#define SSL_HANDSHAKE_MAC_MD5 0x10 +#define SSL_HANDSHAKE_MAC_SHA 0x20 +#define SSL_HANDSHAKE_MAC_GOST94 0x40 +#define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA) + +/* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX + * make sure to update this constant too */ +#define SSL_MAX_DIGEST 4 + +#define TLS1_PRF_DGST_SHIFT 8 +#define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_SHA1 (SSL_HANDSHAKE_MAC_SHA << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_GOST94 (SSL_HANDSHAKE_MAC_GOST94 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1) + +/* Stream MAC for GOST ciphersuites from cryptopro draft + * (currently this also goes into algorithm2) */ +#define TLS1_STREAM_MAC 0x04 + + + +/* + * Export and cipher strength information. For each cipher we have to decide + * whether it is exportable or not. This information is likely to change + * over time, since the export control rules are no static technical issue. + * + * Independent of the export flag the cipher strength is sorted into classes. + * SSL_EXP40 was denoting the 40bit US export limit of past times, which now + * is at 56bit (SSL_EXP56). If the exportable cipher class is going to change + * again (eg. to 64bit) the use of "SSL_EXP*" becomes blurred even more, + * since SSL_EXP64 could be similar to SSL_LOW. + * For this reason SSL_MICRO and SSL_MINI macros are included to widen the + * namespace of SSL_LOW-SSL_HIGH to lower values. As development of speed + * and ciphers goes, another extension to SSL_SUPER and/or SSL_ULTRA would + * be possible. + */ +#define SSL_EXP_MASK		0x00000003L +#define SSL_STRONG_MASK		0x000001fcL + +#define SSL_NOT_EXP		0x00000001L +#define SSL_EXPORT		0x00000002L + +#define SSL_STRONG_NONE		0x00000004L +#define SSL_EXP40		0x00000008L +#define SSL_MICRO		(SSL_EXP40) +#define SSL_EXP56		0x00000010L +#define SSL_MINI		(SSL_EXP56) +#define SSL_LOW			0x00000020L +#define SSL_MEDIUM		0x00000040L +#define SSL_HIGH		0x00000080L +#define SSL_FIPS		0x00000100L + +/* we have used 000001ff - 23 bits left to go */ + +/* + * Macros to check the export status and cipher strength for export ciphers. + * Even though the macros for EXPORT and EXPORT40/56 have similar names, + * their meaning is different: + * *_EXPORT macros check the 'exportable' status. + * *_EXPORT40/56 macros are used to check whether a certain cipher strength + *          is given. + * Since the SSL_IS_EXPORT* and SSL_EXPORT* macros depend on the correct + * algorithm structure element to be passed (algorithms, algo_strength) and no + * typechecking can be done as they are all of type unsigned long, their + * direct usage is discouraged. + * Use the SSL_C_* macros instead. + */ +#define SSL_IS_EXPORT(a)	((a)&SSL_EXPORT) +#define SSL_IS_EXPORT56(a)	((a)&SSL_EXP56) +#define SSL_IS_EXPORT40(a)	((a)&SSL_EXP40) +#define SSL_C_IS_EXPORT(c)	SSL_IS_EXPORT((c)->algo_strength) +#define SSL_C_IS_EXPORT56(c)	SSL_IS_EXPORT56((c)->algo_strength) +#define SSL_C_IS_EXPORT40(c)	SSL_IS_EXPORT40((c)->algo_strength) + +#define SSL_EXPORT_KEYLENGTH(a,s)	(SSL_IS_EXPORT40(s) ? 5 : \ +				 (a) == SSL_DES ? 8 : 7) +#define SSL_EXPORT_PKEYLENGTH(a) (SSL_IS_EXPORT40(a) ? 512 : 1024) +#define SSL_C_EXPORT_KEYLENGTH(c)	SSL_EXPORT_KEYLENGTH((c)->algorithm_enc, \ +				(c)->algo_strength) +#define SSL_C_EXPORT_PKEYLENGTH(c)	SSL_EXPORT_PKEYLENGTH((c)->algo_strength) + + + + +/* 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_ECC            5 +#define SSL_PKEY_GOST94		6 +#define SSL_PKEY_GOST01		7 +#define SSL_PKEY_NUM		8 + +/* 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 +*/ + +#ifndef OPENSSL_NO_EC +/* From ECC-TLS draft, used in encoding the curve type in  + * ECParameters + */ +#define EXPLICIT_PRIME_CURVE_TYPE  1    +#define EXPLICIT_CHAR2_CURVE_TYPE  2 +#define NAMED_CURVE_TYPE           3 +#endif  /* OPENSSL_NO_EC */ + +typedef struct cert_pkey_st +	{ +	X509 *x509; +	STACK_OF(X509) *cert_chain; +	EVP_PKEY *privatekey; +	} CERT_PKEY; + +typedef struct cert_st +	{ +	/* Current active set */ +	CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array +			 * Probably it would make more sense to store +			 * an index, not a pointer. */ +  +	/* The following masks are for the key and auth +	 * algorithms that are supported by the certs below */ +	int valid; +	unsigned long mask_k; +	unsigned long mask_a; +	unsigned long export_mask_k; +	unsigned long export_mask_a; +#ifndef OPENSSL_NO_RSA +	RSA *rsa_tmp; +	RSA *(*rsa_tmp_cb)(SSL *ssl,int is_export,int keysize); +#endif +#ifndef OPENSSL_NO_DH +	DH *dh_tmp; +	DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize); +#endif +#ifndef OPENSSL_NO_ECDH +	EC_KEY *ecdh_tmp; +	/* Callback for generating ephemeral ECDH keys */ +	EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize); +#endif + +	CERT_PKEY pkeys[SSL_PKEY_NUM]; + +	int references; /* >1 only if SSL_copy_session_id is used */ +	} CERT; + + +typedef struct sess_cert_st +	{ +	STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */ + +	/* The 'peer_...' members are used only by clients. */ +	int peer_cert_type; + +	CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */ +	CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; +	/* Obviously we don't have the private keys of these, +	 * so maybe we shouldn't even use the CERT_PKEY type here. */ + +#ifndef OPENSSL_NO_RSA +	RSA *peer_rsa_tmp; /* not used for SSL 2 */ +#endif +#ifndef OPENSSL_NO_DH +	DH *peer_dh_tmp; /* not used for SSL 2 */ +#endif +#ifndef OPENSSL_NO_ECDH +	EC_KEY *peer_ecdh_tmp; +#endif + +	int references; /* actually always 1 at the moment */ +	} SESS_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	*/  + +#define FP_ICC  (int (*)(const void *,const void *)) +#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)) + +/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff + * It is a bit of a mess of functions, but hell, think of it as + * an opaque structure :-) */ +typedef struct ssl3_enc_method +	{ +	int (*enc)(SSL *, int); +	int (*mac)(SSL *, unsigned char *, int); +	int (*setup_key_block)(SSL *); +	int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int); +	int (*change_cipher_state)(SSL *, int); +	int (*final_finish_mac)(SSL *,  const char *, int, unsigned char *); +	int finish_mac_length; +	int (*cert_verify_mac)(SSL *, int, unsigned char *); +	const char *client_finished_label; +	int client_finished_label_len; +	const char *server_finished_label; +	int server_finished_label_len; +	int (*alert_value)(int); +	} SSL3_ENC_METHOD; + +#ifndef OPENSSL_NO_COMP +/* Used for holding the relevant compression methods loaded into SSL_CTX */ +typedef struct ssl3_comp_st +	{ +	int comp_id;	/* The identifier byte for this compression type */ +	char *name;	/* Text name used for the compression type */ +	COMP_METHOD *method; /* The method :-) */ +	} SSL3_COMP; +#endif + +#ifndef OPENSSL_NO_BUF_FREELISTS +typedef struct ssl3_buf_freelist_st +	{ +	size_t chunklen; +	unsigned int len; +	struct ssl3_buf_freelist_entry_st *head; +	} SSL3_BUF_FREELIST; + +typedef struct ssl3_buf_freelist_entry_st +	{ +	struct ssl3_buf_freelist_entry_st *next; +	} SSL3_BUF_FREELIST_ENTRY; +#endif + +extern SSL3_ENC_METHOD ssl3_undef_enc_method; +OPENSSL_EXTERN const SSL_CIPHER ssl2_ciphers[]; +OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[]; + + +SSL_METHOD *ssl_bad_method(int ver); + +extern SSL3_ENC_METHOD TLSv1_enc_data; +extern SSL3_ENC_METHOD SSLv3_enc_data; +extern SSL3_ENC_METHOD DTLSv1_enc_data; + +#define IMPLEMENT_tls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \ +const SSL_METHOD *func_name(void)  \ +	{ \ +	static const SSL_METHOD func_name##_data= { \ +		TLS1_VERSION, \ +		tls1_new, \ +		tls1_clear, \ +		tls1_free, \ +		s_accept, \ +		s_connect, \ +		ssl3_read, \ +		ssl3_peek, \ +		ssl3_write, \ +		ssl3_shutdown, \ +		ssl3_renegotiate, \ +		ssl3_renegotiate_check, \ +		ssl3_get_message, \ +		ssl3_read_bytes, \ +		ssl3_write_bytes, \ +		ssl3_dispatch_alert, \ +		ssl3_ctrl, \ +		ssl3_ctx_ctrl, \ +		ssl3_get_cipher_by_char, \ +		ssl3_put_cipher_by_char, \ +		ssl3_pending, \ +		ssl3_num_ciphers, \ +		ssl3_get_cipher, \ +		s_get_meth, \ +		tls1_default_timeout, \ +		&TLSv1_enc_data, \ +		ssl_undefined_void_function, \ +		ssl3_callback_ctrl, \ +		ssl3_ctx_callback_ctrl, \ +	}; \ +	return &func_name##_data; \ +	} + +#define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect, s_get_meth) \ +const SSL_METHOD *func_name(void)  \ +	{ \ +	static const SSL_METHOD func_name##_data= { \ +		SSL3_VERSION, \ +		ssl3_new, \ +		ssl3_clear, \ +		ssl3_free, \ +		s_accept, \ +		s_connect, \ +		ssl3_read, \ +		ssl3_peek, \ +		ssl3_write, \ +		ssl3_shutdown, \ +		ssl3_renegotiate, \ +		ssl3_renegotiate_check, \ +		ssl3_get_message, \ +		ssl3_read_bytes, \ +		ssl3_write_bytes, \ +		ssl3_dispatch_alert, \ +		ssl3_ctrl, \ +		ssl3_ctx_ctrl, \ +		ssl3_get_cipher_by_char, \ +		ssl3_put_cipher_by_char, \ +		ssl3_pending, \ +		ssl3_num_ciphers, \ +		ssl3_get_cipher, \ +		s_get_meth, \ +		ssl3_default_timeout, \ +		&SSLv3_enc_data, \ +		ssl_undefined_void_function, \ +		ssl3_callback_ctrl, \ +		ssl3_ctx_callback_ctrl, \ +	}; \ +	return &func_name##_data; \ +	} + +#define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \ +const SSL_METHOD *func_name(void)  \ +	{ \ +	static const SSL_METHOD func_name##_data= { \ +	TLS1_VERSION, \ +	tls1_new, \ +	tls1_clear, \ +	tls1_free, \ +	s_accept, \ +	s_connect, \ +	ssl23_read, \ +	ssl23_peek, \ +	ssl23_write, \ +	ssl_undefined_function, \ +	ssl_undefined_function, \ +	ssl_ok, \ +	ssl3_get_message, \ +	ssl3_read_bytes, \ +	ssl3_write_bytes, \ +	ssl3_dispatch_alert, \ +	ssl3_ctrl, \ +	ssl3_ctx_ctrl, \ +	ssl23_get_cipher_by_char, \ +	ssl23_put_cipher_by_char, \ +	ssl_undefined_const_function, \ +	ssl23_num_ciphers, \ +	ssl23_get_cipher, \ +	s_get_meth, \ +	ssl23_default_timeout, \ +	&ssl3_undef_enc_method, \ +	ssl_undefined_void_function, \ +	ssl3_callback_ctrl, \ +	ssl3_ctx_callback_ctrl, \ +	}; \ +	return &func_name##_data; \ +	} + +#define IMPLEMENT_ssl2_meth_func(func_name, s_accept, s_connect, s_get_meth) \ +const SSL_METHOD *func_name(void)  \ +	{ \ +	static const SSL_METHOD func_name##_data= { \ +		SSL2_VERSION, \ +		ssl2_new,	/* local */ \ +		ssl2_clear,	/* local */ \ +		ssl2_free,	/* local */ \ +		s_accept, \ +		s_connect, \ +		ssl2_read, \ +		ssl2_peek, \ +		ssl2_write, \ +		ssl2_shutdown, \ +		ssl_ok,	/* NULL - renegotiate */ \ +		ssl_ok,	/* NULL - check renegotiate */ \ +		NULL, /* NULL - ssl_get_message */ \ +		NULL, /* NULL - ssl_get_record */ \ +		NULL, /* NULL - ssl_write_bytes */ \ +		NULL, /* NULL - dispatch_alert */ \ +		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, \ +		s_get_meth, \ +		ssl2_default_timeout, \ +		&ssl3_undef_enc_method, \ +		ssl_undefined_void_function, \ +		ssl2_callback_ctrl,	/* local */ \ +		ssl2_ctx_callback_ctrl,	/* local */ \ +	}; \ +	return &func_name##_data; \ +	} + +#define IMPLEMENT_dtls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \ +const SSL_METHOD *func_name(void)  \ +	{ \ +	static const SSL_METHOD func_name##_data= { \ +		DTLS1_VERSION, \ +		dtls1_new, \ +		dtls1_clear, \ +		dtls1_free, \ +		s_accept, \ +		s_connect, \ +		ssl3_read, \ +		ssl3_peek, \ +		ssl3_write, \ +		ssl3_shutdown, \ +		ssl3_renegotiate, \ +		ssl3_renegotiate_check, \ +		dtls1_get_message, \ +		dtls1_read_bytes, \ +		dtls1_write_app_data_bytes, \ +		dtls1_dispatch_alert, \ +		dtls1_ctrl, \ +		ssl3_ctx_ctrl, \ +		ssl3_get_cipher_by_char, \ +		ssl3_put_cipher_by_char, \ +		ssl3_pending, \ +		ssl3_num_ciphers, \ +		dtls1_get_cipher, \ +		s_get_meth, \ +		dtls1_default_timeout, \ +		&DTLSv1_enc_data, \ +		ssl_undefined_void_function, \ +		ssl3_callback_ctrl, \ +		ssl3_ctx_callback_ctrl, \ +	}; \ +	return &func_name##_data; \ +	} + +void ssl_clear_cipher_ctx(SSL *s); +int ssl_clear_bad_session(SSL *s); +CERT *ssl_cert_new(void); +CERT *ssl_cert_dup(CERT *cert); +int ssl_cert_inst(CERT **o); +void ssl_cert_free(CERT *c); +SESS_CERT *ssl_sess_cert_new(void); +void ssl_sess_cert_free(SESS_CERT *sc); +int ssl_set_peer_cert_type(SESS_CERT *c, int type); +int ssl_get_new_session(SSL *s, int session); +int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit); +int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b); +DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, +				  ssl_cipher_id); +int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap, +			const SSL_CIPHER * const *bp); +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, +					       STACK_OF(SSL_CIPHER) **skp); +int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, +                             int (*put_cb)(const SSL_CIPHER *, unsigned char *)); +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, +					     STACK_OF(SSL_CIPHER) **pref, +					     STACK_OF(SSL_CIPHER) **sorted, +					     const char *rule_str); +void ssl_update_cache(SSL *s, int mode); +int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc, +		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp); +int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);			    +int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); +int ssl_undefined_function(SSL *s); +int ssl_undefined_void_function(void); +int ssl_undefined_const_function(const SSL *s); +X509 *ssl_get_server_send_cert(SSL *); +EVP_PKEY *ssl_get_sign_pkey(SSL *,const SSL_CIPHER *); +int ssl_cert_type(X509 *x,EVP_PKEY *pkey); +void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher); +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); +int ssl_verify_alarm_type(long type); +void ssl_load_ciphers(void); + +int ssl2_enc_init(SSL *s, int client); +int 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); +const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p); +int ssl2_put_cipher_by_char(const 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, const unsigned char *data); +void ssl2_return_error(SSL *s,int reason); +void ssl2_write_error(SSL *s); +int ssl2_num_ciphers(void); +const 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, void *buf, int len); +int	ssl2_peek(SSL *s, void *buf, int len); +int	ssl2_write(SSL *s, const void *buf, int len); +int	ssl2_shutdown(SSL *s); +void	ssl2_clear(SSL *s); +long	ssl2_ctrl(SSL *s,int cmd, long larg, void *parg); +long	ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg); +long	ssl2_callback_ctrl(SSL *s,int cmd, void (*fp)(void)); +long	ssl2_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void)); +int	ssl2_pending(const SSL *s); +long	ssl2_default_timeout(void ); + +const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); +int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p); +void ssl3_init_finished_mac(SSL *s); +int ssl3_send_server_certificate(SSL *s); +int ssl3_send_newsession_ticket(SSL *s); +int ssl3_send_cert_status(SSL *s); +int ssl3_get_finished(SSL *s,int state_a,int state_b); +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); +int 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, const char *sender,int slen); +int ssl3_num_ciphers(void); +const SSL_CIPHER *ssl3_get_cipher(unsigned int u); +int ssl3_renegotiate(SSL *ssl);  +int ssl3_renegotiate_check(SSL *ssl);  +int ssl3_dispatch_alert(SSL *s); +int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); +int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); +int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,unsigned char *p); +int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p); +void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len); +int ssl3_enc(SSL *s, int send_data); +int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data); +void ssl3_free_digest_list(SSL *s); +unsigned long ssl3_output_cert_chain(SSL *s, X509 *x); +SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt, +			       STACK_OF(SSL_CIPHER) *srvr); +int	ssl3_setup_buffers(SSL *s); +int	ssl3_setup_read_buffer(SSL *s); +int	ssl3_setup_write_buffer(SSL *s); +int	ssl3_release_read_buffer(SSL *s); +int	ssl3_release_write_buffer(SSL *s); +int	ssl3_digest_cached_records(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, void *buf, int len); +int	ssl3_peek(SSL *s, void *buf, int len); +int	ssl3_write(SSL *s, const void *buf, int len); +int	ssl3_shutdown(SSL *s); +void	ssl3_clear(SSL *s); +long	ssl3_ctrl(SSL *s,int cmd, long larg, void *parg); +long	ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg); +long	ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void)); +long	ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void)); +int	ssl3_pending(const SSL *s); + +void ssl3_record_sequence_update(unsigned char *seq); +int ssl3_do_change_cipher_spec(SSL *ssl); +long ssl3_default_timeout(void ); + +int ssl23_num_ciphers(void ); +const SSL_CIPHER *ssl23_get_cipher(unsigned int u); +int ssl23_read(SSL *s, void *buf, int len); +int ssl23_peek(SSL *s, void *buf, int len); +int ssl23_write(SSL *s, const void *buf, int len); +int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p); +const SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p); +long ssl23_default_timeout(void ); + +long tls1_default_timeout(void); +int dtls1_do_write(SSL *s,int type); +int ssl3_read_n(SSL *s, int n, int max, int extend); +int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); +int ssl3_do_compress(SSL *ssl); +int ssl3_do_uncompress(SSL *ssl); +int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, +	unsigned int len); +unsigned char *dtls1_set_message_header(SSL *s,  +	unsigned char *p, unsigned char mt,	unsigned long len,  +	unsigned long frag_off, unsigned long frag_len); + +int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len); +int dtls1_write_bytes(SSL *s, int type, const void *buf, int len); + +int dtls1_send_change_cipher_spec(SSL *s, int a, int b); +int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen); +unsigned long dtls1_output_cert_chain(SSL *s, X509 *x); +int dtls1_read_failed(SSL *s, int code); +int dtls1_buffer_message(SSL *s, int ccs); +int dtls1_retransmit_message(SSL *s, unsigned short seq,  +	unsigned long frag_off, int *found); +int dtls1_get_queue_priority(unsigned short seq, int is_ccs); +int dtls1_retransmit_buffered_messages(SSL *s); +void dtls1_clear_record_buffer(SSL *s); +void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr); +void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); +void dtls1_reset_seq_numbers(SSL *s, int rw); +long dtls1_default_timeout(void); +struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft); +int dtls1_handle_timeout(SSL *s); +const SSL_CIPHER *dtls1_get_cipher(unsigned int u); +void dtls1_start_timer(SSL *s); +void dtls1_stop_timer(SSL *s); +int dtls1_is_timer_expired(SSL *s); +void dtls1_double_timeout(SSL *s); +int dtls1_send_newsession_ticket(SSL *s); + +/* some client-only functions */ +int ssl3_client_hello(SSL *s); +int ssl3_get_server_hello(SSL *s); +int ssl3_get_certificate_request(SSL *s); +int ssl3_get_new_session_ticket(SSL *s); +int ssl3_get_cert_status(SSL *s); +int ssl3_get_server_done(SSL *s); +int ssl3_send_client_verify(SSL *s); +int ssl3_send_client_certificate(SSL *s); +int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey); +int ssl3_send_client_key_exchange(SSL *s); +int ssl3_get_key_exchange(SSL *s); +int ssl3_get_server_certificate(SSL *s); +int ssl3_check_cert_and_algorithm(SSL *s); +#ifndef OPENSSL_NO_TLSEXT +int ssl3_check_finished(SSL *s); +# ifndef OPENSSL_NO_NEXTPROTONEG +int ssl3_send_next_proto(SSL *s); +# endif +#endif + +int dtls1_client_hello(SSL *s); +int dtls1_send_client_certificate(SSL *s); +int dtls1_send_client_key_exchange(SSL *s); +int dtls1_send_client_verify(SSL *s); + +/* some server-only functions */ +int ssl3_get_client_hello(SSL *s); +int ssl3_send_server_hello(SSL *s); +int ssl3_send_hello_request(SSL *s); +int ssl3_send_server_key_exchange(SSL *s); +int ssl3_send_certificate_request(SSL *s); +int ssl3_send_server_done(SSL *s); +int ssl3_check_client_hello(SSL *s); +int ssl3_get_client_certificate(SSL *s); +int ssl3_get_client_key_exchange(SSL *s); +int ssl3_get_cert_verify(SSL *s); +#ifndef OPENSSL_NO_NEXTPROTONEG +int ssl3_get_next_proto(SSL *s); +#endif + +int dtls1_send_hello_request(SSL *s); +int dtls1_send_server_hello(SSL *s); +int dtls1_send_server_certificate(SSL *s); +int dtls1_send_server_key_exchange(SSL *s); +int dtls1_send_certificate_request(SSL *s); +int dtls1_send_server_done(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); + +int tls1_new(SSL *s); +void tls1_free(SSL *s); +void tls1_clear(SSL *s); +long tls1_ctrl(SSL *s,int cmd, long larg, void *parg); +long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)(void)); + +int dtls1_new(SSL *s); +int	dtls1_accept(SSL *s); +int	dtls1_connect(SSL *s); +void dtls1_free(SSL *s); +void dtls1_clear(SSL *s); +long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg); + +long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); +int dtls1_get_record(SSL *s); +int do_dtls1_write(SSL *s, int type, const unsigned char *buf, +	unsigned int len, int create_empty_fragement); +int dtls1_dispatch_alert(SSL *s); +int dtls1_enc(SSL *s, int snd); + +int ssl_init_wbio_buffer(SSL *s, int push); +void ssl_free_wbio_buffer(SSL *s); + +int tls1_change_cipher_state(SSL *s, int which); +int tls1_setup_key_block(SSL *s); +int tls1_enc(SSL *s, int snd); +int tls1_final_finish_mac(SSL *s, +	const char *str, int slen, unsigned char *p); +int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p); +int tls1_mac(SSL *ssl, unsigned char *md, int snd); +int tls1_generate_master_secret(SSL *s, unsigned char *out, +	unsigned char *p, int len); +int tls1_alert_code(int code); +int ssl3_alert_code(int code); +int ssl_ok(SSL *s); + +#ifndef OPENSSL_NO_ECDH +int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs); +#endif + +SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); + +#ifndef OPENSSL_NO_EC +int tls1_ec_curve_id2nid(int curve_id); +int tls1_ec_nid2curve_id(int nid); +#endif /* OPENSSL_NO_EC */ + +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit);  +unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit);  +int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al); +int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al); +int ssl_prepare_clienthello_tlsext(SSL *s); +int ssl_prepare_serverhello_tlsext(SSL *s); +int ssl_check_clienthello_tlsext(SSL *s); +int ssl_check_serverhello_tlsext(SSL *s); + +#ifdef OPENSSL_NO_SHA256 +#define tlsext_tick_md	EVP_sha1 +#else +#define tlsext_tick_md	EVP_sha256 +#endif +int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, +				const unsigned char *limit, SSL_SESSION **ret); +#endif +EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ; +void ssl_clear_hash_ctx(EVP_MD_CTX **hash); +int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len, +					int maxlen); +int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len, +					  int *al); +int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, +					int maxlen); +int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len, +					  int *al); +#endif diff --git a/main/openssl/ssl/ssl_rsa.c b/main/openssl/ssl/ssl_rsa.c new file mode 100644 index 00000000..c43f3e2a --- /dev/null +++ b/main/openssl/ssl/ssl_rsa.c @@ -0,0 +1,815 @@ +/* ssl/ssl_rsa.c */ +/* Copyright (C) 1995-1998 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" +#include <openssl/bio.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/pem.h> + +static int ssl_set_cert(CERT *c, X509 *x509); +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); +int SSL_use_certificate(SSL *ssl, X509 *x) +	{ +	if (x == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (!ssl_cert_inst(&ssl->cert)) +		{ +		SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	return(ssl_set_cert(ssl->cert,x)); +	} + +#ifndef OPENSSL_NO_STDIO +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) +	{ +	int j; +	BIO *in; +	int ret=0; +	X509 *x=NULL; + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		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,ssl->ctx->default_passwd_callback_userdata); +		} +	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); +	} +#endif + +int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) +	{ +	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 OPENSSL_NO_RSA +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) +	{ +	EVP_PKEY *pkey; +	int ret; + +	if (rsa == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (!ssl_cert_inst(&ssl->cert)) +		{ +		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	if ((pkey=EVP_PKEY_new()) == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); +		return(0); +		} + +	RSA_up_ref(rsa); +	EVP_PKEY_assign_RSA(pkey,rsa); + +	ret=ssl_set_pkey(ssl->cert,pkey); +	EVP_PKEY_free(pkey); +	return(ret); +	} +#endif + +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) +	{ +	int i; + +	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) +		{ +		EVP_PKEY *pktmp; +		pktmp =	X509_get_pubkey(c->pkeys[i].x509); +		EVP_PKEY_copy_parameters(pktmp,pkey); +		EVP_PKEY_free(pktmp); +		ERR_clear_error(); + +#ifndef OPENSSL_NO_RSA +		/* Don't check the public/private key, this is mostly +		 * for smart cards. */ +		if ((pkey->type == EVP_PKEY_RSA) && +			(RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) +			; +		else +#endif +		if (!X509_check_private_key(c->pkeys[i].x509,pkey)) +			{ +			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 OPENSSL_NO_RSA +#ifndef OPENSSL_NO_STDIO +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) +	{ +	int j,ret=0; +	BIO *in; +	RSA *rsa=NULL; + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		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,ssl->ctx->default_passwd_callback_userdata); +		} +	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); +	} +#endif + +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len) +	{ +	int ret; +	const 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 /* !OPENSSL_NO_RSA */ + +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) +	{ +	int ret; + +	if (pkey == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (!ssl_cert_inst(&ssl->cert)) +		{ +		SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	ret=ssl_set_pkey(ssl->cert,pkey); +	return(ret); +	} + +#ifndef OPENSSL_NO_STDIO +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) +	{ +	int j,ret=0; +	BIO *in; +	EVP_PKEY *pkey=NULL; + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		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,ssl->ctx->default_passwd_callback_userdata); +		} +	else if (type == SSL_FILETYPE_ASN1) +		{ +		j = ERR_R_ASN1_LIB; +		pkey = d2i_PrivateKey_bio(in,NULL); +		} +	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); +	} +#endif + +int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len) +	{ +	int ret; +	const 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(SSL_CTX *ctx, X509 *x) +	{ +	if (x == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (!ssl_cert_inst(&ctx->cert)) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	return(ssl_set_cert(ctx->cert, x)); +	} + +static int ssl_set_cert(CERT *c, X509 *x) +	{ +	EVP_PKEY *pkey; +	int i; + +	pkey=X509_get_pubkey(x); +	if (pkey == NULL) +		{ +		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB); +		return(0); +		} + +	i=ssl_cert_type(x,pkey); +	if (i < 0) +		{ +		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE); +		EVP_PKEY_free(pkey); +		return(0); +		} + +	if (c->pkeys[i].privatekey != NULL) +		{ +		EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey); +		ERR_clear_error(); + +#ifndef OPENSSL_NO_RSA +		/* Don't check the public/private key, this is mostly +		 * for smart cards. */ +		if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && +			(RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & +			 RSA_METHOD_FLAG_NO_CHECK)) +			 ; +		else +#endif /* OPENSSL_NO_RSA */ +		if (!X509_check_private_key(x,c->pkeys[i].privatekey)) +			{ +			/* don't fail for a cert/key mismatch, just free +			 * current private key (when switching to a different +			 * cert & key, first this function should be used, +			 * then ssl_set_pkey */ +			EVP_PKEY_free(c->pkeys[i].privatekey); +			c->pkeys[i].privatekey=NULL; +			/* clear error queue */ +			ERR_clear_error(); +			} +		} + +	EVP_PKEY_free(pkey); + +	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); +	} + +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) +	{ +	int j; +	BIO *in; +	int ret=0; +	X509 *x=NULL; + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		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,ctx->default_passwd_callback_userdata); +		} +	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); +	} +#endif + +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const 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 OPENSSL_NO_RSA +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) +	{ +	int ret; +	EVP_PKEY *pkey; + +	if (rsa == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (!ssl_cert_inst(&ctx->cert)) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	if ((pkey=EVP_PKEY_new()) == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); +		return(0); +		} + +	RSA_up_ref(rsa); +	EVP_PKEY_assign_RSA(pkey,rsa); + +	ret=ssl_set_pkey(ctx->cert, pkey); +	EVP_PKEY_free(pkey); +	return(ret); +	} + +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) +	{ +	int j,ret=0; +	BIO *in; +	RSA *rsa=NULL; + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		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,ctx->default_passwd_callback_userdata); +		} +	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); +	} +#endif + +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len) +	{ +	int ret; +	const 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 /* !OPENSSL_NO_RSA */ + +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) +	{ +	if (pkey == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (!ssl_cert_inst(&ctx->cert)) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); +		return(0); +		} +	return(ssl_set_pkey(ctx->cert,pkey)); +	} + +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) +	{ +	int j,ret=0; +	BIO *in; +	EVP_PKEY *pkey=NULL; + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		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,ctx->default_passwd_callback_userdata); +		} +	else if (type == SSL_FILETYPE_ASN1) +		{ +		j = ERR_R_ASN1_LIB; +		pkey = d2i_PrivateKey_bio(in,NULL); +		} +	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); +	} +#endif + +int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, +	     long len) +	{ +	int ret; +	const 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); +	} + + +int SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain) +	{ +	if (ssl == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,ERR_R_PASSED_NULL_PARAMETER); +		return(0); +		} +	if (ssl->cert == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED); +		return(0); +		} +	if (ssl->cert->key == NULL) +		{ +		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED); +		return(0); +		} +	ssl->cert->key->cert_chain = cert_chain; +	return(1); +	} + +STACK_OF(X509) *SSL_get_certificate_chain(SSL *ssl, X509 *x) +	{ +	int i; +	if (x == NULL) +		return NULL; +	if (ssl == NULL) +		return NULL; +	if (ssl->cert == NULL) +		return NULL; +	for (i = 0; i < SSL_PKEY_NUM; i++) +		if (ssl->cert->pkeys[i].x509 == x) +			return ssl->cert->pkeys[i].cert_chain; +	return NULL; +	} + +#ifndef OPENSSL_NO_STDIO +/* Read a file that contains our certificate in "PEM" format, + * possibly followed by a sequence of CA certificates that should be + * sent to the peer in the Certificate message. + */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +	{ +	BIO *in; +	int ret=0; +	X509 *x=NULL; + +	ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ + +	in=BIO_new(BIO_s_file_internal()); +	if (in == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB); +		goto end; +		} + +	if (BIO_read_filename(in,file) <= 0) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_SYS_LIB); +		goto end; +		} + +	x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); +	if (x == NULL) +		{ +		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB); +		goto end; +		} + +	ret=SSL_CTX_use_certificate(ctx,x); +	if (ERR_peek_error() != 0) +		ret = 0;  /* Key/certificate mismatch doesn't imply ret==0 ... */ +	if (ret) +		{ +		/* If we could set up our certificate, now proceed to +		 * the CA certificates. +		 */ +		X509 *ca; +		int r; +		unsigned long err; +		 +		if (ctx->extra_certs != NULL)  +			{ +			sk_X509_pop_free(ctx->extra_certs, X509_free); +			ctx->extra_certs = NULL; +			} + +		while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata)) +			!= NULL) +			{ +			r = SSL_CTX_add_extra_chain_cert(ctx, ca); +			if (!r)  +				{ +				X509_free(ca); +				ret = 0; +				goto end; +				} +			/* Note that we must not free r if it was successfully +			 * added to the chain (while we must free the main +			 * certificate, since its reference count is increased +			 * by SSL_CTX_use_certificate). */ +			} +		/* When the while loop ends, it's usually just EOF. */ +		err = ERR_peek_last_error(); +		if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) +			ERR_clear_error(); +		else  +			ret = 0; /* some real error */ +		} + +end: +	if (x != NULL) X509_free(x); +	if (in != NULL) BIO_free(in); +	return(ret); +	} +#endif diff --git a/main/openssl/ssl/ssl_sess.c b/main/openssl/ssl/ssl_sess.c new file mode 100644 index 00000000..93954e48 --- /dev/null +++ b/main/openssl/ssl/ssl_sess.c @@ -0,0 +1,1102 @@ +/* ssl/ssl_sess.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include <openssl/lhash.h> +#include <openssl/rand.h> +#ifndef OPENSSL_NO_ENGINE +#include <openssl/engine.h> +#endif +#include "ssl_locl.h" + +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); +static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s); +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); + +SSL_SESSION *SSL_get_session(const SSL *ssl) +/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ +	{ +	return(ssl->session); +	} + +SSL_SESSION *SSL_get1_session(SSL *ssl) +/* variant of SSL_get_session: caller really gets something */ +	{ +	SSL_SESSION *sess; +	/* Need to lock this all up rather than just use CRYPTO_add so that +	 * somebody doesn't free ssl->session between when we check it's +	 * non-null and when we up the reference count. */ +	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); +	sess = ssl->session; +	if(sess) +		sess->references++; +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); +	return(sess); +	} + +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, +	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +	{ +	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, +			new_func, dup_func, free_func); +	} + +int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) +	{ +	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); +	} + +void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) +	{ +	return(CRYPTO_get_ex_data(&s->ex_data,idx)); +	} + +SSL_SESSION *SSL_SESSION_new(void) +	{ +	SSL_SESSION *ss; + +	ss=(SSL_SESSION *)OPENSSL_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->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ +	ss->references=1; +	ss->timeout=60*5+4; /* 5 minute timeout by default */ +	ss->time=(unsigned long)time(NULL); +	ss->prev=NULL; +	ss->next=NULL; +	ss->compress_meth=0; +#ifndef OPENSSL_NO_TLSEXT +	ss->tlsext_hostname = NULL;  +#ifndef OPENSSL_NO_EC +	ss->tlsext_ecpointformatlist_length = 0; +	ss->tlsext_ecpointformatlist = NULL; +	ss->tlsext_ellipticcurvelist_length = 0; +	ss->tlsext_ellipticcurvelist = NULL; +#endif +#endif +	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); +#ifndef OPENSSL_NO_PSK +	ss->psk_identity_hint=NULL; +	ss->psk_identity=NULL; +#endif +	return(ss); +	} + +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) +	{ +	if(len) +		*len = s->session_id_length; +	return s->session_id; +	} + +/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 + * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly + * until we have no conflict is going to complete in one iteration pretty much + * "most" of the time (btw: understatement). So, if it takes us 10 iterations + * and we still can't avoid a conflict - well that's a reasonable point to call + * it quits. Either the RAND code is broken or someone is trying to open roughly + * very close to 2^128 (or 2^256) SSL sessions to our server. How you might + * store that many sessions is perhaps a more interesting question ... */ + +#define MAX_SESS_ID_ATTEMPTS 10 +static int def_generate_session_id(const SSL *ssl, unsigned char *id, +				unsigned int *id_len) +{ +	unsigned int retry = 0; +	do +		if (RAND_pseudo_bytes(id, *id_len) <= 0) +			return 0; +	while(SSL_has_matching_session_id(ssl, id, *id_len) && +		(++retry < MAX_SESS_ID_ATTEMPTS)); +	if(retry < MAX_SESS_ID_ATTEMPTS) +		return 1; +	/* else - woops a session_id match */ +	/* XXX We should also check the external cache -- +	 * but the probability of a collision is negligible, and +	 * we could not prevent the concurrent creation of sessions +	 * with identical IDs since we currently don't have means +	 * to atomically check whether a session ID already exists +	 * and make a reservation for it if it does not +	 * (this problem applies to the internal cache as well). +	 */ +	return 0; +} + +void SSL_set_session_creation_enabled (SSL *s, int creation_enabled) +	{ +	s->session_creation_enabled = creation_enabled; +	} + +int ssl_get_new_session(SSL *s, int session) +	{ +	/* This gets used by clients and servers. */ + +	unsigned int tmp; +	SSL_SESSION *ss=NULL; +	GEN_SESSION_CB cb = def_generate_session_id; + +	/* caller should check this if they can do better error handling */ +        if (!s->session_creation_enabled) return(0); +	if ((ss=SSL_SESSION_new()) == NULL) return(0); + +	/* If the context has a default timeout, use it */ +	if (s->session_ctx->session_timeout == 0) +		ss->timeout=SSL_get_default_timeout(s); +	else +		ss->timeout=s->session_ctx->session_timeout; + +	if (s->session != NULL) +		{ +		SSL_SESSION_free(s->session); +		s->session=NULL; +		} + +	if (session) +		{ +		if (s->version == SSL2_VERSION) +			{ +			ss->ssl_version=SSL2_VERSION; +			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; +			} +		else if (s->version == SSL3_VERSION) +			{ +			ss->ssl_version=SSL3_VERSION; +			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; +			} +		else if (s->version == TLS1_VERSION) +			{ +			ss->ssl_version=TLS1_VERSION; +			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; +			} +		else if (s->version == DTLS1_BAD_VER) +			{ +			ss->ssl_version=DTLS1_BAD_VER; +			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH; +			} +		else if (s->version == DTLS1_VERSION) +			{ +			ss->ssl_version=DTLS1_VERSION; +			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); +			} +#ifndef OPENSSL_NO_TLSEXT +		/* If RFC4507 ticket use empty session ID */ +		if (s->tlsext_ticket_expected) +			{ +			ss->session_id_length = 0; +			goto sess_id_done; +			} +#endif +		/* Choose which callback will set the session ID */ +		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); +		if(s->generate_session_id) +			cb = s->generate_session_id; +		else if(s->session_ctx->generate_session_id) +			cb = s->session_ctx->generate_session_id; +		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); +		/* Choose a session ID */ +		tmp = ss->session_id_length; +		if(!cb(s, ss->session_id, &tmp)) +			{ +			/* The callback failed */ +			SSLerr(SSL_F_SSL_GET_NEW_SESSION, +				SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); +			SSL_SESSION_free(ss); +			return(0); +			} +		/* Don't allow the callback to set the session length to zero. +		 * nor set it higher than it was. */ +		if(!tmp || (tmp > ss->session_id_length)) +			{ +			/* The callback set an illegal length */ +			SSLerr(SSL_F_SSL_GET_NEW_SESSION, +				SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); +			SSL_SESSION_free(ss); +			return(0); +			} +		/* If the session length was shrunk and we're SSLv2, pad it */ +		if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION)) +			memset(ss->session_id + tmp, 0, ss->session_id_length - tmp); +		else +			ss->session_id_length = tmp; +		/* Finally, check for a conflict */ +		if(SSL_has_matching_session_id(s, ss->session_id, +						ss->session_id_length)) +			{ +			SSLerr(SSL_F_SSL_GET_NEW_SESSION, +				SSL_R_SSL_SESSION_ID_CONFLICT); +			SSL_SESSION_free(ss); +			return(0); +			} +#ifndef OPENSSL_NO_TLSEXT +		sess_id_done: +		if (s->tlsext_hostname) { +			ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname); +			if (ss->tlsext_hostname == NULL) { +				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR); +				SSL_SESSION_free(ss); +				return 0; +				} +			} +#ifndef OPENSSL_NO_EC +		if (s->tlsext_ecpointformatlist) +			{ +			if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist); +			if ((ss->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL) +				{ +				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); +				SSL_SESSION_free(ss); +				return 0; +				} +			ss->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length; +			memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length); +			} +		if (s->tlsext_ellipticcurvelist) +			{ +			if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist); +			if ((ss->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL) +				{ +				SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); +				SSL_SESSION_free(ss); +				return 0; +				} +			ss->tlsext_ellipticcurvelist_length = s->tlsext_ellipticcurvelist_length; +			memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length); +			} +#endif +#endif +		} +	else +		{ +		ss->session_id_length=0; +		} + +	if (s->sid_ctx_length > sizeof ss->sid_ctx) +		{ +		SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR); +		SSL_SESSION_free(ss); +		return 0; +		} +	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); +	ss->sid_ctx_length=s->sid_ctx_length; +	s->session=ss; +	ss->ssl_version=s->version; +	ss->verify_result = X509_V_OK; + +	return(1); +	} + +int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, +			const unsigned char *limit) +	{ +	/* This is used only by servers. */ + +	SSL_SESSION *ret=NULL; +	int fatal = 0; +#ifndef OPENSSL_NO_TLSEXT +	int r; +#endif + +	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) +		goto err; +#ifndef OPENSSL_NO_TLSEXT +	r = tls1_process_ticket(s, session_id, len, limit, &ret); +	if (r == -1) +		{ +		fatal = 1; +		goto err; +		} +	else if (r == 0 || (!ret && !len)) +		goto err; +	else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) +#else +	if (len == 0) +		goto err; +	if (!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) +#endif +		{ +		SSL_SESSION data; +		data.ssl_version=s->version; +		data.session_id_length=len; +		if (len == 0) +			return 0; +		memcpy(data.session_id,session_id,len); +		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); +		ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data); +		if (ret != NULL) +		    /* don't allow other threads to steal it: */ +		    CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); +		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); +		} + +	if (ret == NULL) +		{ +		int copy=1; +	 +		s->session_ctx->stats.sess_miss++; +		ret=NULL; +		if (s->session_ctx->get_session_cb != NULL +		    && (ret=s->session_ctx->get_session_cb(s,session_id,len,©)) +		       != NULL) +			{ +			s->session_ctx->stats.sess_cb_hit++; + +			/* Increment reference count now if the session callback +			 * asks us to do so (note that if the session structures +			 * returned by the callback are shared between threads, +			 * it must handle the reference count itself [i.e. copy == 0], +			 * or things won't be thread-safe). */ +			if (copy) +				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); + +			/* Add the externally cached session to the internal +			 * cache as well if and only if we are supposed to. */ +			if(!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE)) +				/* The following should not return 1, otherwise, +				 * things are very strange */ +				SSL_CTX_add_session(s->session_ctx,ret); +			} +		if (ret == NULL) +			goto err; +		} + +	/* Now ret is non-NULL, and we own one of its reference counts. */ + +	if (ret->sid_ctx_length != s->sid_ctx_length +	    || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)) +		{ +		/* We've found the session named by the client, but we don't +		 * want to use it in this context. */ + +#if 0 /* The client cannot always know when a session is not appropriate, +       * so we shouldn't generate an error message. */ + +		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); +#endif +		goto err; /* treat like cache miss */ +		} +	 +	if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) +		{ +		/* We can't be sure if this session is being used out of +		 * context, which is especially important for SSL_VERIFY_PEER. +		 * The application should have used SSL[_CTX]_set_session_id_context. +		 * +		 * For this error case, we generate an error instead of treating +		 * the event like a cache miss (otherwise it would be easy for +		 * applications to effectively disable the session cache by +		 * accident without anyone noticing). +		 */ +		 +		SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); +		fatal = 1; +		goto err; +		} + +	if (ret->cipher == NULL) +		{ +		unsigned char buf[5],*p; +		unsigned long l; + +		p=buf; +		l=ret->cipher_id; +		l2n(l,p); +		if ((ret->ssl_version>>8) >= SSL3_VERSION_MAJOR) +			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) +			goto err; +		} + + +#if 0 /* This is way too late. */ + +	/* If a thread got the session, then 'swaped', and another got +	 * it and then due to a time-out decided to 'OPENSSL_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); +#endif + +	if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */ +		{ +		s->session_ctx->stats.sess_timeout++; +		/* remove it from the cache */ +		SSL_CTX_remove_session(s->session_ctx,ret); +		goto err; +		} + +	s->session_ctx->stats.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; +	s->verify_result = s->session->verify_result; +	return(1); + + err: +	if (ret != NULL) +		SSL_SESSION_free(ret); +	if (fatal) +		return -1; +	else +		return 0; +	} + +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) +	{ +	int ret=0; +	SSL_SESSION *s; + +	/* add just 1 reference count for the SSL_CTX's session cache +	 * even though it has two ways of access: each session is in a +	 * doubly linked list and an lhash */ +	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); +	/* if session c is in already in cache, we take back the increment later */ + +	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +	s=lh_SSL_SESSION_insert(ctx->sessions,c); +	 +	/* s != NULL iff we already had a session with the given PID. +	 * In this case, s == c should hold (then we did not really modify +	 * ctx->sessions), or we're in trouble. */ +	if (s != NULL && s != c) +		{ +		/* We *are* in trouble ... */ +		SSL_SESSION_list_remove(ctx,s); +		SSL_SESSION_free(s); +		/* ... so pretend the other session did not exist in cache +		 * (we cannot handle two SSL_SESSION structures with identical +		 * session ID in the same cache, which could happen e.g. when +		 * two threads concurrently obtain the same session from an external +		 * cache) */ +		s = NULL; +		} + + 	/* Put at the head of the queue unless it is already in the cache */ +	if (s == NULL) +		SSL_SESSION_list_add(ctx,c); + +	if (s != NULL) +		{ +		/* existing cache entry -- decrement previously incremented reference +		 * count because it already takes into account the cache */ + +		SSL_SESSION_free(s); /* s == c */ +		ret=0; +		} +	else +		{ +		/* new cache entry -- remove old ones if cache has become too large */ +		 +		ret=1; + +		if (SSL_CTX_sess_get_cache_size(ctx) > 0) +			{ +			while (SSL_CTX_sess_number(ctx) > +				SSL_CTX_sess_get_cache_size(ctx)) +				{ +				if (!remove_session_lock(ctx, +					ctx->session_cache_tail, 0)) +					break; +				else +					ctx->stats.sess_cache_full++; +				} +			} +		} +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +	return(ret); +	} + +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) +{ +	return remove_session_lock(ctx, c, 1); +} + +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) +	{ +	SSL_SESSION *r; +	int ret=0; + +	if ((c != NULL) && (c->session_id_length != 0)) +		{ +		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +		if ((r = lh_SSL_SESSION_retrieve(ctx->sessions,c)) == c) +			{ +			ret=1; +			r=lh_SSL_SESSION_delete(ctx->sessions,c); +			SSL_SESSION_list_remove(ctx,c); +			} + +		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + +		if (ret) +			{ +			r->not_resumable=1; +			if (ctx->remove_session_cb != NULL) +				ctx->remove_session_cb(ctx,r); +			SSL_SESSION_free(r); +			} +		} +	else +		ret=0; +	return(ret); +	} + +void SSL_SESSION_free(SSL_SESSION *ss) +	{ +	int i; + +	if(ss == NULL) +	    return; + +	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); +#ifdef REF_PRINT +	REF_PRINT("SSL_SESSION",ss); +#endif +	if (i > 0) return; +#ifdef REF_CHECK +	if (i < 0) +		{ +		fprintf(stderr,"SSL_SESSION_free, bad reference count\n"); +		abort(); /* ok */ +		} +#endif + +	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + +	OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg); +	OPENSSL_cleanse(ss->master_key,sizeof ss->master_key); +	OPENSSL_cleanse(ss->session_id,sizeof ss->session_id); +	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); +	if (ss->peer != NULL) X509_free(ss->peer); +	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers); +#ifndef OPENSSL_NO_TLSEXT +	if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname); +	if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick); +#ifndef OPENSSL_NO_EC +	ss->tlsext_ecpointformatlist_length = 0; +	if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist); +	ss->tlsext_ellipticcurvelist_length = 0; +	if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist); +#endif /* OPENSSL_NO_EC */ +#endif +#ifndef OPENSSL_NO_PSK +	if (ss->psk_identity_hint != NULL) +		OPENSSL_free(ss->psk_identity_hint); +	if (ss->psk_identity != NULL) +		OPENSSL_free(ss->psk_identity); +#endif +	OPENSSL_cleanse(ss,sizeof(*ss)); +	OPENSSL_free(ss); +	} + +int SSL_set_session(SSL *s, SSL_SESSION *session) +	{ +	int ret=0; +	const 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); +			if (s->ctx->session_timeout == 0) +				session->timeout=SSL_get_default_timeout(s); +			else +				session->timeout=s->ctx->session_timeout; +			} + +#ifndef OPENSSL_NO_KRB5 +                if (s->kssl_ctx && !s->kssl_ctx->client_princ && +                    session->krb5_client_princ_len > 0) +                { +                    s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1); +                    memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ, +                            session->krb5_client_princ_len); +                    s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0'; +                } +#endif /* OPENSSL_NO_KRB5 */ + +		/* 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; +		s->verify_result = s->session->verify_result; +		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/ +		ret=1; +		} +	else +		{ +		if (s->session != NULL) +			{ +			SSL_SESSION_free(s->session); +			s->session=NULL; +			} + +		meth=s->ctx->method; +		if (meth != s->method) +			{ +			if (!SSL_set_ssl_method(s,meth)) +				return(0); +			} +		ret=1; +		} +	return(ret); +	} + +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) +	{ +	if (s == NULL) return(0); +	s->timeout=t; +	return(1); +	} + +long SSL_SESSION_get_timeout(const SSL_SESSION *s) +	{ +	if (s == NULL) return(0); +	return(s->timeout); +	} + +long SSL_SESSION_get_time(const SSL_SESSION *s) +	{ +	if (s == NULL) return(0); +	return(s->time); +	} + +long SSL_SESSION_set_time(SSL_SESSION *s, long t) +	{ +	if (s == NULL) return(0); +	s->time=t; +	return(t); +	} + +long SSL_CTX_set_timeout(SSL_CTX *s, long t) +	{ +	long l; +	if (s == NULL) return(0); +	l=s->session_timeout; +	s->session_timeout=t; +	return(l); +	} + +long SSL_CTX_get_timeout(const SSL_CTX *s) +	{ +	if (s == NULL) return(0); +	return(s->session_timeout); +	} + +#ifndef OPENSSL_NO_TLSEXT +int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, +	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) +	{ +	if (s == NULL) return(0); +	s->tls_session_secret_cb = tls_session_secret_cb; +	s->tls_session_secret_cb_arg = arg; +	return(1); +	} + +int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, +				  void *arg) +	{ +	if (s == NULL) return(0); +	s->tls_session_ticket_ext_cb = cb; +	s->tls_session_ticket_ext_cb_arg = arg; +	return(1); +	} + +int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) +	{ +	if (s->version >= TLS1_VERSION) +		{ +		if (s->tlsext_session_ticket) +			{ +			OPENSSL_free(s->tlsext_session_ticket); +			s->tlsext_session_ticket = NULL; +			} + +		s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); +		if (!s->tlsext_session_ticket) +			{ +			SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); +			return 0; +			} + +		if (ext_data) +			{ +			s->tlsext_session_ticket->length = ext_len; +			s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1; +			memcpy(s->tlsext_session_ticket->data, ext_data, ext_len); +			} +		else +			{ +			s->tlsext_session_ticket->length = 0; +			s->tlsext_session_ticket->data = NULL; +			} + +		return 1; +		} + +	return 0; +	} +#endif /* OPENSSL_NO_TLSEXT */ + +typedef struct timeout_param_st +	{ +	SSL_CTX *ctx; +	long time; +	LHASH_OF(SSL_SESSION) *cache; +	} TIMEOUT_PARAM; + +static void timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p) +	{ +	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */ +		{ +		/* The reason we don't call SSL_CTX_remove_session() is to +		 * save on locking overhead */ +		(void)lh_SSL_SESSION_delete(p->cache,s); +		SSL_SESSION_list_remove(p->ctx,s); +		s->not_resumable=1; +		if (p->ctx->remove_session_cb != NULL) +			p->ctx->remove_session_cb(p->ctx,s); +		SSL_SESSION_free(s); +		} +	} + +static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION, TIMEOUT_PARAM) + +void SSL_CTX_flush_sessions(SSL_CTX *s, long t) +	{ +	unsigned long i; +	TIMEOUT_PARAM tp; + +	tp.ctx=s; +	tp.cache=s->sessions; +	if (tp.cache == NULL) return; +	tp.time=t; +	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +	i=CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load; +	CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=0; +	lh_SSL_SESSION_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), +				 TIMEOUT_PARAM, &tp); +	CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=i; +	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +	} + +int ssl_clear_bad_session(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); +	} + +/* locked by SSL_CTX in the calling function */ +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) +	{ +	if ((s->next == NULL) || (s->prev == NULL)) return; + +	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) +		{ /* last element in list */ +		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) +			{ /* only one element in list */ +			ctx->session_cache_head=NULL; +			ctx->session_cache_tail=NULL; +			} +		else +			{ +			ctx->session_cache_tail=s->prev; +			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail); +			} +		} +	else +		{ +		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) +			{ /* first element in list */ +			ctx->session_cache_head=s->next; +			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head); +			} +		else +			{ /* middle of list */ +			s->next->prev=s->prev; +			s->prev->next=s->next; +			} +		} +	s->prev=s->next=NULL; +	} + +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) +	{ +	if ((s->next != NULL) && (s->prev != NULL)) +		SSL_SESSION_list_remove(ctx,s); + +	if (ctx->session_cache_head == NULL) +		{ +		ctx->session_cache_head=s; +		ctx->session_cache_tail=s; +		s->prev=(SSL_SESSION *)&(ctx->session_cache_head); +		s->next=(SSL_SESSION *)&(ctx->session_cache_tail); +		} +	else +		{ +		s->next=ctx->session_cache_head; +		s->next->prev=s; +		s->prev=(SSL_SESSION *)&(ctx->session_cache_head); +		ctx->session_cache_head=s; +		} +	} + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, +	int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess)) +	{ +	ctx->new_session_cb=cb; +	} + +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) +	{ +	return ctx->new_session_cb; +	} + +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, +	void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess)) +	{ +	ctx->remove_session_cb=cb; +	} + +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess) +	{ +	return ctx->remove_session_cb; +	} + +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, +	SSL_SESSION *(*cb)(struct ssl_st *ssl, +	         unsigned char *data,int len,int *copy)) +	{ +	ctx->get_session_cb=cb; +	} + +SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, +	         unsigned char *data,int len,int *copy) +	{ +	return ctx->get_session_cb; +	} + +void SSL_CTX_set_info_callback(SSL_CTX *ctx,  +	void (*cb)(const SSL *ssl,int type,int val)) +	{ +	ctx->info_callback=cb; +	} + +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val) +	{ +	return ctx->info_callback; +	} + +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, +	int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)) +	{ +	ctx->client_cert_cb=cb; +	} + +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey) +	{ +	return ctx->client_cert_cb; +	} + +#ifndef OPENSSL_NO_ENGINE +int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) +	{ +	if (!ENGINE_init(e)) +		{ +		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB); +		return 0; +		} +	if(!ENGINE_get_ssl_client_cert_function(e)) +		{ +		SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD); +		ENGINE_finish(e); +		return 0; +		} +	ctx->client_cert_engine = e; +	return 1; +	} +#endif + +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, +	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)) +	{ +	ctx->app_gen_cookie_cb=cb; +	} + +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, +	int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len)) +	{ +	ctx->app_verify_cookie_cb=cb; +	} + +IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) diff --git a/main/openssl/ssl/ssl_stat.c b/main/openssl/ssl/ssl_stat.c new file mode 100644 index 00000000..144b81e5 --- /dev/null +++ b/main/openssl/ssl/ssl_stat.c @@ -0,0 +1,567 @@ +/* ssl/ssl_stat.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include "ssl_locl.h" + +const char *SSL_state_string_long(const SSL *s) +	{ +	const char *str; + +	switch (s->state) +		{ +case SSL_ST_BEFORE: str="before SSL initialization"; break; +case SSL_ST_ACCEPT: str="before accept initialization"; break; +case SSL_ST_CONNECT: str="before connect initialization"; 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 initialization"; break; +case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initialization"; break; +case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initialization"; break; +case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initialization"; break; +#ifndef OPENSSL_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 OPENSSL_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_SESSION_TICKET_A: str="SSLv3 read server session ticket A";break; +case SSL3_ST_CR_SESSION_TICKET_B: str="SSLv3 read server session ticket 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_CERT_C:		str="SSLv3 write client certificate C"; break; +case SSL3_ST_CW_CERT_D:		str="SSLv3 write client certificate D"; 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 B"; 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 B"; 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_SESSION_TICKET_A: str="SSLv3 write session ticket A"; break; +case SSL3_ST_SW_SESSION_TICKET_B: str="SSLv3 write session ticket 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(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) +/* SSLv2/v3 compatibility 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 + +/* DTLS */ +case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DTLS1 read hello verify request A"; break; +case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DTLS1 read hello verify request B"; break; +case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: str="DTLS1 write hello verify request A"; break; +case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: str="DTLS1 write hello verify request B"; break; + +default:	str="unknown state"; break; +		} +	return(str); +	} + +const char *SSL_rstate_string_long(const SSL *s) +	{ +	const char *str; + +	switch (s->rstate) +		{ +	case SSL_ST_READ_HEADER: str="read header"; break; +	case SSL_ST_READ_BODY: str="read body"; break; +	case SSL_ST_READ_DONE: str="read done"; break; +	default: str="unknown"; break; +		} +	return(str); +	} + +const char *SSL_state_string(const SSL *s) +	{ +	const 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 OPENSSL_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 OPENSSL_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_CERT_C:				str="3WCC_C"; break; +case SSL3_ST_CW_CERT_D:				str="3WCC_D"; 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(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) +/* SSLv2/v3 compatibility 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 +/* DTLS */ +case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DRCHVA"; break; +case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DRCHVB"; break; +case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: str="DWCHVA"; break; +case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: str="DWCHVB"; break; + +default:					str="UNKWN "; break; +		} +	return(str); +	} + +const char *SSL_alert_type_string_long(int value) +	{ +	value>>=8; +	if (value == SSL3_AL_WARNING) +		return("warning"); +	else if (value == SSL3_AL_FATAL) +		return("fatal"); +	else +		return("unknown"); +	} + +const char *SSL_alert_type_string(int value) +	{ +	value>>=8; +	if (value == SSL3_AL_WARNING) +		return("W"); +	else if (value == SSL3_AL_FATAL) +		return("F"); +	else +		return("U"); +	} + +const char *SSL_alert_desc_string(int value) +	{ +	const 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; +	case TLS1_AD_DECRYPTION_FAILED:		str="DC"; break; +	case TLS1_AD_RECORD_OVERFLOW:		str="RO"; break; +	case TLS1_AD_UNKNOWN_CA:		str="CA"; break; +	case TLS1_AD_ACCESS_DENIED:		str="AD"; break; +	case TLS1_AD_DECODE_ERROR:		str="DE"; break; +	case TLS1_AD_DECRYPT_ERROR:		str="CY"; break; +	case TLS1_AD_EXPORT_RESTRICTION:	str="ER"; break; +	case TLS1_AD_PROTOCOL_VERSION:		str="PV"; break; +	case TLS1_AD_INSUFFICIENT_SECURITY:	str="IS"; break; +	case TLS1_AD_INTERNAL_ERROR:		str="IE"; break; +	case TLS1_AD_USER_CANCELLED:		str="US"; break; +	case TLS1_AD_NO_RENEGOTIATION:		str="NR"; break; +	case TLS1_AD_UNSUPPORTED_EXTENSION:	str="UE"; break; +	case TLS1_AD_CERTIFICATE_UNOBTAINABLE:	str="CO"; break; +	case TLS1_AD_UNRECOGNIZED_NAME:		str="UN"; break; +	case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: str="BR"; break; +	case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: str="BH"; break; +	case TLS1_AD_UNKNOWN_PSK_IDENTITY:	str="UP"; break; +	default:				str="UK"; break; +		} +	return(str); +	} + +const char *SSL_alert_desc_string_long(int value) +	{ +	const char *str; + +	switch (value & 0xff) +		{ +	case SSL3_AD_CLOSE_NOTIFY: +		str="close notify"; +		break; +	case SSL3_AD_UNEXPECTED_MESSAGE: +		str="unexpected_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="certificate unknown"; +		break; +	case SSL3_AD_ILLEGAL_PARAMETER: +		str="illegal parameter"; +		break; +	case TLS1_AD_DECRYPTION_FAILED: +		str="decryption failed"; +		break; +	case TLS1_AD_RECORD_OVERFLOW: +		str="record overflow"; +		break; +	case TLS1_AD_UNKNOWN_CA: +		str="unknown CA"; +		break; +	case TLS1_AD_ACCESS_DENIED: +		str="access denied"; +		break; +	case TLS1_AD_DECODE_ERROR: +		str="decode error"; +		break; +	case TLS1_AD_DECRYPT_ERROR: +		str="decrypt error"; +		break; +	case TLS1_AD_EXPORT_RESTRICTION: +		str="export restriction"; +		break; +	case TLS1_AD_PROTOCOL_VERSION: +		str="protocol version"; +		break; +	case TLS1_AD_INSUFFICIENT_SECURITY: +		str="insufficient security"; +		break; +	case TLS1_AD_INTERNAL_ERROR: +		str="internal error"; +		break; +	case TLS1_AD_USER_CANCELLED: +		str="user canceled"; +		break; +	case TLS1_AD_NO_RENEGOTIATION: +		str="no renegotiation"; +		break; +	case TLS1_AD_UNSUPPORTED_EXTENSION: +		str="unsupported extension"; +		break; +	case TLS1_AD_CERTIFICATE_UNOBTAINABLE: +		str="certificate unobtainable"; +		break; +	case TLS1_AD_UNRECOGNIZED_NAME: +		str="unrecognized name"; +		break; +	case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: +		str="bad certificate status response"; +		break; +	case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: +		str="bad certificate hash value"; +		break; +	case TLS1_AD_UNKNOWN_PSK_IDENTITY: +		str="unknown PSK identity"; +		break; +	default: str="unknown"; break; +		} +	return(str); +	} + +const char *SSL_rstate_string(const SSL *s) +	{ +	const 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/main/openssl/ssl/ssl_txt.c b/main/openssl/ssl/ssl_txt.c new file mode 100644 index 00000000..3122440e --- /dev/null +++ b/main/openssl/ssl/ssl_txt.c @@ -0,0 +1,240 @@ +/* ssl/ssl_txt.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include <openssl/buffer.h> +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_FP_API +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) +	{ +	BIO *b; +	int ret; + +	if ((b=BIO_new(BIO_s_file_internal())) == 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(BIO *bp, const SSL_SESSION *x) +	{ +	unsigned int i; +	const char *s; + +	if (x == NULL) goto err; +	if (BIO_puts(bp,"SSL-Session:\n") <= 0) goto err; +	if (x->ssl_version == SSL2_VERSION) +		s="SSLv2"; +	else if (x->ssl_version == SSL3_VERSION) +		s="SSLv3"; +	else if (x->ssl_version == TLS1_VERSION) +		s="TLSv1"; +	else if (x->ssl_version == DTLS1_VERSION) +		s="DTLSv1"; +	else if (x->ssl_version == DTLS1_BAD_VER) +		s="DTLSv1-bad"; +	else +		s="unknown"; +	if (BIO_printf(bp,"    Protocol  : %s\n",s) <= 0) goto err; + +	if (x->cipher == NULL) +		{ +		if (((x->cipher_id) & 0xff000000) == 0x02000000) +			{ +			if (BIO_printf(bp,"    Cipher    : %06lX\n",x->cipher_id&0xffffff) <= 0) +				goto err; +			} +		else +			{ +			if (BIO_printf(bp,"    Cipher    : %04lX\n",x->cipher_id&0xffff) <= 0) +				goto err; +			} +		} +	else +		{ +		if (BIO_printf(bp,"    Cipher    : %s\n",((x->cipher == NULL)?"unknown":x->cipher->name)) <= 0) +			goto err; +		} +	if (BIO_puts(bp,"    Session-ID: ") <= 0) goto err; +	for (i=0; i<x->session_id_length; i++) +		{ +		if (BIO_printf(bp,"%02X",x->session_id[i]) <= 0) goto err; +		} +	if (BIO_puts(bp,"\n    Session-ID-ctx: ") <= 0) goto err; +	for (i=0; i<x->sid_ctx_length; i++) +		{ +		if (BIO_printf(bp,"%02X",x->sid_ctx[i]) <= 0) +			goto err; +		} +	if (BIO_puts(bp,"\n    Master-Key: ") <= 0) goto err; +	for (i=0; i<(unsigned int)x->master_key_length; i++) +		{ +		if (BIO_printf(bp,"%02X",x->master_key[i]) <= 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<x->key_arg_length; i++) +			{ +			if (BIO_printf(bp,"%02X",x->key_arg[i]) <= 0) goto err; +			} +#ifndef OPENSSL_NO_KRB5 +       if (BIO_puts(bp,"\n    Krb5 Principal: ") <= 0) goto err; +            if (x->krb5_client_princ_len == 0) +            { +		if (BIO_puts(bp,"None") <= 0) goto err; +		} +	else +		for (i=0; i<x->krb5_client_princ_len; i++) +			{ +			if (BIO_printf(bp,"%02X",x->krb5_client_princ[i]) <= 0) goto err; +			} +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_PSK +	if (BIO_puts(bp,"\n    PSK identity: ") <= 0) goto err; +	if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) goto err; +	if (BIO_puts(bp,"\n    PSK identity hint: ") <= 0) goto err; +	if (BIO_printf(bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None") <= 0) goto err; +#endif +#ifndef OPENSSL_NO_TLSEXT +	if (x->tlsext_tick_lifetime_hint) +		{ +		if (BIO_printf(bp, +			"\n    TLS session ticket lifetime hint: %ld (seconds)", +			x->tlsext_tick_lifetime_hint) <=0) +			goto err; +		} +	if (x->tlsext_tick) +		{ +		if (BIO_puts(bp, "\n    TLS session ticket:\n") <= 0) goto err; +		if (BIO_dump_indent(bp, (char *)x->tlsext_tick, x->tlsext_ticklen, 4) <= 0) +			goto err; +		} +#endif + +#ifndef OPENSSL_NO_COMP +	if (x->compress_meth != 0) +		{ +		SSL_COMP *comp = NULL; + +		ssl_cipher_get_evp(x,NULL,NULL,NULL,NULL,&comp); +		if (comp == NULL) +			{ +			if (BIO_printf(bp,"\n    Compression: %d",x->compress_meth) <= 0) goto err; +			} +		else +			{ +			if (BIO_printf(bp,"\n    Compression: %d (%s)", comp->id,comp->method->name) <= 0) goto err; +			} +		}	 +#endif +	if (x->time != 0L) +		{ +		if (BIO_printf(bp, "\n    Start Time: %ld",x->time) <= 0) goto err; +		} +	if (x->timeout != 0L) +		{ +		if (BIO_printf(bp, "\n    Timeout   : %ld (sec)",x->timeout) <= 0) goto err; +		} +	if (BIO_puts(bp,"\n") <= 0) goto err; + +	if (BIO_puts(bp, "    Verify return code: ") <= 0) goto err; +	if (BIO_printf(bp, "%ld (%s)\n", x->verify_result, +		X509_verify_cert_error_string(x->verify_result)) <= 0) goto err; +		 +	return(1); +err: +	return(0); +	} + diff --git a/main/openssl/ssl/ssltest.c b/main/openssl/ssl/ssltest.c new file mode 100644 index 00000000..f6a2c79d --- /dev/null +++ b/main/openssl/ssl/ssltest.c @@ -0,0 +1,2503 @@ +/* ssl/ssltest.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by  + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#define _BSD_SOURCE 1		/* Or gethostname won't be declared properly +				   on Linux and GNU platforms. */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#define USE_SOCKETS +#include "e_os.h" + +#ifdef OPENSSL_SYS_VMS +#define _XOPEN_SOURCE 500	/* Or isascii won't be declared properly on +				   VMS (at least with DECompHP C).  */ +#endif + +#include <ctype.h> + +#include <openssl/bio.h> +#include <openssl/crypto.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/ssl.h> +#ifndef OPENSSL_NO_ENGINE +#include <openssl/engine.h> +#endif +#include <openssl/err.h> +#include <openssl/rand.h> +#ifndef OPENSSL_NO_RSA +#include <openssl/rsa.h> +#endif +#ifndef OPENSSL_NO_DSA +#include <openssl/dsa.h> +#endif +#ifndef OPENSSL_NO_DH +#include <openssl/dh.h> +#endif +#include <openssl/bn.h> + +#define _XOPEN_SOURCE_EXTENDED	1 /* Or gethostname won't be declared properly +				     on Compaq platforms (at least with DEC C). +				     Do not try to put it earlier, or IPv6 includes +				     get screwed... +				  */ + +#ifdef OPENSSL_SYS_WINDOWS +#include <winsock.h> +#else +#include OPENSSL_UNISTD +#endif + +#ifdef OPENSSL_SYS_VMS +#  define TEST_SERVER_CERT "SYS$DISK:[-.APPS]SERVER.PEM" +#  define TEST_CLIENT_CERT "SYS$DISK:[-.APPS]CLIENT.PEM" +#elif defined(OPENSSL_SYS_WINCE) +#  define TEST_SERVER_CERT "\\OpenSSL\\server.pem" +#  define TEST_CLIENT_CERT "\\OpenSSL\\client.pem" +#elif defined(OPENSSL_SYS_NETWARE) +#  define TEST_SERVER_CERT "\\openssl\\apps\\server.pem" +#  define TEST_CLIENT_CERT "\\openssl\\apps\\client.pem" +#else +#  define TEST_SERVER_CERT "../apps/server.pem" +#  define TEST_CLIENT_CERT "../apps/client.pem" +#endif + +/* There is really no standard for this, so let's assign some tentative +   numbers.  In any case, these numbers are only for this test */ +#define COMP_RLE	255 +#define COMP_ZLIB	1 + +static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); +#ifndef OPENSSL_NO_RSA +static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength); +static void free_tmp_rsa(void); +#endif +static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg); +#define APP_CALLBACK_STRING "Test Callback Argument" +struct app_verify_arg +	{ +	char *string; +	int app_verify; +	int allow_proxy_certs; +	char *proxy_auth; +	char *proxy_cond; +	}; + +#ifndef OPENSSL_NO_DH +static DH *get_dh512(void); +static DH *get_dh1024(void); +static DH *get_dh1024dsa(void); +#endif + + +static char *psk_key=NULL; /* by default PSK is not used */ +#ifndef OPENSSL_NO_PSK +static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity, +	unsigned int max_identity_len, unsigned char *psk, +	unsigned int max_psk_len); +static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, +	unsigned int max_psk_len); +#endif + +static BIO *bio_err=NULL; +static BIO *bio_stdout=NULL; + +static char *cipher=NULL; +static int verbose=0; +static int debug=0; +#if 0 +/* Not used yet. */ +#ifdef FIONBIO +static int s_nbio=0; +#endif +#endif + +static const char rnd_seed[] = "string to make the random number generator think it has entropy"; + +int doit_biopair(SSL *s_ssl,SSL *c_ssl,long bytes,clock_t *s_time,clock_t *c_time); +int doit(SSL *s_ssl,SSL *c_ssl,long bytes); +static int do_test_cipherlist(void); +static void sv_usage(void) +	{ +	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," -proxy        - allow proxy certificates\n"); +	fprintf(stderr," -proxy_auth <val> - set proxy policy rights\n"); +	fprintf(stderr," -proxy_cond <val> - experssion to test proxy policy rights\n"); +	fprintf(stderr," -v            - more output\n"); +	fprintf(stderr," -d            - debug output\n"); +	fprintf(stderr," -reuse        - use session-id reuse\n"); +	fprintf(stderr," -num <val>    - number of connections to perform\n"); +	fprintf(stderr," -bytes <val>  - number of bytes to swap between client/server\n"); +#ifndef OPENSSL_NO_DH +	fprintf(stderr," -dhe1024      - use 1024 bit key (safe prime) for DHE\n"); +	fprintf(stderr," -dhe1024dsa   - use 1024 bit key (with 160-bit subprime) for DHE\n"); +	fprintf(stderr," -no_dhe       - disable DHE\n"); +#endif +#ifndef OPENSSL_NO_ECDH +	fprintf(stderr," -no_ecdhe     - disable ECDHE\n"); +#endif +#ifndef OPENSSL_NO_PSK +	fprintf(stderr," -psk arg      - PSK in hex (without 0x)\n"); +#endif +#ifndef OPENSSL_NO_SSL2 +	fprintf(stderr," -ssl2         - use SSLv2\n"); +#endif +#ifndef OPENSSL_NO_SSL3 +	fprintf(stderr," -ssl3         - use SSLv3\n"); +#endif +#ifndef OPENSSL_NO_TLS1 +	fprintf(stderr," -tls1         - use TLSv1\n"); +#endif +	fprintf(stderr," -CApath arg   - PEM format directory of CA's\n"); +	fprintf(stderr," -CAfile arg   - PEM format file of CA's\n"); +	fprintf(stderr," -cert arg     - Server certificate file\n"); +	fprintf(stderr," -key arg      - Server key file (default: same as -cert)\n"); +	fprintf(stderr," -c_cert arg   - Client certificate file\n"); +	fprintf(stderr," -c_key arg    - Client key file (default: same as -c_cert)\n"); +	fprintf(stderr," -cipher arg   - The cipher list\n"); +	fprintf(stderr," -bio_pair     - Use BIO pairs\n"); +	fprintf(stderr," -f            - Test even cases that can't work\n"); +	fprintf(stderr," -time         - measure processor time used by client and server\n"); +	fprintf(stderr," -zlib         - use zlib compression\n"); +	fprintf(stderr," -rle          - use rle compression\n"); +#ifndef OPENSSL_NO_ECDH +	fprintf(stderr," -named_curve arg  - Elliptic curve name to use for ephemeral ECDH keys.\n" \ +	               "                 Use \"openssl ecparam -list_curves\" for all names\n"  \ +	               "                 (default is sect163r2).\n"); +#endif +	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n"); +	fprintf(stderr," -c_small_records - enable client side use of small SSL record buffers\n"); +	fprintf(stderr," -s_small_records - enable server side use of small SSL record buffers\n"); +	fprintf(stderr," -cutthrough      - enable 1-RTT full-handshake for strong ciphers\n"); +	} + +static void print_details(SSL *c_ssl, const char *prefix) +	{ +	const SSL_CIPHER *ciph; +	X509 *cert; +		 +	ciph=SSL_get_current_cipher(c_ssl); +	BIO_printf(bio_stdout,"%s%s, cipher %s %s", +		prefix, +		SSL_get_version(c_ssl), +		SSL_CIPHER_get_version(ciph), +		SSL_CIPHER_get_name(ciph)); +	cert=SSL_get_peer_certificate(c_ssl); +	if (cert != NULL) +		{ +		EVP_PKEY *pkey = X509_get_pubkey(cert); +		if (pkey != NULL) +			{ +			if (0)  +				; +#ifndef OPENSSL_NO_RSA +			else if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL +				&& pkey->pkey.rsa->n != NULL) +				{ +				BIO_printf(bio_stdout, ", %d bit RSA", +					BN_num_bits(pkey->pkey.rsa->n)); +				} +#endif +#ifndef OPENSSL_NO_DSA +			else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL +				&& pkey->pkey.dsa->p != NULL) +				{ +				BIO_printf(bio_stdout, ", %d bit DSA", +					BN_num_bits(pkey->pkey.dsa->p)); +				} +#endif +			EVP_PKEY_free(pkey); +			} +		X509_free(cert); +		} +	/* The SSL API does not allow us to look at temporary RSA/DH keys, +	 * otherwise we should print their lengths too */ +	BIO_printf(bio_stdout,"\n"); +	} + +static void lock_dbg_cb(int mode, int type, const char *file, int line) +	{ +	static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */ +	const char *errstr = NULL; +	int rw; +	 +	rw = mode & (CRYPTO_READ|CRYPTO_WRITE); +	if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) +		{ +		errstr = "invalid mode"; +		goto err; +		} + +	if (type < 0 || type >= CRYPTO_NUM_LOCKS) +		{ +		errstr = "type out of bounds"; +		goto err; +		} + +	if (mode & CRYPTO_LOCK) +		{ +		if (modes[type]) +			{ +			errstr = "already locked"; +			/* must not happen in a single-threaded program +			 * (would deadlock) */ +			goto err; +			} + +		modes[type] = rw; +		} +	else if (mode & CRYPTO_UNLOCK) +		{ +		if (!modes[type]) +			{ +			errstr = "not locked"; +			goto err; +			} +		 +		if (modes[type] != rw) +			{ +			errstr = (rw == CRYPTO_READ) ? +				"CRYPTO_r_unlock on write lock" : +				"CRYPTO_w_unlock on read lock"; +			} + +		modes[type] = 0; +		} +	else +		{ +		errstr = "invalid mode"; +		goto err; +		} + + err: +	if (errstr) +		{ +		/* we cannot use bio_err here */ +		fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n", +			errstr, mode, type, file, line); +		} +	} + +#ifdef TLSEXT_TYPE_opaque_prf_input +struct cb_info_st { void *input; size_t len; int ret; }; +struct cb_info_st co1 = { "C", 1, 1 }; /* try to negotiate oqaque PRF input */ +struct cb_info_st co2 = { "C", 1, 2 }; /* insist on oqaque PRF input */ +struct cb_info_st so1 = { "S", 1, 1 }; /* try to negotiate oqaque PRF input */ +struct cb_info_st so2 = { "S", 1, 2 }; /* insist on oqaque PRF input */ + +int opaque_prf_input_cb(SSL *ssl, void *peerinput, size_t len, void *arg_) +	{ +	struct cb_info_st *arg = arg_; + +	if (arg == NULL) +		return 1; +	 +	if (!SSL_set_tlsext_opaque_prf_input(ssl, arg->input, arg->len)) +		return 0; +	return arg->ret; +	} +#endif +	int ssl_mode = 0; +	int c_small_records=0; +	int s_small_records=0; +	int cutthrough = 0; + +int main(int argc, char *argv[]) +	{ +	char *CApath=NULL,*CAfile=NULL; +	int badop=0; +	int bio_pair=0; +	int force=0; +	int tls1=0,ssl2=0,ssl3=0,ret=1; +	int client_auth=0; +	int server_auth=0,i; +	struct app_verify_arg app_verify_arg = +		{ APP_CALLBACK_STRING, 0, 0, NULL, NULL }; +	char *server_cert=TEST_SERVER_CERT; +	char *server_key=NULL; +	char *client_cert=TEST_CLIENT_CERT; +	char *client_key=NULL; +#ifndef OPENSSL_NO_ECDH +	char *named_curve = NULL; +#endif +	SSL_CTX *s_ctx=NULL; +	SSL_CTX *c_ctx=NULL; +	const SSL_METHOD *meth=NULL; +	SSL *c_ssl,*s_ssl; +	int number=1,reuse=0; +	long bytes=256L; +#ifndef OPENSSL_NO_DH +	DH *dh; +	int dhe1024 = 0, dhe1024dsa = 0; +#endif +#ifndef OPENSSL_NO_ECDH +	EC_KEY *ecdh = NULL; +#endif +	int no_dhe = 0; +	int no_ecdhe = 0; +	int no_psk = 0; +	int print_time = 0; +	clock_t s_time = 0, c_time = 0; +	int comp = 0; +#ifndef OPENSSL_NO_COMP +	COMP_METHOD *cm = NULL; +#endif +	STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; +	int test_cipherlist = 0; + +	verbose = 0; +	debug = 0; +	cipher = 0; + +	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE|BIO_FP_TEXT);	 + +	CRYPTO_set_locking_callback(lock_dbg_cb); + +	/* enable memory leak checking unless explicitly disabled */ +	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) +		{ +		CRYPTO_malloc_debug_init(); +		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); +		} +	else +		{ +		/* OPENSSL_DEBUG_MEMORY=off */ +		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); +		} +	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + +	RAND_seed(rnd_seed, sizeof rnd_seed); + +	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE|BIO_FP_TEXT); + +	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,"-proxy_auth") == 0) +			{ +			if (--argc < 1) goto bad; +			app_verify_arg.proxy_auth= *(++argv); +			} +		else if (strcmp(*argv,"-proxy_cond") == 0) +			{ +			if (--argc < 1) goto bad; +			app_verify_arg.proxy_cond= *(++argv); +			} +		else if	(strcmp(*argv,"-v") == 0) +			verbose=1; +		else if	(strcmp(*argv,"-d") == 0) +			debug=1; +		else if	(strcmp(*argv,"-reuse") == 0) +			reuse=1; +		else if	(strcmp(*argv,"-dhe1024") == 0) +			{ +#ifndef OPENSSL_NO_DH +			dhe1024=1; +#else +			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n"); +#endif +			} +		else if	(strcmp(*argv,"-dhe1024dsa") == 0) +			{ +#ifndef OPENSSL_NO_DH +			dhe1024dsa=1; +#else +			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n"); +#endif +			} +		else if	(strcmp(*argv,"-no_dhe") == 0) +			no_dhe=1; +		else if	(strcmp(*argv,"-no_ecdhe") == 0) +			no_ecdhe=1; +		else if (strcmp(*argv,"-psk") == 0) +			{ +			if (--argc < 1) goto bad; +			psk_key=*(++argv); +#ifndef OPENSSL_NO_PSK +			if (strspn(psk_key, "abcdefABCDEF1234567890") != strlen(psk_key)) +				{ +				BIO_printf(bio_err,"Not a hex number '%s'\n",*argv); +				goto bad; +				} +#else +			no_psk=1; +#endif +			} +		else if	(strcmp(*argv,"-ssl2") == 0) +			ssl2=1; +		else if	(strcmp(*argv,"-tls1") == 0) +			tls1=1; +		else if	(strcmp(*argv,"-ssl3") == 0) +			ssl3=1; +		else if	(strncmp(*argv,"-num",4) == 0) +			{ +			if (--argc < 1) goto bad; +			number= atoi(*(++argv)); +			if (number == 0) number=1; +			} +		else if	(strcmp(*argv,"-bytes") == 0) +			{ +			if (--argc < 1) goto bad; +			bytes= atol(*(++argv)); +			if (bytes == 0L) bytes=1L; +			i=strlen(argv[0]); +			if (argv[0][i-1] == 'k') bytes*=1024L; +			if (argv[0][i-1] == 'm') bytes*=1024L*1024L; +			} +		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,"-key") == 0) +			{ +			if (--argc < 1) goto bad; +			server_key= *(++argv); +			} +		else if	(strcmp(*argv,"-s_key") == 0) +			{ +			if (--argc < 1) goto bad; +			server_key= *(++argv); +			} +		else if	(strcmp(*argv,"-c_cert") == 0) +			{ +			if (--argc < 1) goto bad; +			client_cert= *(++argv); +			} +		else if	(strcmp(*argv,"-c_key") == 0) +			{ +			if (--argc < 1) goto bad; +			client_key= *(++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 if	(strcmp(*argv,"-bio_pair") == 0) +			{ +			bio_pair = 1; +			} +		else if	(strcmp(*argv,"-f") == 0) +			{ +			force = 1; +			} +		else if	(strcmp(*argv,"-time") == 0) +			{ +			print_time = 1; +			} +		else if	(strcmp(*argv,"-zlib") == 0) +			{ +			comp = COMP_ZLIB; +			} +		else if	(strcmp(*argv,"-rle") == 0) +			{ +			comp = COMP_RLE; +			} +		else if	(strcmp(*argv,"-named_curve") == 0) +			{ +			if (--argc < 1) goto bad; +#ifndef OPENSSL_NO_ECDH		 +			named_curve = *(++argv); +#else +			fprintf(stderr,"ignoring -named_curve, since I'm compiled without ECDH\n"); +			++argv; +#endif +			} +		else if	(strcmp(*argv,"-app_verify") == 0) +			{ +			app_verify_arg.app_verify = 1; +			} +		else if	(strcmp(*argv,"-proxy") == 0) +			{ +			app_verify_arg.allow_proxy_certs = 1; +			} +		else if (strcmp(*argv,"-test_cipherlist") == 0) +			{ +			test_cipherlist = 1; +			} +		else if (strcmp(*argv, "-c_small_records") == 0) +			{ +			c_small_records = 1; +			} +		else if (strcmp(*argv, "-s_small_records") == 0) +			{ +			s_small_records = 1; +			} +		else if (strcmp(*argv, "-cutthrough") == 0) +			{ +			cutthrough = 1; +			} +		else +			{ +			fprintf(stderr,"unknown option %s\n",*argv); +			badop=1; +			break; +			} +		argc--; +		argv++; +		} +	if (badop) +		{ +bad: +		sv_usage(); +		goto end; +		} + +	if (test_cipherlist == 1) +		{ +		/* ensure that the cipher list are correctly sorted and exit */ +		if (do_test_cipherlist() == 0) +			EXIT(1); +		ret = 0; +		goto end; +		} + +	if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) +		{ +		fprintf(stderr, "This case cannot work.  Use -f to perform " +			"the test anyway (and\n-d to see what happens), " +			"or add one of -ssl2, -ssl3, -tls1, -reuse\n" +			"to avoid protocol mismatch.\n"); +		EXIT(1); +		} + +	if (print_time) +		{ +		if (!bio_pair) +			{ +			fprintf(stderr, "Using BIO pair (-bio_pair)\n"); +			bio_pair = 1; +			} +		if (number < 50 && !force) +			fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n"); +		} + +/*	if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ + +	SSL_library_init(); +	SSL_load_error_strings(); + +#ifndef OPENSSL_NO_COMP +	if (comp == COMP_ZLIB) cm = COMP_zlib(); +	if (comp == COMP_RLE) cm = COMP_rle(); +	if (cm != NULL) +		{ +		if (cm->type != NID_undef) +			{ +			if (SSL_COMP_add_compression_method(comp, cm) != 0) +				{ +				fprintf(stderr, +					"Failed to add compression method\n"); +				ERR_print_errors_fp(stderr); +				} +			} +		else +			{ +			fprintf(stderr, +				"Warning: %s compression not supported\n", +				(comp == COMP_RLE ? "rle" : +					(comp == COMP_ZLIB ? "zlib" : +						"unknown"))); +			ERR_print_errors_fp(stderr); +			} +		} +	ssl_comp_methods = SSL_COMP_get_compression_methods(); +	fprintf(stderr, "Available compression methods:\n"); +	{ +	int j, n = sk_SSL_COMP_num(ssl_comp_methods); +	if (n == 0) +		fprintf(stderr, "  NONE\n"); +	else +		for (j = 0; j < n; j++) +			{ +			SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j); +			fprintf(stderr, "  %d: %s\n", c->id, c->name); +			} +	} +#endif + +#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) +	if (ssl2) +		meth=SSLv2_method(); +	else  +	if (tls1) +		meth=TLSv1_method(); +	else +	if (ssl3) +		meth=SSLv3_method(); +	else +		meth=SSLv23_method(); +#else +#ifdef OPENSSL_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); +		} + +	ssl_mode = 0; +	if (c_small_records) +		{ +		ssl_mode = SSL_CTX_get_mode(c_ctx); +		ssl_mode |= SSL_MODE_SMALL_BUFFERS; +		SSL_CTX_set_mode(c_ctx, ssl_mode); +		} +	ssl_mode = 0; +	if (s_small_records) +		{ +		ssl_mode = SSL_CTX_get_mode(s_ctx); +		ssl_mode |= SSL_MODE_SMALL_BUFFERS; +		SSL_CTX_set_mode(s_ctx, ssl_mode); +		} +	ssl_mode = 0; +	if (cutthrough) +		{ +		ssl_mode = SSL_CTX_get_mode(c_ctx); +		ssl_mode = SSL_MODE_HANDSHAKE_CUTTHROUGH; +		SSL_CTX_set_mode(c_ctx, ssl_mode); +		} + +#ifndef OPENSSL_NO_DH +	if (!no_dhe) +		{ +		if (dhe1024dsa) +			{ +			/* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */ +			SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); +			dh=get_dh1024dsa(); +			} +		else if (dhe1024) +			dh=get_dh1024(); +		else +			dh=get_dh512(); +		SSL_CTX_set_tmp_dh(s_ctx,dh); +		DH_free(dh); +		} +#else +	(void)no_dhe; +#endif + +#ifndef OPENSSL_NO_ECDH +	if (!no_ecdhe) +		{ +		int nid; + +		if (named_curve != NULL) +			{ +			nid = OBJ_sn2nid(named_curve); +			if (nid == 0) +			{ +				BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); +				goto end; +				} +			} +		else +			nid = NID_sect163r2; + +		ecdh = EC_KEY_new_by_curve_name(nid); +		if (ecdh == NULL) +			{ +			BIO_printf(bio_err, "unable to create curve\n"); +			goto end; +			} + +		SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); +		SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); +		EC_KEY_free(ecdh); +		} +#else +	(void)no_ecdhe; +#endif + +#ifndef OPENSSL_NO_RSA +	SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb); +#endif + +#ifdef TLSEXT_TYPE_opaque_prf_input +	SSL_CTX_set_tlsext_opaque_prf_input_callback(c_ctx, opaque_prf_input_cb); +	SSL_CTX_set_tlsext_opaque_prf_input_callback(s_ctx, opaque_prf_input_cb); +	SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(c_ctx, &co1); /* or &co2 or NULL */ +	SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(s_ctx, &so1); /* or &so2 or NULL */ +#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_key?server_key: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_key?client_key: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) +		{ +		BIO_printf(bio_err,"client authentication\n"); +		SSL_CTX_set_verify(s_ctx, +			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, +			verify_callback); +		SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, &app_verify_arg); +		} +	if (server_auth) +		{ +		BIO_printf(bio_err,"server authentication\n"); +		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, +			verify_callback); +		SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback, &app_verify_arg); +		} +	 +	{ +		int session_id_context = 0; +		SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context); +	} + +	/* Use PSK only if PSK key is given */ +	if (psk_key != NULL) +		{ +		/* no_psk is used to avoid putting psk command to openssl tool */ +		if (no_psk) +			{ +			/* if PSK is not compiled in and psk key is +			 * given, do nothing and exit successfully */ +			ret=0; +			goto end; +			} +#ifndef OPENSSL_NO_PSK +		SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback); +		SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback); +		if (debug) +			BIO_printf(bio_err,"setting PSK identity hint to s_ctx\n"); +		if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint")) +			{ +			BIO_printf(bio_err,"error setting PSK identity hint to s_ctx\n"); +			ERR_print_errors(bio_err); +			goto end; +			} +#endif +		} + +	c_ssl=SSL_new(c_ctx); +	s_ssl=SSL_new(s_ctx); + +#ifndef OPENSSL_NO_KRB5 +	if (c_ssl  &&  c_ssl->kssl_ctx) +                { +                char	localhost[MAXHOSTNAMELEN+2]; + +		if (gethostname(localhost, sizeof localhost-1) == 0) +                        { +			localhost[sizeof localhost-1]='\0'; +			if(strlen(localhost) == sizeof localhost-1) +				{ +				BIO_printf(bio_err,"localhost name too long\n"); +				goto end; +				} +			kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER, +                                localhost); +			} +		} +#endif    /* OPENSSL_NO_KRB5  */ + +	for (i=0; i<number; i++) +		{ +		if (!reuse) SSL_set_session(c_ssl,NULL); +		if (bio_pair) +			ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time); +		else +			ret=doit(s_ssl,c_ssl,bytes); +		} + +	if (!verbose) +		{ +		print_details(c_ssl, ""); +		} +	if ((number > 1) || (bytes > 1L)) +		BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes); +	if (print_time) +		{ +#ifdef CLOCKS_PER_SEC +		/* "To determine the time in seconds, the value returned +		 * by the clock function should be divided by the value +		 * of the macro CLOCKS_PER_SEC." +		 *                                       -- ISO/IEC 9899 */ +		BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n" +			"Approximate total client time: %6.2f s\n", +			(double)s_time/CLOCKS_PER_SEC, +			(double)c_time/CLOCKS_PER_SEC); +#else +		/* "`CLOCKS_PER_SEC' undeclared (first use this function)" +		 *                            -- cc on NeXTstep/OpenStep */ +		BIO_printf(bio_stdout, +			"Approximate total server time: %6.2f units\n" +			"Approximate total client time: %6.2f units\n", +			(double)s_time, +			(double)c_time); +#endif +		} + +	SSL_free(s_ssl); +	SSL_free(c_ssl); + +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); + +#ifndef OPENSSL_NO_RSA +	free_tmp_rsa(); +#endif +#ifndef OPENSSL_NO_ENGINE +	ENGINE_cleanup(); +#endif +	CRYPTO_cleanup_all_ex_data(); +	ERR_free_strings(); +	ERR_remove_thread_state(NULL); +	EVP_cleanup(); +	CRYPTO_mem_leaks(bio_err); +	if (bio_err != NULL) BIO_free(bio_err); +	EXIT(ret); +	return ret; +	} + +int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, +	clock_t *s_time, clock_t *c_time) +	{ +	long cw_num = count, cr_num = count, sw_num = count, sr_num = count; +	BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL; +	BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL; +	int ret = 1; +	 +	size_t bufsiz = 256; /* small buffer for testing */ + +	if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz)) +		goto err; +	if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz)) +		goto err; +	 +	s_ssl_bio = BIO_new(BIO_f_ssl()); +	if (!s_ssl_bio) +		goto err; + +	c_ssl_bio = BIO_new(BIO_f_ssl()); +	if (!c_ssl_bio) +		goto err; + +	SSL_set_connect_state(c_ssl); +	SSL_set_bio(c_ssl, client, client); +	(void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE); + +	SSL_set_accept_state(s_ssl); +	SSL_set_bio(s_ssl, server, server); +	(void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE); + +	do +		{ +		/* c_ssl_bio:          SSL filter BIO +		 * +		 * client:             pseudo-I/O for SSL library +		 * +		 * client_io:          client's SSL communication; usually to be +		 *                     relayed over some I/O facility, but in this +		 *                     test program, we're the server, too: +		 * +		 * server_io:          server's SSL communication +		 * +		 * server:             pseudo-I/O for SSL library +		 * +		 * s_ssl_bio:          SSL filter BIO +		 * +		 * The client and the server each employ a "BIO pair": +		 * client + client_io, server + server_io. +		 * BIO pairs are symmetric.  A BIO pair behaves similar +		 * to a non-blocking socketpair (but both endpoints must +		 * be handled by the same thread). +		 * [Here we could connect client and server to the ends +		 * of a single BIO pair, but then this code would be less +		 * suitable as an example for BIO pairs in general.] +		 * +		 * Useful functions for querying the state of BIO pair endpoints: +		 * +		 * BIO_ctrl_pending(bio)              number of bytes we can read now +		 * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil +		 *                                      other side's read attempt +		 * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now +		 * +		 * ..._read_request is never more than ..._write_guarantee; +		 * it depends on the application which one you should use. +		 */ + +		/* We have non-blocking behaviour throughout this test program, but +		 * can be sure that there is *some* progress in each iteration; so +		 * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE +		 * -- we just try everything in each iteration +		 */ + +			{ +			/* CLIENT */ +		 +			MS_STATIC char cbuf[1024*8]; +			int i, r; +			clock_t c_clock = clock(); + +			memset(cbuf, 0, sizeof(cbuf)); + +			if (debug) +				if (SSL_in_init(c_ssl)) +					printf("client waiting in SSL_connect - %s\n", +						SSL_state_string_long(c_ssl)); + +			if (cw_num > 0) +				{ +				/* Write to server. */ +				 +				if (cw_num > (long)sizeof cbuf) +					i = sizeof cbuf; +				else +					i = (int)cw_num; +				r = BIO_write(c_ssl_bio, cbuf, i); +				if (r < 0) +					{ +					if (!BIO_should_retry(c_ssl_bio)) +						{ +						fprintf(stderr,"ERROR in CLIENT\n"); +						goto err; +						} +					/* BIO_should_retry(...) can just be ignored here. +					 * The library expects us to call BIO_write with +					 * the same arguments again, and that's what we will +					 * do in the next iteration. */ +					} +				else if (r == 0) +					{ +					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n"); +					goto err; +					} +				else +					{ +					if (debug) +						printf("client wrote %d\n", r); +					cw_num -= r;				 +					} +				} + +			if (cr_num > 0) +				{ +				/* Read from server. */ + +				r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf)); +				if (r < 0) +					{ +					if (!BIO_should_retry(c_ssl_bio)) +						{ +						fprintf(stderr,"ERROR in CLIENT\n"); +						goto err; +						} +					/* Again, "BIO_should_retry" can be ignored. */ +					} +				else if (r == 0) +					{ +					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n"); +					goto err; +					} +				else +					{ +					if (debug) +						printf("client read %d\n", r); +					cr_num -= r; +					} +				} + +			/* c_time and s_time increments will typically be very small +			 * (depending on machine speed and clock tick intervals), +			 * but sampling over a large number of connections should +			 * result in fairly accurate figures.  We cannot guarantee +			 * a lot, however -- if each connection lasts for exactly +			 * one clock tick, it will be counted only for the client +			 * or only for the server or even not at all. +			 */ +			*c_time += (clock() - c_clock); +			} + +			{ +			/* SERVER */ +		 +			MS_STATIC char sbuf[1024*8]; +			int i, r; +			clock_t s_clock = clock(); + +			memset(sbuf, 0, sizeof(sbuf)); + +			if (debug) +				if (SSL_in_init(s_ssl)) +					printf("server waiting in SSL_accept - %s\n", +						SSL_state_string_long(s_ssl)); + +			if (sw_num > 0) +				{ +				/* Write to client. */ +				 +				if (sw_num > (long)sizeof sbuf) +					i = sizeof sbuf; +				else +					i = (int)sw_num; +				r = BIO_write(s_ssl_bio, sbuf, i); +				if (r < 0) +					{ +					if (!BIO_should_retry(s_ssl_bio)) +						{ +						fprintf(stderr,"ERROR in SERVER\n"); +						goto err; +						} +					/* Ignore "BIO_should_retry". */ +					} +				else if (r == 0) +					{ +					fprintf(stderr,"SSL SERVER STARTUP FAILED\n"); +					goto err; +					} +				else +					{ +					if (debug) +						printf("server wrote %d\n", r); +					sw_num -= r;				 +					} +				} + +			if (sr_num > 0) +				{ +				/* Read from client. */ + +				r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf)); +				if (r < 0) +					{ +					if (!BIO_should_retry(s_ssl_bio)) +						{ +						fprintf(stderr,"ERROR in SERVER\n"); +						goto err; +						} +					/* blah, blah */ +					} +				else if (r == 0) +					{ +					fprintf(stderr,"SSL SERVER STARTUP FAILED\n"); +					goto err; +					} +				else +					{ +					if (debug) +						printf("server read %d\n", r); +					sr_num -= r; +					} +				} + +			*s_time += (clock() - s_clock); +			} +			 +			{ +			/* "I/O" BETWEEN CLIENT AND SERVER. */ + +			size_t r1, r2; +			BIO *io1 = server_io, *io2 = client_io; +			/* we use the non-copying interface for io1 +			 * and the standard BIO_write/BIO_read interface for io2 +			 */ +			 +			static int prev_progress = 1; +			int progress = 0; +			 +			/* io1 to io2 */ +			do +				{ +				size_t num; +				int r; + +				r1 = BIO_ctrl_pending(io1); +				r2 = BIO_ctrl_get_write_guarantee(io2); + +				num = r1; +				if (r2 < num) +					num = r2; +				if (num) +					{ +					char *dataptr; + +					if (INT_MAX < num) /* yeah, right */ +						num = INT_MAX; +					 +					r = BIO_nread(io1, &dataptr, (int)num); +					assert(r > 0); +					assert(r <= (int)num); +					/* possibly r < num (non-contiguous data) */ +					num = r; +					r = BIO_write(io2, dataptr, (int)num); +					if (r != (int)num) /* can't happen */ +						{ +						fprintf(stderr, "ERROR: BIO_write could not write " +							"BIO_ctrl_get_write_guarantee() bytes"); +						goto err; +						} +					progress = 1; + +					if (debug) +						printf((io1 == client_io) ? +							"C->S relaying: %d bytes\n" : +							"S->C relaying: %d bytes\n", +							(int)num); +					} +				} +			while (r1 && r2); + +			/* io2 to io1 */ +			{ +				size_t num; +				int r; + +				r1 = BIO_ctrl_pending(io2); +				r2 = BIO_ctrl_get_read_request(io1); +				/* here we could use ..._get_write_guarantee instead of +				 * ..._get_read_request, but by using the latter +				 * we test restartability of the SSL implementation +				 * more thoroughly */ +				num = r1; +				if (r2 < num) +					num = r2; +				if (num) +					{ +					char *dataptr; +					 +					if (INT_MAX < num) +						num = INT_MAX; + +					if (num > 1) +						--num; /* test restartability even more thoroughly */ +					 +					r = BIO_nwrite0(io1, &dataptr); +					assert(r > 0); +					if (r < (int)num) +						num = r; +					r = BIO_read(io2, dataptr, (int)num); +					if (r != (int)num) /* can't happen */ +						{ +						fprintf(stderr, "ERROR: BIO_read could not read " +							"BIO_ctrl_pending() bytes"); +						goto err; +						} +					progress = 1; +					r = BIO_nwrite(io1, &dataptr, (int)num); +					if (r != (int)num) /* can't happen */ +						{ +						fprintf(stderr, "ERROR: BIO_nwrite() did not accept " +							"BIO_nwrite0() bytes"); +						goto err; +						} +					 +					if (debug) +						printf((io2 == client_io) ? +							"C->S relaying: %d bytes\n" : +							"S->C relaying: %d bytes\n", +							(int)num); +					} +			} /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */ + +			if (!progress && !prev_progress) +				if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0) +					{ +					fprintf(stderr, "ERROR: got stuck\n"); +					if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0) +						{ +						fprintf(stderr, "This can happen for SSL2 because " +							"CLIENT-FINISHED and SERVER-VERIFY are written \n" +							"concurrently ..."); +						if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0 +							&& strncmp("2SSV", SSL_state_string(s_ssl), 4) == 0) +							{ +							fprintf(stderr, " ok.\n"); +							goto end; +							} +						} +					fprintf(stderr, " ERROR.\n"); +					goto err; +					} +			prev_progress = progress; +			} +		} +	while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0); + +	if (verbose) +		print_details(c_ssl, "DONE via BIO pair: "); +end: +	ret = 0; + + err: +	ERR_print_errors(bio_err); +	 +	if (server) +		BIO_free(server); +	if (server_io) +		BIO_free(server_io); +	if (client) +		BIO_free(client); +	if (client_io) +		BIO_free(client_io); +	if (s_ssl_bio) +		BIO_free(s_ssl_bio); +	if (c_ssl_bio) +		BIO_free(c_ssl_bio); + +	return ret; +	} + + +#define W_READ	1 +#define W_WRITE	2 +#define C_DONE	1 +#define S_DONE	2 + +int doit(SSL *s_ssl, SSL *c_ssl, long count) +	{ +	MS_STATIC char cbuf[1024*8],sbuf[1024*8]; +	long cw_num=count,cr_num=count; +	long sw_num=count,sr_num=count; +	int ret=1; +	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 i,j; +	int done=0; +	int c_write,s_write; +	int do_server=0,do_client=0; + +	memset(cbuf,0,sizeof(cbuf)); +	memset(sbuf,0,sizeof(sbuf)); + +	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_NOCLOSE); + +	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_NOCLOSE); + +	c_r=0; s_r=1; +	c_w=1; s_w=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 && debug) +			{ +			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 && debug) +			{ +			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) +				{ +				j = (cw_num > (long)sizeof(cbuf)) ? +					(int)sizeof(cbuf) : (int)cw_num; +				i=BIO_write(c_bio,cbuf,j); +				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 +					{ +					if (debug) +						printf("client wrote %d\n",i); +					/* ok */ +					s_r=1; +					c_write=0; +					cw_num-=i; +					} +				} +			else +				{ +				i=BIO_read(c_bio,cbuf,sizeof(cbuf)); +				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 +					{ +					if (debug) +						printf("client read %d\n",i); +					cr_num-=i; +					if (sw_num > 0) +						{ +						s_write=1; +						s_w=1; +						} +					if (cr_num <= 0) +						{ +						s_write=1; +						s_w=1; +						done=S_DONE|C_DONE; +						} +					} +				} +			} + +		if (do_server && !(done & S_DONE)) +			{ +			if (!s_write) +				{ +				i=BIO_read(s_bio,sbuf,sizeof(cbuf)); +				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 +					{ +					if (debug) +						printf("server read %d\n",i); +					sr_num-=i; +					if (cw_num > 0) +						{ +						c_write=1; +						c_w=1; +						} +					if (sr_num <= 0) +						{ +						s_write=1; +						s_w=1; +						c_write=0; +						} +					} +				} +			else +				{ +				j = (sw_num > (long)sizeof(sbuf)) ? +					(int)sizeof(sbuf) : (int)sw_num; +				i=BIO_write(s_bio,sbuf,j); +				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 +					{ +					if (debug) +						printf("server wrote %d\n",i); +					sw_num-=i; +					s_write=0; +					c_r=1; +					if (sw_num <= 0) +						done|=S_DONE; +					} +				} +			} + +		if ((done & S_DONE) && (done & C_DONE)) break; +		} + +	if (verbose) +		print_details(c_ssl, "DONE: "); +	ret=0; +err: +	/* We have to set the BIO's to NULL otherwise they will be +	 * OPENSSL_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_all(c_bio); +	if (s_bio != NULL) BIO_free_all(s_bio); +	return(ret); +	} + +static int get_proxy_auth_ex_data_idx(void) +	{ +	static volatile int idx = -1; +	if (idx < 0) +		{ +		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); +		if (idx < 0) +			{ +			idx = X509_STORE_CTX_get_ex_new_index(0, +				"SSLtest for verify callback", NULL,NULL,NULL); +			} +		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +		} +	return idx; +	} + +static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) +	{ +	char *s,buf[256]; + +	s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf, +			    sizeof buf); +	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) +		{ +		fprintf(stderr,"Error string: %s\n", +			X509_verify_cert_error_string(ctx->error)); +		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: +			fprintf(stderr,"  ... ignored.\n"); +			ok=1; +			} +		} + +	if (ok == 1) +		{ +		X509 *xs = ctx->current_cert; +#if 0 +		X509 *xi = ctx->current_issuer; +#endif + +		if (xs->ex_flags & EXFLAG_PROXY) +			{ +			unsigned int *letters = +				X509_STORE_CTX_get_ex_data(ctx, +					get_proxy_auth_ex_data_idx()); + +			if (letters) +				{ +				int found_any = 0; +				int i; +				PROXY_CERT_INFO_EXTENSION *pci = +					X509_get_ext_d2i(xs, NID_proxyCertInfo, +						NULL, NULL); + +				switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage)) +					{ +				case NID_Independent: +					/* Completely meaningless in this +					   program, as there's no way to +					   grant explicit rights to a +					   specific PrC.  Basically, using +					   id-ppl-Independent is the perfect +					   way to grant no rights at all. */ +					fprintf(stderr, "  Independent proxy certificate"); +					for (i = 0; i < 26; i++) +						letters[i] = 0; +					break; +				case NID_id_ppl_inheritAll: +					/* This is basically a NOP, we +					   simply let the current rights +					   stand as they are. */ +					fprintf(stderr, "  Proxy certificate inherits all"); +					break; +				default: +					s = (char *) +						pci->proxyPolicy->policy->data; +					i = pci->proxyPolicy->policy->length; + +					/* The algorithm works as follows: +					   it is assumed that previous +					   iterations or the initial granted +					   rights has already set some elements +					   of `letters'.  What we need to do is +					   to clear those that weren't granted +					   by the current PrC as well.  The +					   easiest way to do this is to add 1 +					   to all the elements whose letters +					   are given with the current policy. +					   That way, all elements that are set +					   by the current policy and were +					   already set by earlier policies and +					   through the original grant of rights +					   will get the value 2 or higher. +					   The last thing to do is to sweep +					   through `letters' and keep the +					   elements having the value 2 as set, +					   and clear all the others. */ + +					fprintf(stderr, "  Certificate proxy rights = %*.*s", i, i, s); +					while(i-- > 0) +						{ +						int c = *s++; +						if (isascii(c) && isalpha(c)) +							{ +							if (islower(c)) +								c = toupper(c); +							letters[c - 'A']++; +							} +						} +					for (i = 0; i < 26; i++) +						if (letters[i] < 2) +							letters[i] = 0; +						else +							letters[i] = 1; +					} + +				found_any = 0; +				fprintf(stderr, +					", resulting proxy rights = "); +				for(i = 0; i < 26; i++) +					if (letters[i]) +						{ +						fprintf(stderr, "%c", i + 'A'); +						found_any = 1; +						} +				if (!found_any) +					fprintf(stderr, "none"); +				fprintf(stderr, "\n"); + +				PROXY_CERT_INFO_EXTENSION_free(pci); +				} +			} +		} + +	return(ok); +	} + +static void process_proxy_debug(int indent, const char *format, ...) +	{ +	static const char indentation[] = +		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" +		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; /* That's 80 > */ +	char my_format[256]; +	va_list args; + +	BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s", +		indent, indent, indentation, format); + +	va_start(args, format); +	vfprintf(stderr, my_format, args); +	va_end(args); +	} +/* Priority levels: +   0	[!]var, () +   1	& ^ +   2	| +*/ +static int process_proxy_cond_adders(unsigned int letters[26], +	const char *cond, const char **cond_end, int *pos, int indent); +static int process_proxy_cond_val(unsigned int letters[26], +	const char *cond, const char **cond_end, int *pos, int indent) +	{ +	int c; +	int ok = 1; +	int negate = 0; + +	while(isspace((int)*cond)) +		{ +		cond++; (*pos)++; +		} +	c = *cond; + +	if (debug) +		process_proxy_debug(indent, +			"Start process_proxy_cond_val at position %d: %s\n", +			*pos, cond); + +	while(c == '!') +		{ +		negate = !negate; +		cond++; (*pos)++; +		while(isspace((int)*cond)) +			{ +			cond++; (*pos)++; +			} +		c = *cond; +		} + +	if (c == '(') +		{ +		cond++; (*pos)++; +		ok = process_proxy_cond_adders(letters, cond, cond_end, pos, +			indent + 1); +		cond = *cond_end; +		if (ok < 0) +			goto end; +		while(isspace((int)*cond)) +			{ +			cond++; (*pos)++; +			} +		c = *cond; +		if (c != ')') +			{ +			fprintf(stderr, +				"Weird condition character in position %d: " +				"%c\n", *pos, c); +			ok = -1; +			goto end; +			} +		cond++; (*pos)++; +		} +	else if (isascii(c) && isalpha(c)) +		{ +		if (islower(c)) +			c = toupper(c); +		ok = letters[c - 'A']; +		cond++; (*pos)++; +		} +	else +		{ +		fprintf(stderr, +			"Weird condition character in position %d: " +			"%c\n", *pos, c); +		ok = -1; +		goto end; +		} + end: +	*cond_end = cond; +	if (ok >= 0 && negate) +		ok = !ok; + +	if (debug) +		process_proxy_debug(indent, +			"End process_proxy_cond_val at position %d: %s, returning %d\n", +			*pos, cond, ok); + +	return ok; +	} +static int process_proxy_cond_multipliers(unsigned int letters[26], +	const char *cond, const char **cond_end, int *pos, int indent) +	{ +	int ok; +	char c; + +	if (debug) +		process_proxy_debug(indent, +			"Start process_proxy_cond_multipliers at position %d: %s\n", +			*pos, cond); + +	ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1); +	cond = *cond_end; +	if (ok < 0) +		goto end; + +	while(ok >= 0) +		{ +		while(isspace((int)*cond)) +			{ +			cond++; (*pos)++; +			} +		c = *cond; + +		switch(c) +			{ +		case '&': +		case '^': +			{ +			int save_ok = ok; + +			cond++; (*pos)++; +			ok = process_proxy_cond_val(letters, +				cond, cond_end, pos, indent + 1); +			cond = *cond_end; +			if (ok < 0) +				break; + +			switch(c) +				{ +			case '&': +				ok &= save_ok; +				break; +			case '^': +				ok ^= save_ok; +				break; +			default: +				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!" +					" STOPPING\n"); +				EXIT(1); +				} +			} +			break; +		default: +			goto end; +			} +		} + end: +	if (debug) +		process_proxy_debug(indent, +			"End process_proxy_cond_multipliers at position %d: %s, returning %d\n", +			*pos, cond, ok); + +	*cond_end = cond; +	return ok; +	} +static int process_proxy_cond_adders(unsigned int letters[26], +	const char *cond, const char **cond_end, int *pos, int indent) +	{ +	int ok; +	char c; + +	if (debug) +		process_proxy_debug(indent, +			"Start process_proxy_cond_adders at position %d: %s\n", +			*pos, cond); + +	ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos, +		indent + 1); +	cond = *cond_end; +	if (ok < 0) +		goto end; + +	while(ok >= 0) +		{ +		while(isspace((int)*cond)) +			{ +			cond++; (*pos)++; +			} +		c = *cond; + +		switch(c) +			{ +		case '|': +			{ +			int save_ok = ok; + +			cond++; (*pos)++; +			ok = process_proxy_cond_multipliers(letters, +				cond, cond_end, pos, indent + 1); +			cond = *cond_end; +			if (ok < 0) +				break; + +			switch(c) +				{ +			case '|': +				ok |= save_ok; +				break; +			default: +				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!" +					" STOPPING\n"); +				EXIT(1); +				} +			} +			break; +		default: +			goto end; +			} +		} + end: +	if (debug) +		process_proxy_debug(indent, +			"End process_proxy_cond_adders at position %d: %s, returning %d\n", +			*pos, cond, ok); + +	*cond_end = cond; +	return ok; +	} + +static int process_proxy_cond(unsigned int letters[26], +	const char *cond, const char **cond_end) +	{ +	int pos = 1; +	return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1); +	} + +static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) +	{ +	int ok=1; +	struct app_verify_arg *cb_arg = arg; +	unsigned int letters[26]; /* only used with proxy_auth */ + +	if (cb_arg->app_verify) +		{ +		char *s = NULL,buf[256]; + +		fprintf(stderr, "In app_verify_callback, allowing cert. "); +		fprintf(stderr, "Arg is: %s\n", cb_arg->string); +		fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n", +			(void *)ctx, (void *)ctx->cert); +		if (ctx->cert) +			s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256); +		if (s != NULL) +			{ +			fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf); +			} +		return(1); +		} +	if (cb_arg->proxy_auth) +		{ +		int found_any = 0, i; +		char *sp; + +		for(i = 0; i < 26; i++) +			letters[i] = 0; +		for(sp = cb_arg->proxy_auth; *sp; sp++) +			{ +			int c = *sp; +			if (isascii(c) && isalpha(c)) +				{ +				if (islower(c)) +					c = toupper(c); +				letters[c - 'A'] = 1; +				} +			} + +		fprintf(stderr, +			"  Initial proxy rights = "); +		for(i = 0; i < 26; i++) +			if (letters[i]) +				{ +				fprintf(stderr, "%c", i + 'A'); +				found_any = 1; +				} +		if (!found_any) +			fprintf(stderr, "none"); +		fprintf(stderr, "\n"); + +		X509_STORE_CTX_set_ex_data(ctx, +			get_proxy_auth_ex_data_idx(),letters); +		} +	if (cb_arg->allow_proxy_certs) +		{ +		X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS); +		} + +#ifndef OPENSSL_NO_X509_VERIFY +# ifdef OPENSSL_FIPS +	if(s->version == TLS1_VERSION) +		FIPS_allow_md5(1); +# endif +	ok = X509_verify_cert(ctx); +# ifdef OPENSSL_FIPS +	if(s->version == TLS1_VERSION) +		FIPS_allow_md5(0); +# endif +#endif + +	if (cb_arg->proxy_auth) +		{ +		if (ok > 0) +			{ +			const char *cond_end = NULL; + +			ok = process_proxy_cond(letters, +				cb_arg->proxy_cond, &cond_end); + +			if (ok < 0) +				EXIT(3); +			if (*cond_end) +				{ +				fprintf(stderr, "Stopped processing condition before it's end.\n"); +				ok = 0; +				} +			if (!ok) +				fprintf(stderr, "Proxy rights check with condition '%s' proved invalid\n", +					cb_arg->proxy_cond); +			else +				fprintf(stderr, "Proxy rights check with condition '%s' proved valid\n", +					cb_arg->proxy_cond); +			} +		} +	return(ok); +	} + +#ifndef OPENSSL_NO_RSA +static RSA *rsa_tmp=NULL; + +static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) +	{ +	BIGNUM *bn = NULL; +	if (rsa_tmp == NULL) +		{ +		bn = BN_new(); +		rsa_tmp = RSA_new(); +		if(!bn || !rsa_tmp || !BN_set_word(bn, RSA_F4)) +			{ +			BIO_printf(bio_err, "Memory error..."); +			goto end; +			} +		BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength); +		(void)BIO_flush(bio_err); +		if(!RSA_generate_key_ex(rsa_tmp,keylength,bn,NULL)) +			{ +			BIO_printf(bio_err, "Error generating key."); +			RSA_free(rsa_tmp); +			rsa_tmp = NULL; +			} +end: +		BIO_printf(bio_err,"\n"); +		(void)BIO_flush(bio_err); +		} +	if(bn) BN_free(bn); +	return(rsa_tmp); +	} + +static void free_tmp_rsa(void) +	{ +	if (rsa_tmp != NULL) +		{ +		RSA_free(rsa_tmp); +		rsa_tmp = NULL; +		} +	} +#endif + +#ifndef OPENSSL_NO_DH +/* These DH parameters have been generated as follows: + *    $ openssl dhparam -C -noout 512 + *    $ openssl dhparam -C -noout 1024 + *    $ openssl dhparam -C -noout -dsaparam 1024 + * (The third function has been renamed to avoid name conflicts.) + */ +static DH *get_dh512() +	{ +	static unsigned char dh512_p[]={ +		0xCB,0xC8,0xE1,0x86,0xD0,0x1F,0x94,0x17,0xA6,0x99,0xF0,0xC6, +		0x1F,0x0D,0xAC,0xB6,0x25,0x3E,0x06,0x39,0xCA,0x72,0x04,0xB0, +		0x6E,0xDA,0xC0,0x61,0xE6,0x7A,0x77,0x25,0xE8,0x3B,0xB9,0x5F, +		0x9A,0xB6,0xB5,0xFE,0x99,0x0B,0xA1,0x93,0x4E,0x35,0x33,0xB8, +		0xE1,0xF1,0x13,0x4F,0x59,0x1A,0xD2,0x57,0xC0,0x26,0x21,0x33, +		0x02,0xC5,0xAE,0x23, +		}; +	static unsigned char dh512_g[]={ +		0x02, +		}; +	DH *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)) +		{ DH_free(dh); return(NULL); } +	return(dh); +	} + +static DH *get_dh1024() +	{ +	static unsigned char dh1024_p[]={ +		0xF8,0x81,0x89,0x7D,0x14,0x24,0xC5,0xD1,0xE6,0xF7,0xBF,0x3A, +		0xE4,0x90,0xF4,0xFC,0x73,0xFB,0x34,0xB5,0xFA,0x4C,0x56,0xA2, +		0xEA,0xA7,0xE9,0xC0,0xC0,0xCE,0x89,0xE1,0xFA,0x63,0x3F,0xB0, +		0x6B,0x32,0x66,0xF1,0xD1,0x7B,0xB0,0x00,0x8F,0xCA,0x87,0xC2, +		0xAE,0x98,0x89,0x26,0x17,0xC2,0x05,0xD2,0xEC,0x08,0xD0,0x8C, +		0xFF,0x17,0x52,0x8C,0xC5,0x07,0x93,0x03,0xB1,0xF6,0x2F,0xB8, +		0x1C,0x52,0x47,0x27,0x1B,0xDB,0xD1,0x8D,0x9D,0x69,0x1D,0x52, +		0x4B,0x32,0x81,0xAA,0x7F,0x00,0xC8,0xDC,0xE6,0xD9,0xCC,0xC1, +		0x11,0x2D,0x37,0x34,0x6C,0xEA,0x02,0x97,0x4B,0x0E,0xBB,0xB1, +		0x71,0x33,0x09,0x15,0xFD,0xDD,0x23,0x87,0x07,0x5E,0x89,0xAB, +		0x6B,0x7C,0x5F,0xEC,0xA6,0x24,0xDC,0x53, +		}; +	static unsigned char dh1024_g[]={ +		0x02, +		}; +	DH *dh; + +	if ((dh=DH_new()) == NULL) return(NULL); +	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL); +	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL); +	if ((dh->p == NULL) || (dh->g == NULL)) +		{ DH_free(dh); return(NULL); } +	return(dh); +	} + +static DH *get_dh1024dsa() +	{ +	static unsigned char dh1024_p[]={ +		0xC8,0x00,0xF7,0x08,0x07,0x89,0x4D,0x90,0x53,0xF3,0xD5,0x00, +		0x21,0x1B,0xF7,0x31,0xA6,0xA2,0xDA,0x23,0x9A,0xC7,0x87,0x19, +		0x3B,0x47,0xB6,0x8C,0x04,0x6F,0xFF,0xC6,0x9B,0xB8,0x65,0xD2, +		0xC2,0x5F,0x31,0x83,0x4A,0xA7,0x5F,0x2F,0x88,0x38,0xB6,0x55, +		0xCF,0xD9,0x87,0x6D,0x6F,0x9F,0xDA,0xAC,0xA6,0x48,0xAF,0xFC, +		0x33,0x84,0x37,0x5B,0x82,0x4A,0x31,0x5D,0xE7,0xBD,0x52,0x97, +		0xA1,0x77,0xBF,0x10,0x9E,0x37,0xEA,0x64,0xFA,0xCA,0x28,0x8D, +		0x9D,0x3B,0xD2,0x6E,0x09,0x5C,0x68,0xC7,0x45,0x90,0xFD,0xBB, +		0x70,0xC9,0x3A,0xBB,0xDF,0xD4,0x21,0x0F,0xC4,0x6A,0x3C,0xF6, +		0x61,0xCF,0x3F,0xD6,0x13,0xF1,0x5F,0xBC,0xCF,0xBC,0x26,0x9E, +		0xBC,0x0B,0xBD,0xAB,0x5D,0xC9,0x54,0x39, +		}; +	static unsigned char dh1024_g[]={ +		0x3B,0x40,0x86,0xE7,0xF3,0x6C,0xDE,0x67,0x1C,0xCC,0x80,0x05, +		0x5A,0xDF,0xFE,0xBD,0x20,0x27,0x74,0x6C,0x24,0xC9,0x03,0xF3, +		0xE1,0x8D,0xC3,0x7D,0x98,0x27,0x40,0x08,0xB8,0x8C,0x6A,0xE9, +		0xBB,0x1A,0x3A,0xD6,0x86,0x83,0x5E,0x72,0x41,0xCE,0x85,0x3C, +		0xD2,0xB3,0xFC,0x13,0xCE,0x37,0x81,0x9E,0x4C,0x1C,0x7B,0x65, +		0xD3,0xE6,0xA6,0x00,0xF5,0x5A,0x95,0x43,0x5E,0x81,0xCF,0x60, +		0xA2,0x23,0xFC,0x36,0xA7,0x5D,0x7A,0x4C,0x06,0x91,0x6E,0xF6, +		0x57,0xEE,0x36,0xCB,0x06,0xEA,0xF5,0x3D,0x95,0x49,0xCB,0xA7, +		0xDD,0x81,0xDF,0x80,0x09,0x4A,0x97,0x4D,0xA8,0x22,0x72,0xA1, +		0x7F,0xC4,0x70,0x56,0x70,0xE8,0x20,0x10,0x18,0x8F,0x2E,0x60, +		0x07,0xE7,0x68,0x1A,0x82,0x5D,0x32,0xA2, +		}; +	DH *dh; + +	if ((dh=DH_new()) == NULL) return(NULL); +	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL); +	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL); +	if ((dh->p == NULL) || (dh->g == NULL)) +		{ DH_free(dh); return(NULL); } +	dh->length = 160; +	return(dh); +	} +#endif + +#ifndef OPENSSL_NO_PSK +/* convert the PSK key (psk_key) in ascii to binary (psk) */ +static int psk_key2bn(const char *pskkey, unsigned char *psk, +	unsigned int max_psk_len) +	{ +	int ret; +	BIGNUM *bn = NULL; + +	ret = BN_hex2bn(&bn, pskkey); +	if (!ret) +		{ +		BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", pskkey);  +		if (bn) +			BN_free(bn); +		return 0; +		} +	if (BN_num_bytes(bn) > (int)max_psk_len) +		{ +		BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n", +			max_psk_len, BN_num_bytes(bn)); +		BN_free(bn); +		return 0; +		} +	ret = BN_bn2bin(bn, psk); +	BN_free(bn); +	return ret; +	} + +static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity, +	unsigned int max_identity_len, unsigned char *psk, +	unsigned int max_psk_len) +	{ +	int ret; +	unsigned int psk_len = 0; + +	ret = BIO_snprintf(identity, max_identity_len, "Client_identity"); +	if (ret < 0) +		goto out_err; +	if (debug) +		fprintf(stderr, "client: created identity '%s' len=%d\n", identity, ret); +	ret = psk_key2bn(psk_key, psk, max_psk_len); +	if (ret < 0) +		goto out_err; +	psk_len = ret; +out_err: +	return psk_len; +	} + +static unsigned int psk_server_callback(SSL *ssl, const char *identity, +	unsigned char *psk, unsigned int max_psk_len) +	{ +	unsigned int psk_len=0; + +	if (strcmp(identity, "Client_identity") != 0) +		{ +		BIO_printf(bio_err, "server: PSK error: client identity not found\n"); +		return 0; +		} +	psk_len=psk_key2bn(psk_key, psk, max_psk_len); +	return psk_len; +	} +#endif + +static int do_test_cipherlist(void) +	{ +	int i = 0; +	const SSL_METHOD *meth; +	const SSL_CIPHER *ci, *tci = NULL; + +#ifndef OPENSSL_NO_SSL2 +	fprintf(stderr, "testing SSLv2 cipher list order: "); +	meth = SSLv2_method(); +	while ((ci = meth->get_cipher(i++)) != NULL) +		{ +		if (tci != NULL) +			if (ci->id >= tci->id) +				{ +				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id); +				return 0; +				} +		tci = ci; +		} +	fprintf(stderr, "ok\n"); +#endif +#ifndef OPENSSL_NO_SSL3 +	fprintf(stderr, "testing SSLv3 cipher list order: "); +	meth = SSLv3_method(); +	tci = NULL; +	while ((ci = meth->get_cipher(i++)) != NULL) +		{ +		if (tci != NULL) +			if (ci->id >= tci->id) +				{ +				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id); +				return 0; +				} +		tci = ci; +		} +	fprintf(stderr, "ok\n"); +#endif +#ifndef OPENSSL_NO_TLS1 +	fprintf(stderr, "testing TLSv1 cipher list order: "); +	meth = TLSv1_method(); +	tci = NULL; +	while ((ci = meth->get_cipher(i++)) != NULL) +		{ +		if (tci != NULL) +			if (ci->id >= tci->id) +				{ +				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id); +				return 0; +				} +		tci = ci; +		} +	fprintf(stderr, "ok\n"); +#endif + +	return 1; +	} diff --git a/main/openssl/ssl/t1_clnt.c b/main/openssl/ssl/t1_clnt.c new file mode 100644 index 00000000..c87af177 --- /dev/null +++ b/main/openssl/ssl/t1_clnt.c @@ -0,0 +1,79 @@ +/* ssl/t1_clnt.c */ +/* Copyright (C) 1995-1998 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" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + +static const SSL_METHOD *tls1_get_client_method(int ver); +static const SSL_METHOD *tls1_get_client_method(int ver) +	{ +	if (ver == TLS1_VERSION) +		return(TLSv1_client_method()); +	else +		return(NULL); +	} + +IMPLEMENT_tls1_meth_func(TLSv1_client_method, +			ssl_undefined_function, +			ssl3_connect, +			tls1_get_client_method) + diff --git a/main/openssl/ssl/t1_enc.c b/main/openssl/ssl/t1_enc.c new file mode 100644 index 00000000..793ea43e --- /dev/null +++ b/main/openssl/ssl/t1_enc.c @@ -0,0 +1,1045 @@ +/* ssl/t1_enc.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include <stdio.h> +#include "ssl_locl.h" +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/md5.h> +#ifdef KSSL_DEBUG +#include <openssl/des.h> +#endif + +/* seed1 through seed5 are virtually concatenated */ +static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, +			int sec_len, +			const void *seed1, int seed1_len, +			const void *seed2, int seed2_len, +			const void *seed3, int seed3_len, +			const void *seed4, int seed4_len, +			const void *seed5, int seed5_len, +			unsigned char *out, int olen) +	{ +	int chunk; +	unsigned int j; +	HMAC_CTX ctx; +	HMAC_CTX ctx_tmp; +	unsigned char A1[EVP_MAX_MD_SIZE]; +	unsigned int A1_len; +	int ret = 0; +	 +	chunk=EVP_MD_size(md); +	OPENSSL_assert(chunk >= 0); + +	HMAC_CTX_init(&ctx); +	HMAC_CTX_init(&ctx_tmp); +	if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL)) +		goto err; +	if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL)) +		goto err; +	if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len)) +		goto err; +	if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len)) +		goto err; +	if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len)) +		goto err; +	if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len)) +		goto err; +	if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len)) +		goto err; +	if (!HMAC_Final(&ctx,A1,&A1_len)) +		goto err; + +	for (;;) +		{ +		if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */ +			goto err; +		if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */ +			goto err; +		if (!HMAC_Update(&ctx,A1,A1_len)) +			goto err; +		if (!HMAC_Update(&ctx_tmp,A1,A1_len)) +			goto err; +		if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len)) +			goto err; +		if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len)) +			goto err; +		if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len)) +			goto err; +		if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len)) +			goto err; +		if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len)) +			goto err; + +		if (olen > chunk) +			{ +			if (!HMAC_Final(&ctx,out,&j)) +				goto err; +			out+=j; +			olen-=j; +			if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */ +				goto err; +			} +		else	/* last one */ +			{ +			if (!HMAC_Final(&ctx,A1,&A1_len)) +				goto err; +			memcpy(out,A1,olen); +			break; +			} +		} +	ret = 1; +err: +	HMAC_CTX_cleanup(&ctx); +	HMAC_CTX_cleanup(&ctx_tmp); +	OPENSSL_cleanse(A1,sizeof(A1)); +	return ret; +	} + +/* seed1 through seed5 are virtually concatenated */ +static int tls1_PRF(long digest_mask, +		     const void *seed1, int seed1_len, +		     const void *seed2, int seed2_len, +		     const void *seed3, int seed3_len, +		     const void *seed4, int seed4_len, +		     const void *seed5, int seed5_len, +		     const unsigned char *sec, int slen, +		     unsigned char *out1, +		     unsigned char *out2, int olen) +	{ +	int len,i,idx,count; +	const unsigned char *S1; +	long m; +	const EVP_MD *md; +	int ret = 0; + +	/* Count number of digests and partition sec evenly */ +	count=0; +	for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { +		if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++; +	}	 +	len=slen/count; +	S1=sec; +	memset(out1,0,olen); +	for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { +		if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) { +			if (!md) { +				SSLerr(SSL_F_TLS1_PRF, +				SSL_R_UNSUPPORTED_DIGEST_TYPE); +				goto err;				 +			} +			if (!tls1_P_hash(md ,S1,len+(slen&1), +					seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len, +					out2,olen)) +				goto err; +			S1+=len; +			for (i=0; i<olen; i++) +			{ +				out1[i]^=out2[i]; +			} +		} +	} +	ret = 1; +err: +	return ret; +} +static int tls1_generate_key_block(SSL *s, unsigned char *km, +	     unsigned char *tmp, int num) +	{ +	int ret; +	ret = tls1_PRF(s->s3->tmp.new_cipher->algorithm2, +		 TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE, +		 s->s3->server_random,SSL3_RANDOM_SIZE, +		 s->s3->client_random,SSL3_RANDOM_SIZE, +		 NULL,0,NULL,0, +		 s->session->master_key,s->session->master_key_length, +		 km,tmp,num); +#ifdef KSSL_DEBUG +	printf("tls1_generate_key_block() ==> %d byte master_key =\n\t", +                s->session->master_key_length); +	{ +        int i; +        for (i=0; i < s->session->master_key_length; i++) +                { +                printf("%02X", s->session->master_key[i]); +                } +        printf("\n");  } +#endif    /* KSSL_DEBUG */ +	return ret; +	} + +int tls1_change_cipher_state(SSL *s, int which) +	{ +	static const unsigned char empty[]=""; +	unsigned char *p,*mac_secret; +	unsigned char *exp_label; +	unsigned char tmp1[EVP_MAX_KEY_LENGTH]; +	unsigned char tmp2[EVP_MAX_KEY_LENGTH]; +	unsigned char iv1[EVP_MAX_IV_LENGTH*2]; +	unsigned char iv2[EVP_MAX_IV_LENGTH*2]; +	unsigned char *ms,*key,*iv; +	int client_write; +	EVP_CIPHER_CTX *dd; +	const EVP_CIPHER *c; +#ifndef OPENSSL_NO_COMP +	const SSL_COMP *comp; +#endif +	const EVP_MD *m; +	int mac_type; +	int *mac_secret_size; +	EVP_MD_CTX *mac_ctx; +	EVP_PKEY *mac_key; +	int is_export,n,i,j,k,exp_label_len,cl; +	int reuse_dd = 0; + +	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); +	c=s->s3->tmp.new_sym_enc; +	m=s->s3->tmp.new_hash; +	mac_type = s->s3->tmp.new_mac_pkey_type; +#ifndef OPENSSL_NO_COMP +	comp=s->s3->tmp.new_compression; +#endif + +#ifdef KSSL_DEBUG +	printf("tls1_change_cipher_state(which= %d) w/\n", which); +	printf("\talg= %ld/%ld, comp= %p\n", +	       s->s3->tmp.new_cipher->algorithm_mkey, +	       s->s3->tmp.new_cipher->algorithm_auth, +	       comp); +	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); +	printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", +                c->nid,c->block_size,c->key_len,c->iv_len); +	printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); +	{ +        int i; +        for (i=0; i<s->s3->tmp.key_block_length; i++) +		printf("%02x", key_block[i]);  printf("\n"); +        } +#endif	/* KSSL_DEBUG */ + +	if (which & SSL3_CC_READ) +		{ +		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) +			s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; +			else +			s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; + +		if (s->enc_read_ctx != NULL) +			reuse_dd = 1; +		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) +			goto err; +		else +			/* make sure it's intialized in case we exit later with an error */ +			EVP_CIPHER_CTX_init(s->enc_read_ctx); +		dd= s->enc_read_ctx; +		mac_ctx=ssl_replace_hash(&s->read_hash,NULL); +#ifndef OPENSSL_NO_COMP +		if (s->expand != NULL) +			{ +			COMP_CTX_free(s->expand); +			s->expand=NULL; +			} +		if (comp != NULL) +			{ +			s->expand=COMP_CTX_new(comp->method); +			if (s->expand == NULL) +				{ +				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); +				goto err2; +				} +			if (s->s3->rrec.comp == NULL) +				s->s3->rrec.comp=(unsigned char *) +					OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); +			if (s->s3->rrec.comp == NULL) +				goto err; +			} +#endif +		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ + 		if (s->version != DTLS1_VERSION) +			memset(&(s->s3->read_sequence[0]),0,8); +		mac_secret= &(s->s3->read_mac_secret[0]); +		mac_secret_size=&(s->s3->read_mac_secret_size); +		} +	else +		{ +		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) +			s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; +			else +			s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; +		if (s->enc_write_ctx != NULL) +			reuse_dd = 1; +		else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) +			goto err; +		else +			/* make sure it's intialized in case we exit later with an error */ +			EVP_CIPHER_CTX_init(s->enc_write_ctx); +		dd= s->enc_write_ctx; +		mac_ctx = ssl_replace_hash(&s->write_hash,NULL); +#ifndef OPENSSL_NO_COMP +		if (s->compress != NULL) +			{ +			COMP_CTX_free(s->compress); +			s->compress=NULL; +			} +		if (comp != NULL) +			{ +			s->compress=COMP_CTX_new(comp->method); +			if (s->compress == NULL) +				{ +				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); +				goto err2; +				} +			} +#endif +		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ + 		if (s->version != DTLS1_VERSION) +			memset(&(s->s3->write_sequence[0]),0,8); +		mac_secret= &(s->s3->write_mac_secret[0]); +		mac_secret_size = &(s->s3->write_mac_secret_size); +		} + +	if (reuse_dd) +		EVP_CIPHER_CTX_cleanup(dd); + +	p=s->s3->tmp.key_block; +	i=*mac_secret_size=s->s3->tmp.new_mac_secret_size; + +	cl=EVP_CIPHER_key_length(c); +	j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? +	               cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; +	/* Was 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; +		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; +		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; +		client_write=1; +		} +	else +		{ +		n=i; +		ms=  &(p[ n]); n+=i+j; +		key= &(p[ n]); n+=j+k; +		iv=  &(p[ n]); n+=k; +		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; +		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; +		client_write=0; +		} + +	if (n > s->s3->tmp.key_block_length) +		{ +		SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); +		goto err2; +		} + +	memcpy(mac_secret,ms,i); +	mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, +			mac_secret,*mac_secret_size); +	EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key); +	EVP_PKEY_free(mac_key); +#ifdef TLS_DEBUG +printf("which = %04X\nmac key=",which); +{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); } +#endif +	if (is_export) +		{ +		/* In here I set both the read and write key/iv to the +		 * same value since only the correct one will be used :-). +		 */ +		if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2, +				exp_label,exp_label_len, +				s->s3->client_random,SSL3_RANDOM_SIZE, +				s->s3->server_random,SSL3_RANDOM_SIZE, +				NULL,0,NULL,0, +				key,j,tmp1,tmp2,EVP_CIPHER_key_length(c))) +			goto err2; +		key=tmp1; + +		if (k > 0) +			{ +			if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2, +					TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE, +					s->s3->client_random,SSL3_RANDOM_SIZE, +					s->s3->server_random,SSL3_RANDOM_SIZE, +					NULL,0,NULL,0, +					empty,0,iv1,iv2,k*2)) +				goto err2; +			if (client_write) +				iv=iv1; +			else +				iv= &(iv1[k]); +			} +		} + +	s->session->key_arg_length=0; +#ifdef KSSL_DEBUG +	{ +        int i; +	printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); +	printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]); +	printf("\n"); +	printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]); +	printf("\n"); +	} +#endif	/* KSSL_DEBUG */ + +	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); +#ifdef TLS_DEBUG +printf("which = %04X\nkey=",which); +{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); } +printf("\niv="); +{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); } +printf("\n"); +#endif + +	OPENSSL_cleanse(tmp1,sizeof(tmp1)); +	OPENSSL_cleanse(tmp2,sizeof(tmp1)); +	OPENSSL_cleanse(iv1,sizeof(iv1)); +	OPENSSL_cleanse(iv2,sizeof(iv2)); +	return(1); +err: +	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); +err2: +	return(0); +	} + +int tls1_setup_key_block(SSL *s) +	{ +	unsigned char *p1,*p2=NULL; +	const EVP_CIPHER *c; +	const EVP_MD *hash; +	int num; +	SSL_COMP *comp; +	int mac_type= NID_undef,mac_secret_size=0; +	int ret=0; + +#ifdef KSSL_DEBUG +	printf ("tls1_setup_key_block()\n"); +#endif	/* KSSL_DEBUG */ + +	if (s->s3->tmp.key_block_length != 0) +		return(1); + +	if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp)) +		{ +		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); +		return(0); +		} + +	s->s3->tmp.new_sym_enc=c; +	s->s3->tmp.new_hash=hash; +	s->s3->tmp.new_mac_pkey_type = mac_type; +	s->s3->tmp.new_mac_secret_size = mac_secret_size; +	num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c); +	num*=2; + +	ssl3_cleanup_key_block(s); + +	if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL) +		{ +		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); +		goto err; +		} + +	s->s3->tmp.key_block_length=num; +	s->s3->tmp.key_block=p1; + +	if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL) +		{ +		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); +		goto err; +		} + +#ifdef TLS_DEBUG +printf("client random\n"); +{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); } +printf("server random\n"); +{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); } +printf("pre-master\n"); +{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); } +#endif +	if (!tls1_generate_key_block(s,p1,p2,num)) +		goto err; +#ifdef TLS_DEBUG +printf("\nkey block\n"); +{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); } +#endif + +	if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) +		{ +		/* enable vulnerability countermeasure for CBC ciphers with +		 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) +		 */ +		s->s3->need_empty_fragments = 1; + +		if (s->session->cipher != NULL) +			{ +			if (s->session->cipher->algorithm_enc == SSL_eNULL) +				s->s3->need_empty_fragments = 0; +			 +#ifndef OPENSSL_NO_RC4 +			if (s->session->cipher->algorithm_enc == SSL_RC4) +				s->s3->need_empty_fragments = 0; +#endif +			} +		} +		 +	ret = 1; +err: +	if (p2) +		{ +		OPENSSL_cleanse(p2,num); +		OPENSSL_free(p2); +		} +	return(ret); +	} + +int tls1_enc(SSL *s, int send) +	{ +	SSL3_RECORD *rec; +	EVP_CIPHER_CTX *ds; +	unsigned long l; +	int bs,i,ii,j,k,n=0; +	const EVP_CIPHER *enc; + +	if (send) +		{ +		if (EVP_MD_CTX_md(s->write_hash)) +			{ +			n=EVP_MD_CTX_size(s->write_hash); +			OPENSSL_assert(n >= 0); +			} +		ds=s->enc_write_ctx; +		rec= &(s->s3->wrec); +		if (s->enc_write_ctx == NULL) +			enc=NULL; +		else +			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); +		} +	else +		{ +		if (EVP_MD_CTX_md(s->read_hash)) +			{ +			n=EVP_MD_CTX_size(s->read_hash); +			OPENSSL_assert(n >= 0); +			} +		ds=s->enc_read_ctx; +		rec= &(s->s3->rrec); +		if (s->enc_read_ctx == NULL) +			enc=NULL; +		else +			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); +		} + +#ifdef KSSL_DEBUG +	printf("tls1_enc(%d)\n", send); +#endif    /* KSSL_DEBUG */ + +	if ((s->session == NULL) || (ds == NULL) || +		(enc == NULL)) +		{ +		memmove(rec->data,rec->input,rec->length); +		rec->input=rec->data; +		} +	else +		{ +		l=rec->length; +		bs=EVP_CIPHER_block_size(ds->cipher); + +		if ((bs != 1) && send) +			{ +			i=bs-((int)l%bs); + +			/* Add weird padding of upto 256 bytes */ + +			/* we need to add 'i' padding bytes of value j */ +			j=i-1; +			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) +				{ +				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) +					j++; +				} +			for (k=(int)l; k<(int)(l+i); k++) +				rec->input[k]=j; +			l+=i; +			rec->length+=i; +			} + +#ifdef KSSL_DEBUG +		{ +                unsigned long ui; +		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", +                        ds,rec->data,rec->input,l); +		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", +                        ds->buf_len, ds->cipher->key_len, +                        DES_KEY_SZ, DES_SCHEDULE_SZ, +                        ds->cipher->iv_len); +		printf("\t\tIV: "); +		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]); +		printf("\n"); +		printf("\trec->input="); +		for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]); +		printf("\n"); +		} +#endif	/* KSSL_DEBUG */ + +		if (!send) +			{ +			if (l == 0 || l%bs != 0) +				{ +				SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); +				return 0; +				} +			} +		 +		EVP_Cipher(ds,rec->data,rec->input,l); + +#ifdef KSSL_DEBUG +		{ +                unsigned long i; +                printf("\trec->data="); +		for (i=0; i<l; i++) +                        printf(" %02x", rec->data[i]);  printf("\n"); +                } +#endif	/* KSSL_DEBUG */ + +		if ((bs != 1) && !send) +			{ +			ii=i=rec->data[l-1]; /* padding_length */ +			i++; +			/* NB: if compression is in operation the first packet +			 * may not be of even length so the padding bug check +			 * cannot be performed. This bug workaround has been +			 * around since SSLeay so hopefully it is either fixed +			 * now or no buggy implementation supports compression  +			 * [steve] +			 */ +			if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) +				&& !s->expand) +				{ +				/* First packet is even in size, so check */ +				if ((memcmp(s->s3->read_sequence, +					"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) +					s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; +				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) +					i--; +				} +			/* TLS 1.0 does not bound the number of padding bytes by the block size. +			 * All of them must have value 'padding_length'. */ +			if (i > (int)rec->length) +				{ +				/* Incorrect padding. SSLerr() and ssl3_alert are done +				 * by caller: we don't want to reveal whether this is +				 * a decryption error or a MAC verification failure +				 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ +				return -1; +				} +			for (j=(int)(l-i); j<(int)l; j++) +				{ +				if (rec->data[j] != ii) +					{ +					/* Incorrect padding */ +					return -1; +					} +				} +			rec->length-=i; +			} +		} +	return(1); +	} +int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) +	{ +	unsigned int ret; +	EVP_MD_CTX ctx, *d=NULL; +	int i; + +	if (s->s3->handshake_buffer)  +		if (!ssl3_digest_cached_records(s)) +			return 0; + +	for (i=0;i<SSL_MAX_DIGEST;i++)  +		{ +		  if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid)  +		  	{ +		  	d=s->s3->handshake_dgst[i]; +			break; +			} +		} +	if (!d) { +		SSLerr(SSL_F_TLS1_CERT_VERIFY_MAC,SSL_R_NO_REQUIRED_DIGEST); +		return 0; +	}	 + +	EVP_MD_CTX_init(&ctx); +	EVP_MD_CTX_copy_ex(&ctx,d); +	EVP_DigestFinal_ex(&ctx,out,&ret); +	EVP_MD_CTX_cleanup(&ctx); +	return((int)ret); +	} + +int tls1_final_finish_mac(SSL *s, +	     const char *str, int slen, unsigned char *out) +	{ +	unsigned int i; +	EVP_MD_CTX ctx; +	unsigned char buf[2*EVP_MAX_MD_SIZE]; +	unsigned char *q,buf2[12]; +	int idx; +	long mask; +	int err=0; +	const EVP_MD *md;  + +	q=buf; + +	if (s->s3->handshake_buffer)  +		if (!ssl3_digest_cached_records(s)) +			return 0; + +	EVP_MD_CTX_init(&ctx); + +	for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++) +		{ +		if (mask & s->s3->tmp.new_cipher->algorithm2) +			{ +			int hashsize = EVP_MD_size(md); +			if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf))) +				{ +				/* internal error: 'buf' is too small for this cipersuite! */ +				err = 1; +				} +			else +				{ +				EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]); +				EVP_DigestFinal_ex(&ctx,q,&i); +				if (i != (unsigned int)hashsize) /* can't really happen */ +					err = 1; +				q+=i; +				} +			} +		} +		 +	if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2, +			str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0, +			s->session->master_key,s->session->master_key_length, +			out,buf2,sizeof buf2)) +		err = 1; +	EVP_MD_CTX_cleanup(&ctx); + +	if (err) +		return 0; +	else +		return sizeof buf2; +	} + +int tls1_mac(SSL *ssl, unsigned char *md, int send) +	{ +	SSL3_RECORD *rec; +	unsigned char *seq; +	EVP_MD_CTX *hash; +	size_t md_size; +	int i; +	EVP_MD_CTX hmac, *mac_ctx; +	unsigned char buf[5];  +	int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM)); +	int t; + +	if (send) +		{ +		rec= &(ssl->s3->wrec); +		seq= &(ssl->s3->write_sequence[0]); +		hash=ssl->write_hash; +		} +	else +		{ +		rec= &(ssl->s3->rrec); +		seq= &(ssl->s3->read_sequence[0]); +		hash=ssl->read_hash; +		} + +	t=EVP_MD_CTX_size(hash); +	OPENSSL_assert(t >= 0); +	md_size=t; + +	buf[0]=rec->type; +	buf[1]=(unsigned char)(ssl->version>>8); +	buf[2]=(unsigned char)(ssl->version); +	buf[3]=rec->length>>8; +	buf[4]=rec->length&0xff; + +	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ +	if (stream_mac)  +		{ +			mac_ctx = hash; +		} +		else +		{ +			EVP_MD_CTX_copy(&hmac,hash); +			mac_ctx = &hmac; +		} + +	if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER) +		{ +		unsigned char dtlsseq[8],*p=dtlsseq; + +		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); +		memcpy (p,&seq[2],6); + +		EVP_DigestSignUpdate(mac_ctx,dtlsseq,8); +		} +	else +		EVP_DigestSignUpdate(mac_ctx,seq,8); + +	EVP_DigestSignUpdate(mac_ctx,buf,5); +	EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); +	t=EVP_DigestSignFinal(mac_ctx,md,&md_size); +	OPENSSL_assert(t > 0); +		 +	if (!stream_mac) EVP_MD_CTX_cleanup(&hmac); +#ifdef TLS_DEBUG +printf("sec="); +{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); } +printf("seq="); +{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); } +printf("buf="); +{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); } +printf("rec="); +{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); } +#endif + +	if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER) +		{ +		for (i=7; i>=0; i--) +			{ +			++seq[i]; +			if (seq[i] != 0) break;  +			} +		} + +#ifdef TLS_DEBUG +{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",md[z]); printf("\n"); } +#endif +	return(md_size); +	} + +int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, +	     int len) +	{ +	unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH]; +	const void *co = NULL, *so = NULL; +	int col = 0, sol = 0; + +#ifdef KSSL_DEBUG +	printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len); +#endif	/* KSSL_DEBUG */ + +#ifdef TLSEXT_TYPE_opaque_prf_input +	if (s->s3->client_opaque_prf_input != NULL && s->s3->server_opaque_prf_input != NULL && +	    s->s3->client_opaque_prf_input_len > 0 && +	    s->s3->client_opaque_prf_input_len == s->s3->server_opaque_prf_input_len) +		{ +		co = s->s3->client_opaque_prf_input; +		col = s->s3->server_opaque_prf_input_len; +		so = s->s3->server_opaque_prf_input; +		sol = s->s3->client_opaque_prf_input_len; /* must be same as col (see draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1) */ +		} +#endif + +	tls1_PRF(s->s3->tmp.new_cipher->algorithm2, +		TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE, +		s->s3->client_random,SSL3_RANDOM_SIZE, +		co, col, +		s->s3->server_random,SSL3_RANDOM_SIZE, +		so, sol, +		p,len, +		s->session->master_key,buff,sizeof buff); + +#ifdef KSSL_DEBUG +	printf ("tls1_generate_master_secret() complete\n"); +#endif	/* KSSL_DEBUG */ +	return(SSL3_MASTER_SECRET_SIZE); +	} + +int tls1_alert_code(int code) +	{ +	switch (code) +		{ +	case SSL_AD_CLOSE_NOTIFY:	return(SSL3_AD_CLOSE_NOTIFY); +	case SSL_AD_UNEXPECTED_MESSAGE:	return(SSL3_AD_UNEXPECTED_MESSAGE); +	case SSL_AD_BAD_RECORD_MAC:	return(SSL3_AD_BAD_RECORD_MAC); +	case SSL_AD_DECRYPTION_FAILED:	return(TLS1_AD_DECRYPTION_FAILED); +	case SSL_AD_RECORD_OVERFLOW:	return(TLS1_AD_RECORD_OVERFLOW); +	case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE); +	case SSL_AD_HANDSHAKE_FAILURE:	return(SSL3_AD_HANDSHAKE_FAILURE); +	case SSL_AD_NO_CERTIFICATE:	return(-1); +	case SSL_AD_BAD_CERTIFICATE:	return(SSL3_AD_BAD_CERTIFICATE); +	case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE); +	case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED); +	case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED); +	case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN); +	case SSL_AD_ILLEGAL_PARAMETER:	return(SSL3_AD_ILLEGAL_PARAMETER); +	case SSL_AD_UNKNOWN_CA:		return(TLS1_AD_UNKNOWN_CA); +	case SSL_AD_ACCESS_DENIED:	return(TLS1_AD_ACCESS_DENIED); +	case SSL_AD_DECODE_ERROR:	return(TLS1_AD_DECODE_ERROR); +	case SSL_AD_DECRYPT_ERROR:	return(TLS1_AD_DECRYPT_ERROR); +	case SSL_AD_EXPORT_RESTRICTION:	return(TLS1_AD_EXPORT_RESTRICTION); +	case SSL_AD_PROTOCOL_VERSION:	return(TLS1_AD_PROTOCOL_VERSION); +	case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY); +	case SSL_AD_INTERNAL_ERROR:	return(TLS1_AD_INTERNAL_ERROR); +	case SSL_AD_USER_CANCELLED:	return(TLS1_AD_USER_CANCELLED); +	case SSL_AD_NO_RENEGOTIATION:	return(TLS1_AD_NO_RENEGOTIATION); +	case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION); +	case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE); +	case SSL_AD_UNRECOGNIZED_NAME:	return(TLS1_AD_UNRECOGNIZED_NAME); +	case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE); +	case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE); +	case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); +#if 0 /* not appropriate for TLS, not used for DTLS */ +	case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return  +					  (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); +#endif +	default:			return(-1); +		} +	} + diff --git a/main/openssl/ssl/t1_lib.c b/main/openssl/ssl/t1_lib.c new file mode 100644 index 00000000..bbab4675 --- /dev/null +++ b/main/openssl/ssl/t1_lib.c @@ -0,0 +1,1859 @@ +/* ssl/t1_lib.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/ocsp.h> +#include "ssl_locl.h" + +const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT; + +#ifndef OPENSSL_NO_TLSEXT +static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, +				const unsigned char *sess_id, int sesslen, +				SSL_SESSION **psess); +#endif + +SSL3_ENC_METHOD TLSv1_enc_data={ +	tls1_enc, +	tls1_mac, +	tls1_setup_key_block, +	tls1_generate_master_secret, +	tls1_change_cipher_state, +	tls1_final_finish_mac, +	TLS1_FINISH_MAC_LENGTH, +	tls1_cert_verify_mac, +	TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, +	TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, +	tls1_alert_code, +	}; + +long tls1_default_timeout(void) +	{ +	/* 2 hours, the 24 hours mentioned in the TLSv1 spec +	 * is way too long for http, the cache would over fill */ +	return(60*60*2); +	} + +int tls1_new(SSL *s) +	{ +	if (!ssl3_new(s)) return(0); +	s->method->ssl_clear(s); +	return(1); +	} + +void tls1_free(SSL *s) +	{ +#ifndef OPENSSL_NO_TLSEXT +	if (s->tlsext_session_ticket) +		{ +		OPENSSL_free(s->tlsext_session_ticket); +		} +#endif /* OPENSSL_NO_TLSEXT */ +	ssl3_free(s); +	} + +void tls1_clear(SSL *s) +	{ +	ssl3_clear(s); +	s->version=TLS1_VERSION; +	} + +#ifndef OPENSSL_NO_EC +static int nid_list[] = +	{ +		NID_sect163k1, /* sect163k1 (1) */ +		NID_sect163r1, /* sect163r1 (2) */ +		NID_sect163r2, /* sect163r2 (3) */ +		NID_sect193r1, /* sect193r1 (4) */  +		NID_sect193r2, /* sect193r2 (5) */  +		NID_sect233k1, /* sect233k1 (6) */ +		NID_sect233r1, /* sect233r1 (7) */  +		NID_sect239k1, /* sect239k1 (8) */  +		NID_sect283k1, /* sect283k1 (9) */ +		NID_sect283r1, /* sect283r1 (10) */  +		NID_sect409k1, /* sect409k1 (11) */  +		NID_sect409r1, /* sect409r1 (12) */ +		NID_sect571k1, /* sect571k1 (13) */  +		NID_sect571r1, /* sect571r1 (14) */  +		NID_secp160k1, /* secp160k1 (15) */ +		NID_secp160r1, /* secp160r1 (16) */  +		NID_secp160r2, /* secp160r2 (17) */  +		NID_secp192k1, /* secp192k1 (18) */ +		NID_X9_62_prime192v1, /* secp192r1 (19) */  +		NID_secp224k1, /* secp224k1 (20) */  +		NID_secp224r1, /* secp224r1 (21) */ +		NID_secp256k1, /* secp256k1 (22) */  +		NID_X9_62_prime256v1, /* secp256r1 (23) */  +		NID_secp384r1, /* secp384r1 (24) */ +		NID_secp521r1  /* secp521r1 (25) */	 +	}; +	 +int tls1_ec_curve_id2nid(int curve_id) +	{ +	/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ +	if ((curve_id < 1) || ((unsigned int)curve_id > +				sizeof(nid_list)/sizeof(nid_list[0]))) +		return 0; +	return nid_list[curve_id-1]; +	} + +int tls1_ec_nid2curve_id(int nid) +	{ +	/* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ +	switch (nid) +		{ +	case NID_sect163k1: /* sect163k1 (1) */ +		return 1; +	case NID_sect163r1: /* sect163r1 (2) */ +		return 2; +	case NID_sect163r2: /* sect163r2 (3) */ +		return 3; +	case NID_sect193r1: /* sect193r1 (4) */  +		return 4; +	case NID_sect193r2: /* sect193r2 (5) */  +		return 5; +	case NID_sect233k1: /* sect233k1 (6) */ +		return 6; +	case NID_sect233r1: /* sect233r1 (7) */  +		return 7; +	case NID_sect239k1: /* sect239k1 (8) */  +		return 8; +	case NID_sect283k1: /* sect283k1 (9) */ +		return 9; +	case NID_sect283r1: /* sect283r1 (10) */  +		return 10; +	case NID_sect409k1: /* sect409k1 (11) */  +		return 11; +	case NID_sect409r1: /* sect409r1 (12) */ +		return 12; +	case NID_sect571k1: /* sect571k1 (13) */  +		return 13; +	case NID_sect571r1: /* sect571r1 (14) */  +		return 14; +	case NID_secp160k1: /* secp160k1 (15) */ +		return 15; +	case NID_secp160r1: /* secp160r1 (16) */  +		return 16; +	case NID_secp160r2: /* secp160r2 (17) */  +		return 17; +	case NID_secp192k1: /* secp192k1 (18) */ +		return 18; +	case NID_X9_62_prime192v1: /* secp192r1 (19) */  +		return 19; +	case NID_secp224k1: /* secp224k1 (20) */  +		return 20; +	case NID_secp224r1: /* secp224r1 (21) */ +		return 21; +	case NID_secp256k1: /* secp256k1 (22) */  +		return 22; +	case NID_X9_62_prime256v1: /* secp256r1 (23) */  +		return 23; +	case NID_secp384r1: /* secp384r1 (24) */ +		return 24; +	case NID_secp521r1:  /* secp521r1 (25) */	 +		return 25; +	default: +		return 0; +		} +	} +#endif /* OPENSSL_NO_EC */ + +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) +	{ +	int extdatalen=0; +	unsigned char *ret = p; + +	/* don't add extensions for SSLv3 unless doing secure renegotiation */ +	if (s->client_version == SSL3_VERSION +					&& !s->s3->send_connection_binding) +		return p; + +	ret+=2; + +	if (ret>=limit) return NULL; /* this really never occurs, but ... */ + + 	if (s->tlsext_hostname != NULL) +		{  +		/* Add TLS extension servername to the Client Hello message */ +		unsigned long size_str; +		long lenmax;  + +		/* check for enough space. +		   4 for the servername type and entension length +		   2 for servernamelist length +		   1 for the hostname type +		   2 for hostname length +		   + hostname length  +		*/ +		    +		if ((lenmax = limit - ret - 9) < 0  +		    || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax)  +			return NULL; +			 +		/* extension type and length */ +		s2n(TLSEXT_TYPE_server_name,ret);  +		s2n(size_str+5,ret); +		 +		/* length of servername list */ +		s2n(size_str+3,ret); +	 +		/* hostname type, length and hostname */ +		*(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name; +		s2n(size_str,ret); +		memcpy(ret, s->tlsext_hostname, size_str); +		ret+=size_str; +		} + +        /* Add RI if renegotiating */ +        if (s->new_session) +          { +          int el; +           +          if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) +              { +              SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +              return NULL; +              } + +          if((limit - p - 4 - el) < 0) return NULL; +           +          s2n(TLSEXT_TYPE_renegotiate,ret); +          s2n(el,ret); + +          if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) +              { +              SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +              return NULL; +              } + +          ret += el; +        } + +#ifndef OPENSSL_NO_EC +	if (s->tlsext_ecpointformatlist != NULL && +	    s->version != DTLS1_VERSION) +		{ +		/* Add TLS extension ECPointFormats to the ClientHello message */ +		long lenmax;  + +		if ((lenmax = limit - ret - 5) < 0) return NULL;  +		if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL; +		if (s->tlsext_ecpointformatlist_length > 255) +			{ +			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +			return NULL; +			} +		 +		s2n(TLSEXT_TYPE_ec_point_formats,ret); +		s2n(s->tlsext_ecpointformatlist_length + 1,ret); +		*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length; +		memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length); +		ret+=s->tlsext_ecpointformatlist_length; +		} +	if (s->tlsext_ellipticcurvelist != NULL && +	    s->version != DTLS1_VERSION) +		{ +		/* Add TLS extension EllipticCurves to the ClientHello message */ +		long lenmax;  + +		if ((lenmax = limit - ret - 6) < 0) return NULL;  +		if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) return NULL; +		if (s->tlsext_ellipticcurvelist_length > 65532) +			{ +			SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +			return NULL; +			} +		 +		s2n(TLSEXT_TYPE_elliptic_curves,ret); +		s2n(s->tlsext_ellipticcurvelist_length + 2, ret); + +		/* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for +		 * elliptic_curve_list, but the examples use two bytes. +		 * http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html +		 * resolves this to two bytes. +		 */ +		s2n(s->tlsext_ellipticcurvelist_length, ret); +		memcpy(ret, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length); +		ret+=s->tlsext_ellipticcurvelist_length; +		} +#endif /* OPENSSL_NO_EC */ + +	if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) +		{ +		int ticklen; +		if (!s->new_session && s->session && s->session->tlsext_tick) +			ticklen = s->session->tlsext_ticklen; +		else if (s->session && s->tlsext_session_ticket && +			 s->tlsext_session_ticket->data) +			{ +			ticklen = s->tlsext_session_ticket->length; +			s->session->tlsext_tick = OPENSSL_malloc(ticklen); +			if (!s->session->tlsext_tick) +				return NULL; +			memcpy(s->session->tlsext_tick, +			       s->tlsext_session_ticket->data, +			       ticklen); +			s->session->tlsext_ticklen = ticklen; +			} +		else +			ticklen = 0; +		if (ticklen == 0 && s->tlsext_session_ticket && +		    s->tlsext_session_ticket->data == NULL) +			goto skip_ext; +		/* Check for enough room 2 for extension type, 2 for len + 		 * rest for ticket +  		 */ +		if ((long)(limit - ret - 4 - ticklen) < 0) return NULL; +		s2n(TLSEXT_TYPE_session_ticket,ret);  +		s2n(ticklen,ret); +		if (ticklen) +			{ +			memcpy(ret, s->session->tlsext_tick, ticklen); +			ret += ticklen; +			} +		} +		skip_ext: + +#ifdef TLSEXT_TYPE_opaque_prf_input +	if (s->s3->client_opaque_prf_input != NULL && +	    s->version != DTLS1_VERSION) +		{ +		size_t col = s->s3->client_opaque_prf_input_len; +		 +		if ((long)(limit - ret - 6 - col < 0)) +			return NULL; +		if (col > 0xFFFD) /* can't happen */ +			return NULL; + +		s2n(TLSEXT_TYPE_opaque_prf_input, ret);  +		s2n(col + 2, ret); +		s2n(col, ret); +		memcpy(ret, s->s3->client_opaque_prf_input, col); +		ret += col; +		} +#endif + +	if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && +	    s->version != DTLS1_VERSION) +		{ +		int i; +		long extlen, idlen, itmp; +		OCSP_RESPID *id; + +		idlen = 0; +		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) +			{ +			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); +			itmp = i2d_OCSP_RESPID(id, NULL); +			if (itmp <= 0) +				return NULL; +			idlen += itmp + 2; +			} + +		if (s->tlsext_ocsp_exts) +			{ +			extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL); +			if (extlen < 0) +				return NULL; +			} +		else +			extlen = 0; +			 +		if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL; +		s2n(TLSEXT_TYPE_status_request, ret); +		if (extlen + idlen > 0xFFF0) +			return NULL; +		s2n(extlen + idlen + 5, ret); +		*(ret++) = TLSEXT_STATUSTYPE_ocsp; +		s2n(idlen, ret); +		for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) +			{ +			/* save position of id len */ +			unsigned char *q = ret; +			id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); +			/* skip over id len */ +			ret += 2; +			itmp = i2d_OCSP_RESPID(id, &ret); +			/* write id len */ +			s2n(itmp, q); +			} +		s2n(extlen, ret); +		if (extlen > 0) +			i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); +		} + +#ifndef OPENSSL_NO_NEXTPROTONEG +	if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) +		{ +		/* The client advertises an emtpy extension to indicate its +		 * support for Next Protocol Negotiation */ +		if (limit - ret - 4 < 0) +			return NULL; +		s2n(TLSEXT_TYPE_next_proto_neg,ret); +		s2n(0,ret); +		} +#endif + +	if ((extdatalen = ret-p-2)== 0)  +		return p; + +	s2n(extdatalen,p); +	return ret; +	} + +unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) +	{ +	int extdatalen=0; +	unsigned char *ret = p; +#ifndef OPENSSL_NO_NEXTPROTONEG +	int next_proto_neg_seen; +#endif + +	/* don't add extensions for SSLv3, unless doing secure renegotiation */ +	if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) +		return p; +	 +	ret+=2; +	if (ret>=limit) return NULL; /* this really never occurs, but ... */ + +	if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL) +		{  +		if ((long)(limit - ret - 4) < 0) return NULL;  + +		s2n(TLSEXT_TYPE_server_name,ret); +		s2n(0,ret); +		} + +	if(s->s3->send_connection_binding) +        { +          int el; +           +          if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) +              { +              SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +              return NULL; +              } + +          if((limit - p - 4 - el) < 0) return NULL; +           +          s2n(TLSEXT_TYPE_renegotiate,ret); +          s2n(el,ret); + +          if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) +              { +              SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +              return NULL; +              } + +          ret += el; +        } + +#ifndef OPENSSL_NO_EC +	if (s->tlsext_ecpointformatlist != NULL && +	    s->version != DTLS1_VERSION) +		{ +		/* Add TLS extension ECPointFormats to the ServerHello message */ +		long lenmax;  + +		if ((lenmax = limit - ret - 5) < 0) return NULL;  +		if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL; +		if (s->tlsext_ecpointformatlist_length > 255) +			{ +			SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); +			return NULL; +			} +		 +		s2n(TLSEXT_TYPE_ec_point_formats,ret); +		s2n(s->tlsext_ecpointformatlist_length + 1,ret); +		*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length; +		memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length); +		ret+=s->tlsext_ecpointformatlist_length; + +		} +	/* Currently the server should not respond with a SupportedCurves extension */ +#endif /* OPENSSL_NO_EC */ + +	if (s->tlsext_ticket_expected +		&& !(SSL_get_options(s) & SSL_OP_NO_TICKET))  +		{  +		if ((long)(limit - ret - 4) < 0) return NULL;  +		s2n(TLSEXT_TYPE_session_ticket,ret); +		s2n(0,ret); +		} + +	if (s->tlsext_status_expected) +		{  +		if ((long)(limit - ret - 4) < 0) return NULL;  +		s2n(TLSEXT_TYPE_status_request,ret); +		s2n(0,ret); +		} + +#ifdef TLSEXT_TYPE_opaque_prf_input +	if (s->s3->server_opaque_prf_input != NULL && +	    s->version != DTLS1_VERSION) +		{ +		size_t sol = s->s3->server_opaque_prf_input_len; +		 +		if ((long)(limit - ret - 6 - sol) < 0) +			return NULL; +		if (sol > 0xFFFD) /* can't happen */ +			return NULL; + +		s2n(TLSEXT_TYPE_opaque_prf_input, ret);  +		s2n(sol + 2, ret); +		s2n(sol, ret); +		memcpy(ret, s->s3->server_opaque_prf_input, sol); +		ret += sol; +		} +#endif +	if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81)  +		&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG)) +		{ const unsigned char cryptopro_ext[36] = { +			0xfd, 0xe8, /*65000*/ +			0x00, 0x20, /*32 bytes length*/ +			0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,  +			0x03,   0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,  +			0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,  +			0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17}; +			if (limit-ret<36) return NULL; +			memcpy(ret,cryptopro_ext,36); +			ret+=36; + +		} + +#ifndef OPENSSL_NO_NEXTPROTONEG +	next_proto_neg_seen = s->s3->next_proto_neg_seen; +	s->s3->next_proto_neg_seen = 0; +	if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) +		{ +		const unsigned char *npa; +		unsigned int npalen; +		int r; + +		r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen, s->ctx->next_protos_advertised_cb_arg); +		if (r == SSL_TLSEXT_ERR_OK) +			{ +			if ((long)(limit - ret - 4 - npalen) < 0) return NULL; +			s2n(TLSEXT_TYPE_next_proto_neg,ret); +			s2n(npalen,ret); +			memcpy(ret, npa, npalen); +			ret += npalen; +			s->s3->next_proto_neg_seen = 1; +			} +		} +#endif + +	if ((extdatalen = ret-p-2)== 0)  +		return p; + +	s2n(extdatalen,p); +	return ret; +	} + +int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) +	{ +	unsigned short type; +	unsigned short size; +	unsigned short len; +	unsigned char *data = *p; +	int renegotiate_seen = 0; + +	s->servername_done = 0; +	s->tlsext_status_type = -1; + +	if (data >= (d+n-2)) +		goto ri_check; +	n2s(data,len); + +	if (data > (d+n-len))  +		goto ri_check; + +	while (data <= (d+n-4)) +		{ +		n2s(data,type); +		n2s(data,size); + +		if (data+size > (d+n)) +	   		goto ri_check; +#if 0 +		fprintf(stderr,"Received extension type %d size %d\n",type,size); +#endif +		if (s->tlsext_debug_cb) +			s->tlsext_debug_cb(s, 0, type, data, size, +						s->tlsext_debug_arg); +/* The servername extension is treated as follows: + +   - Only the hostname type is supported with a maximum length of 255. +   - The servername is rejected if too long or if it contains zeros, +     in which case an fatal alert is generated. +   - The servername field is maintained together with the session cache. +   - When a session is resumed, the servername call back invoked in order +     to allow the application to position itself to the right context.  +   - The servername is acknowledged if it is new for a session or when  +     it is identical to a previously used for the same session.  +     Applications can control the behaviour.  They can at any time +     set a 'desirable' servername for a new SSL object. This can be the +     case for example with HTTPS when a Host: header field is received and +     a renegotiation is requested. In this case, a possible servername +     presented in the new client hello is only acknowledged if it matches +     the value of the Host: field.  +   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION +     if they provide for changing an explicit servername context for the session, +     i.e. when the session has been established with a servername extension.  +   - On session reconnect, the servername extension may be absent.  + +*/       + +		if (type == TLSEXT_TYPE_server_name) +			{ +			unsigned char *sdata; +			int servname_type; +			int dsize;  +		 +			if (size < 2)  +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} +			n2s(data,dsize);   +			size -= 2; +			if (dsize > size  )  +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				}  + +			sdata = data; +			while (dsize > 3)  +				{ +	 			servname_type = *(sdata++);  +				n2s(sdata,len); +				dsize -= 3; + +				if (len > dsize)  +					{ +					*al = SSL_AD_DECODE_ERROR; +					return 0; +					} +				if (s->servername_done == 0) +				switch (servname_type) +					{ +				case TLSEXT_NAMETYPE_host_name: +					if (!s->hit) +						{ +						if(s->session->tlsext_hostname) +							{ +							*al = SSL_AD_DECODE_ERROR; +							return 0; +							} +						if (len > TLSEXT_MAXLEN_host_name) +							{ +							*al = TLS1_AD_UNRECOGNIZED_NAME; +							return 0; +							} +						if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL) +							{ +							*al = TLS1_AD_INTERNAL_ERROR; +							return 0; +							} +						memcpy(s->session->tlsext_hostname, sdata, len); +						s->session->tlsext_hostname[len]='\0'; +						if (strlen(s->session->tlsext_hostname) != len) { +							OPENSSL_free(s->session->tlsext_hostname); +							s->session->tlsext_hostname = NULL; +							*al = TLS1_AD_UNRECOGNIZED_NAME; +							return 0; +						} +						s->servername_done = 1;  + +						} +					else  +						s->servername_done = s->session->tlsext_hostname +							&& strlen(s->session->tlsext_hostname) == len  +							&& strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0; +					 +					break; + +				default: +					break; +					} +				  +				dsize -= len; +				} +			if (dsize != 0)  +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} + +			} + +#ifndef OPENSSL_NO_EC +		else if (type == TLSEXT_TYPE_ec_point_formats && +	             s->version != DTLS1_VERSION) +			{ +			unsigned char *sdata = data; +			int ecpointformatlist_length = *(sdata++); + +			if (ecpointformatlist_length != size - 1) +				{ +				*al = TLS1_AD_DECODE_ERROR; +				return 0; +				} +			if (!s->hit) +				{ +				if(s->session->tlsext_ecpointformatlist) +					{ +					OPENSSL_free(s->session->tlsext_ecpointformatlist); +					s->session->tlsext_ecpointformatlist = NULL; +					} +				s->session->tlsext_ecpointformatlist_length = 0; +				if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL) +					{ +					*al = TLS1_AD_INTERNAL_ERROR; +					return 0; +					} +				s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length; +				memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length); +				} +#if 0 +			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ecpointformatlist (length=%i) ", s->session->tlsext_ecpointformatlist_length); +			sdata = s->session->tlsext_ecpointformatlist; +			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++) +				fprintf(stderr,"%i ",*(sdata++)); +			fprintf(stderr,"\n"); +#endif +			} +		else if (type == TLSEXT_TYPE_elliptic_curves && +	             s->version != DTLS1_VERSION) +			{ +			unsigned char *sdata = data; +			int ellipticcurvelist_length = (*(sdata++) << 8); +			ellipticcurvelist_length += (*(sdata++)); + +			if (ellipticcurvelist_length != size - 2) +				{ +				*al = TLS1_AD_DECODE_ERROR; +				return 0; +				} +			if (!s->hit) +				{ +				if(s->session->tlsext_ellipticcurvelist) +					{ +					*al = TLS1_AD_DECODE_ERROR; +					return 0; +					} +				s->session->tlsext_ellipticcurvelist_length = 0; +				if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL) +					{ +					*al = TLS1_AD_INTERNAL_ERROR; +					return 0; +					} +				s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length; +				memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length); +				} +#if 0 +			fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length); +			sdata = s->session->tlsext_ellipticcurvelist; +			for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++) +				fprintf(stderr,"%i ",*(sdata++)); +			fprintf(stderr,"\n"); +#endif +			} +#endif /* OPENSSL_NO_EC */ +#ifdef TLSEXT_TYPE_opaque_prf_input +		else if (type == TLSEXT_TYPE_opaque_prf_input && +	             s->version != DTLS1_VERSION) +			{ +			unsigned char *sdata = data; + +			if (size < 2) +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} +			n2s(sdata, s->s3->client_opaque_prf_input_len); +			if (s->s3->client_opaque_prf_input_len != size - 2) +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} + +			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */ +				OPENSSL_free(s->s3->client_opaque_prf_input); +			if (s->s3->client_opaque_prf_input_len == 0) +				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */ +			else +				s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len); +			if (s->s3->client_opaque_prf_input == NULL) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			} +#endif +		else if (type == TLSEXT_TYPE_session_ticket) +			{ +			if (s->tls_session_ticket_ext_cb && +			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg)) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			} +		else if (type == TLSEXT_TYPE_renegotiate) +			{ +			if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) +				return 0; +			renegotiate_seen = 1; +			} +		else if (type == TLSEXT_TYPE_status_request && +		         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) +			{ +		 +			if (size < 5)  +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} + +			s->tlsext_status_type = *data++; +			size--; +			if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) +				{ +				const unsigned char *sdata; +				int dsize; +				/* Read in responder_id_list */ +				n2s(data,dsize); +				size -= 2; +				if (dsize > size  )  +					{ +					*al = SSL_AD_DECODE_ERROR; +					return 0; +					} +				while (dsize > 0) +					{ +					OCSP_RESPID *id; +					int idsize; +					if (dsize < 4) +						{ +						*al = SSL_AD_DECODE_ERROR; +						return 0; +						} +					n2s(data, idsize); +					dsize -= 2 + idsize; +					size -= 2 + idsize; +					if (dsize < 0) +						{ +						*al = SSL_AD_DECODE_ERROR; +						return 0; +						} +					sdata = data; +					data += idsize; +					id = d2i_OCSP_RESPID(NULL, +								&sdata, idsize); +					if (!id) +						{ +						*al = SSL_AD_DECODE_ERROR; +						return 0; +						} +					if (data != sdata) +						{ +						OCSP_RESPID_free(id); +						*al = SSL_AD_DECODE_ERROR; +						return 0; +						} +					if (!s->tlsext_ocsp_ids +						&& !(s->tlsext_ocsp_ids = +						sk_OCSP_RESPID_new_null())) +						{ +						OCSP_RESPID_free(id); +						*al = SSL_AD_INTERNAL_ERROR; +						return 0; +						} +					if (!sk_OCSP_RESPID_push( +							s->tlsext_ocsp_ids, id)) +						{ +						OCSP_RESPID_free(id); +						*al = SSL_AD_INTERNAL_ERROR; +						return 0; +						} +					} + +				/* Read in request_extensions */ +				if (size < 2) +					{ +					*al = SSL_AD_DECODE_ERROR; +					return 0; +					} +				n2s(data,dsize); +				size -= 2; +				if (dsize != size) +					{ +					*al = SSL_AD_DECODE_ERROR; +					return 0; +					} +				sdata = data; +				if (dsize > 0) +					{ +					s->tlsext_ocsp_exts = +						d2i_X509_EXTENSIONS(NULL, +							&sdata, dsize); +					if (!s->tlsext_ocsp_exts +						|| (data + dsize != sdata)) +						{ +						*al = SSL_AD_DECODE_ERROR; +						return 0; +						} +					} +				} +				/* We don't know what to do with any other type + 			 	* so ignore it. + 			 	*/ +				else +					s->tlsext_status_type = -1; +			} +#ifndef OPENSSL_NO_NEXTPROTONEG +		else if (type == TLSEXT_TYPE_next_proto_neg && +                         s->s3->tmp.finish_md_len == 0) +			{ +			/* We shouldn't accept this extension on a +			 * renegotiation. +			 * +			 * s->new_session will be set on renegotiation, but we +			 * probably shouldn't rely that it couldn't be set on +			 * the initial renegotation too in certain cases (when +			 * there's some other reason to disallow resuming an +			 * earlier session -- the current code won't be doing +			 * anything like that, but this might change). + +			 * A valid sign that there's been a previous handshake +			 * in this connection is if s->s3->tmp.finish_md_len > +			 * 0.  (We are talking about a check that will happen +			 * in the Hello protocol round, well before a new +			 * Finished message could have been computed.) */ +			s->s3->next_proto_neg_seen = 1; +			} +#endif + +		/* session ticket processed earlier */ +		data+=size; +		} +				 +	*p = data; + +	ri_check: + +	/* Need RI if renegotiating */ + +	if (!renegotiate_seen && s->new_session && +		!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) +		{ +		*al = SSL_AD_HANDSHAKE_FAILURE; +	 	SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, +				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); +		return 0; +		} + +	return 1; +	} + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* ssl_next_proto_validate validates a Next Protocol Negotiation block. No + * elements of zero length are allowed and the set of elements must exactly fill + * the length of the block. */ +static int ssl_next_proto_validate(unsigned char *d, unsigned len) +	{ +	unsigned int off = 0; + +	while (off < len) +		{ +		if (d[off] == 0) +			return 0; +		off += d[off]; +		off++; +		} + +	return off == len; +	} +#endif + +int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) +	{ +	unsigned short length; +	unsigned short type; +	unsigned short size; +	unsigned char *data = *p; +	int tlsext_servername = 0; +	int renegotiate_seen = 0; + +	if (data >= (d+n-2)) +		goto ri_check; + +	n2s(data,length); +	if (data+length != d+n) +		{ +		*al = SSL_AD_DECODE_ERROR; +		return 0; +		} + +	while(data <= (d+n-4)) +		{ +		n2s(data,type); +		n2s(data,size); + +		if (data+size > (d+n)) +	   		goto ri_check; + +		if (s->tlsext_debug_cb) +			s->tlsext_debug_cb(s, 1, type, data, size, +						s->tlsext_debug_arg); + +		if (type == TLSEXT_TYPE_server_name) +			{ +			if (s->tlsext_hostname == NULL || size > 0) +				{ +				*al = TLS1_AD_UNRECOGNIZED_NAME; +				return 0; +				} +			tlsext_servername = 1;    +			} + +#ifndef OPENSSL_NO_EC +		else if (type == TLSEXT_TYPE_ec_point_formats && +	             s->version != DTLS1_VERSION) +			{ +			unsigned char *sdata = data; +			int ecpointformatlist_length = *(sdata++); + +			if (ecpointformatlist_length != size - 1) +				{ +				*al = TLS1_AD_DECODE_ERROR; +				return 0; +				} +			s->session->tlsext_ecpointformatlist_length = 0; +			if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist); +			if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length; +			memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length); +#if 0 +			fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist "); +			sdata = s->session->tlsext_ecpointformatlist; +			for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++) +				fprintf(stderr,"%i ",*(sdata++)); +			fprintf(stderr,"\n"); +#endif +			} +#endif /* OPENSSL_NO_EC */ + +		else if (type == TLSEXT_TYPE_session_ticket) +			{ +			if (s->tls_session_ticket_ext_cb && +			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg)) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			if ((SSL_get_options(s) & SSL_OP_NO_TICKET) +				|| (size > 0)) +				{ +				*al = TLS1_AD_UNSUPPORTED_EXTENSION; +				return 0; +				} +			s->tlsext_ticket_expected = 1; +			} +#ifdef TLSEXT_TYPE_opaque_prf_input +		else if (type == TLSEXT_TYPE_opaque_prf_input && +	             s->version != DTLS1_VERSION) +			{ +			unsigned char *sdata = data; + +			if (size < 2) +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} +			n2s(sdata, s->s3->server_opaque_prf_input_len); +			if (s->s3->server_opaque_prf_input_len != size - 2) +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} +			 +			if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */ +				OPENSSL_free(s->s3->server_opaque_prf_input); +			if (s->s3->server_opaque_prf_input_len == 0) +				s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */ +			else +				s->s3->server_opaque_prf_input = BUF_memdup(sdata, s->s3->server_opaque_prf_input_len); + +			if (s->s3->server_opaque_prf_input == NULL) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			} +#endif +		else if (type == TLSEXT_TYPE_status_request && +		         s->version != DTLS1_VERSION) +			{ +			/* MUST be empty and only sent if we've requested +			 * a status request message. +			 */  +			if ((s->tlsext_status_type == -1) || (size > 0)) +				{ +				*al = TLS1_AD_UNSUPPORTED_EXTENSION; +				return 0; +				} +			/* Set flag to expect CertificateStatus message */ +			s->tlsext_status_expected = 1; +			} +#ifndef OPENSSL_NO_NEXTPROTONEG +		else if (type == TLSEXT_TYPE_next_proto_neg) +			{ +			unsigned char *selected; +			unsigned char selected_len; + +			/* We must have requested it. */ +			if ((s->ctx->next_proto_select_cb == NULL)) +				{ +				*al = TLS1_AD_UNSUPPORTED_EXTENSION; +				return 0; +				} +			/* The data must be valid */ +			if (!ssl_next_proto_validate(data, size)) +				{ +				*al = TLS1_AD_DECODE_ERROR; +				return 0; +				} +			if (s->ctx->next_proto_select_cb(s, &selected, &selected_len, data, size, s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			s->next_proto_negotiated = OPENSSL_malloc(selected_len); +			if (!s->next_proto_negotiated) +				{ +				*al = TLS1_AD_INTERNAL_ERROR; +				return 0; +				} +			memcpy(s->next_proto_negotiated, selected, selected_len); +			s->next_proto_negotiated_len = selected_len; +			} +#endif +		else if (type == TLSEXT_TYPE_renegotiate) +			{ +			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) +				return 0; +			renegotiate_seen = 1; +			} +		data+=size;		 +		} + +	if (data != d+n) +		{ +		*al = SSL_AD_DECODE_ERROR; +		return 0; +		} + +	if (!s->hit && tlsext_servername == 1) +		{ + 		if (s->tlsext_hostname) +			{ +			if (s->session->tlsext_hostname == NULL) +				{ +				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	 +				if (!s->session->tlsext_hostname) +					{ +					*al = SSL_AD_UNRECOGNIZED_NAME; +					return 0; +					} +				} +			else  +				{ +				*al = SSL_AD_DECODE_ERROR; +				return 0; +				} +			} +		} + +	*p = data; + +	ri_check: + +	/* Determine if we need to see RI. Strictly speaking if we want to +	 * avoid an attack we should *always* see RI even on initial server +	 * hello because the client doesn't see any renegotiation during an +	 * attack. However this would mean we could not connect to any server +	 * which doesn't support RI so for the immediate future tolerate RI +	 * absence on initial connect only. +	 */ +	if (!renegotiate_seen +		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) +		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) +		{ +		*al = SSL_AD_HANDSHAKE_FAILURE; +		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, +				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); +		return 0; +		} + +	return 1; +	} + + +int ssl_prepare_clienthello_tlsext(SSL *s) +	{ +#ifndef OPENSSL_NO_EC +	/* If we are client and using an elliptic curve cryptography cipher suite, send the point formats  +	 * and elliptic curves we support. +	 */ +	int using_ecc = 0; +	int i; +	unsigned char *j; +	unsigned long alg_k, alg_a; +	STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); + +	for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) +		{ +		SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); + +		alg_k = c->algorithm_mkey; +		alg_a = c->algorithm_auth; +		if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA))) +			{ +			using_ecc = 1; +			break; +			} +		} +	using_ecc = using_ecc && (s->version == TLS1_VERSION); +	if (using_ecc) +		{ +		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist); +		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) +			{ +			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE); +			return -1; +			} +		s->tlsext_ecpointformatlist_length = 3; +		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed; +		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; +		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + +		/* we support all named elliptic curves in draft-ietf-tls-ecc-12 */ +		if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist); +		s->tlsext_ellipticcurvelist_length = sizeof(nid_list)/sizeof(nid_list[0]) * 2; +		if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL) +			{ +			s->tlsext_ellipticcurvelist_length = 0; +			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE); +			return -1; +			} +		for (i = 1, j = s->tlsext_ellipticcurvelist; (unsigned int)i <= +				sizeof(nid_list)/sizeof(nid_list[0]); i++) +			s2n(i,j); +		} +#endif /* OPENSSL_NO_EC */ + +#ifdef TLSEXT_TYPE_opaque_prf_input + 	{ +		int r = 1; +	 +		if (s->ctx->tlsext_opaque_prf_input_callback != 0) +			{ +			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg); +			if (!r) +				return -1; +			} + +		if (s->tlsext_opaque_prf_input != NULL) +			{ +			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */ +				OPENSSL_free(s->s3->client_opaque_prf_input); + +			if (s->tlsext_opaque_prf_input_len == 0) +				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */ +			else +				s->s3->client_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len); +			if (s->s3->client_opaque_prf_input == NULL) +				{ +				SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE); +				return -1; +				} +			s->s3->client_opaque_prf_input_len = s->tlsext_opaque_prf_input_len; +			} + +		if (r == 2) +			/* at callback's request, insist on receiving an appropriate server opaque PRF input */ +			s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len; +	} +#endif + +	return 1; +	} + +int ssl_prepare_serverhello_tlsext(SSL *s) +	{ +#ifndef OPENSSL_NO_EC +	/* If we are server and using an ECC cipher suite, send the point formats we support  +	 * if the client sent us an ECPointsFormat extension.  Note that the server is not +	 * supposed to send an EllipticCurves extension. +	 */ + +	unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; +	unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; +	int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA); +	using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); +	 +	if (using_ecc) +		{ +		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist); +		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) +			{ +			SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE); +			return -1; +			} +		s->tlsext_ecpointformatlist_length = 3; +		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed; +		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; +		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; +		} +#endif /* OPENSSL_NO_EC */ + +	return 1; +	} + +int ssl_check_clienthello_tlsext(SSL *s) +	{ +	int ret=SSL_TLSEXT_ERR_NOACK; +	int al = SSL_AD_UNRECOGNIZED_NAME; + +#ifndef OPENSSL_NO_EC +	/* The handling of the ECPointFormats extension is done elsewhere, namely in  +	 * ssl3_choose_cipher in s3_lib.c. +	 */ +	/* The handling of the EllipticCurves extension is done elsewhere, namely in  +	 * ssl3_choose_cipher in s3_lib.c. +	 */ +#endif + +	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)  +		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg); +	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		 +		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg); + +	/* If status request then ask callback what to do. + 	 * Note: this must be called after servername callbacks in case  + 	 * the certificate has changed. + 	 */ +	if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) +		{ +		int r; +		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); +		switch (r) +			{ +			/* We don't want to send a status request response */ +			case SSL_TLSEXT_ERR_NOACK: +				s->tlsext_status_expected = 0; +				break; +			/* status request response should be sent */ +			case SSL_TLSEXT_ERR_OK: +				if (s->tlsext_ocsp_resp) +					s->tlsext_status_expected = 1; +				else +					s->tlsext_status_expected = 0; +				break; +			/* something bad happened */ +			case SSL_TLSEXT_ERR_ALERT_FATAL: +				ret = SSL_TLSEXT_ERR_ALERT_FATAL; +				al = SSL_AD_INTERNAL_ERROR; +				goto err; +			} +		} +	else +		s->tlsext_status_expected = 0; + +#ifdef TLSEXT_TYPE_opaque_prf_input + 	{ +		/* This sort of belongs into ssl_prepare_serverhello_tlsext(), +		 * but we might be sending an alert in response to the client hello, +		 * so this has to happen here in ssl_check_clienthello_tlsext(). */ + +		int r = 1; +	 +		if (s->ctx->tlsext_opaque_prf_input_callback != 0) +			{ +			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg); +			if (!r) +				{ +				ret = SSL_TLSEXT_ERR_ALERT_FATAL; +				al = SSL_AD_INTERNAL_ERROR; +				goto err; +				} +			} + +		if (s->s3->server_opaque_prf_input != NULL) /* shouldn't really happen */ +			OPENSSL_free(s->s3->server_opaque_prf_input); +		s->s3->server_opaque_prf_input = NULL; + +		if (s->tlsext_opaque_prf_input != NULL) +			{ +			if (s->s3->client_opaque_prf_input != NULL && +				s->s3->client_opaque_prf_input_len == s->tlsext_opaque_prf_input_len) +				{ +				/* can only use this extension if we have a server opaque PRF input +				 * of the same length as the client opaque PRF input! */ + +				if (s->tlsext_opaque_prf_input_len == 0) +					s->s3->server_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */ +				else +					s->s3->server_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len); +				if (s->s3->server_opaque_prf_input == NULL) +					{ +					ret = SSL_TLSEXT_ERR_ALERT_FATAL; +					al = SSL_AD_INTERNAL_ERROR; +					goto err; +					} +				s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len; +				} +			} + +		if (r == 2 && s->s3->server_opaque_prf_input == NULL) +			{ +			/* The callback wants to enforce use of the extension, +			 * but we can't do that with the client opaque PRF input; +			 * abort the handshake. +			 */ +			ret = SSL_TLSEXT_ERR_ALERT_FATAL; +			al = SSL_AD_HANDSHAKE_FAILURE; +			} +	} + +#endif + err: +	switch (ret) +		{ +		case SSL_TLSEXT_ERR_ALERT_FATAL: +			ssl3_send_alert(s,SSL3_AL_FATAL,al);  +			return -1; + +		case SSL_TLSEXT_ERR_ALERT_WARNING: +			ssl3_send_alert(s,SSL3_AL_WARNING,al); +			return 1;  +					 +		case SSL_TLSEXT_ERR_NOACK: +			s->servername_done=0; +			default: +		return 1; +		} +	} + +int ssl_check_serverhello_tlsext(SSL *s) +	{ +	int ret=SSL_TLSEXT_ERR_NOACK; +	int al = SSL_AD_UNRECOGNIZED_NAME; + +#ifndef OPENSSL_NO_EC +	/* If we are client and using an elliptic curve cryptography cipher +	 * suite, then if server returns an EC point formats lists extension +	 * it must contain uncompressed. +	 */ +	unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; +	unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; +	if ((s->tlsext_ecpointformatlist != NULL) && (s->tlsext_ecpointformatlist_length > 0) &&  +	    (s->session->tlsext_ecpointformatlist != NULL) && (s->session->tlsext_ecpointformatlist_length > 0) &&  +	    ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA))) +		{ +		/* we are using an ECC cipher */ +		size_t i; +		unsigned char *list; +		int found_uncompressed = 0; +		list = s->session->tlsext_ecpointformatlist; +		for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++) +			{ +			if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed) +				{ +				found_uncompressed = 1; +				break; +				} +			} +		if (!found_uncompressed) +			{ +			SSLerr(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); +			return -1; +			} +		} +	ret = SSL_TLSEXT_ERR_OK; +#endif /* OPENSSL_NO_EC */ + +	if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)  +		ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg); +	else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) 		 +		ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg); + +#ifdef TLSEXT_TYPE_opaque_prf_input +	if (s->s3->server_opaque_prf_input_len > 0) +		{ +		/* This case may indicate that we, as a client, want to insist on using opaque PRF inputs. +		 * So first verify that we really have a value from the server too. */ + +		if (s->s3->server_opaque_prf_input == NULL) +			{ +			ret = SSL_TLSEXT_ERR_ALERT_FATAL; +			al = SSL_AD_HANDSHAKE_FAILURE; +			} +		 +		/* Anytime the server *has* sent an opaque PRF input, we need to check +		 * that we have a client opaque PRF input of the same size. */ +		if (s->s3->client_opaque_prf_input == NULL || +		    s->s3->client_opaque_prf_input_len != s->s3->server_opaque_prf_input_len) +			{ +			ret = SSL_TLSEXT_ERR_ALERT_FATAL; +			al = SSL_AD_ILLEGAL_PARAMETER; +			} +		} +#endif + +	/* If we've requested certificate status and we wont get one + 	 * tell the callback + 	 */ +	if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected) +			&& s->ctx && s->ctx->tlsext_status_cb) +		{ +		int r; +		/* Set resp to NULL, resplen to -1 so callback knows + 		 * there is no response. + 		 */ +		if (s->tlsext_ocsp_resp) +			{ +			OPENSSL_free(s->tlsext_ocsp_resp); +			s->tlsext_ocsp_resp = NULL; +			} +		s->tlsext_ocsp_resplen = -1; +		r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); +		if (r == 0) +			{ +			al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE; +			ret = SSL_TLSEXT_ERR_ALERT_FATAL; +			} +		if (r < 0) +			{ +			al = SSL_AD_INTERNAL_ERROR; +			ret = SSL_TLSEXT_ERR_ALERT_FATAL; +			} +		} + +	switch (ret) +		{ +		case SSL_TLSEXT_ERR_ALERT_FATAL: +			ssl3_send_alert(s,SSL3_AL_FATAL,al);  +			return -1; + +		case SSL_TLSEXT_ERR_ALERT_WARNING: +			ssl3_send_alert(s,SSL3_AL_WARNING,al); +			return 1;  +					 +		case SSL_TLSEXT_ERR_NOACK: +			s->servername_done=0; +			default: +		return 1; +		} +	} + +/* Since the server cache lookup is done early on in the processing of client + * hello and other operations depend on the result we need to handle any TLS + * session ticket extension at the same time. + */ + +int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, +				const unsigned char *limit, SSL_SESSION **ret) +	{ +	/* Point after session ID in client hello */ +	const unsigned char *p = session_id + len; +	unsigned short i; + +	/* If tickets disabled behave as if no ticket present + 	 * to permit stateful resumption. + 	 */ +	if (SSL_get_options(s) & SSL_OP_NO_TICKET) +		return 1; + +	if ((s->version <= SSL3_VERSION) || !limit) +		return 1; +	if (p >= limit) +		return -1; +	/* Skip past DTLS cookie */ +	if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) +		{ +		i = *(p++); +		p+= i; +		if (p >= limit) +			return -1; +		} +	/* Skip past cipher list */ +	n2s(p, i); +	p+= i; +	if (p >= limit) +		return -1; +	/* Skip past compression algorithm list */ +	i = *(p++); +	p += i; +	if (p > limit) +		return -1; +	/* Now at start of extensions */ +	if ((p + 2) >= limit) +		return 1; +	n2s(p, i); +	while ((p + 4) <= limit) +		{ +		unsigned short type, size; +		n2s(p, type); +		n2s(p, size); +		if (p + size > limit) +			return 1; +		if (type == TLSEXT_TYPE_session_ticket) +			{ +			/* If tickets disabled indicate cache miss which will + 			 * trigger a full handshake + 			 */ +			if (SSL_get_options(s) & SSL_OP_NO_TICKET) +				return 1; +			/* If zero length note client will accept a ticket + 			 * and indicate cache miss to trigger full handshake + 			 */ +			if (size == 0) +				{ +				s->tlsext_ticket_expected = 1; +				return 0;	/* Cache miss */ +				} +			if (s->tls_session_secret_cb) +				{ +				/* Indicate cache miss here and instead of +				 * generating the session from ticket now, +				 * trigger abbreviated handshake based on +				 * external mechanism to calculate the master +				 * secret later. */ +				return 0; +				} +			return tls_decrypt_ticket(s, p, size, session_id, len, +									ret); +			} +		p += size; +		} +	return 1; +	} + +static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, +				const unsigned char *sess_id, int sesslen, +				SSL_SESSION **psess) +	{ +	SSL_SESSION *sess; +	unsigned char *sdec; +	const unsigned char *p; +	int slen, mlen, renew_ticket = 0; +	unsigned char tick_hmac[EVP_MAX_MD_SIZE]; +	HMAC_CTX hctx; +	EVP_CIPHER_CTX ctx; +	SSL_CTX *tctx = s->initial_ctx; +	/* Need at least keyname + iv + some encrypted data */ +	if (eticklen < 48) +		goto tickerr; +	/* Initialize session ticket encryption and HMAC contexts */ +	HMAC_CTX_init(&hctx); +	EVP_CIPHER_CTX_init(&ctx); +	if (tctx->tlsext_ticket_key_cb) +		{ +		unsigned char *nctick = (unsigned char *)etick; +		int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, +							&ctx, &hctx, 0); +		if (rv < 0) +			return -1; +		if (rv == 0) +			goto tickerr; +		if (rv == 2) +			renew_ticket = 1; +		} +	else +		{ +		/* Check key name matches */ +		if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) +			goto tickerr; +		HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, +					tlsext_tick_md(), NULL); +		EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, +				tctx->tlsext_tick_aes_key, etick + 16); +		} +	/* Attempt to process session ticket, first conduct sanity and + 	 * integrity checks on ticket. + 	 */ +	mlen = HMAC_size(&hctx); +	if (mlen < 0) +		{ +		EVP_CIPHER_CTX_cleanup(&ctx); +		return -1; +		} +	eticklen -= mlen; +	/* Check HMAC of encrypted ticket */ +	HMAC_Update(&hctx, etick, eticklen); +	HMAC_Final(&hctx, tick_hmac, NULL); +	HMAC_CTX_cleanup(&hctx); +	if (memcmp(tick_hmac, etick + eticklen, mlen)) +		goto tickerr; +	/* Attempt to decrypt session data */ +	/* Move p after IV to start of encrypted ticket, update length */ +	p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); +	eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); +	sdec = OPENSSL_malloc(eticklen); +	if (!sdec) +		{ +		EVP_CIPHER_CTX_cleanup(&ctx); +		return -1; +		} +	EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen); +	if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0) +		goto tickerr; +	slen += mlen; +	EVP_CIPHER_CTX_cleanup(&ctx); +	p = sdec; +		 +	sess = d2i_SSL_SESSION(NULL, &p, slen); +	OPENSSL_free(sdec); +	if (sess) +		{ +		/* The session ID if non-empty is used by some clients to + 		 * detect that the ticket has been accepted. So we copy it to + 		 * the session structure. If it is empty set length to zero + 		 * as required by standard. + 		 */ +		if (sesslen) +			memcpy(sess->session_id, sess_id, sesslen); +		sess->session_id_length = sesslen; +		*psess = sess; +		s->tlsext_ticket_expected = renew_ticket; +		return 1; +		} +	/* If session decrypt failure indicate a cache miss and set state to + 	 * send a new ticket + 	 */ +	tickerr:	 +	s->tlsext_ticket_expected = 1; +	return 0; +	} + +#endif diff --git a/main/openssl/ssl/t1_meth.c b/main/openssl/ssl/t1_meth.c new file mode 100644 index 00000000..6ce7c0bb --- /dev/null +++ b/main/openssl/ssl/t1_meth.c @@ -0,0 +1,76 @@ +/* ssl/t1_meth.c */ +/* Copyright (C) 1995-1998 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 <openssl/objects.h> +#include "ssl_locl.h" + +static const SSL_METHOD *tls1_get_method(int ver); +static const SSL_METHOD *tls1_get_method(int ver) +	{ +	if (ver == TLS1_VERSION) +		return(TLSv1_method()); +	else +		return(NULL); +	} + +IMPLEMENT_tls1_meth_func(TLSv1_method, +			ssl3_accept, +			ssl3_connect, +			tls1_get_method) + diff --git a/main/openssl/ssl/t1_reneg.c b/main/openssl/ssl/t1_reneg.c new file mode 100644 index 00000000..9c2cc3c7 --- /dev/null +++ b/main/openssl/ssl/t1_reneg.c @@ -0,0 +1,292 @@ +/* ssl/t1_reneg.c */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2009 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#include <stdio.h> +#include <openssl/objects.h> +#include "ssl_locl.h" + +/* Add the client's renegotiation binding */ +int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, +					int maxlen) +    { +    if(p) +        { +	if((s->s3->previous_client_finished_len+1) > maxlen) +            { +            SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG); +            return 0; +            } +             +        /* Length byte */ +	*p = s->s3->previous_client_finished_len; +        p++; + +        memcpy(p, s->s3->previous_client_finished, +	       s->s3->previous_client_finished_len); +#ifdef OPENSSL_RI_DEBUG +    fprintf(stderr, "%s RI extension sent by client\n", +		s->s3->previous_client_finished_len ? "Non-empty" : "Empty"); +#endif +        } +     +    *len=s->s3->previous_client_finished_len + 1; + +  +    return 1; +    } + +/* Parse the client's renegotiation binding and abort if it's not +   right */ +int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len, +					  int *al) +    { +    int ilen; + +    /* Parse the length byte */ +    if(len < 1) +        { +        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); +        *al=SSL_AD_ILLEGAL_PARAMETER; +        return 0; +        } +    ilen = *d; +    d++; + +    /* Consistency check */ +    if((ilen+1) != len) +        { +        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); +        *al=SSL_AD_ILLEGAL_PARAMETER; +        return 0; +        } + +    /* Check that the extension matches */ +    if(ilen != s->s3->previous_client_finished_len) +        { +        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); +        *al=SSL_AD_HANDSHAKE_FAILURE; +        return 0; +        } +     +    if(memcmp(d, s->s3->previous_client_finished, +	      s->s3->previous_client_finished_len)) +        { +        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); +        *al=SSL_AD_HANDSHAKE_FAILURE; +        return 0; +        } +#ifdef OPENSSL_RI_DEBUG +    fprintf(stderr, "%s RI extension received by server\n", +				ilen ? "Non-empty" : "Empty"); +#endif + +    s->s3->send_connection_binding=1; + +    return 1; +    } + +/* Add the server's renegotiation binding */ +int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len, +					int maxlen) +    { +    if(p) +        { +        if((s->s3->previous_client_finished_len + +            s->s3->previous_server_finished_len + 1) > maxlen) +            { +            SSLerr(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG); +            return 0; +            } +         +        /* Length byte */ +        *p = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; +        p++; + +        memcpy(p, s->s3->previous_client_finished, +	       s->s3->previous_client_finished_len); +        p += s->s3->previous_client_finished_len; + +        memcpy(p, s->s3->previous_server_finished, +	       s->s3->previous_server_finished_len); +#ifdef OPENSSL_RI_DEBUG +    fprintf(stderr, "%s RI extension sent by server\n", +    		s->s3->previous_client_finished_len ? "Non-empty" : "Empty"); +#endif +        } +     +    *len=s->s3->previous_client_finished_len +	+ s->s3->previous_server_finished_len + 1; +     +    return 1; +    } + +/* Parse the server's renegotiation binding and abort if it's not +   right */ +int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len, +					  int *al) +    { +    int expected_len=s->s3->previous_client_finished_len +	+ s->s3->previous_server_finished_len; +    int ilen; + +    /* Check for logic errors */ +    OPENSSL_assert(!expected_len || s->s3->previous_client_finished_len); +    OPENSSL_assert(!expected_len || s->s3->previous_server_finished_len); +     +    /* Parse the length byte */ +    if(len < 1) +        { +        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); +        *al=SSL_AD_ILLEGAL_PARAMETER; +        return 0; +        } +    ilen = *d; +    d++; + +    /* Consistency check */ +    if(ilen+1 != len) +        { +        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); +        *al=SSL_AD_ILLEGAL_PARAMETER; +        return 0; +        } +     +    /* Check that the extension matches */ +    if(ilen != expected_len) +        { +        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); +        *al=SSL_AD_HANDSHAKE_FAILURE; +        return 0; +        } + +    if(memcmp(d, s->s3->previous_client_finished, +	      s->s3->previous_client_finished_len)) +        { +        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); +        *al=SSL_AD_HANDSHAKE_FAILURE; +        return 0; +        } +    d += s->s3->previous_client_finished_len; + +    if(memcmp(d, s->s3->previous_server_finished, +	      s->s3->previous_server_finished_len)) +        { +        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); +        *al=SSL_AD_ILLEGAL_PARAMETER; +        return 0; +        } +#ifdef OPENSSL_RI_DEBUG +    fprintf(stderr, "%s RI extension received by client\n", +				ilen ? "Non-empty" : "Empty"); +#endif +    s->s3->send_connection_binding=1; + +    return 1; +    } diff --git a/main/openssl/ssl/t1_srvr.c b/main/openssl/ssl/t1_srvr.c new file mode 100644 index 00000000..42525e9e --- /dev/null +++ b/main/openssl/ssl/t1_srvr.c @@ -0,0 +1,80 @@ +/* ssl/t1_srvr.c */ +/* Copyright (C) 1995-1998 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" +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/x509.h> + +static const SSL_METHOD *tls1_get_server_method(int ver); +static const SSL_METHOD *tls1_get_server_method(int ver) +	{ +	if (ver == TLS1_VERSION) +		return(TLSv1_server_method()); +	else +		return(NULL); +	} + +IMPLEMENT_tls1_meth_func(TLSv1_server_method, +			ssl3_accept, +			ssl_undefined_function, +			tls1_get_server_method) + diff --git a/main/openssl/ssl/tls1.h b/main/openssl/ssl/tls1.h new file mode 100644 index 00000000..76f368ac --- /dev/null +++ b/main/openssl/ssl/tls1.h @@ -0,0 +1,537 @@ +/* ssl/tls1.h */ +/* Copyright (C) 1995-1998 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.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved. + * + * 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 above 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 acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + *    endorse or promote products derived from this software without + *    prior written permission. For written permission, please contact + *    openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + *    nor may "OpenSSL" appear in their names without prior written + *    permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + *    acknowledgment: + *    "This product includes software developed by the OpenSSL Project + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com).  This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by  + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_TLS1_H  +#define HEADER_TLS1_H  + +#include <openssl/buffer.h> + +#ifdef  __cplusplus +extern "C" { +#endif + +#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES	0 + +#define TLS1_VERSION			0x0301 +#define TLS1_VERSION_MAJOR		0x03 +#define TLS1_VERSION_MINOR		0x01 + +#define TLS1_AD_DECRYPTION_FAILED	21 +#define TLS1_AD_RECORD_OVERFLOW		22 +#define TLS1_AD_UNKNOWN_CA		48	/* fatal */ +#define TLS1_AD_ACCESS_DENIED		49	/* fatal */ +#define TLS1_AD_DECODE_ERROR		50	/* fatal */ +#define TLS1_AD_DECRYPT_ERROR		51 +#define TLS1_AD_EXPORT_RESTRICTION	60	/* fatal */ +#define TLS1_AD_PROTOCOL_VERSION	70	/* fatal */ +#define TLS1_AD_INSUFFICIENT_SECURITY	71	/* fatal */ +#define TLS1_AD_INTERNAL_ERROR		80	/* fatal */ +#define TLS1_AD_USER_CANCELLED		90 +#define TLS1_AD_NO_RENEGOTIATION	100 +/* codes 110-114 are from RFC3546 */ +#define TLS1_AD_UNSUPPORTED_EXTENSION	110 +#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +#define TLS1_AD_UNRECOGNIZED_NAME 	112 +#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +#define TLS1_AD_UNKNOWN_PSK_IDENTITY	115	/* fatal */ + +/* ExtensionType values from RFC3546 / RFC4366 */ +#define TLSEXT_TYPE_server_name			0 +#define TLSEXT_TYPE_max_fragment_length		1 +#define TLSEXT_TYPE_client_certificate_url	2 +#define TLSEXT_TYPE_trusted_ca_keys		3 +#define TLSEXT_TYPE_truncated_hmac		4 +#define TLSEXT_TYPE_status_request		5 +/* ExtensionType values from RFC4492 */ +#define TLSEXT_TYPE_elliptic_curves		10 +#define TLSEXT_TYPE_ec_point_formats		11 +#define TLSEXT_TYPE_session_ticket		35 +/* ExtensionType value from draft-rescorla-tls-opaque-prf-input-00.txt */ +#if 0 /* will have to be provided externally for now , +       * i.e. build with -DTLSEXT_TYPE_opaque_prf_input=38183 +       * using whatever extension number you'd like to try */ +# define TLSEXT_TYPE_opaque_prf_input		?? */ +#endif + +/* Temporary extension type */ +#define TLSEXT_TYPE_renegotiate                 0xff01 + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* This is not an IANA defined extension number */ +#define TLSEXT_TYPE_next_proto_neg		13172 +#endif + +/* NameType value from RFC 3546 */ +#define TLSEXT_NAMETYPE_host_name 0 +/* status request value from RFC 3546 */ +#define TLSEXT_STATUSTYPE_ocsp 1 + +/* ECPointFormat values from draft-ietf-tls-ecc-12 */ +#define TLSEXT_ECPOINTFORMAT_first			0 +#define TLSEXT_ECPOINTFORMAT_uncompressed		0 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime	1 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2	2 +#define TLSEXT_ECPOINTFORMAT_last			2 + +#ifndef OPENSSL_NO_TLSEXT + +#define TLSEXT_MAXLEN_host_name 255 + +const char *SSL_get_servername(const SSL *s, const int type) ; +int SSL_get_servername_type(const SSL *s) ; + +#define SSL_set_tlsext_host_name(s,name) \ +SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name) + +#define SSL_set_tlsext_debug_callback(ssl, cb) \ +SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb) + +#define SSL_set_tlsext_debug_arg(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg) + +#define SSL_set_tlsext_status_type(ssl, type) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL) + +#define SSL_get_tlsext_status_exts(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg) + +#define SSL_set_tlsext_status_exts(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg) + +#define SSL_get_tlsext_status_ids(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg) + +#define SSL_set_tlsext_status_ids(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg) + +#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg) + +#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg) + +#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ +SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb) + +#define SSL_TLSEXT_ERR_OK 0 +#define SSL_TLSEXT_ERR_ALERT_WARNING 1 +#define SSL_TLSEXT_ERR_ALERT_FATAL 2 +#define SSL_TLSEXT_ERR_NOACK 3 + +#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg) + +#define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLSEXT_TICKET_KEYS,(keylen),(keys)) +#define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \ +	SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLSEXT_TICKET_KEYS,(keylen),(keys)) + +#define SSL_CTX_set_tlsext_status_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb) + +#define SSL_CTX_set_tlsext_status_arg(ssl, arg) \ +SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg) + +#define SSL_set_tlsext_opaque_prf_input(s, src, len) \ +SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT, len, src) +#define SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb) \ +SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB, (void (*)(void))cb) +#define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG, 0, arg) + +#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) + +#endif + +/* PSK ciphersuites from 4279 */ +#define TLS1_CK_PSK_WITH_RC4_128_SHA                    0x0300008A +#define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA               0x0300008B +#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA                0x0300008C +#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA                0x0300008D + +/* Additional TLS ciphersuites from expired Internet Draft + * draft-ietf-tls-56-bit-ciphersuites-01.txt + * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see + * s3_lib.c).  We actually treat them like SSL 3.0 ciphers, which we probably + * shouldn't.  Note that the first two are actually not in the IDs. */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5		0x03000060 /* not in ID */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5	0x03000061 /* not in ID */ +#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA		0x03000062 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA	0x03000063 +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA		0x03000064 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA	0x03000065 +#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA		0x03000066 + +/* AES ciphersuites from RFC3268 */ + +#define TLS1_CK_RSA_WITH_AES_128_SHA			0x0300002F +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA			0x03000030 +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA			0x03000031 +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA		0x03000032 +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA		0x03000033 +#define TLS1_CK_ADH_WITH_AES_128_SHA			0x03000034 + +#define TLS1_CK_RSA_WITH_AES_256_SHA			0x03000035 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA			0x03000036 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA			0x03000037 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA		0x03000038 +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA		0x03000039 +#define TLS1_CK_ADH_WITH_AES_256_SHA			0x0300003A + +/* Camellia ciphersuites from RFC4132 */ +#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA		0x03000041 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA	0x03000042 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA	0x03000043 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA	0x03000044 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA	0x03000045 +#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA		0x03000046 + +#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA		0x03000084 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA	0x03000085 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA	0x03000086 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA	0x03000087 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA	0x03000088 +#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA		0x03000089 + +/* SEED ciphersuites from RFC4162 */ +#define TLS1_CK_RSA_WITH_SEED_SHA                       0x03000096 +#define TLS1_CK_DH_DSS_WITH_SEED_SHA                    0x03000097 +#define TLS1_CK_DH_RSA_WITH_SEED_SHA                    0x03000098 +#define TLS1_CK_DHE_DSS_WITH_SEED_SHA                   0x03000099 +#define TLS1_CK_DHE_RSA_WITH_SEED_SHA                   0x0300009A +#define TLS1_CK_ADH_WITH_SEED_SHA                	0x0300009B + +/* ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in draft 13 */ +#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA                0x0300C001 +#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA             0x0300C002 +#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA        0x0300C003 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA         0x0300C004 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA         0x0300C005 + +#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA               0x0300C006 +#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA            0x0300C007 +#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA       0x0300C008 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA        0x0300C009 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA        0x0300C00A + +#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA                  0x0300C00B +#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA               0x0300C00C +#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA          0x0300C00D +#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA           0x0300C00E +#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA           0x0300C00F + +#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA                 0x0300C010 +#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA              0x0300C011 +#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA         0x0300C012 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA          0x0300C013 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA          0x0300C014 + +#define TLS1_CK_ECDH_anon_WITH_NULL_SHA                 0x0300C015 +#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA              0x0300C016 +#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA         0x0300C017 +#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA          0x0300C018 +#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA          0x0300C019 + +/* XXX + * Inconsistency alert: + * The OpenSSL names of ciphers with ephemeral DH here include the string + * "DHE", while elsewhere it has always been "EDH". + * (The alias for the list of all such ciphers also is "EDH".) + * The specifications speak of "EDH"; maybe we should allow both forms + * for everything. */ +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5		"EXP1024-RC4-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5	"EXP1024-RC2-CBC-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA	"EXP1024-DES-CBC-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA	"EXP1024-DHE-DSS-DES-CBC-SHA" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA		"EXP1024-RC4-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA	"EXP1024-DHE-DSS-RC4-SHA" +#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA		"DHE-DSS-RC4-SHA" + +/* AES ciphersuites from RFC3268 */ +#define TLS1_TXT_RSA_WITH_AES_128_SHA			"AES128-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA		"DH-DSS-AES128-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA		"DH-RSA-AES128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA		"DHE-DSS-AES128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA		"DHE-RSA-AES128-SHA" +#define TLS1_TXT_ADH_WITH_AES_128_SHA			"ADH-AES128-SHA" + +#define TLS1_TXT_RSA_WITH_AES_256_SHA			"AES256-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA		"DH-DSS-AES256-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA		"DH-RSA-AES256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA		"DHE-DSS-AES256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA		"DHE-RSA-AES256-SHA" +#define TLS1_TXT_ADH_WITH_AES_256_SHA			"ADH-AES256-SHA" + +/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */ +#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA               "ECDH-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA            "ECDH-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA       "ECDH-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA        "ECDH-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA        "ECDH-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA              "ECDHE-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA           "ECDHE-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA      "ECDHE-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA       "ECDHE-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA       "ECDHE-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA                 "ECDH-RSA-NULL-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA              "ECDH-RSA-RC4-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA         "ECDH-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA          "ECDH-RSA-AES128-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA          "ECDH-RSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA                "ECDHE-RSA-NULL-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA             "ECDHE-RSA-RC4-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA        "ECDHE-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA         "ECDHE-RSA-AES128-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA         "ECDHE-RSA-AES256-SHA" + +#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA                "AECDH-NULL-SHA" +#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA             "AECDH-RC4-SHA" +#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA        "AECDH-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA         "AECDH-AES128-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA         "AECDH-AES256-SHA" + +/* PSK ciphersuites from RFC 4279 */ +#define TLS1_TXT_PSK_WITH_RC4_128_SHA			"PSK-RC4-SHA" +#define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA		"PSK-3DES-EDE-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA		"PSK-AES128-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA		"PSK-AES256-CBC-SHA" + +/* Camellia ciphersuites from RFC4132 */ +#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA		"CAMELLIA128-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA	"DH-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA	"DH-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA	"DHE-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA	"DHE-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA		"ADH-CAMELLIA128-SHA" + +#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA		"CAMELLIA256-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA	"DH-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA	"DH-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA	"DHE-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA	"DHE-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA		"ADH-CAMELLIA256-SHA" + +/* SEED ciphersuites from RFC4162 */ +#define TLS1_TXT_RSA_WITH_SEED_SHA                      "SEED-SHA" +#define TLS1_TXT_DH_DSS_WITH_SEED_SHA                   "DH-DSS-SEED-SHA" +#define TLS1_TXT_DH_RSA_WITH_SEED_SHA                   "DH-RSA-SEED-SHA" +#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA                  "DHE-DSS-SEED-SHA" +#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA                  "DHE-RSA-SEED-SHA" +#define TLS1_TXT_ADH_WITH_SEED_SHA                      "ADH-SEED-SHA" + + +#define TLS_CT_RSA_SIGN			1 +#define TLS_CT_DSS_SIGN			2 +#define TLS_CT_RSA_FIXED_DH		3 +#define TLS_CT_DSS_FIXED_DH		4 +#define TLS_CT_ECDSA_SIGN		64 +#define TLS_CT_RSA_FIXED_ECDH		65 +#define TLS_CT_ECDSA_FIXED_ECDH 	66 +#define TLS_CT_GOST94_SIGN		21 +#define TLS_CT_GOST01_SIGN		22 +/* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see + * comment there) */ +#define TLS_CT_NUMBER			9 + +#define TLS1_FINISH_MAC_LENGTH		12 + +#define TLS_MD_MAX_CONST_SIZE			20 +#define TLS_MD_CLIENT_FINISH_CONST		"client finished" +#define TLS_MD_CLIENT_FINISH_CONST_SIZE		15 +#define TLS_MD_SERVER_FINISH_CONST		"server finished" +#define TLS_MD_SERVER_FINISH_CONST_SIZE		15 +#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key" +#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16 +#define TLS_MD_KEY_EXPANSION_CONST		"key expansion" +#define TLS_MD_KEY_EXPANSION_CONST_SIZE		13 +#define TLS_MD_CLIENT_WRITE_KEY_CONST		"client write key" +#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE	16 +#define TLS_MD_SERVER_WRITE_KEY_CONST		"server write key" +#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE	16 +#define TLS_MD_IV_BLOCK_CONST			"IV block" +#define TLS_MD_IV_BLOCK_CONST_SIZE		8 +#define TLS_MD_MASTER_SECRET_CONST		"master secret" +#define TLS_MD_MASTER_SECRET_CONST_SIZE		13 + +#ifdef CHARSET_EBCDIC +#undef TLS_MD_CLIENT_FINISH_CONST +#define TLS_MD_CLIENT_FINISH_CONST    "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64"  /*client finished*/ +#undef TLS_MD_SERVER_FINISH_CONST +#define TLS_MD_SERVER_FINISH_CONST    "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64"  /*server finished*/ +#undef TLS_MD_SERVER_WRITE_KEY_CONST +#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*server write key*/ +#undef TLS_MD_KEY_EXPANSION_CONST +#define TLS_MD_KEY_EXPANSION_CONST    "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e"  /*key expansion*/ +#undef TLS_MD_CLIENT_WRITE_KEY_CONST +#define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*client write key*/ +#undef TLS_MD_SERVER_WRITE_KEY_CONST +#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79"  /*server write key*/ +#undef TLS_MD_IV_BLOCK_CONST +#define TLS_MD_IV_BLOCK_CONST         "\x49\x56\x20\x62\x6c\x6f\x63\x6b"  /*IV block*/ +#undef TLS_MD_MASTER_SECRET_CONST +#define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/ +#endif + +/* TLS Session Ticket extension struct */ +struct tls_session_ticket_ext_st +	{ +	unsigned short length; +	void *data; +	}; + +#ifdef  __cplusplus +} +#endif +#endif  | 
