diff options
author | Jung-uk Kim <jkim@FreeBSD.org> | 2018-09-13 19:18:07 +0000 |
---|---|---|
committer | Jung-uk Kim <jkim@FreeBSD.org> | 2018-09-13 19:18:07 +0000 |
commit | a43ce912fc025d11e1395506111f75fc194d7ba5 (patch) | |
tree | 9794cf7720d75938ed0ea4f499c0dcd4b6eacdda /ssl | |
parent | 02be298e504b8554caca6dc85af450e1ea44d19d (diff) | |
download | src-a43ce912fc025d11e1395506111f75fc194d7ba5.tar.gz src-a43ce912fc025d11e1395506111f75fc194d7ba5.zip |
Import OpenSSL 1.1.1.vendor/openssl/1.1.1
Notes
Notes:
svn path=/vendor-crypto/openssl/dist/; revision=338658
svn path=/vendor-crypto/openssl/1.1.1/; revision=338659; tag=vendor/openssl/1.1.1
Diffstat (limited to 'ssl')
100 files changed, 45554 insertions, 54740 deletions
diff --git a/ssl/Makefile b/ssl/Makefile deleted file mode 100644 index b0a4ee8577c8..000000000000 --- a/ssl/Makefile +++ /dev/null @@ -1,1124 +0,0 @@ -# -# 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 heartbeat_test.c clienthellotest.c sslv2conftest.c dtlstest.c \ - bad_dtls_test.c fatalerrtest.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 s3_cbc.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_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_srtp.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 ssl_conf.c \ - bio_ssl.c ssl_err.c kssl.c t1_reneg.c tls_srp.c t1_trce.c ssl_utst.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 s3_cbc.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 t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_srtp.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 ssl_conf.o \ - bio_ssl.o ssl_err.o kssl.o t1_reneg.o tls_srp.o t1_trce.o ssl_utst.o - -SRC= $(LIBSRC) - -EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h srtp.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 - -update: local_depend - @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi - -depend: local_depend - @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi -local_depend: - @[ -z "$(THIS)" ] || $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC) - -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/srtp.h ../include/openssl/ssl.h -bio_ssl.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -bio_ssl.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -bio_ssl.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -bio_ssl.o: ../include/openssl/x509.h ../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/srtp.h -d1_both.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -d1_both.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -d1_both.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -d1_both.o: ../include/openssl/tls1.h ../include/openssl/x509.h -d1_both.o: ../include/openssl/x509_vfy.h d1_both.c 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/srtp.h ../include/openssl/ssl.h -d1_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -d1_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -d1_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -d1_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_clnt.c -d1_clnt.o: kssl_lcl.h 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/srtp.h ../include/openssl/ssl.h -d1_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -d1_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -d1_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -d1_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_lib.c -d1_lib.o: 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/srtp.h ../include/openssl/ssl.h -d1_meth.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -d1_meth.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -d1_meth.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -d1_meth.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_meth.c -d1_meth.o: 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/srtp.h -d1_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -d1_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -d1_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -d1_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h -d1_pkt.o: ../include/openssl/x509_vfy.h d1_pkt.c ssl_locl.h -d1_srtp.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -d1_srtp.o: ../include/openssl/buffer.h ../include/openssl/comp.h -d1_srtp.o: ../include/openssl/crypto.h ../include/openssl/dsa.h -d1_srtp.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -d1_srtp.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -d1_srtp.o: ../include/openssl/ecdsa.h ../include/openssl/err.h -d1_srtp.o: ../include/openssl/evp.h ../include/openssl/hmac.h -d1_srtp.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -d1_srtp.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -d1_srtp.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -d1_srtp.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -d1_srtp.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -d1_srtp.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -d1_srtp.o: ../include/openssl/safestack.h ../include/openssl/sha.h -d1_srtp.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -d1_srtp.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -d1_srtp.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -d1_srtp.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -d1_srtp.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_srtp.c -d1_srtp.o: srtp.h 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/srtp.h ../include/openssl/ssl.h -d1_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -d1_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -d1_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -d1_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_srvr.c -d1_srvr.o: ssl_locl.h -kssl.o: ../crypto/o_time.h ../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/srtp.h ../include/openssl/ssl.h -kssl.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -kssl.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -kssl.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -kssl.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h kssl.c -kssl.o: 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/srtp.h -s23_clnt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s23_clnt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s23_clnt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s23_clnt.o: ../include/openssl/tls1.h ../include/openssl/x509.h -s23_clnt.o: ../include/openssl/x509_vfy.h s23_clnt.c 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/srtp.h ../include/openssl/ssl.h -s23_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s23_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s23_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s23_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_lib.c -s23_lib.o: 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/srtp.h ../include/openssl/ssl.h -s23_meth.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s23_meth.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s23_meth.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s23_meth.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_meth.c -s23_meth.o: 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/srtp.h ../include/openssl/ssl.h -s23_pkt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s23_pkt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s23_pkt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s23_pkt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s23_pkt.c -s23_pkt.o: 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/srtp.h -s23_srvr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s23_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s23_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s23_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h -s23_srvr.o: ../include/openssl/x509_vfy.h s23_srvr.c 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/rsa.h -s2_clnt.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s2_clnt.o: ../include/openssl/srtp.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/srtp.h ../include/openssl/ssl.h -s2_enc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s2_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s2_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s2_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_enc.c -s2_enc.o: 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/obj_mac.h ../include/openssl/objects.h -s2_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -s2_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -s2_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -s2_lib.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -s2_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s2_lib.o: ../include/openssl/srtp.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/srtp.h ../include/openssl/ssl.h -s2_meth.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s2_meth.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s2_meth.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s2_meth.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_meth.c -s2_meth.o: 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/srtp.h ../include/openssl/ssl.h -s2_pkt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s2_pkt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s2_pkt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s2_pkt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_pkt.c -s2_pkt.o: 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/rsa.h -s2_srvr.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s2_srvr.o: ../include/openssl/srtp.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/srtp.h -s3_both.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s3_both.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s3_both.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s3_both.o: ../include/openssl/tls1.h ../include/openssl/x509.h -s3_both.o: ../include/openssl/x509_vfy.h s3_both.c ssl_locl.h -s3_cbc.o: ../crypto/constant_time_locl.h ../e_os.h ../include/openssl/asn1.h -s3_cbc.o: ../include/openssl/bio.h ../include/openssl/buffer.h -s3_cbc.o: ../include/openssl/comp.h ../include/openssl/crypto.h -s3_cbc.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h -s3_cbc.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -s3_cbc.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -s3_cbc.o: ../include/openssl/err.h ../include/openssl/evp.h -s3_cbc.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -s3_cbc.o: ../include/openssl/lhash.h ../include/openssl/md5.h -s3_cbc.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -s3_cbc.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -s3_cbc.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -s3_cbc.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -s3_cbc.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -s3_cbc.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s3_cbc.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -s3_cbc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s3_cbc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s3_cbc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s3_cbc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_cbc.c -s3_cbc.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/srtp.h -s3_clnt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s3_clnt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s3_clnt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s3_clnt.o: ../include/openssl/tls1.h ../include/openssl/x509.h -s3_clnt.o: ../include/openssl/x509_vfy.h kssl_lcl.h 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/srtp.h -s3_enc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s3_enc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s3_enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s3_enc.o: ../include/openssl/tls1.h ../include/openssl/x509.h -s3_enc.o: ../include/openssl/x509_vfy.h s3_enc.c ssl_locl.h -s3_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.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/srtp.h ../include/openssl/ssl.h -s3_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s3_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s3_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s3_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h kssl_lcl.h -s3_lib.o: 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/srtp.h ../include/openssl/ssl.h -s3_meth.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s3_meth.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s3_meth.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s3_meth.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_meth.c -s3_meth.o: 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/rand.h -s3_pkt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -s3_pkt.o: ../include/openssl/sha.h ../include/openssl/srtp.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: ../crypto/constant_time_locl.h ../e_os.h ../include/openssl/asn1.h -s3_srvr.o: ../include/openssl/bio.h ../include/openssl/bn.h -s3_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h -s3_srvr.o: ../include/openssl/crypto.h ../include/openssl/dh.h -s3_srvr.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h -s3_srvr.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -s3_srvr.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -s3_srvr.o: ../include/openssl/err.h ../include/openssl/evp.h -s3_srvr.o: ../include/openssl/hmac.h ../include/openssl/krb5_asn.h -s3_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -s3_srvr.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h -s3_srvr.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h -s3_srvr.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -s3_srvr.o: ../include/openssl/pem.h ../include/openssl/pem2.h -s3_srvr.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h -s3_srvr.o: ../include/openssl/rand.h ../include/openssl/rsa.h -s3_srvr.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s3_srvr.o: ../include/openssl/srtp.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/srtp.h ../include/openssl/ssl.h -ssl_algs.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_algs.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_algs.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_algs.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_algs.c -ssl_algs.o: 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/srtp.h -ssl_asn1.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -ssl_asn1.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -ssl_asn1.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -ssl_asn1.o: ../include/openssl/tls1.h ../include/openssl/x509.h -ssl_asn1.o: ../include/openssl/x509_vfy.h ssl_asn1.c 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/srtp.h ../include/openssl/ssl.h -ssl_cert.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_cert.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_cert.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_cert.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -ssl_cert.o: ../include/openssl/x509v3.h 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/srtp.h -ssl_ciph.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -ssl_ciph.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -ssl_ciph.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -ssl_ciph.o: ../include/openssl/tls1.h ../include/openssl/x509.h -ssl_ciph.o: ../include/openssl/x509_vfy.h ssl_ciph.c ssl_locl.h -ssl_conf.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ssl_conf.o: ../include/openssl/buffer.h ../include/openssl/comp.h -ssl_conf.o: ../include/openssl/conf.h ../include/openssl/crypto.h -ssl_conf.o: ../include/openssl/dh.h ../include/openssl/dsa.h -ssl_conf.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -ssl_conf.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -ssl_conf.o: ../include/openssl/ecdsa.h ../include/openssl/err.h -ssl_conf.o: ../include/openssl/evp.h ../include/openssl/hmac.h -ssl_conf.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -ssl_conf.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -ssl_conf.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -ssl_conf.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -ssl_conf.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -ssl_conf.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -ssl_conf.o: ../include/openssl/safestack.h ../include/openssl/sha.h -ssl_conf.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -ssl_conf.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_conf.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_conf.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_conf.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_conf.c -ssl_conf.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/srtp.h ../include/openssl/ssl.h -ssl_err.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_err.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_err.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_err.o: ../include/openssl/x509.h ../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/srtp.h ../include/openssl/ssl.h -ssl_err2.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_err2.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_err2.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_err2.o: ../include/openssl/x509.h ../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/srtp.h -ssl_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -ssl_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -ssl_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -ssl_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h -ssl_lib.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h kssl_lcl.h -ssl_lib.o: 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/srtp.h ../include/openssl/ssl.h -ssl_rsa.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_rsa.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_rsa.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_rsa.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -ssl_rsa.o: 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/srtp.h ../include/openssl/ssl.h -ssl_sess.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_sess.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_sess.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_sess.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -ssl_sess.o: 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/srtp.h ../include/openssl/ssl.h -ssl_stat.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_stat.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_stat.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_stat.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -ssl_stat.o: 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/srtp.h ../include/openssl/ssl.h -ssl_txt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_txt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_txt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_txt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -ssl_txt.o: ssl_txt.c -ssl_utst.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ssl_utst.o: ../include/openssl/buffer.h ../include/openssl/comp.h -ssl_utst.o: ../include/openssl/crypto.h ../include/openssl/dsa.h -ssl_utst.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -ssl_utst.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -ssl_utst.o: ../include/openssl/ecdsa.h ../include/openssl/err.h -ssl_utst.o: ../include/openssl/evp.h ../include/openssl/hmac.h -ssl_utst.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -ssl_utst.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -ssl_utst.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -ssl_utst.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -ssl_utst.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -ssl_utst.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -ssl_utst.o: ../include/openssl/safestack.h ../include/openssl/sha.h -ssl_utst.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -ssl_utst.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ssl_utst.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ssl_utst.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ssl_utst.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -ssl_utst.o: ssl_utst.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/srtp.h -t1_clnt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -t1_clnt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -t1_clnt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -t1_clnt.o: ../include/openssl/tls1.h ../include/openssl/x509.h -t1_clnt.o: ../include/openssl/x509_vfy.h ssl_locl.h 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/rand.h ../include/openssl/rsa.h -t1_enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h -t1_enc.o: ../include/openssl/srtp.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_ext.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -t1_ext.o: ../include/openssl/buffer.h ../include/openssl/comp.h -t1_ext.o: ../include/openssl/crypto.h ../include/openssl/dsa.h -t1_ext.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -t1_ext.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -t1_ext.o: ../include/openssl/ecdsa.h ../include/openssl/err.h -t1_ext.o: ../include/openssl/evp.h ../include/openssl/hmac.h -t1_ext.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -t1_ext.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -t1_ext.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -t1_ext.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -t1_ext.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -t1_ext.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -t1_ext.o: ../include/openssl/safestack.h ../include/openssl/sha.h -t1_ext.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -t1_ext.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -t1_ext.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -t1_ext.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -t1_ext.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -t1_ext.o: t1_ext.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/rand.h -t1_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -t1_lib.o: ../include/openssl/sha.h ../include/openssl/srtp.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/srtp.h ../include/openssl/ssl.h -t1_meth.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -t1_meth.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -t1_meth.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -t1_meth.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -t1_meth.o: 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/srtp.h ../include/openssl/ssl.h -t1_reneg.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -t1_reneg.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -t1_reneg.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -t1_reneg.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -t1_reneg.o: 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/srtp.h -t1_srvr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -t1_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h -t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -t1_trce.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -t1_trce.o: ../include/openssl/buffer.h ../include/openssl/comp.h -t1_trce.o: ../include/openssl/crypto.h ../include/openssl/dsa.h -t1_trce.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -t1_trce.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -t1_trce.o: ../include/openssl/ecdsa.h ../include/openssl/err.h -t1_trce.o: ../include/openssl/evp.h ../include/openssl/hmac.h -t1_trce.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -t1_trce.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -t1_trce.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -t1_trce.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -t1_trce.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -t1_trce.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h -t1_trce.o: ../include/openssl/safestack.h ../include/openssl/sha.h -t1_trce.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -t1_trce.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -t1_trce.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -t1_trce.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -t1_trce.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h -t1_trce.o: t1_trce.c -tls_srp.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -tls_srp.o: ../include/openssl/bn.h ../include/openssl/buffer.h -tls_srp.o: ../include/openssl/comp.h ../include/openssl/crypto.h -tls_srp.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h -tls_srp.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -tls_srp.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -tls_srp.o: ../include/openssl/err.h ../include/openssl/evp.h -tls_srp.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -tls_srp.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -tls_srp.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h -tls_srp.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -tls_srp.o: ../include/openssl/pem.h ../include/openssl/pem2.h -tls_srp.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h -tls_srp.o: ../include/openssl/rand.h ../include/openssl/rsa.h -tls_srp.o: ../include/openssl/safestack.h ../include/openssl/sha.h -tls_srp.o: ../include/openssl/srp.h ../include/openssl/srtp.h -tls_srp.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -tls_srp.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -tls_srp.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -tls_srp.o: ../include/openssl/tls1.h ../include/openssl/x509.h -tls_srp.o: ../include/openssl/x509_vfy.h ssl_locl.h tls_srp.c diff --git a/ssl/bad_dtls_test.c b/ssl/bad_dtls_test.c deleted file mode 100644 index ff754e1e497b..000000000000 --- a/ssl/bad_dtls_test.c +++ /dev/null @@ -1,926 +0,0 @@ -/* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Unit test for Cisco DTLS1_BAD_VER session resume, as used by - * AnyConnect VPN protocol. - * - * This is designed to exercise the code paths in - * http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/dtls.c - * which have frequently been affected by regressions in DTLS1_BAD_VER - * support. - * - * Note that unlike other SSL tests, we don't test against our own SSL - * server method. Firstly because we don't have one; we *only* support - * DTLS1_BAD_VER as a client. And secondly because even if that were - * fixed up it's the wrong thing to test against - because if changes - * are made in generic DTLS code which don't take DTLS1_BAD_VER into - * account, there's plenty of scope for making those changes such that - * they break *both* the client and the server in the same way. - * - * So we handle the server side manually. In a session resume there isn't - * much to be done anyway. - */ -#include <string.h> - -/* On Windows this will include <winsock2.h> and thus it needs to be - * included *before* anything that includes <windows.h>. Ick. */ -#include "e_os.h" /* for 'inline' */ - -#include <openssl/bio.h> -#include <openssl/crypto.h> -#include <openssl/evp.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/rand.h> - -/* PACKET functions lifted from OpenSSL 1.1's ssl/packet_locl.h */ -typedef struct { - /* Pointer to where we are currently reading from */ - const unsigned char *curr; - /* Number of bytes remaining */ - size_t remaining; -} PACKET; - -/* Internal unchecked shorthand; don't use outside this file. */ -static inline void packet_forward(PACKET *pkt, size_t len) -{ - pkt->curr += len; - pkt->remaining -= len; -} - -/* - * Returns the number of bytes remaining to be read in the PACKET - */ -static inline size_t PACKET_remaining(const PACKET *pkt) -{ - return pkt->remaining; -} - -/* - * Initialise a PACKET with |len| bytes held in |buf|. This does not make a - * copy of the data so |buf| must be present for the whole time that the PACKET - * is being used. - */ -static inline int PACKET_buf_init(PACKET *pkt, - const unsigned char *buf, - size_t len) -{ - /* Sanity check for negative values. */ - if (len > (size_t)65536) - return 0; - - pkt->curr = buf; - pkt->remaining = len; - return 1; -} - -/* - * Returns 1 if the packet has length |num| and its contents equal the |num| - * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal). - * If lengths are equal, performs the comparison in constant time. - */ -static inline int PACKET_equal(const PACKET *pkt, const void *ptr, - size_t num) -{ - if (PACKET_remaining(pkt) != num) - return 0; - return CRYPTO_memcmp(pkt->curr, ptr, num) == 0; -} - -/* - * Peek ahead at 2 bytes in network order from |pkt| and store the value in - * |*data| - */ -static inline int PACKET_peek_net_2(const PACKET *pkt, - unsigned int *data) -{ - if (PACKET_remaining(pkt) < 2) - return 0; - - *data = ((unsigned int)(*pkt->curr)) << 8; - *data |= *(pkt->curr + 1); - - return 1; -} - -/* Equivalent of n2s */ -/* Get 2 bytes in network order from |pkt| and store the value in |*data| */ -static inline int PACKET_get_net_2(PACKET *pkt, - unsigned int *data) -{ - if (!PACKET_peek_net_2(pkt, data)) - return 0; - - packet_forward(pkt, 2); - - return 1; -} - -/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ -static inline int PACKET_peek_1(const PACKET *pkt, - unsigned int *data) -{ - if (!PACKET_remaining(pkt)) - return 0; - - *data = *pkt->curr; - - return 1; -} - -/* Get 1 byte from |pkt| and store the value in |*data| */ -static inline int PACKET_get_1(PACKET *pkt, unsigned int *data) -{ - if (!PACKET_peek_1(pkt, data)) - return 0; - - packet_forward(pkt, 1); - - return 1; -} - -/* - * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in - * |*data|. This just points at the underlying buffer that |pkt| is using. The - * caller should not free this data directly (it will be freed when the - * underlying buffer gets freed - */ -static inline int PACKET_peek_bytes(const PACKET *pkt, - const unsigned char **data, - size_t len) -{ - if (PACKET_remaining(pkt) < len) - return 0; - - *data = pkt->curr; - - return 1; -} - -/* - * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This - * just points at the underlying buffer that |pkt| is using. The caller should - * not free this data directly (it will be freed when the underlying buffer gets - * freed - */ -static inline int PACKET_get_bytes(PACKET *pkt, - const unsigned char **data, - size_t len) -{ - if (!PACKET_peek_bytes(pkt, data, len)) - return 0; - - packet_forward(pkt, len); - - return 1; -} - -/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */ -static inline int PACKET_peek_copy_bytes(const PACKET *pkt, - unsigned char *data, - size_t len) -{ - if (PACKET_remaining(pkt) < len) - return 0; - - memcpy(data, pkt->curr, len); - - return 1; -} - -/* - * Read |len| bytes from |pkt| and copy them to |data|. - * The caller is responsible for ensuring that |data| can hold |len| bytes. - */ -static inline int PACKET_copy_bytes(PACKET *pkt, - unsigned char *data, - size_t len) -{ - if (!PACKET_peek_copy_bytes(pkt, data, len)) - return 0; - - packet_forward(pkt, len); - - return 1; -} - - -/* Move the current reading position forward |len| bytes */ -static inline int PACKET_forward(PACKET *pkt, size_t len) -{ - if (PACKET_remaining(pkt) < len) - return 0; - - packet_forward(pkt, len); - - return 1; -} - -/* - * Reads a variable-length vector prefixed with a one-byte length, and stores - * the contents in |subpkt|. |pkt| can equal |subpkt|. - * Data is not copied: the |subpkt| packet will share its underlying buffer with - * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. - * Upon failure, the original |pkt| and |subpkt| are not modified. - */ -static inline int PACKET_get_length_prefixed_1(PACKET *pkt, - PACKET *subpkt) -{ - unsigned int length; - const unsigned char *data; - PACKET tmp = *pkt; - if (!PACKET_get_1(&tmp, &length) || - !PACKET_get_bytes(&tmp, &data, (size_t)length)) { - return 0; - } - - *pkt = tmp; - subpkt->curr = data; - subpkt->remaining = length; - - return 1; -} - -#define OSSL_NELEM(x) (sizeof(x)/sizeof(x[0])) - -/* For DTLS1_BAD_VER packets the MAC doesn't include the handshake header */ -#define MAC_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH) - -static unsigned char client_random[SSL3_RANDOM_SIZE]; -static unsigned char server_random[SSL3_RANDOM_SIZE]; - -/* These are all generated locally, sized purely according to our own whim */ -static unsigned char session_id[32]; -static unsigned char master_secret[48]; -static unsigned char cookie[20]; - -/* We've hard-coded the cipher suite; we know it's 104 bytes */ -static unsigned char key_block[104]; -#define mac_key (key_block + 20) -#define dec_key (key_block + 40) -#define enc_key (key_block + 56) - -static EVP_MD_CTX handshake_md5; -static EVP_MD_CTX handshake_sha1; - -/* PRF lifted from ssl/t1_enc.c since we can't easily use it directly */ -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, - unsigned char *out, int olen) -{ - int chunk; - size_t j; - EVP_MD_CTX ctx, ctx_tmp, ctx_init; - EVP_PKEY *prf_mac_key; - unsigned char A1[EVP_MAX_MD_SIZE]; - size_t A1_len; - int ret = 0; - - chunk = EVP_MD_size(md); - OPENSSL_assert(chunk >= 0); - - EVP_MD_CTX_init(&ctx); - EVP_MD_CTX_init(&ctx_tmp); - EVP_MD_CTX_init(&ctx_init); - EVP_MD_CTX_set_flags(&ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - prf_mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len); - if (!prf_mac_key) - goto err; - if (!EVP_DigestSignInit(&ctx_init, NULL, md, NULL, prf_mac_key)) - goto err; - if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init)) - goto err; - if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) - goto err; - if (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) - goto err; - if (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len)) - goto err; - if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) - goto err; - - for (;;) { - /* Reinit mac contexts */ - if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init)) - goto err; - if (!EVP_DigestSignUpdate(&ctx, A1, A1_len)) - goto err; - if (olen > chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx)) - goto err; - if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) - goto err; - if (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) - goto err; - if (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len)) - goto err; - - if (olen > chunk) { - if (!EVP_DigestSignFinal(&ctx, out, &j)) - goto err; - out += j; - olen -= j; - /* calc the next A1 value */ - if (!EVP_DigestSignFinal(&ctx_tmp, A1, &A1_len)) - goto err; - } else { /* last one */ - - if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) - goto err; - memcpy(out, A1, olen); - break; - } - } - ret = 1; - err: - EVP_PKEY_free(prf_mac_key); - EVP_MD_CTX_cleanup(&ctx); - EVP_MD_CTX_cleanup(&ctx_tmp); - EVP_MD_CTX_cleanup(&ctx_init); - OPENSSL_cleanse(A1, sizeof(A1)); - return ret; -} - -/* seed1 through seed5 are virtually concatenated */ -static int do_PRF(const void *seed1, int seed1_len, - const void *seed2, int seed2_len, - const void *seed3, int seed3_len, - unsigned char *out, int olen) -{ - unsigned char out2[104]; - int i, len; - - if (olen > (int)sizeof(out2)) - return 0; - - len = sizeof(master_secret) / 2; - - if (!tls1_P_hash(EVP_md5(), master_secret, len, - seed1, seed1_len, seed2, seed2_len, seed3, - seed3_len, out, olen)) - return 0; - - if (!tls1_P_hash(EVP_sha1(), master_secret + len, len, - seed1, seed1_len, seed2, seed2_len, seed3, - seed3_len, out2, olen)) - return 0; - - for (i = 0; i < olen; i++) { - out[i] ^= out2[i]; - } - - return 1; -} - -static SSL_SESSION *client_session(void) -{ - static unsigned char session_asn1[] = { - 0x30, 0x5F, /* SEQUENCE, length 0x5F */ - 0x02, 0x01, 0x01, /* INTEGER, SSL_SESSION_ASN1_VERSION */ - 0x02, 0x02, 0x01, 0x00, /* INTEGER, DTLS1_BAD_VER */ - 0x04, 0x02, 0x00, 0x2F, /* OCTET_STRING, AES128-SHA */ - 0x04, 0x20, /* OCTET_STRING, session id */ -#define SS_SESSID_OFS 15 /* Session ID goes here */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x30, /* OCTET_STRING, master secret */ -#define SS_SECRET_OFS 49 /* Master secret goes here */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - const unsigned char *p = session_asn1; - - /* Copy the randomly-generated fields into the above ASN1 */ - memcpy(session_asn1 + SS_SESSID_OFS, session_id, sizeof(session_id)); - memcpy(session_asn1 + SS_SECRET_OFS, master_secret, sizeof(master_secret)); - - return d2i_SSL_SESSION(NULL, &p, sizeof(session_asn1)); -} - -/* Returns 1 for initial ClientHello, 2 for ClientHello with cookie */ -static int validate_client_hello(BIO *wbio) -{ - PACKET pkt, pkt2; - long len; - unsigned char *data; - int cookie_found = 0; - unsigned int u; - - len = BIO_get_mem_data(wbio, (char **)&data); - if (!PACKET_buf_init(&pkt, data, len)) - return 0; - - /* Check record header type */ - if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE) - return 0; - /* Version */ - if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER) - return 0; - /* Skip the rest of the record header */ - if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3)) - return 0; - - /* Check it's a ClientHello */ - if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CLIENT_HELLO) - return 0; - /* Skip the rest of the handshake message header */ - if (!PACKET_forward(&pkt, DTLS1_HM_HEADER_LENGTH - 1)) - return 0; - - /* Check client version */ - if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER) - return 0; - - /* Store random */ - if (!PACKET_copy_bytes(&pkt, client_random, SSL3_RANDOM_SIZE)) - return 0; - - /* Check session id length and content */ - if (!PACKET_get_length_prefixed_1(&pkt, &pkt2) || - !PACKET_equal(&pkt2, session_id, sizeof(session_id))) - return 0; - - /* Check cookie */ - if (!PACKET_get_length_prefixed_1(&pkt, &pkt2)) - return 0; - if (PACKET_remaining(&pkt2)) { - if (!PACKET_equal(&pkt2, cookie, sizeof(cookie))) - return 0; - cookie_found = 1; - } - - /* Skip ciphers */ - if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u)) - return 0; - - /* Skip compression */ - if (!PACKET_get_1(&pkt, &u) || !PACKET_forward(&pkt, u)) - return 0; - - /* Skip extensions */ - if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u)) - return 0; - - /* Now we are at the end */ - if (PACKET_remaining(&pkt)) - return 0; - - /* Update handshake MAC for second ClientHello (with cookie) */ - if (cookie_found && (!EVP_DigestUpdate(&handshake_md5, data + MAC_OFFSET, - len - MAC_OFFSET) || - !EVP_DigestUpdate(&handshake_sha1, data + MAC_OFFSET, - len - MAC_OFFSET))) - printf("EVP_DigestUpdate() failed\n"); - - (void)BIO_reset(wbio); - - return 1 + cookie_found; -} - -static int send_hello_verify(BIO *rbio) -{ - static unsigned char hello_verify[] = { - 0x16, /* Handshake */ - 0x01, 0x00, /* DTLS1_BAD_VER */ - 0x00, 0x00, /* Epoch 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Seq# 0 */ - 0x00, 0x23, /* Length */ - 0x03, /* Hello Verify */ - 0x00, 0x00, 0x17, /* Length */ - 0x00, 0x00, /* Seq# 0 */ - 0x00, 0x00, 0x00, /* Fragment offset */ - 0x00, 0x00, 0x17, /* Fragment length */ - 0x01, 0x00, /* DTLS1_BAD_VER */ - 0x14, /* Cookie length */ -#define HV_COOKIE_OFS 28 /* Cookie goes here */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }; - - memcpy(hello_verify + HV_COOKIE_OFS, cookie, sizeof(cookie)); - - BIO_write(rbio, hello_verify, sizeof(hello_verify)); - - return 1; -} - -static int send_server_hello(BIO *rbio) -{ - static unsigned char server_hello[] = { - 0x16, /* Handshake */ - 0x01, 0x00, /* DTLS1_BAD_VER */ - 0x00, 0x00, /* Epoch 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* Seq# 1 */ - 0x00, 0x52, /* Length */ - 0x02, /* Server Hello */ - 0x00, 0x00, 0x46, /* Length */ - 0x00, 0x01, /* Seq# */ - 0x00, 0x00, 0x00, /* Fragment offset */ - 0x00, 0x00, 0x46, /* Fragment length */ - 0x01, 0x00, /* DTLS1_BAD_VER */ -#define SH_RANDOM_OFS 27 /* Server random goes here */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, /* Session ID length */ -#define SH_SESSID_OFS 60 /* Session ID goes here */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x2f, /* Cipher suite AES128-SHA */ - 0x00, /* Compression null */ - }; - static unsigned char change_cipher_spec[] = { - 0x14, /* Change Cipher Spec */ - 0x01, 0x00, /* DTLS1_BAD_VER */ - 0x00, 0x00, /* Epoch 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* Seq# 2 */ - 0x00, 0x03, /* Length */ - 0x01, 0x00, 0x02, /* Message */ - }; - - memcpy(server_hello + SH_RANDOM_OFS, server_random, sizeof(server_random)); - memcpy(server_hello + SH_SESSID_OFS, session_id, sizeof(session_id)); - - if (!EVP_DigestUpdate(&handshake_md5, server_hello + MAC_OFFSET, - sizeof(server_hello) - MAC_OFFSET) || - !EVP_DigestUpdate(&handshake_sha1, server_hello + MAC_OFFSET, - sizeof(server_hello) - MAC_OFFSET)) - printf("EVP_DigestUpdate() failed\n"); - - BIO_write(rbio, server_hello, sizeof(server_hello)); - BIO_write(rbio, change_cipher_spec, sizeof(change_cipher_spec)); - - return 1; -} - -/* Create header, HMAC, pad, encrypt and send a record */ -static int send_record(BIO *rbio, unsigned char type, unsigned long seqnr, - const void *msg, size_t len) -{ - /* Note that the order of the record header fields on the wire, - * and in the HMAC, is different. So we just keep them in separate - * variables and handle them individually. */ - static unsigned char epoch[2] = { 0x00, 0x01 }; - static unsigned char seq[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static unsigned char ver[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */ - unsigned char lenbytes[2]; - HMAC_CTX ctx; - EVP_CIPHER_CTX enc_ctx; - unsigned char iv[16]; - unsigned char pad; - unsigned char *enc; - -#ifdef SIXTY_FOUR_BIT_LONG - seq[0] = (unsigned char)(seqnr >> 40); - seq[1] = (unsigned char)(seqnr >> 32); -#endif - seq[2] = (unsigned char)(seqnr >> 24); - seq[3] = (unsigned char)(seqnr >> 16); - seq[4] = (unsigned char)(seqnr >> 8); - seq[5] = (unsigned char)(seqnr); - - pad = 15 - ((len + SHA_DIGEST_LENGTH) % 16); - enc = OPENSSL_malloc(len + SHA_DIGEST_LENGTH + 1 + pad); - if (enc == NULL) - return 0; - - /* Copy record to encryption buffer */ - memcpy(enc, msg, len); - - /* Append HMAC to data */ - HMAC_Init(&ctx, mac_key, 20, EVP_sha1()); - HMAC_Update(&ctx, epoch, 2); - HMAC_Update(&ctx, seq, 6); - HMAC_Update(&ctx, &type, 1); - HMAC_Update(&ctx, ver, 2); /* Version */ - lenbytes[0] = (unsigned char)(len >> 8); - lenbytes[1] = (unsigned char)(len); - HMAC_Update(&ctx, lenbytes, 2); /* Length */ - HMAC_Update(&ctx, enc, len); /* Finally the data itself */ - HMAC_Final(&ctx, enc + len, NULL); - HMAC_CTX_cleanup(&ctx); - - /* Append padding bytes */ - len += SHA_DIGEST_LENGTH; - do { - enc[len++] = pad; - } while (len % 16); - - /* Generate IV, and encrypt */ - RAND_bytes(iv, sizeof(iv)); - EVP_CIPHER_CTX_init(&enc_ctx); - EVP_CipherInit_ex(&enc_ctx, EVP_aes_128_cbc(), NULL, enc_key, iv, 1); - EVP_Cipher(&enc_ctx, enc, enc, len); - EVP_CIPHER_CTX_cleanup(&enc_ctx); - - /* Finally write header (from fragmented variables), IV and encrypted record */ - BIO_write(rbio, &type, 1); - BIO_write(rbio, ver, 2); - BIO_write(rbio, epoch, 2); - BIO_write(rbio, seq, 6); - lenbytes[0] = (unsigned char)((len + sizeof(iv)) >> 8); - lenbytes[1] = (unsigned char)(len + sizeof(iv)); - BIO_write(rbio, lenbytes, 2); - - BIO_write(rbio, iv, sizeof(iv)); - BIO_write(rbio, enc, len); - - OPENSSL_free(enc); - return 1; -} - -static int send_finished(SSL *s, BIO *rbio) -{ - static unsigned char finished_msg[DTLS1_HM_HEADER_LENGTH + - TLS1_FINISH_MAC_LENGTH] = { - 0x14, /* Finished */ - 0x00, 0x00, 0x0c, /* Length */ - 0x00, 0x03, /* Seq# 3 */ - 0x00, 0x00, 0x00, /* Fragment offset */ - 0x00, 0x00, 0x0c, /* Fragment length */ - /* Finished MAC (12 bytes) */ - }; - unsigned char handshake_hash[EVP_MAX_MD_SIZE * 2]; - - /* Derive key material */ - do_PRF(TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, - server_random, SSL3_RANDOM_SIZE, - client_random, SSL3_RANDOM_SIZE, - key_block, sizeof(key_block)); - - /* Generate Finished MAC */ - if (!EVP_DigestFinal_ex(&handshake_md5, handshake_hash, NULL) || - !EVP_DigestFinal_ex(&handshake_sha1, handshake_hash + EVP_MD_CTX_size(&handshake_md5), NULL)) - printf("EVP_DigestFinal_ex() failed\n"); - - do_PRF(TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, - handshake_hash, EVP_MD_CTX_size(&handshake_md5) + EVP_MD_CTX_size(&handshake_sha1), - NULL, 0, - finished_msg + DTLS1_HM_HEADER_LENGTH, TLS1_FINISH_MAC_LENGTH); - - return send_record(rbio, SSL3_RT_HANDSHAKE, 0, - finished_msg, sizeof(finished_msg)); -} - -static int validate_ccs(BIO *wbio) -{ - PACKET pkt; - long len; - unsigned char *data; - unsigned int u; - - len = BIO_get_mem_data(wbio, (char **)&data); - if (!PACKET_buf_init(&pkt, data, len)) - return 0; - - /* Check record header type */ - if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_CHANGE_CIPHER_SPEC) - return 0; - /* Version */ - if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER) - return 0; - /* Skip the rest of the record header */ - if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3)) - return 0; - - /* Check ChangeCipherSpec message */ - if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CCS) - return 0; - /* A DTLS1_BAD_VER ChangeCipherSpec also contains the - * handshake sequence number (which is 2 here) */ - if (!PACKET_get_net_2(&pkt, &u) || u != 0x0002) - return 0; - - /* Now check the Finished packet */ - if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE) - return 0; - if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER) - return 0; - - /* Check epoch is now 1 */ - if (!PACKET_get_net_2(&pkt, &u) || u != 0x0001) - return 0; - - /* That'll do for now. If OpenSSL accepted *our* Finished packet - * then it's evidently remembered that DTLS1_BAD_VER doesn't - * include the handshake header in the MAC. There's not a lot of - * point in implementing decryption here, just to check that it - * continues to get it right for one more packet. */ - - return 1; -} - -#define NODROP(x) { x##UL, 0 } -#define DROP(x) { x##UL, 1 } - -static struct { - unsigned long seq; - int drop; -} tests[] = { - NODROP(1), NODROP(3), NODROP(2), - NODROP(0x1234), NODROP(0x1230), NODROP(0x1235), - NODROP(0xffff), NODROP(0x10001), NODROP(0xfffe), NODROP(0x10000), - DROP(0x10001), DROP(0xff), NODROP(0x100000), NODROP(0x800000), NODROP(0x7fffe1), - NODROP(0xffffff), NODROP(0x1000000), NODROP(0xfffffe), DROP(0xffffff), NODROP(0x1000010), - NODROP(0xfffffd), NODROP(0x1000011), DROP(0x12), NODROP(0x1000012), - NODROP(0x1ffffff), NODROP(0x2000000), DROP(0x1ff00fe), NODROP(0x2000001), - NODROP(0x20fffff), NODROP(0x2105500), DROP(0x20ffffe), NODROP(0x21054ff), - NODROP(0x211ffff), DROP(0x2110000), NODROP(0x2120000) - /* The last test should be NODROP, because a DROP wouldn't get tested. */ -}; - -int main(int argc, char *argv[]) -{ - SSL_SESSION *sess; - SSL_CTX *ctx; - SSL *con; - BIO *rbio; - BIO *wbio; - BIO *err; - time_t now = 0; - int testresult = 0; - int ret; - int i; - - SSL_library_init(); - SSL_load_error_strings(); - - err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - RAND_bytes(session_id, sizeof(session_id)); - RAND_bytes(master_secret, sizeof(master_secret)); - RAND_bytes(cookie, sizeof(cookie)); - RAND_bytes(server_random + 4, sizeof(server_random) - 4); - - now = time(NULL); - memcpy(server_random, &now, sizeof(now)); - - sess = client_session(); - if (sess == NULL) { - printf("Failed to generate SSL_SESSION\n"); - goto end; - } - - if (!EVP_DigestInit_ex(&handshake_md5, EVP_md5(), NULL) || - !EVP_DigestInit_ex(&handshake_sha1, EVP_sha1(), NULL)) { - printf("Failed to initialise handshake_md\n"); - goto end; - } - - ctx = SSL_CTX_new(DTLSv1_client_method()); - if (ctx == NULL) { - printf("Failed to allocate SSL_CTX\n"); - goto end_md; - } - SSL_CTX_set_options(ctx, SSL_OP_CISCO_ANYCONNECT); - - if (!SSL_CTX_set_cipher_list(ctx, "AES128-SHA")) { - printf("SSL_CTX_set_cipher_list() failed\n"); - goto end_ctx; - } - - con = SSL_new(ctx); - if (!SSL_set_session(con, sess)) { - printf("SSL_set_session() failed\n"); - goto end_con; - } - SSL_SESSION_free(sess); - - rbio = BIO_new(BIO_s_mem()); - wbio = BIO_new(BIO_s_mem()); - - BIO_set_nbio(rbio, 1); - BIO_set_nbio(wbio, 1); - - SSL_set_bio(con, rbio, wbio); - SSL_set_connect_state(con); - - /* Send initial ClientHello */ - ret = SSL_do_handshake(con); - if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) { - printf("Unexpected handshake result at initial call!\n"); - goto end_con; - } - - if (validate_client_hello(wbio) != 1) { - printf("Initial ClientHello failed validation\n"); - goto end_con; - } - if (send_hello_verify(rbio) != 1) { - printf("Failed to send HelloVerify\n"); - goto end_con; - } - ret = SSL_do_handshake(con); - if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) { - printf("Unexpected handshake result after HelloVerify!\n"); - goto end_con; - } - if (validate_client_hello(wbio) != 2) { - printf("Second ClientHello failed validation\n"); - goto end_con; - } - if (send_server_hello(rbio) != 1) { - printf("Failed to send ServerHello\n"); - goto end_con; - } - ret = SSL_do_handshake(con); - if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) { - printf("Unexpected handshake result after ServerHello!\n"); - goto end_con; - } - if (send_finished(con, rbio) != 1) { - printf("Failed to send Finished\n"); - goto end_con; - } - ret = SSL_do_handshake(con); - if (ret < 1) { - printf("Handshake not successful after Finished!\n"); - goto end_con; - } - if (validate_ccs(wbio) != 1) { - printf("Failed to validate client CCS/Finished\n"); - goto end_con; - } - - /* While we're here and crafting packets by hand, we might as well do a - bit of a stress test on the DTLS record replay handling. Not Cisco-DTLS - specific but useful anyway for the general case. It's been broken - before, and in fact was broken even for a basic 0, 2, 1 test case - when this test was first added.... */ - for (i = 0; i < (int)OSSL_NELEM(tests); i++) { - unsigned long recv_buf[2]; - - if (send_record(rbio, SSL3_RT_APPLICATION_DATA, tests[i].seq, - &tests[i].seq, sizeof(unsigned long)) != 1) { - printf("Failed to send data seq #0x%lx (%d)\n", - tests[i].seq, i); - goto end_con; - } - - if (tests[i].drop) - continue; - - ret = SSL_read(con, recv_buf, 2 * sizeof(unsigned long)); - if (ret != sizeof(unsigned long)) { - printf("SSL_read failed or wrong size on seq#0x%lx (%d)\n", - tests[i].seq, i); - goto end_con; - } - if (recv_buf[0] != tests[i].seq) { - printf("Wrong data packet received (0x%lx not 0x%lx) at packet %d\n", - recv_buf[0], tests[i].seq, i); - goto end_con; - } - } - if (tests[i-1].drop) { - printf("Error: last test cannot be DROP()\n"); - goto end_con; - } - testresult=1; - - end_con: - SSL_free(con); - end_ctx: - SSL_CTX_free(ctx); - end_md: - EVP_MD_CTX_cleanup(&handshake_md5); - EVP_MD_CTX_cleanup(&handshake_sha1); - end: - ERR_print_errors_fp(stderr); - - if (!testresult) { - printf("Cisco BadDTLS test: FAILED\n"); - } - - ERR_free_strings(); - ERR_remove_thread_state(NULL); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - CRYPTO_mem_leaks(err); - BIO_free(err); - - return testresult?0:1; -} diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c index d2d4d2ea2d2d..d1876d8b8c1f 100644 --- a/ssl/bio_ssl.c +++ b/ssl/bio_ssl.c @@ -1,59 +1,10 @@ -/* ssl/bio_ssl.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2016 The OpenSSL Project Authors. 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.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> @@ -61,58 +12,61 @@ #include <string.h> #include <errno.h> #include <openssl/crypto.h> -#include <openssl/bio.h> +#include "internal/bio.h" #include <openssl/err.h> -#include <openssl/ssl.h> +#include "ssl_locl.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_write(BIO *h, const char *buf, size_t size, size_t *written); +static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes); 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); +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; + size_t byte_count; unsigned long renegotiate_timeout; unsigned long last_time; } BIO_SSL; -static BIO_METHOD methods_sslp = { - BIO_TYPE_SSL, "ssl", +static const BIO_METHOD methods_sslp = { + BIO_TYPE_SSL, + "ssl", ssl_write, + NULL, /* ssl_write_old, */ ssl_read, + NULL, /* ssl_read_old, */ ssl_puts, - NULL, /* ssl_gets, */ + NULL, /* ssl_gets, */ ssl_ctrl, ssl_new, ssl_free, ssl_callback_ctrl, }; -BIO_METHOD *BIO_f_ssl(void) +const BIO_METHOD *BIO_f_ssl(void) { - return (&methods_sslp); + return &methods_sslp; } static int ssl_new(BIO *bi) { - BIO_SSL *bs; + BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs)); - bs = (BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL)); if (bs == NULL) { BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE); - return (0); + return 0; } - memset(bs, 0, sizeof(BIO_SSL)); - bi->init = 0; - bi->ptr = (char *)bs; - bi->flags = 0; - return (1); + BIO_set_init(bi, 0); + BIO_set_data(bi, bs); + /* Clear all flags */ + BIO_clear_flags(bi, ~0); + + return 1; } static int ssl_free(BIO *a) @@ -120,22 +74,22 @@ static int ssl_free(BIO *a) BIO_SSL *bs; if (a == NULL) - return (0); - bs = (BIO_SSL *)a->ptr; + return 0; + bs = BIO_get_data(a); if (bs->ssl != NULL) SSL_shutdown(bs->ssl); - if (a->shutdown) { - if (a->init && (bs->ssl != NULL)) + if (BIO_get_shutdown(a)) { + if (BIO_get_init(a)) SSL_free(bs->ssl); - a->init = 0; - a->flags = 0; + /* Clear all flags */ + BIO_clear_flags(a, ~0); + BIO_set_init(a, 0); } - if (a->ptr != NULL) - OPENSSL_free(a->ptr); - return (1); + OPENSSL_free(bs); + return 1; } -static int ssl_read(BIO *b, char *out, int outl) +static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes) { int ret = 1; BIO_SSL *sb; @@ -143,33 +97,19 @@ static int ssl_read(BIO *b, char *out, int outl) int retry_reason = 0; int r = 0; - if (out == NULL) - return (0); - sb = (BIO_SSL *)b->ptr; + if (buf == NULL) + return 0; + sb = BIO_get_data(b); 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); + ret = ssl_read_internal(ssl, buf, size, readbytes); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: - if (ret <= 0) - break; if (sb->renegotiate_count > 0) { - sb->byte_count += ret; + sb->byte_count += *readbytes; if (sb->byte_count > sb->renegotiate_count) { sb->byte_count = 0; sb->num_renegotiates++; @@ -214,35 +154,31 @@ static int ssl_read(BIO *b, char *out, int outl) break; } - b->retry_reason = retry_reason; - return (ret); + BIO_set_retry_reason(b, retry_reason); + + return ret; } -static int ssl_write(BIO *b, const char *out, int outl) +static int ssl_write(BIO *b, const char *buf, size_t size, size_t *written) { int ret, r = 0; int retry_reason = 0; SSL *ssl; BIO_SSL *bs; - if (out == NULL) - return (0); - bs = (BIO_SSL *)b->ptr; + if (buf == NULL) + return 0; + bs = BIO_get_data(b); ssl = bs->ssl; BIO_clear_retry_flags(b); - /* - * ret=SSL_do_handshake(ssl); if (ret > 0) - */ - ret = SSL_write(ssl, out, outl); + ret = ssl_write_internal(ssl, buf, size, written); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: - if (ret <= 0) - break; if (bs->renegotiate_count > 0) { - bs->byte_count += ret; + bs->byte_count += *written; if (bs->byte_count > bs->renegotiate_count) { bs->byte_count = 0; bs->num_renegotiates++; @@ -280,21 +216,24 @@ static int ssl_write(BIO *b, const char *out, int outl) break; } - b->retry_reason = retry_reason; - return (ret); + BIO_set_retry_reason(b, retry_reason); + + return ret; } static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) { SSL **sslp, *ssl; - BIO_SSL *bs; + BIO_SSL *bs, *dbs; BIO *dbio, *bio; long ret = 1; + BIO *next; - bs = (BIO_SSL *)b->ptr; + bs = BIO_get_data(b); + next = BIO_next(b); ssl = bs->ssl; if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) - return (0); + return 0; switch (cmd) { case BIO_CTRL_RESET: SSL_shutdown(ssl); @@ -304,10 +243,13 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) else if (ssl->handshake_func == ssl->method->ssl_accept) SSL_set_accept_state(ssl); - SSL_clear(ssl); + if (!SSL_clear(ssl)) { + ret = 0; + break; + } - if (b->next_bio != NULL) - ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + if (next != NULL) + ret = BIO_ctrl(next, cmd, num, ptr); else if (ssl->rbio != NULL) ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); else @@ -343,17 +285,17 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) if (!ssl_new(b)) return 0; } - b->shutdown = (int)num; + BIO_set_shutdown(b, num); ssl = (SSL *)ptr; - ((BIO_SSL *)b->ptr)->ssl = ssl; + bs->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); + if (next != NULL) + BIO_push(bio, next); + BIO_set_next(b, bio); + BIO_up_ref(bio); } - b->init = 1; + BIO_set_init(b, 1); break; case BIO_C_GET_SSL: if (ptr != NULL) { @@ -363,10 +305,10 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; break; case BIO_CTRL_GET_CLOSE: - ret = b->shutdown; + ret = BIO_get_shutdown(b); break; case BIO_CTRL_SET_CLOSE: - b->shutdown = (int)num; + BIO_set_shutdown(b, (int)num); break; case BIO_CTRL_WPENDING: ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); @@ -382,30 +324,26 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *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); + if ((next != NULL) && (next != ssl->rbio)) { + /* + * We are going to pass ownership of next to the SSL object...but + * we don't own a reference to pass yet - so up ref + */ + BIO_up_ref(next); + SSL_set_bio(ssl, next, next); } 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; + /* This will clear the reference we obtained during push */ + SSL_set_bio(ssl, NULL, NULL); } break; case BIO_C_DO_STATE_MACHINE: BIO_clear_retry_flags(b); - b->retry_reason = 0; + BIO_set_retry_reason(b, 0); ret = (int)SSL_do_handshake(ssl); switch (SSL_get_error(ssl, (int)ret)) { @@ -417,11 +355,11 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) 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; + BIO_set_retry_reason(b, BIO_get_retry_reason(next)); break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_set_retry_special(b); - b->retry_reason = BIO_RR_SSL_X509_LOOKUP; + BIO_set_retry_reason(b, BIO_RR_SSL_X509_LOOKUP); break; default: break; @@ -429,69 +367,46 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) 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); + dbs = BIO_get_data(dbio); + SSL_free(dbs->ssl); + dbs->ssl = SSL_dup(ssl); + dbs->num_renegotiates = bs->num_renegotiates; + dbs->renegotiate_count = bs->renegotiate_count; + dbs->byte_count = bs->byte_count; + dbs->renegotiate_timeout = bs->renegotiate_timeout; + dbs->last_time = bs->last_time; + ret = (dbs->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); - } + ret = 0; /* use callback ctrl */ break; default: ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); break; } - return (ret); + return ret; } -static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +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; + bs = BIO_get_data(b); 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); - } + ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); break; default: - ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); + ret = 0; break; } - return (ret); + return ret; } static int ssl_puts(BIO *bp, const char *str) @@ -500,7 +415,7 @@ static int ssl_puts(BIO *bp, const char *str) n = strlen(str); ret = BIO_write(bp, str, n); - return (ret); + return ret; } BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) @@ -509,19 +424,17 @@ BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) BIO *ret = NULL, *buf = NULL, *ssl = NULL; if ((buf = BIO_new(BIO_f_buffer())) == NULL) - return (NULL); + return NULL; if ((ssl = BIO_new_ssl_connect(ctx)) == NULL) goto err; if ((ret = BIO_push(buf, ssl)) == NULL) goto err; - return (ret); + return ret; err: - if (buf != NULL) - BIO_free(buf); - if (ssl != NULL) - BIO_free(ssl); + BIO_free(buf); + BIO_free(ssl); #endif - return (NULL); + return NULL; } BIO *BIO_new_ssl_connect(SSL_CTX *ctx) @@ -530,17 +443,16 @@ 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); + return NULL; if ((ssl = BIO_new_ssl(ctx, 1)) == NULL) goto err; if ((ret = BIO_push(ssl, con)) == NULL) goto err; - return (ret); + return ret; err: - if (con != NULL) - BIO_free(con); + BIO_free(con); #endif - return (NULL); + return NULL; } BIO *BIO_new_ssl(SSL_CTX *ctx, int client) @@ -549,10 +461,10 @@ BIO *BIO_new_ssl(SSL_CTX *ctx, int client) SSL *ssl; if ((ret = BIO_new(BIO_f_ssl())) == NULL) - return (NULL); + return NULL; if ((ssl = SSL_new(ctx)) == NULL) { BIO_free(ret); - return (NULL); + return NULL; } if (client) SSL_set_connect_state(ssl); @@ -560,32 +472,34 @@ BIO *BIO_new_ssl(SSL_CTX *ctx, int client) SSL_set_accept_state(ssl); BIO_set_ssl(ret, ssl, BIO_CLOSE); - return (ret); + return ret; } int BIO_ssl_copy_session_id(BIO *t, BIO *f) { + BIO_SSL *tdata, *fdata; 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); + return 0; + tdata = BIO_get_data(t); + fdata = BIO_get_data(f); + if ((tdata->ssl == NULL) || (fdata->ssl == NULL)) + return 0; + if (!SSL_copy_session_id(tdata->ssl, (fdata->ssl))) + return 0; + 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; + BIO_SSL *bdata; + + for (; b != NULL; b = BIO_next(b)) { + if (BIO_method_type(b) != BIO_TYPE_SSL) + continue; + bdata = BIO_get_data(b); + if (bdata != NULL && bdata->ssl != NULL) + SSL_shutdown(bdata->ssl); } } diff --git a/ssl/build.info b/ssl/build.info new file mode 100644 index 000000000000..bb2f1deb5300 --- /dev/null +++ b/ssl/build.info @@ -0,0 +1,15 @@ +LIBS=../libssl +SOURCE[../libssl]=\ + pqueue.c packet.c \ + statem/statem_srvr.c statem/statem_clnt.c s3_lib.c s3_enc.c record/rec_layer_s3.c \ + statem/statem_lib.c statem/extensions.c statem/extensions_srvr.c \ + statem/extensions_clnt.c statem/extensions_cust.c s3_cbc.c s3_msg.c \ + methods.c t1_lib.c t1_enc.c tls13_enc.c \ + d1_lib.c record/rec_layer_d1.c d1_msg.c \ + statem/statem_dtls.c d1_srtp.c \ + ssl_lib.c ssl_cert.c ssl_sess.c \ + ssl_ciph.c ssl_stat.c ssl_rsa.c \ + ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \ + bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \ + record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \ + statem/statem.c record/ssl3_record_tls13.c diff --git a/ssl/clienthellotest.c b/ssl/clienthellotest.c deleted file mode 100644 index 77517c61b1f3..000000000000 --- a/ssl/clienthellotest.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Written by Matt Caswell for the OpenSSL Project */ -/* ==================================================================== - * Copyright (c) 1998-2015 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 <string.h> - -#include <openssl/bio.h> -#include <openssl/crypto.h> -#include <openssl/evp.h> -#include <openssl/ssl.h> -#include <openssl/err.h> - - -#define CLIENT_VERSION_LEN 2 -#define SESSION_ID_LEN_LEN 1 -#define CIPHERS_LEN_LEN 2 -#define COMPRESSION_LEN_LEN 1 -#define EXTENSIONS_LEN_LEN 2 -#define EXTENSION_TYPE_LEN 2 -#define EXTENSION_SIZE_LEN 2 - - -#define TOTAL_NUM_TESTS 2 - -/* - * Test that explicitly setting ticket data results in it appearing in the - * ClientHello for TLS1.2 - */ -#define TEST_SET_SESSION_TICK_DATA_TLS_1_2 0 - -/* - * Test that explicitly setting ticket data results in it appearing in the - * ClientHello for a negotiated SSL/TLS version - */ -#define TEST_SET_SESSION_TICK_DATA_VER_NEG 1 - -int main(int argc, char *argv[]) -{ - SSL_CTX *ctx; - SSL *con; - BIO *rbio; - BIO *wbio; - BIO *err; - long len; - unsigned char *data; - unsigned char *dataend; - char *dummytick = "Hello World!"; - unsigned int tmplen; - unsigned int type; - unsigned int size; - int testresult = 0; - int currtest = 0; - - SSL_library_init(); - SSL_load_error_strings(); - - err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - /* - * For each test set up an SSL_CTX and SSL and see what ClientHello gets - * produced when we try to connect - */ - for (; currtest < TOTAL_NUM_TESTS; currtest++) { - testresult = 0; - if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2) { - ctx = SSL_CTX_new(TLSv1_2_method()); - } else { - ctx = SSL_CTX_new(SSLv23_method()); - } - con = SSL_new(ctx); - - rbio = BIO_new(BIO_s_mem()); - wbio = BIO_new(BIO_s_mem()); - SSL_set_bio(con, rbio, wbio); - SSL_set_connect_state(con); - - if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2 - || currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) { - if (!SSL_set_session_ticket_ext(con, dummytick, strlen(dummytick))) - goto end; - } - - if (SSL_connect(con) > 0) { - /* This shouldn't succeed because we don't have a server! */ - goto end; - } - - len = BIO_get_mem_data(wbio, (char **)&data); - dataend = data + len; - - /* Skip the record header */ - data += SSL3_RT_HEADER_LENGTH; - /* Skip the handshake message header */ - data += SSL3_HM_HEADER_LENGTH; - /* Skip client version and random */ - data += CLIENT_VERSION_LEN + SSL3_RANDOM_SIZE; - if (data + SESSION_ID_LEN_LEN > dataend) - goto end; - /* Skip session id */ - tmplen = *data; - data += SESSION_ID_LEN_LEN + tmplen; - if (data + CIPHERS_LEN_LEN > dataend) - goto end; - /* Skip ciphers */ - tmplen = ((*data) << 8) | *(data + 1); - data += CIPHERS_LEN_LEN + tmplen; - if (data + COMPRESSION_LEN_LEN > dataend) - goto end; - /* Skip compression */ - tmplen = *data; - data += COMPRESSION_LEN_LEN + tmplen; - if (data + EXTENSIONS_LEN_LEN > dataend) - goto end; - /* Extensions len */ - tmplen = ((*data) << 8) | *(data + 1); - data += EXTENSIONS_LEN_LEN; - if (data + tmplen > dataend) - goto end; - - /* Loop through all extensions */ - while (tmplen > EXTENSION_TYPE_LEN + EXTENSION_SIZE_LEN) { - type = ((*data) << 8) | *(data + 1); - data += EXTENSION_TYPE_LEN; - size = ((*data) << 8) | *(data + 1); - data += EXTENSION_SIZE_LEN; - if (data + size > dataend) - goto end; - - if (type == TLSEXT_TYPE_session_ticket) { - if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2 - || currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) { - if (size == strlen(dummytick) - && memcmp(data, dummytick, size) == 0) { - /* Ticket data is as we expected */ - testresult = 1; - } else { - printf("Received session ticket is not as expected\n"); - } - break; - } - } - - tmplen -= EXTENSION_TYPE_LEN + EXTENSION_SIZE_LEN + size; - data += size; - } - - end: - SSL_free(con); - SSL_CTX_free(ctx); - if (!testresult) { - printf("ClientHello test: FAILED (Test %d)\n", currtest); - break; - } - } - - ERR_free_strings(); - ERR_remove_thread_state(NULL); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - CRYPTO_mem_leaks(err); - BIO_free(err); - - return testresult?0:1; -} diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c deleted file mode 100644 index 76451a346d86..000000000000 --- a/ssl/d1_clnt.c +++ /dev/null @@ -1,875 +0,0 @@ -/* 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 == DTLS_ANY_VERSION) - return DTLS_client_method(); - else if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER) - return DTLSv1_client_method(); - else if (ver == DTLS1_2_VERSION) - return DTLSv1_2_client_method(); - else - return NULL; -} - -IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, - DTLSv1_client_method, - ssl_undefined_function, - dtls1_connect, - dtls1_get_client_method, DTLSv1_enc_data) - -IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, - DTLSv1_2_client_method, - ssl_undefined_function, - dtls1_connect, - dtls1_get_client_method, DTLSv1_2_enc_data) - -IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, - DTLS_client_method, - ssl_undefined_function, - dtls1_connect, - dtls1_get_client_method, DTLSv1_2_enc_data) - -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; -#ifndef OPENSSL_NO_SCTP - unsigned char sctpauthkey[64]; - char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; -#endif - - 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); - -#ifndef OPENSSL_NO_SCTP - /* - * Notify SCTP BIO socket to enter handshake mode and prevent stream - * identifier other than 0. Will be ignored if no SCTP is used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, - s->in_handshake, NULL); -#endif - -#ifndef OPENSSL_NO_HEARTBEATS - /* - * If we're awaiting a HeartbeatResponse, pretend we already got and - * don't await it anymore, because Heartbeats don't make sense during - * handshakes anyway. - */ - if (s->tlsext_hb_pending) { - dtls1_stop_timer(s); - s->tlsext_hb_pending = 0; - s->tlsext_hb_seq++; - } -#endif - - for (;;) { - state = s->state; - - switch (s->state) { - case SSL_ST_RENEGOTIATE: - s->renegotiate = 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; - s->state = SSL_ST_ERR; - goto end; - } - - /* s->version=SSL3_VERSION; */ - s->type = SSL_ST_CONNECT; - - if (s->init_buf == NULL) { - if ((buf = BUF_MEM_new()) == NULL) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - s->init_buf = buf; - buf = NULL; - } - - if (!ssl3_setup_buffers(s)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - /* setup buffing BIO */ - if (!ssl_init_wbio_buffer(s, 0)) { - ret = -1; - s->state = SSL_ST_ERR; - 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; - s->d1->change_cipher_spec_ok = 0; - /* - * Should have been reset by ssl3_get_finished, too. - */ - s->s3->change_cipher_spec = 0; - break; - -#ifndef OPENSSL_NO_SCTP - case DTLS1_SCTP_ST_CR_READ_SOCK: - - if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { - s->s3->in_read_app_data = 2; - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - ret = -1; - goto end; - } - - s->state = s->s3->tmp.next_state; - break; - - case DTLS1_SCTP_ST_CW_WRITE_SOCK: - /* read app data until dry event */ - - ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); - if (ret < 0) - goto end; - - if (ret == 0) { - s->s3->in_read_app_data = 2; - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - ret = -1; - goto end; - } - - s->state = s->d1->next_state; - break; -#endif - - case SSL3_ST_CW_CLNT_HELLO_A: - s->shutdown = 0; - - /* every DTLS ClientHello resets Finished MAC */ - if (!ssl3_init_finished_mac(s)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - /* fall thru */ - case SSL3_ST_CW_CLNT_HELLO_B: - dtls1_start_timer(s); - ret = ssl3_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; - -#ifndef OPENSSL_NO_SCTP - /* Disable buffering for SCTP */ - if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) { -#endif - /* - * turn on buffering for the next lot of output - */ - if (s->bbio != s->wbio) - s->wbio = BIO_push(s->bbio, s->wbio); -#ifndef OPENSSL_NO_SCTP - } -#endif - - 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 { - if (s->hit) { -#ifndef OPENSSL_NO_SCTP - /* - * Add new shared key for SCTP-Auth, will be ignored if - * no SCTP used. - */ - snprintf((char *)labelbuffer, - sizeof(DTLS1_SCTP_AUTH_LABEL), - DTLS1_SCTP_AUTH_LABEL); - - if (SSL_export_keying_material(s, sctpauthkey, - sizeof(sctpauthkey), - labelbuffer, - sizeof(labelbuffer), NULL, 0, - 0) <= 0) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - BIO_ctrl(SSL_get_wbio(s), - BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, - sizeof(sctpauthkey), sctpauthkey); -#endif - - s->state = SSL3_ST_CR_FINISHED_A; - if (s->tlsext_ticket_expected) { - /* receive renewed session ticket */ - s->state = SSL3_ST_CR_SESSION_TICKET_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: - /* 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; - s->state = SSL_ST_ERR; - 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; - dtls1_stop_timer(s); - if (s->s3->tmp.cert_req) - s->s3->tmp.next_state = SSL3_ST_CW_CERT_A; - else - s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A; - s->init_num = 0; - -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && - state == SSL_ST_RENEGOTIATE) - s->state = DTLS1_SCTP_ST_CR_READ_SOCK; - else -#endif - s->state = s->s3->tmp.next_state; - 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 = 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: - dtls1_start_timer(s); - ret = ssl3_send_client_key_exchange(s); - if (ret <= 0) - goto end; - -#ifndef OPENSSL_NO_SCTP - /* - * Add new shared key for SCTP-Auth, will be ignored if no SCTP - * used. - */ - snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), - DTLS1_SCTP_AUTH_LABEL); - - if (SSL_export_keying_material(s, sctpauthkey, - sizeof(sctpauthkey), labelbuffer, - sizeof(labelbuffer), NULL, 0, 0) <= 0) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, - sizeof(sctpauthkey), sctpauthkey); -#endif - - /* - * 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 { -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = SSL3_ST_CW_CHANGE_A; - s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK; - } else -#endif - s->state = SSL3_ST_CW_CHANGE_A; - } - - s->init_num = 0; - break; - - case SSL3_ST_CW_CERT_VRFY_A: - case SSL3_ST_CW_CERT_VRFY_B: - dtls1_start_timer(s); - ret = ssl3_send_client_verify(s); - if (ret <= 0) - goto end; -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = SSL3_ST_CW_CHANGE_A; - s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK; - } else -#endif - s->state = SSL3_ST_CW_CHANGE_A; - s->init_num = 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; - s->state = SSL_ST_ERR; - goto end; - } - - if (!s->method->ssl3_enc->change_cipher_state(s, - SSL3_CHANGE_CIPHER_CLIENT_WRITE)) - { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } -#ifndef OPENSSL_NO_SCTP - if (s->hit) { - /* - * Change to new shared key of SCTP-Auth, will be ignored if - * no SCTP used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, - 0, NULL); - } -#endif - - 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 = 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; -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = s->s3->tmp.next_state; - s->s3->tmp.next_state = DTLS1_SCTP_ST_CW_WRITE_SOCK; - } -#endif - if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) { - s->state = SSL_ST_OK; -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = SSL_ST_OK; - s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK; - } -#endif - s->s3->flags |= SSL3_FLAGS_POP_BUFFER; - s->s3->delay_buf_pop_ret = 0; - } - } else { -#ifndef OPENSSL_NO_SCTP - /* - * Change to new shared key of SCTP-Auth, will be ignored if - * no SCTP used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, - 0, NULL); -#endif - -#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; - -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && - state == SSL_ST_RENEGOTIATE) { - s->d1->next_state = s->state; - s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK; - } -#endif - - s->init_num = 0; - break; - - case SSL3_ST_CW_FLUSH: - s->rwstate = SSL_WRITING; - if (BIO_flush(s->wbio) <= 0) { - /* - * If the write error was fatal, stop trying - */ - if (!BIO_should_retry(s->wbio)) { - s->rwstate = SSL_NOTHING; - s->state = s->s3->tmp.next_state; - } - - 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->renegotiate = 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; - dtls1_clear_received_buffer(s); - goto end; - /* break; */ - - case SSL_ST_ERR: - 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--; - -#ifndef OPENSSL_NO_SCTP - /* - * Notify SCTP BIO socket to leave handshake mode and allow stream - * identifier other than 0. Will be ignored if no SCTP is used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, - s->in_handshake, NULL); -#endif - - if (buf != NULL) - BUF_MEM_free(buf); - if (cb != NULL) - cb(s, SSL_CB_CONNECT_EXIT, ret); - return (ret); -} - -static int dtls1_get_hello_verify(SSL *s) -{ - int n, al, ok = 0; - unsigned char *data; - unsigned int cookie_len; - - s->first_packet = 1; - 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); - s->first_packet = 0; - - 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 0 - if (s->method->version != DTLS_ANY_VERSION && - ((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; - } -#endif - 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); - s->state = SSL_ST_ERR; - return -1; -} diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 95b5033d3d33..f80851251fe2 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -1,113 +1,57 @@ -/* 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). + * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ +#include "e_os.h" #include <stdio.h> -#define USE_SOCKETS #include <openssl/objects.h> +#include <openssl/rand.h> #include "ssl_locl.h" -#if defined(OPENSSL_SYS_VMS) -# include <sys/timeb.h> -#endif - static void get_current_time(struct timeval *t); -static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len); static int dtls1_handshake_write(SSL *s); -const char dtls1_version_str[] = "DTLSv1" OPENSSL_VERSION_PTEXT; -int dtls1_listen(SSL *s, struct sockaddr *client); +static size_t dtls1_link_min_mtu(void); + +/* XDTLS: figure out the right values */ +static const size_t g_probable_mtu[] = { 1500, 512, 256 }; -SSL3_ENC_METHOD DTLSv1_enc_data = { +const SSL3_ENC_METHOD DTLSv1_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, tls1_export_keying_material, SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV, - DTLS1_HM_HEADER_LENGTH, dtls1_set_handshake_header, + dtls1_close_construct_packet, dtls1_handshake_write }; -SSL3_ENC_METHOD DTLSv1_2_enc_data = { +const SSL3_ENC_METHOD DTLSv1_2_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, tls1_export_keying_material, SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS, - DTLS1_HM_HEADER_LENGTH, dtls1_set_handshake_header, + dtls1_close_construct_packet, dtls1_handshake_write }; @@ -124,19 +68,19 @@ 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)); + if (!DTLS_RECORD_LAYER_new(&s->rlayer)) { + return 0; + } - /* d1->handshake_epoch=0; */ + if (!ssl3_new(s)) + return 0; + if ((d1 = OPENSSL_zalloc(sizeof(*d1))) == NULL) { + ssl3_free(s); + return 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); @@ -145,60 +89,24 @@ int dtls1_new(SSL *s) d1->link_mtu = 0; d1->mtu = 0; - 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); + if (d1->buffered_messages == NULL || d1->sent_messages == NULL) { + pqueue_free(d1->buffered_messages); + pqueue_free(d1->sent_messages); OPENSSL_free(d1); - return (0); + ssl3_free(s); + return 0; } s->d1 = d1; - s->method->ssl_clear(s); - return (1); + + if (!s->method->ssl_clear(s)) + return 0; + + return 1; } static void dtls1_clear_queues(SSL *s) { - pitem *item = 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_app_data.q)) != NULL) { - rdata = (DTLS1_RECORD_DATA *)item->data; - if (rdata->rbuf.buf) { - OPENSSL_free(rdata->rbuf.buf); - } - OPENSSL_free(item->data); - pitem_free(item); - } - dtls1_clear_received_buffer(s); dtls1_clear_sent_buffer(s); } @@ -230,42 +138,42 @@ void dtls1_clear_sent_buffer(SSL *s) void dtls1_free(SSL *s) { + DTLS_RECORD_LAYER_free(&s->rlayer); + 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); s->d1 = NULL; } -void dtls1_clear(SSL *s) +int dtls1_clear(SSL *s) { - pqueue unprocessed_rcds; - pqueue processed_rcds; - pqueue buffered_messages; - pqueue sent_messages; - pqueue buffered_app_data; - unsigned int mtu; - unsigned int link_mtu; + pqueue *buffered_messages; + pqueue *sent_messages; + size_t mtu; + size_t link_mtu; + + DTLS_RECORD_LAYER_clear(&s->rlayer); if (s->d1) { - unprocessed_rcds = s->d1->unprocessed_rcds.q; - processed_rcds = s->d1->processed_rcds.q; + DTLS_timer_cb timer_cb = s->d1->timer_cb; + buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; - buffered_app_data = s->d1->buffered_app_data.q; mtu = s->d1->mtu; link_mtu = s->d1->link_mtu; dtls1_clear_queues(s); - memset(s->d1, 0, sizeof(*(s->d1))); + memset(s->d1, 0, sizeof(*s->d1)); + + /* Restore the timer callback from previous state */ + s->d1->timer_cb = timer_cb; if (s->server) { s->d1->cookie_len = sizeof(s->d1->cookie); @@ -276,20 +184,23 @@ void dtls1_clear(SSL *s) s->d1->link_mtu = link_mtu; } - 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) + if (!ssl3_clear(s)) + return 0; + + if (s->method->version == DTLS_ANY_VERSION) + s->version = DTLS_MAX_VERSION; +#ifndef OPENSSL_NO_DTLS1_METHOD + else if (s->options & SSL_OP_CISCO_ANYCONNECT) s->client_version = s->version = DTLS1_BAD_VER; - else if (s->method->version == DTLS_ANY_VERSION) - s->version = DTLS1_2_VERSION; +#endif else s->version = s->method->version; + + return 1; } long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) @@ -305,31 +216,6 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) case DTLS_CTRL_HANDLE_TIMEOUT: ret = dtls1_handle_timeout(s); break; - case DTLS_CTRL_LISTEN: - ret = dtls1_listen(s, parg); - break; - case SSL_CTRL_CHECK_PROTO_VERSION: - /* - * For library-internal use; checks that the current protocol is the - * highest enabled version (according to s->ctx->method, as version - * negotiation may have changed s->method). - */ - if (s->version == s->ctx->method->version) - return 1; - /* - * Apparently we're using a version-flexible SSL_METHOD (not at its - * highest protocol version). - */ - if (s->ctx->method->version == DTLS_method()->version) { -#if DTLS_MAX_VERSION != DTLS1_2_VERSION -# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION. -#endif - if (!(s->options & SSL_OP_NO_DTLSv1_2)) - return s->version == DTLS1_2_VERSION; - if (!(s->options & SSL_OP_NO_DTLSv1)) - return s->version == DTLS1_VERSION; - } - return 0; /* Unexpected state; fail closed. */ case DTLS_CTRL_SET_LINK_MTU: if (larg < (long)dtls1_link_min_mtu()) return 0; @@ -350,48 +236,49 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) 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; + return ret; } void dtls1_start_timer(SSL *s) { + unsigned int sec, usec; + #ifndef OPENSSL_NO_SCTP /* Disable timer for SCTP */ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); + memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout)); return; } #endif - /* If timer is not set, initialize duration with 1 second */ + /* + * If timer is not set, initialize duration with 1 second or + * a user-specified value if the timer callback is installed. + */ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { - s->d1->timeout_duration = 1; + + if (s->d1->timer_cb != NULL) + s->d1->timeout_duration_us = s->d1->timer_cb(s, 0); + else + s->d1->timeout_duration_us = 1000000; } /* 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; + + sec = s->d1->timeout_duration_us / 1000000; + usec = s->d1->timeout_duration_us - (sec * 1000000); + + s->d1->next_timeout.tv_sec += sec; + s->d1->next_timeout.tv_usec += usec; + + if (s->d1->next_timeout.tv_usec >= 1000000) { + s->d1->next_timeout.tv_sec++; + s->d1->next_timeout.tv_usec -= 1000000; + } + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); } @@ -412,7 +299,7 @@ struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft) 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)); + memset(timeleft, 0, sizeof(*timeleft)); return timeleft; } @@ -427,10 +314,10 @@ struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft) /* * If remaining time is less than 15 ms, set it to 0 to prevent issues - * because of small devergences with socket timeouts. + * because of small divergences with socket timeouts. */ if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) { - memset(timeleft, 0, sizeof(struct timeval)); + memset(timeleft, 0, sizeof(*timeleft)); } return timeleft; @@ -456,18 +343,18 @@ int dtls1_is_timer_expired(SSL *s) void dtls1_double_timeout(SSL *s) { - s->d1->timeout_duration *= 2; - if (s->d1->timeout_duration > 60) - s->d1->timeout_duration = 60; + s->d1->timeout_duration_us *= 2; + if (s->d1->timeout_duration_us > 60000000) + s->d1->timeout_duration_us = 60000000; dtls1_start_timer(s); } void dtls1_stop_timer(SSL *s) { /* Reset everything */ - memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st)); - memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); - s->d1->timeout_duration = 1; + memset(&s->d1->timeout, 0, sizeof(s->d1->timeout)); + memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout)); + s->d1->timeout_duration_us = 1000000; BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); /* Clear retransmission buffer */ @@ -476,7 +363,7 @@ void dtls1_stop_timer(SSL *s) int dtls1_check_timeout_num(SSL *s) { - unsigned int mtu; + size_t mtu; s->d1->timeout.num_alerts++; @@ -484,15 +371,15 @@ int dtls1_check_timeout_num(SSL *s) if (s->d1->timeout.num_alerts > 2 && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { mtu = - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, - NULL); + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); if (mtu < s->d1->mtu) s->d1->mtu = mtu; } if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { /* fail the connection, enough alerts have been sent */ - SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED); + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_CHECK_TIMEOUT_NUM, + SSL_R_READ_TIMEOUT_EXPIRED); return -1; } @@ -506,23 +393,23 @@ int dtls1_handle_timeout(SSL *s) return 0; } - dtls1_double_timeout(s); + if (s->d1->timer_cb != NULL) + s->d1->timeout_duration_us = s->d1->timer_cb(s, s->d1->timeout_duration_us); + else + dtls1_double_timeout(s); - if (dtls1_check_timeout_num(s) < 0) + if (dtls1_check_timeout_num(s) < 0) { + /* SSLfatal() already called */ return -1; + } s->d1->timeout.read_timeouts++; if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) { s->d1->timeout.read_timeouts = 1; } -#ifndef OPENSSL_NO_HEARTBEATS - if (s->tlsext_hb_pending) { - s->tlsext_hb_pending = 0; - return dtls1_heartbeat(s); - } -#endif dtls1_start_timer(s); + /* Calls SSLfatal() if required */ return dtls1_retransmit_buffered_messages(s); } @@ -537,52 +424,568 @@ static void get_current_time(struct timeval *t) GetSystemTime(&st); SystemTimeToFileTime(&st, &now.ft); + /* re-bias to 1/1/1970 */ # ifdef __MINGW32__ now.ul -= 116444736000000000ULL; # else - now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ + /* *INDENT-OFF* */ + now.ul -= 116444736000000000UI64; + /* *INDENT-ON* */ # endif t->tv_sec = (long)(now.ul / 10000000); t->tv_usec = ((int)(now.ul % 10000000)) / 10; -#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) +#define LISTEN_SUCCESS 2 +#define LISTEN_SEND_VERIFY_REQUEST 1 + +#ifndef OPENSSL_NO_SOCK +int DTLSv1_listen(SSL *s, BIO_ADDR *client) { - int ret; + int next, n, ret = 0, clearpkt = 0; + unsigned char cookie[DTLS1_COOKIE_LENGTH]; + unsigned char seq[SEQ_NUM_SIZE]; + const unsigned char *data; + unsigned char *buf; + size_t fragoff, fraglen, msglen; + unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen; + BIO *rbio, *wbio; + BUF_MEM *bufm; + BIO_ADDR *tmpclient = NULL; + PACKET pkt, msgpkt, msgpayload, session, cookiepkt; + + if (s->handshake_func == NULL) { + /* Not properly initialized yet */ + SSL_set_accept_state(s); + } /* Ensure there is no state left over from a previous invocation */ - SSL_clear(s); + if (!SSL_clear(s)) + return -1; + + ERR_clear_error(); + + rbio = SSL_get_rbio(s); + wbio = SSL_get_wbio(s); + + if (!rbio || !wbio) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET); + return -1; + } + + /* + * We only peek at incoming ClientHello's until we're sure we are going to + * to respond with a HelloVerifyRequest. If its a ClientHello with a valid + * cookie then we leave it in the BIO for accept to handle. + */ + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL); + + /* + * Note: This check deliberately excludes DTLS1_BAD_VER because that version + * requires the MAC to be calculated *including* the first ClientHello + * (without the cookie). Since DTLSv1_listen is stateless that cannot be + * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via + * SSL_accept) + */ + if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION); + return -1; + } + + if (s->init_buf == NULL) { + if ((bufm = BUF_MEM_new()) == NULL) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); + return -1; + } + + if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) { + BUF_MEM_free(bufm); + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); + return -1; + } + s->init_buf = bufm; + } + buf = (unsigned char *)s->init_buf->data; + + do { + /* Get a packet */ + + clear_sys_error(); + /* + * Technically a ClientHello could be SSL3_RT_MAX_PLAIN_LENGTH + * + DTLS1_RT_HEADER_LENGTH bytes long. Normally init_buf does not store + * the record header as well, but we do here. We've set up init_buf to + * be the standard size for simplicity. In practice we shouldn't ever + * receive a ClientHello as long as this. If we do it will get dropped + * in the record length check below. + */ + n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH); + + if (n <= 0) { + if (BIO_should_retry(rbio)) { + /* Non-blocking IO */ + goto end; + } + return -1; + } + /* If we hit any problems we need to clear this packet from the BIO */ + clearpkt = 1; + + if (!PACKET_buf_init(&pkt, buf, n)) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* + * Parse the received record. If there are any problems with it we just + * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is + * resilient in the face of invalid records (e.g., invalid formatting, + * length, MAC, etc.). In general, invalid records SHOULD be silently + * discarded, thus preserving the association; however, an error MAY be + * logged for diagnostic purposes." + */ + + /* this packet contained a partial record, dump it */ + if (n < DTLS1_RT_HEADER_LENGTH) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL); + goto end; + } + + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, buf, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + + /* Get the record header */ + if (!PACKET_get_1(&pkt, &rectype) + || !PACKET_get_1(&pkt, &versmajor)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + if (rectype != SSL3_RT_HANDSHAKE) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); + goto end; + } + + /* + * Check record version number. We only check that the major version is + * the same. + */ + if (versmajor != DTLS1_VERSION_MAJOR) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + goto end; + } + + if (!PACKET_forward(&pkt, 1) + /* Save the sequence number: 64 bits, with top 2 bytes = epoch */ + || !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE) + || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + /* + * We allow data remaining at the end of the packet because there could + * be a second record (but we ignore it) + */ + + /* This is an initial ClientHello so the epoch has to be 0 */ + if (seq[0] != 0 || seq[1] != 0) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); + goto end; + } + + /* Get a pointer to the raw message for the later callback */ + data = PACKET_data(&msgpkt); + + /* Finished processing the record header, now process the message */ + if (!PACKET_get_1(&msgpkt, &msgtype) + || !PACKET_get_net_3_len(&msgpkt, &msglen) + || !PACKET_get_net_2(&msgpkt, &msgseq) + || !PACKET_get_net_3_len(&msgpkt, &fragoff) + || !PACKET_get_net_3_len(&msgpkt, &fraglen) + || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen) + || PACKET_remaining(&msgpkt) != 0) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + if (msgtype != SSL3_MT_CLIENT_HELLO) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); + goto end; + } + + /* Message sequence number can only be 0 or 1 */ + if (msgseq > 2) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER); + goto end; + } + + /* + * We don't support fragment reassembly for ClientHellos whilst + * listening because that would require server side state (which is + * against the whole point of the ClientHello/HelloVerifyRequest + * mechanism). Instead we only look at the first ClientHello fragment + * and require that the cookie must be contained within it. + */ + if (fragoff != 0 || fraglen > msglen) { + /* Non initial ClientHello fragment (or bad fragment) */ + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO); + goto end; + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data, + fraglen + DTLS1_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + + if (!PACKET_get_net_2(&msgpayload, &clientvers)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + /* + * Verify client version is supported + */ + if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) && + s->method->version != DTLS_ANY_VERSION) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER); + goto end; + } + + if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE) + || !PACKET_get_length_prefixed_1(&msgpayload, &session) + || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) { + /* + * Could be malformed or the cookie does not fit within the initial + * ClientHello fragment. Either way we can't handle it. + */ + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + /* + * Check if we have a cookie or not. If not we need to send a + * HelloVerifyRequest. + */ + if (PACKET_remaining(&cookiepkt) == 0) { + next = LISTEN_SEND_VERIFY_REQUEST; + } else { + /* + * We have a cookie, so lets check it. + */ + if (s->ctx->app_verify_cookie_cb == NULL) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK); + /* This is fatal */ + return -1; + } + if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt), + (unsigned int)PACKET_remaining(&cookiepkt)) == 0) { + /* + * We treat invalid cookies in the same was as no cookie as + * per RFC6347 + */ + next = LISTEN_SEND_VERIFY_REQUEST; + } else { + /* Cookie verification succeeded */ + next = LISTEN_SUCCESS; + } + } + + if (next == LISTEN_SEND_VERIFY_REQUEST) { + WPACKET wpkt; + unsigned int version; + size_t wreclen; + + /* + * There was no cookie in the ClientHello so we need to send a + * HelloVerifyRequest. If this fails we do not worry about trying + * to resend, we just drop it. + */ + + /* + * Dump the read packet, we don't need it any more. Ignore return + * value + */ + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL); + BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH); + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL); + + /* Generate the cookie */ + if (s->ctx->app_gen_cookie_cb == NULL || + s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 || + cookielen > 255) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); + /* This is fatal */ + return -1; + } + + /* + * Special case: for hello verify request, client version 1.0 and we + * haven't decided which version to use yet send back using version + * 1.0 header: otherwise some clients will ignore it. + */ + version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION + : s->version; + + /* Construct the record and message headers */ + if (!WPACKET_init(&wpkt, s->init_buf) + || !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE) + || !WPACKET_put_bytes_u16(&wpkt, version) + /* + * Record sequence number is always the same as in the + * received ClientHello + */ + || !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE) + /* End of record, start sub packet for message */ + || !WPACKET_start_sub_packet_u16(&wpkt) + /* Message type */ + || !WPACKET_put_bytes_u8(&wpkt, + DTLS1_MT_HELLO_VERIFY_REQUEST) + /* + * Message length - doesn't follow normal TLS convention: + * the length isn't the last thing in the message header. + * We'll need to fill this in later when we know the + * length. Set it to zero for now + */ + || !WPACKET_put_bytes_u24(&wpkt, 0) + /* + * Message sequence number is always 0 for a + * HelloVerifyRequest + */ + || !WPACKET_put_bytes_u16(&wpkt, 0) + /* + * We never fragment a HelloVerifyRequest, so fragment + * offset is 0 + */ + || !WPACKET_put_bytes_u24(&wpkt, 0) + /* + * Fragment length is the same as message length, but + * this *is* the last thing in the message header so we + * can just start a sub-packet. No need to come back + * later for this one. + */ + || !WPACKET_start_sub_packet_u24(&wpkt) + /* Create the actual HelloVerifyRequest body */ + || !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen) + /* Close message body */ + || !WPACKET_close(&wpkt) + /* Close record body */ + || !WPACKET_close(&wpkt) + || !WPACKET_get_total_written(&wpkt, &wreclen) + || !WPACKET_finish(&wpkt)) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR); + WPACKET_cleanup(&wpkt); + /* This is fatal */ + return -1; + } + + /* + * Fix up the message len in the message header. Its the same as the + * fragment len which has been filled in by WPACKET, so just copy + * that. Destination for the message len is after the record header + * plus one byte for the message content type. The source is the + * last 3 bytes of the message header + */ + memcpy(&buf[DTLS1_RT_HEADER_LENGTH + 1], + &buf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3], + 3); + + if (s->msg_callback) + s->msg_callback(1, 0, SSL3_RT_HEADER, buf, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + + if ((tmpclient = BIO_ADDR_new()) == NULL) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * This is unnecessary if rbio and wbio are one and the same - but + * maybe they're not. We ignore errors here - some BIOs do not + * support this. + */ + if (BIO_dgram_get_peer(rbio, tmpclient) > 0) { + (void)BIO_dgram_set_peer(wbio, tmpclient); + } + BIO_ADDR_free(tmpclient); + tmpclient = NULL; + + /* TODO(size_t): convert this call */ + if (BIO_write(wbio, buf, wreclen) < (int)wreclen) { + if (BIO_should_retry(wbio)) { + /* + * Non-blocking IO...but we're stateless, so we're just + * going to drop this packet. + */ + goto end; + } + return -1; + } + + if (BIO_flush(wbio) <= 0) { + if (BIO_should_retry(wbio)) { + /* + * Non-blocking IO...but we're stateless, so we're just + * going to drop this packet. + */ + goto end; + } + return -1; + } + } + } while (next != LISTEN_SUCCESS); + + /* + * Set expected sequence numbers to continue the handshake. + */ + s->d1->handshake_read_seq = 1; + s->d1->handshake_write_seq = 1; + s->d1->next_handshake_write_seq = 1; + DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq); + + /* + * We are doing cookie exchange, so make sure we set that option in the + * SSL object + */ SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); - s->d1->listen = 1; - ret = SSL_accept(s); - if (ret <= 0) - return ret; + /* + * Tell the state machine that we've done the initial hello verify + * exchange + */ + ossl_statem_set_hello_verify_done(s); + + /* + * Some BIOs may not support this. If we fail we clear the client address + */ + if (BIO_dgram_get_peer(rbio, client) <= 0) + BIO_ADDR_clear(client); + + ret = 1; + clearpkt = 0; + end: + BIO_ADDR_free(tmpclient); + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL); + if (clearpkt) { + /* Dump this packet. Ignore return value */ + BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH); + } + return ret; +} +#endif + +static int dtls1_handshake_write(SSL *s) +{ + return dtls1_do_write(s, SSL3_RT_HANDSHAKE); +} + +int dtls1_shutdown(SSL *s) +{ + int ret; +#ifndef OPENSSL_NO_SCTP + BIO *wbio; + + wbio = SSL_get_wbio(s); + if (wbio != NULL && BIO_dgram_is_sctp(wbio) && + !(s->shutdown & SSL_SENT_SHUTDOWN)) { + ret = BIO_dgram_sctp_wait_for_dry(wbio); + if (ret < 0) + return -1; + + if (ret == 0) + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, + NULL); + } +#endif + ret = ssl3_shutdown(s); +#ifndef OPENSSL_NO_SCTP + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL); +#endif + return ret; +} - (void)BIO_dgram_get_peer(SSL_get_rbio(s), client); +int dtls1_query_mtu(SSL *s) +{ + if (s->d1->link_mtu) { + s->d1->mtu = + s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); + s->d1->link_mtu = 0; + } + + /* AHA! Figure out the MTU, and stick to the right size */ + if (s->d1->mtu < dtls1_min_mtu(s)) { + 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)) { + /* Set to min mtu */ + s->d1->mtu = dtls1_min_mtu(s); + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, + (long)s->d1->mtu, NULL); + } + } else + return 0; + } return 1; } -static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len) +static size_t dtls1_link_min_mtu(void) { - unsigned char *p = (unsigned char *)s->init_buf->data; - dtls1_set_message_header(s, p, htype, len, 0, len); - s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - /* Buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); + return (g_probable_mtu[(sizeof(g_probable_mtu) / + sizeof(g_probable_mtu[0])) - 1]); } -static int dtls1_handshake_write(SSL *s) +size_t dtls1_min_mtu(SSL *s) { - return dtls1_do_write(s, SSL3_RT_HANDSHAKE); + return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); +} + +size_t DTLS_get_data_mtu(const SSL *s) +{ + size_t mac_overhead, int_overhead, blocksize, ext_overhead; + const SSL_CIPHER *ciph = SSL_get_current_cipher(s); + size_t mtu = s->d1->mtu; + + if (ciph == NULL) + return 0; + + if (!ssl_cipher_get_overhead(ciph, &mac_overhead, &int_overhead, + &blocksize, &ext_overhead)) + return 0; + + if (SSL_READ_ETM(s)) + ext_overhead += mac_overhead; + else + int_overhead += mac_overhead; + + /* Subtract external overhead (e.g. IV/nonce, separate MAC) */ + if (ext_overhead + DTLS1_RT_HEADER_LENGTH >= mtu) + return 0; + mtu -= ext_overhead + DTLS1_RT_HEADER_LENGTH; + + /* Round encrypted payload down to cipher block size (for CBC etc.) + * No check for overflow since 'mtu % blocksize' cannot exceed mtu. */ + if (blocksize) + mtu -= (mtu % blocksize); + + /* Subtract internal overhead (e.g. CBC padding len byte) */ + if (int_overhead >= mtu) + return 0; + mtu -= int_overhead; + + return mtu; +} + +void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb) +{ + s->d1->timer_cb = cb; } diff --git a/ssl/d1_meth.c b/ssl/d1_meth.c deleted file mode 100644 index 899010e9851c..000000000000 --- a/ssl/d1_meth.c +++ /dev/null @@ -1,90 +0,0 @@ -/* 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 == DTLS_ANY_VERSION) - return DTLS_method(); - else if (ver == DTLS1_VERSION) - return DTLSv1_method(); - else if (ver == DTLS1_2_VERSION) - return DTLSv1_2_method(); - else - return NULL; -} - -IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, - DTLSv1_method, - dtls1_accept, - dtls1_connect, dtls1_get_method, DTLSv1_enc_data) - -IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, - DTLSv1_2_method, - dtls1_accept, - dtls1_connect, dtls1_get_method, DTLSv1_2_enc_data) - -IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, - DTLS_method, - dtls1_accept, - dtls1_connect, dtls1_get_method, DTLSv1_2_enc_data) diff --git a/ssl/d1_msg.c b/ssl/d1_msg.c new file mode 100644 index 000000000000..5906e88ca68f --- /dev/null +++ b/ssl/d1_msg.c @@ -0,0 +1,73 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" + +int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, size_t len, + size_t *written) +{ + int i; + + if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) { + 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; + } + + return dtls1_write_bytes(s, type, buf_, len, written); +} + +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]; + size_t written; + + s->s3->alert_dispatch = 0; + + memset(buf, 0, sizeof(buf)); + *ptr++ = s->s3->send_alert[0]; + *ptr++ = s->s3->send_alert[1]; + + i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0, &written); + 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) + (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/ssl/d1_pkt.c b/ssl/d1_pkt.c deleted file mode 100644 index f5deddf7706a..000000000000 --- a/ssl/d1_pkt.c +++ /dev/null @@ -1,2041 +0,0 @@ -/* ssl/d1_pkt.c */ -/* - * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. - */ -/* ==================================================================== - * Copyright (c) 1998-2018 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, 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 = 0; - for (i=0; i<7; i++) { - if (v1[i] > v2[i]) { - /* v1 is larger... but by how much? */ - if (v1[i] != v2[i] + 1) - return 128; - while (++i <= 6) { - if (v1[i] != 0x00 || v2[i] != 0xff) - return 128; /* too much */ - } - /* We checked all the way to the penultimate byte, - * so despite higher bytes changing we actually - * know that it only changed from (e.g.) - * ... (xx) ff ff ff ?? - * to ... (xx+1) 00 00 00 ?? - * so we add a 'bias' of 256 for the carry that - * happened, and will eventually return - * 256 + v1[7] - v2[7]. */ - ret = 256; - break; - } else if (v2[i] > v1[i]) { - /* v2 is larger... but by how much? */ - if (v2[i] != v1[i] + 1) - return -128; - while (++i <= 6) { - if (v2[i] != 0x00 || v1[i] != 0xff) - return -128; /* too much */ - } - /* Similar to the case above, we know it changed - * from ... (xx) 00 00 00 ?? - * to ... (xx-1) ff ff ff ?? - * so we add a 'bias' of -256 for the borrow, - * to return -256 + v1[7] - v2[7]. */ - ret = -256; - } - } - - ret += (int)v1[7] - (int)v2[7]; - - if (ret > 128) - return 128; - else if (ret < -128) - return -128; - else - return ret; -} - -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, DTLS1_BITMAP *bitmap); - -/* 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 -1; - } - - 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; - -#ifndef OPENSSL_NO_SCTP - /* Store bio_dgram_sctp_rcvinfo struct */ - if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - (s->state == SSL3_ST_SR_FINISHED_A - || s->state == SSL3_ST_CR_FINISHED_A)) { - BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, - sizeof(rdata->recordinfo), &rdata->recordinfo); - } -#endif - - 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); - if (rdata->rbuf.buf != NULL) - OPENSSL_free(rdata->rbuf.buf); - OPENSSL_free(rdata); - pitem_free(item); - return (-1); - } - - /* insert should not fail, since duplicates are dropped */ - if (pqueue_insert(queue->q, item) == NULL) { - SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR); - if (rdata->rbuf.buf != NULL) - OPENSSL_free(rdata->rbuf.buf); - OPENSSL_free(rdata); - pitem_free(item); - return (-1); - } - - 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; - SSL3_BUFFER *rb; - SSL3_RECORD *rr; - DTLS1_BITMAP *bitmap; - unsigned int is_next_epoch; - int replayok = 1; - - 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. */ - - rr = &s->s3->rrec; - rb = &s->s3->rbuf; - - if (rb->left > 0) { - /* - * We've still got data from the current packet to read. There could - * be a record from the new epoch in it - so don't overwrite it - * with the unprocessed records yet (we'll do it when we've - * finished reading the current packet). - */ - return 1; - } - - - /* Process all the records. */ - while (pqueue_peek(s->d1->unprocessed_rcds.q)) { - dtls1_get_unprocessed_record(s); - bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); - if (bitmap == NULL) { - /* - * Should not happen. This will only ever be NULL when the - * current record is from a different epoch. But that cannot - * be the case because we already checked the epoch above - */ - SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, - ERR_R_INTERNAL_ERROR); - return 0; - } -#ifndef OPENSSL_NO_SCTP - /* Only do replay check if no SCTP bio */ - if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) -#endif - { - /* - * Check whether this is a repeat, or aged record. We did this - * check once already when we first received the record - but - * we might have updated the window since then due to - * records we subsequently processed. - */ - replayok = dtls1_record_replay_check(s, bitmap); - } - - if (!replayok || !dtls1_process_record(s, bitmap)) { - /* dump this record */ - rr->length = 0; - s->packet_length = 0; - continue; - } - - if (dtls1_buffer_record(s, &(s->d1->processed_rcds), - s->s3->rrec.seq_num) < 0) - return 0; - } - } - - /* - * 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 we're not (re)negotiating, nothing buffered */ - if (!SSL_in_init(s)) - 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, DTLS1_BITMAP *bitmap) -{ - int i, al; - int enc_err; - SSL_SESSION *sess; - SSL3_RECORD *rr; - unsigned int mac_size, orig_len; - 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); - /*- - * enc_err is: - * 0: (in non-constant time) if the record is publically invalid. - * 1: if the padding is valid - * -1: if the padding is invalid - */ - if (enc_err == 0) { - /* For DTLS we simply ignore bad packets. */ - 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) && (EVP_MD_CTX_md(s->read_hash) != NULL)) { - /* s->read_hash != NULL => mac_size != -1 */ - unsigned char *mac = NULL; - unsigned char mac_tmp[EVP_MAX_MD_SIZE]; - mac_size = EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - - /* - * kludge: *_cbc_remove_padding passes padding length in rr->type - */ - orig_len = rr->length + ((unsigned int)rr->type >> 8); - - /* - * orig_len is the length of the record before any padding was - * removed. This is public information, as is the MAC in use, - * therefore we can safely process the record in a different amount - * of time if it's too short to possibly contain a MAC. - */ - if (orig_len < mac_size || - /* CBC records must have a padding length byte too. */ - (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && - orig_len < mac_size + 1)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - - if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { - /* - * We update the length so that the TLS header bytes can be - * constructed correctly but we need to extract the MAC in - * constant time from within the record, without leaking the - * contents of the padding bytes. - */ - mac = mac_tmp; - ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); - rr->length -= mac_size; - } else { - /* - * In this case there's no padding, so |orig_len| equals - * |rec->length| and we checked that there's enough bytes for - * |mac_size| above. - */ - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } - - i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ ); - if (i < 0 || mac == NULL - || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) - enc_err = -1; - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) - enc_err = -1; - } - - if (enc_err < 0) { - /* decryption failed, silently discard message */ - rr->length = 0; - s->packet_length = 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; - - /* Mark receipt of record. */ - dtls1_record_bitmap_update(s, bitmap); - - 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); - - again: - /* - * The epoch may have changed. If so, process all the pending records. - * This is a non-blocking operation. - */ - if (!dtls1_process_buffered_records(s)) - return -1; - - /* if we're renegotiating, then there may be buffered records */ - if (dtls1_get_processed_record(s)) - return 1; - - /* get something from the wire */ - /* 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; - - if (s->msg_callback) - s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH, - s, s->msg_callback_arg); - - /* 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 the version. We tolerate alerts that don't have the exact - * version number (e.g. because of protocol version errors) - */ - if (!s->first_packet && rr->type != SSL3_RT_ALERT) { - 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; - } - - /* 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); - /* 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 */ - } -#ifndef OPENSSL_NO_SCTP - /* Only do replay check if no SCTP bio */ - if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) { -#endif - /* - * 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 && - s->packet_length > DTLS1_RT_HEADER_LENGTH && - s->packet[DTLS1_RT_HEADER_LENGTH] == 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 */ - } -#ifndef OPENSSL_NO_SCTP - } -#endif - - /* 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) { - if (dtls1_buffer_record - (s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0) - return -1; - } - rr->length = 0; - s->packet_length = 0; - goto again; - } - - if (!dtls1_process_record(s, bitmap)) { - rr->length = 0; - s->packet_length = 0; /* dump this record */ - goto again; /* get another record */ - } - - 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. - */ - -#ifndef OPENSSL_NO_SCTP - /* - * Continue handshake if it had to be interrupted to read app data with - * SCTP. - */ - if ((!s->in_handshake && SSL_in_init(s)) || - (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - (s->state == DTLS1_SCTP_ST_SR_READ_SOCK - || s->state == DTLS1_SCTP_ST_CR_READ_SOCK) - && s->s3->in_read_app_data != 2)) -#else - if (!s->in_handshake && SSL_in_init(s)) -#endif - { - /* 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) { -#ifndef OPENSSL_NO_SCTP - /* Restore bio_dgram_sctp_rcvinfo struct */ - if (BIO_dgram_is_sctp(SSL_get_rbio(s))) { - DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data; - BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, - sizeof(rdata->recordinfo), &rdata->recordinfo); - } -#endif - - 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; - } - } - - if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) { - rr->length = 0; - goto start; - } - - /* - * Reset the count of consecutive warning alerts if we've got a non-empty - * record that isn't an alert. - */ - if (rr->type != SSL3_RT_ALERT && rr->length != 0) - s->cert->alert_count = 0; - - /* 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. - */ - if (dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num) < - 0) { - SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); - return -1; - } - 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; - } - } -#ifndef OPENSSL_NO_SCTP - /* - * We were about to renegotiate but had to read belated application - * data first, so retry. - */ - if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - rr->type == SSL3_RT_APPLICATION_DATA && - (s->state == DTLS1_SCTP_ST_SR_READ_SOCK - || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)) { - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - } - - /* - * We might had to delay a close_notify alert because of reordered - * app data. If there was an alert and there is no message to read - * anymore, finally set shutdown. - */ - if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - s->d1->shutdown_received - && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { - s->shutdown |= SSL_RECEIVED_SHUTDOWN; - return (0); - } -#endif - 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; - } -#ifndef OPENSSL_NO_HEARTBEATS - else if (rr->type == TLS1_RT_HEARTBEAT) { - dtls1_process_heartbeat(s); - - /* Exit and notify application to read again */ - rr->length = 0; - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - return (-1); - } -#endif - /* 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 f_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) { - s->d1->handshake_read_seq++; - s->new_session = 1; - 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 we are a server and get a client hello when renegotiation isn't - * allowed send back a no renegotiation alert and carry on. - */ - if (s->server - && SSL_is_init_finished(s) - && !s->s3->send_connection_binding - && s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH - && s->d1->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO - && s->s3->previous_client_finished_len != 0 - && (s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0) { - s->d1->handshake_fragment_len = 0; - rr->length = 0; - ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); - 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 == SSL3_AL_WARNING) { - s->s3->warn_alert = alert_descr; - - s->cert->alert_count++; - if (s->cert->alert_count == MAX_WARN_ALERT_COUNT) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); - goto f_err; - } - - if (alert_descr == SSL_AD_CLOSE_NOTIFY) { -#ifndef OPENSSL_NO_SCTP - /* - * With SCTP and streams the socket may deliver app data - * after a close_notify alert. We have to check this first so - * that nothing gets discarded. - */ - if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && - BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { - s->d1->shutdown_received = 1; - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - return -1; - } -#endif - 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 == SSL3_AL_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->session_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)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_CHANGE_CIPHER_SPEC); - 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); - - /* - * 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++; - -#ifndef OPENSSL_NO_SCTP - /* - * Remember that a CCS has been received, so that an old key of - * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no - * SCTP is used - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL); -#endif - - 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) { - if (dtls1_check_timeout_num(s) < 0) - return -1; - - 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->renegotiate = 1; - 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; - -#ifndef OPENSSL_NO_SCTP - /* - * Check if we have to continue an interrupted handshake for reading - * belated app data with SCTP. - */ - if ((SSL_in_init(s) && !s->in_handshake) || - (BIO_dgram_is_sctp(SSL_get_wbio(s)) && - (s->state == DTLS1_SCTP_ST_SR_READ_SOCK - || s->state == DTLS1_SCTP_ST_CR_READ_SOCK))) -#else - if (SSL_in_init(s) && !s->in_handshake) -#endif - { - 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; - int eivlen; - SSL3_RECORD *wr; - SSL3_BUFFER *wb; - SSL_SESSION *sess; - - /* - * 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 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; - /* - * Special case: for hello verify request, client version 1.0 and we - * haven't decided which version to use yet send back using version 1.0 - * header: otherwise some clients will ignore it. - */ - if (s->method->version == DTLS_ANY_VERSION) { - *(p++) = DTLS1_VERSION >> 8; - *(p++) = DTLS1_VERSION & 0xff; - } else { - *(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; - - /* Explicit IV length, block ciphers appropriate version flag */ - if (s->enc_write_ctx) { - int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); - if (mode == EVP_CIPH_CBC_MODE) { - eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); - if (eivlen <= 1) - eivlen = 0; - } - /* Need explicit part of IV for GCM mode */ - else if (mode == EVP_CIPH_GCM_MODE) - eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; - else - eivlen = 0; - } else - eivlen = 0; - - /* lets setup the record stuff. */ - wr->data = p + eivlen; /* 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 + eivlen]), 1) < 0) - goto err; - wr->length += mac_size; - } - - /* this is true regardless of mac size */ - wr->input = p; - wr->data = p; - - if (eivlen) - wr->length += eivlen; - - if (s->method->ssl3_enc->enc(s, 1) < 1) - goto err; - - /* 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); - - if (s->msg_callback) - s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH, - DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); - - /* - * 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 and only if we - * have already processed all of the unprocessed records from the last - * epoch - */ - else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) && - s->d1->unprocessed_rcds.epoch != s->d1->r_epoch && - (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)); - - /* - * We must not use any buffered messages received from the previous - * epoch - */ - dtls1_clear_received_buffer(s); - } 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); -} diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c index 64d0634a381e..ff8f0c5712df 100644 --- a/ssl/d1_srtp.c +++ b/ssl/d1_srtp.c @@ -1,113 +1,12 @@ -/* 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-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 2011-2016 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + /* * DTLS code by Eric Rescorla <ekr@rtfm.com> * @@ -117,7 +16,6 @@ #include <stdio.h> #include <openssl/objects.h> #include "ssl_locl.h" -#include "srtp.h" #ifndef OPENSSL_NO_SRTP @@ -130,27 +28,26 @@ static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = { "SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32, }, -# if 0 { - "SRTP_NULL_SHA1_80", - SRTP_NULL_SHA1_80, + "SRTP_AEAD_AES_128_GCM", + SRTP_AEAD_AES_128_GCM, }, { - "SRTP_NULL_SHA1_32", - SRTP_NULL_SHA1_32, + "SRTP_AEAD_AES_256_GCM", + SRTP_AEAD_AES_256_GCM, }, -# endif {0} }; static int find_profile_by_name(char *profile_name, - SRTP_PROTECTION_PROFILE **pptr, unsigned len) + SRTP_PROTECTION_PROFILE **pptr, size_t len) { SRTP_PROTECTION_PROFILE *p; p = srtp_known_profiles; while (p->name) { - if ((len == strlen(p->name)) && !strncmp(p->name, profile_name, len)) { + if ((len == strlen(p->name)) + && strncmp(p->name, profile_name, len) == 0) { *pptr = p; return 0; } @@ -168,10 +65,9 @@ static int ssl_ctx_make_profiles(const char *profiles_string, char *col; char *ptr = (char *)profiles_string; - SRTP_PROTECTION_PROFILE *p; - if (!(profiles = sk_SRTP_PROTECTION_PROFILE_new_null())) { + if ((profiles = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) { SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); return 1; @@ -180,30 +76,37 @@ static int ssl_ctx_make_profiles(const char *profiles_string, do { col = strchr(ptr, ':'); - if (!find_profile_by_name(ptr, &p, - col ? col - ptr : (int)strlen(ptr))) { + if (!find_profile_by_name(ptr, &p, col ? (size_t)(col - ptr) + : strlen(ptr))) { if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) { SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - sk_SRTP_PROTECTION_PROFILE_free(profiles); - return 1; + goto err; } - sk_SRTP_PROTECTION_PROFILE_push(profiles, p); + if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); + goto err; + } } else { SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); - sk_SRTP_PROTECTION_PROFILE_free(profiles); - return 1; + goto err; } if (col) ptr = col + 1; } while (col); + sk_SRTP_PROTECTION_PROFILE_free(*out); + *out = profiles; return 0; + err: + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; } int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) @@ -233,216 +136,4 @@ SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s) { return s->srtp_profile; } - -/* - * Note: this function returns 0 length if there are no profiles specified - */ -int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, - int maxlen) -{ - int ct = 0; - int i; - STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = 0; - SRTP_PROTECTION_PROFILE *prof; - - clnt = SSL_get_srtp_profiles(s); - ct = sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */ - - if (p) { - if (ct == 0) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT, - SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST); - return 1; - } - - if ((2 + ct * 2 + 1) > maxlen) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT, - SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG); - return 1; - } - - /* Add the length */ - s2n(ct * 2, p); - for (i = 0; i < ct; i++) { - prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i); - s2n(prof->id, p); - } - - /* Add an empty use_mki value */ - *p++ = 0; - } - - *len = 2 + ct * 2 + 1; - - return 0; -} - -int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len, - int *al) -{ - SRTP_PROTECTION_PROFILE *sprof; - STACK_OF(SRTP_PROTECTION_PROFILE) *srvr; - int ct; - int mki_len; - int i, srtp_pref; - unsigned int id; - - /* Length value + the MKI length */ - if (len < 3) { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - /* Pull off the length of the cipher suite list */ - n2s(d, ct); - len -= 2; - - /* Check that it is even */ - if (ct % 2) { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - /* Check that lengths are consistent */ - if (len < (ct + 1)) { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - srvr = SSL_get_srtp_profiles(s); - s->srtp_profile = NULL; - /* Search all profiles for a match initially */ - srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr); - - while (ct) { - n2s(d, id); - ct -= 2; - len -= 2; - - /* - * Only look for match in profiles of higher preference than - * current match. - * If no profiles have been have been configured then this - * does nothing. - */ - for (i = 0; i < srtp_pref; i++) { - sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i); - if (sprof->id == id) { - s->srtp_profile = sprof; - srtp_pref = i; - break; - } - } - } - - /* - * Now extract the MKI value as a sanity check, but discard it for now - */ - mki_len = *d; - d++; - len--; - - if (mki_len != len) { - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_MKI_VALUE); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - return 0; -} - -int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, - int maxlen) -{ - if (p) { - if (maxlen < 5) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT, - SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG); - return 1; - } - - if (s->srtp_profile == 0) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT, - SSL_R_USE_SRTP_NOT_NEGOTIATED); - return 1; - } - s2n(2, p); - s2n(s->srtp_profile->id, p); - *p++ = 0; - } - *len = 5; - - return 0; -} - -int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len, - int *al) -{ - unsigned id; - int i; - int ct; - - STACK_OF(SRTP_PROTECTION_PROFILE) *clnt; - SRTP_PROTECTION_PROFILE *prof; - - if (len != 5) { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - n2s(d, ct); - if (ct != 2) { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - n2s(d, id); - if (*d) { /* Must be no MKI, since we never offer one */ - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_MKI_VALUE); - *al = SSL_AD_ILLEGAL_PARAMETER; - return 1; - } - - clnt = SSL_get_srtp_profiles(s); - - /* Throw an error if the server gave us an unsolicited extension */ - if (clnt == NULL) { - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, - SSL_R_NO_SRTP_PROFILES); - *al = SSL_AD_DECODE_ERROR; - return 1; - } - - /* - * Check to see if the server gave us something we support (and - * presumably offered) - */ - for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) { - prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i); - - if (prof->id == id) { - s->srtp_profile = prof; - *al = 0; - return 0; - } - } - - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, - SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); - *al = SSL_AD_DECODE_ERROR; - return 1; -} - #endif diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c deleted file mode 100644 index 8502b242e51c..000000000000 --- a/ssl/d1_srvr.c +++ /dev/null @@ -1,985 +0,0 @@ -/* 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 == DTLS_ANY_VERSION) - return DTLS_server_method(); - else if (ver == DTLS1_VERSION) - return DTLSv1_server_method(); - else if (ver == DTLS1_2_VERSION) - return DTLSv1_2_server_method(); - else - return NULL; -} - -IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, - DTLSv1_server_method, - dtls1_accept, - ssl_undefined_function, - dtls1_get_server_method, DTLSv1_enc_data) - -IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, - DTLSv1_2_server_method, - dtls1_accept, - ssl_undefined_function, - dtls1_get_server_method, DTLSv1_2_enc_data) - -IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, - DTLS_server_method, - dtls1_accept, - ssl_undefined_function, - dtls1_get_server_method, DTLSv1_2_enc_data) - -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; -#ifndef OPENSSL_NO_SCTP - unsigned char sctpauthkey[64]; - char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; -#endif - - 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; -#ifndef OPENSSL_NO_SCTP - /* - * Notify SCTP BIO socket to enter handshake mode and prevent stream - * identifier other than 0. Will be ignored if no SCTP is used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, - s->in_handshake, NULL); -#endif - - if (s->cert == NULL) { - SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_NO_CERTIFICATE_SET); - return (-1); - } -#ifndef OPENSSL_NO_HEARTBEATS - /* - * If we're awaiting a HeartbeatResponse, pretend we already got and - * don't await it anymore, because Heartbeats don't make sense during - * handshakes anyway. - */ - if (s->tlsext_hb_pending) { - dtls1_stop_timer(s); - s->tlsext_hb_pending = 0; - s->tlsext_hb_seq++; - } -#endif - - for (;;) { - state = s->state; - - switch (s->state) { - case SSL_ST_RENEGOTIATE: - s->renegotiate = 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; - s->state = SSL_ST_ERR; - goto end; - } - if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { - BUF_MEM_free(buf); - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - s->init_buf = buf; - } - - if (!ssl3_setup_buffers(s)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - s->init_num = 0; - s->d1->change_cipher_spec_ok = 0; - /* - * Should have been reset by ssl3_get_finished, too. - */ - s->s3->change_cipher_spec = 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 :-) ...but not with - * SCTP :-) - */ -#ifndef OPENSSL_NO_SCTP - if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) -#endif - if (!ssl_init_wbio_buffer(s, 1)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - if (!ssl3_init_finished_mac(s)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - 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_DTLS1_ACCEPT, - SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - ret = -1; - s->state = SSL_ST_ERR; - 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; - dtls1_clear_sent_buffer(s); - dtls1_start_timer(s); - ret = ssl3_send_hello_request(s); - if (ret <= 0) - goto end; - s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; - s->state = SSL3_ST_SW_FLUSH; - s->init_num = 0; - - if (!ssl3_init_finished_mac(s)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - 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; - - /* 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) - if (!ssl3_init_finished_mac(s)) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - break; - -#ifndef OPENSSL_NO_SCTP - case DTLS1_SCTP_ST_SR_READ_SOCK: - - if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { - s->s3->in_read_app_data = 2; - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - ret = -1; - goto end; - } - - s->state = SSL3_ST_SR_FINISHED_A; - break; - - case DTLS1_SCTP_ST_SW_WRITE_SOCK: - ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); - if (ret < 0) - goto end; - - if (ret == 0) { - if (s->d1->next_state != SSL_ST_OK) { - s->s3->in_read_app_data = 2; - s->rwstate = SSL_READING; - BIO_clear_retry_flags(SSL_get_rbio(s)); - BIO_set_retry_read(SSL_get_rbio(s)); - ret = -1; - goto end; - } - } - - s->state = s->d1->next_state; - break; -#endif - - case SSL3_ST_SW_SRVR_HELLO_A: - case SSL3_ST_SW_SRVR_HELLO_B: - s->renegotiate = 2; - dtls1_start_timer(s); - ret = ssl3_send_server_hello(s); - if (ret <= 0) - goto end; - - if (s->hit) { -#ifndef OPENSSL_NO_SCTP - /* - * Add new shared key for SCTP-Auth, will be ignored if no - * SCTP used. - */ - snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), - DTLS1_SCTP_AUTH_LABEL); - - if (SSL_export_keying_material(s, sctpauthkey, - sizeof(sctpauthkey), labelbuffer, - sizeof(labelbuffer), NULL, 0, 0) <= 0) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, - sizeof(sctpauthkey), sctpauthkey); -#endif -#ifndef OPENSSL_NO_TLSEXT - if (s->tlsext_ticket_expected) - s->state = SSL3_ST_SW_SESSION_TICKET_A; - else - s->state = SSL3_ST_SW_CHANGE_A; -#else - 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 = 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 - */ - s->s3->tmp.use_rsa_tmp = 0; - - /* - * only send if a DH key exchange or RSA but we have a sign only - * certificate - */ - if (0 - /* - * 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_kDHE) - || (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 = 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; -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; - s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; - } -#endif - } else { - s->s3->tmp.cert_request = 1; - dtls1_start_timer(s); - ret = ssl3_send_certificate_request(s); - if (ret <= 0) - goto end; -#ifndef NETSCAPE_HANG_BUG - s->state = SSL3_ST_SW_SRVR_DONE_A; -# ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; - s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; - } -# endif -#else - s->state = SSL3_ST_SW_FLUSH; - s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; -# ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = s->s3->tmp.next_state; - s->s3->tmp.next_state = DTLS1_SCTP_ST_SW_WRITE_SOCK; - } -# endif -#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 = 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: - s->rwstate = SSL_WRITING; - if (BIO_flush(s->wbio) <= 0) { - /* - * If the write error was fatal, stop trying - */ - if (!BIO_should_retry(s->wbio)) { - s->rwstate = SSL_NOTHING; - s->state = s->s3->tmp.next_state; - } - - 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: - 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; -#ifndef OPENSSL_NO_SCTP - /* - * Add new shared key for SCTP-Auth, will be ignored if no SCTP - * used. - */ - snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), - DTLS1_SCTP_AUTH_LABEL); - - if (SSL_export_keying_material(s, sctpauthkey, - sizeof(sctpauthkey), labelbuffer, - sizeof(labelbuffer), NULL, 0, 0) <= 0) { - ret = -1; - s->state = SSL_ST_ERR; - goto end; - } - - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, - sizeof(sctpauthkey), sctpauthkey); -#endif - - 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 if (SSL_USE_SIGALGS(s)) { - s->state = SSL3_ST_SR_CERT_VRFY_A; - s->init_num = 0; - if (!s->session->peer) - break; - /* - * For sigalgs freeze the handshake buffer at this point and - * digest cached records. - */ - if (!s->s3->handshake_buffer) { - SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); - s->state = SSL_ST_ERR; - return -1; - } - s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; - if (!ssl3_digest_cached_records(s)) { - s->state = SSL_ST_ERR; - return -1; - } - } 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: - ret = ssl3_get_cert_verify(s); - if (ret <= 0) - goto end; -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && - state == SSL_ST_RENEGOTIATE) - s->state = DTLS1_SCTP_ST_SR_READ_SOCK; - else -#endif - s->state = SSL3_ST_SR_FINISHED_A; - s->init_num = 0; - break; - - case SSL3_ST_SR_FINISHED_A: - case SSL3_ST_SR_FINISHED_B: - /* - * Enable CCS. Receiving a CCS clears the flag, so make - * sure not to re-enable it to ban duplicates. This *should* be the - * first time we have received one - but we check anyway to be - * cautious. - * s->s3->change_cipher_spec is set when a CCS is - * processed in d1_pkt.c, and remains set until - * the client's Finished message is read. - */ - if (!s->s3->change_cipher_spec) - 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 = 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; - s->state = SSL_ST_ERR; - goto end; - } - - ret = dtls1_send_change_cipher_spec(s, - SSL3_ST_SW_CHANGE_A, - SSL3_ST_SW_CHANGE_B); - - if (ret <= 0) - goto end; - -#ifndef OPENSSL_NO_SCTP - if (!s->hit) { - /* - * Change to new shared key of SCTP-Auth, will be ignored if - * no SCTP used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, - 0, NULL); - } -#endif - - 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; - s->state = SSL_ST_ERR; - goto end; - } - - dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); - 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) { - s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A; - -#ifndef OPENSSL_NO_SCTP - /* - * Change to new shared key of SCTP-Auth, will be ignored if - * no SCTP used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, - 0, NULL); -#endif - } else { - s->s3->tmp.next_state = SSL_ST_OK; -#ifndef OPENSSL_NO_SCTP - if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { - s->d1->next_state = s->s3->tmp.next_state; - s->s3->tmp.next_state = DTLS1_SCTP_ST_SW_WRITE_SOCK; - } -#endif - } - 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->renegotiate == 2) { /* skipped if we just sent a - * HelloRequest */ - s->renegotiate = 0; - 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; - dtls1_clear_received_buffer(s); - goto end; - /* break; */ - - case SSL_ST_ERR: - 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--; -#ifndef OPENSSL_NO_SCTP - /* - * Notify SCTP BIO socket to leave handshake mode and prevent stream - * identifier other than 0. Will be ignored if no SCTP is used. - */ - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, - s->in_handshake, NULL); -#endif - - if (cb != NULL) - cb(s, SSL_CB_ACCEPT_EXIT, ret); - return (ret); -} - -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]); - /* Always use DTLS 1.0 version: see RFC 6347 */ - *(p++) = DTLS1_VERSION >> 8; - *(p++) = DTLS1_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); - s->state = SSL_ST_ERR; - 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)); -} diff --git a/ssl/dtls1.h b/ssl/dtls1.h deleted file mode 100644 index 30bbcf278a43..000000000000 --- a/ssl/dtls1.h +++ /dev/null @@ -1,272 +0,0 @@ -/* 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 -# if defined(OPENSSL_SYS_VXWORKS) -# include <sys/times.h> -# else -# include <sys/time.h> -# endif -# endif - -#ifdef __cplusplus -extern "C" { -#endif - -# define DTLS1_VERSION 0xFEFF -# define DTLS1_2_VERSION 0xFEFD -# define DTLS_MAX_VERSION DTLS1_2_VERSION -# define DTLS1_VERSION_MAJOR 0xFE - -# define DTLS1_BAD_VER 0x0100 - -/* Special value for method supporting multiple versions */ -# define DTLS_ANY_VERSION 0x1FFFF - -# 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 - -# ifndef OPENSSL_NO_SSL_INTERN - -# ifndef OPENSSL_NO_SCTP -# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP" -# endif - -/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */ -# define DTLS1_MAX_MTU_OVERHEAD 48 - -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 link_mtu; /* max on-the-wire DTLS packet size */ - 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 or heartbeat 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; - /* - * Set when the handshake is ready to process peer's ChangeCipherSpec message. - * Cleared after the message has been processed. - */ - unsigned int change_cipher_spec_ok; -# ifndef OPENSSL_NO_SCTP - /* used when SSL_ST_XX_FLUSH is entered */ - int next_state; - int shutdown_received; -# endif -} DTLS1_STATE; - -typedef struct dtls1_record_data_st { - unsigned char *packet; - unsigned int packet_length; - SSL3_BUFFER rbuf; - SSL3_RECORD rrec; -# ifndef OPENSSL_NO_SCTP - struct bio_dgram_sctp_rcvinfo recordinfo; -# endif -} DTLS1_RECORD_DATA; - -# endif - -/* 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/ssl/dtlstest.c b/ssl/dtlstest.c deleted file mode 100644 index 78ebc67744c4..000000000000 --- a/ssl/dtlstest.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/bio.h> -#include <openssl/crypto.h> -#include <openssl/ssl.h> -#include <openssl/err.h> - -#include "ssltestlib.h" -#include "testutil.h" - -static char *cert = NULL; -static char *privkey = NULL; - -#define NUM_TESTS 2 - - -#define DUMMY_CERT_STATUS_LEN 12 - -unsigned char certstatus[] = { - SSL3_RT_HANDSHAKE, /* Content type */ - 0xfe, 0xfd, /* Record version */ - 0, 1, /* Epoch */ - 0, 0, 0, 0, 0, 0x0f, /* Record sequence number */ - 0, DTLS1_HM_HEADER_LENGTH + DUMMY_CERT_STATUS_LEN - 2, - SSL3_MT_CERTIFICATE_STATUS, /* Cert Status handshake message type */ - 0, 0, DUMMY_CERT_STATUS_LEN, /* Message len */ - 0, 5, /* Message sequence */ - 0, 0, 0, /* Fragment offset */ - 0, 0, DUMMY_CERT_STATUS_LEN - 2, /* Fragment len */ - 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80 /* Dummy data */ -}; - -#define RECORD_SEQUENCE 10 - -static int test_dtls_unprocessed(int testidx) -{ - SSL_CTX *sctx = NULL, *cctx = NULL; - SSL *serverssl1 = NULL, *clientssl1 = NULL; - BIO *c_to_s_fbio, *c_to_s_mempacket; - int testresult = 0; - - printf("Starting Test %d\n", testidx); - - if (!create_ssl_ctx_pair(DTLS_server_method(), DTLS_client_method(), &sctx, - &cctx, cert, privkey)) { - printf("Unable to create SSL_CTX pair\n"); - return 0; - } - - if (!SSL_CTX_set_ecdh_auto(sctx, 1)) { - printf("Failed configuring auto ECDH\n"); - } - - if (!SSL_CTX_set_cipher_list(cctx, "AES128-SHA")) { - printf("Failed setting cipher list\n"); - } - - c_to_s_fbio = BIO_new(bio_f_tls_dump_filter()); - if (c_to_s_fbio == NULL) { - printf("Failed to create filter BIO\n"); - goto end; - } - - /* BIO is freed by create_ssl_connection on error */ - if (!create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1, NULL, - c_to_s_fbio)) { - printf("Unable to create SSL objects\n"); - ERR_print_errors_fp(stdout); - goto end; - } - - if (testidx == 1) - certstatus[RECORD_SEQUENCE] = 0xff; - - /* - * Inject a dummy record from the next epoch. In test 0, this should never - * get used because the message sequence number is too big. In test 1 we set - * the record sequence number to be way off in the future. This should not - * have an impact on the record replay protection because the record should - * be dropped before it is marked as arrivedg - */ - c_to_s_mempacket = SSL_get_wbio(clientssl1); - c_to_s_mempacket = BIO_next(c_to_s_mempacket); - mempacket_test_inject(c_to_s_mempacket, (char *)certstatus, - sizeof(certstatus), 1, INJECT_PACKET_IGNORE_REC_SEQ); - - if (!create_ssl_connection(serverssl1, clientssl1)) { - printf("Unable to create SSL connection\n"); - ERR_print_errors_fp(stdout); - goto end; - } - - testresult = 1; - end: - SSL_free(serverssl1); - SSL_free(clientssl1); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - - return testresult; -} - -int main(int argc, char *argv[]) -{ - BIO *err = NULL; - int testresult = 0; - - if (argc != 3) { - printf("Invalid argument count\n"); - return 1; - } - - cert = argv[1]; - privkey = argv[2]; - - err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - SSL_library_init(); - SSL_load_error_strings(); - - CRYPTO_malloc_debug_init(); - CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - if (!test_dtls_unprocessed(0) || !test_dtls_unprocessed(1)) - testresult = 1; - - ERR_free_strings(); - ERR_remove_thread_state(NULL); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - CRYPTO_mem_leaks(err); - BIO_free(err); - - if (!testresult) - printf("PASS\n"); - - return testresult; -} diff --git a/ssl/fatalerrtest.c b/ssl/fatalerrtest.c deleted file mode 100644 index f9d66e27b30c..000000000000 --- a/ssl/fatalerrtest.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include <openssl/ssl.h> -#include <openssl/err.h> -#include "ssltestlib.h" - -int main(int argc, char *argv[]) -{ - SSL_CTX *sctx = NULL, *cctx = NULL; - SSL *sssl = NULL, *cssl = NULL; - const char *msg = "Dummy"; - BIO *err = NULL, *wbio = NULL; - int ret = 1, len; - char buf[80]; - unsigned char dummyrec[] = { - 0x17, 0x03, 0x03, 0x00, 0x05, 'D', 'u', 'm', 'm', 'y' - }; - - if (argc != 3) { - printf("Incorrect number of parameters\n"); - return 1; - } - - SSL_library_init(); - SSL_load_error_strings(); - err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - if (!create_ssl_ctx_pair(SSLv23_method(), SSLv23_method(), &sctx, &cctx, - argv[1], argv[2])) { - printf("Failed to create SSL_CTX pair\n"); - goto err; - } - - /* - * Deliberately set the cipher lists for client and server to be different - * to force a handshake failure. - */ - if (!SSL_CTX_set_cipher_list(sctx, "AES128-SHA") - || !SSL_CTX_set_cipher_list(cctx, "AES256-SHA")) { - printf("Failed to set cipher lists\n"); - goto err; - } - - if (!create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL)) { - printf("Failed to create SSL objectx\n"); - goto err; - } - - wbio = SSL_get_wbio(cssl); - if (wbio == NULL) { - printf("Unexpected NULL bio received\n"); - goto err; - } - - if (create_ssl_connection(sssl, cssl)) { - printf("Unexpected success creating a connection\n"); - goto err; - } - - ERR_clear_error(); - - /* Inject a plaintext record from client to server */ - if (BIO_write(wbio, dummyrec, sizeof(dummyrec)) <= 0) { - printf("Unexpected failure injecting dummy record\n"); - goto err; - } - - /* SSL_read()/SSL_write should fail because of a previous fatal error */ - if ((len = SSL_read(sssl, buf, sizeof(buf) - 1)) > 0) { - buf[len] = '\0'; - printf("Unexpected success reading data: %s\n", buf); - goto err; - } - if (SSL_write(sssl, msg, strlen(msg)) > 0) { - printf("Unexpected success writing data\n"); - goto err; - } - - ret = 0; - err: - SSL_free(sssl); - SSL_free(cssl); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - ERR_print_errors_fp(stderr); - - if (ret) { - printf("Fatal err test: FAILED\n"); - } - - ERR_free_strings(); - ERR_remove_thread_state(NULL); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - CRYPTO_mem_leaks(err); - BIO_free(err); - - return ret; -} diff --git a/ssl/heartbeat_test.c b/ssl/heartbeat_test.c deleted file mode 100644 index 7623c36ccf18..000000000000 --- a/ssl/heartbeat_test.c +++ /dev/null @@ -1,474 +0,0 @@ -/* test/heartbeat_test.c */ -/*- - * Unit test for TLS heartbeats. - * - * Acts as a regression test against the Heartbleed bug (CVE-2014-0160). - * - * Author: Mike Bland (mbland@acm.org, http://mike-bland.com/) - * Date: 2014-04-12 - * License: Creative Commons Attribution 4.0 International (CC By 4.0) - * http://creativecommons.org/licenses/by/4.0/deed.en_US - * - * OUTPUT - * ------ - * The program returns zero on success. It will print a message with a count - * of the number of failed tests and return nonzero if any tests fail. - * - * It will print the contents of the request and response buffers for each - * failing test. In a "fixed" version, all the tests should pass and there - * should be no output. - * - * In a "bleeding" version, you'll see: - * - * test_dtls1_heartbleed failed: - * expected payload len: 0 - * received: 1024 - * sent 26 characters - * "HEARTBLEED " - * received 1024 characters - * "HEARTBLEED \xde\xad\xbe\xef..." - * ** test_dtls1_heartbleed failed ** - * - * The contents of the returned buffer in the failing test will depend on the - * contents of memory on your machine. - * - * MORE INFORMATION - * ---------------- - * http://mike-bland.com/2014/04/12/heartbleed.html - * http://mike-bland.com/tags/heartbleed.html - */ - -#define OPENSSL_UNIT_TEST - -#include "../test/testutil.h" - -#include "../ssl/ssl_locl.h" -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST) - -/* As per https://tools.ietf.org/html/rfc6520#section-4 */ -# define MIN_PADDING_SIZE 16 - -/* Maximum number of payload characters to print as test output */ -# define MAX_PRINTABLE_CHARACTERS 1024 - -typedef struct heartbeat_test_fixture { - SSL_CTX *ctx; - SSL *s; - const char *test_case_name; - int (*process_heartbeat) (SSL *s); - unsigned char *payload; - int sent_payload_len; - int expected_return_value; - int return_payload_offset; - int expected_payload_len; - const char *expected_return_payload; -} HEARTBEAT_TEST_FIXTURE; - -static HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name, - const SSL_METHOD *meth) -{ - HEARTBEAT_TEST_FIXTURE fixture; - int setup_ok = 1; - memset(&fixture, 0, sizeof(fixture)); - fixture.test_case_name = test_case_name; - - fixture.ctx = SSL_CTX_new(meth); - if (!fixture.ctx) { - fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n", - test_case_name); - setup_ok = 0; - goto fail; - } - - fixture.s = SSL_new(fixture.ctx); - if (!fixture.s) { - fprintf(stderr, "Failed to allocate SSL for test: %s\n", - test_case_name); - setup_ok = 0; - goto fail; - } - - if (!ssl_init_wbio_buffer(fixture.s, 1)) { - fprintf(stderr, "Failed to set up wbio buffer for test: %s\n", - test_case_name); - setup_ok = 0; - goto fail; - } - - if (!ssl3_setup_buffers(fixture.s)) { - fprintf(stderr, "Failed to setup buffers for test: %s\n", - test_case_name); - setup_ok = 0; - goto fail; - } - - /* - * Clear the memory for the return buffer, since this isn't automatically - * zeroed in opt mode and will cause spurious test failures that will - * change with each execution. - */ - memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len); - - fail: - if (!setup_ok) { - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); - } - return fixture; -} - -static HEARTBEAT_TEST_FIXTURE set_up_dtls(const char *const test_case_name) -{ - HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name, - DTLSv1_server_method()); - fixture.process_heartbeat = dtls1_process_heartbeat; - - /* - * As per dtls1_get_record(), skipping the following from the beginning - * of the returned heartbeat message: type-1 byte; version-2 bytes; - * sequence number-8 bytes; length-2 bytes And then skipping the 1-byte - * type encoded by process_heartbeat for a total of 14 bytes, at which - * point we can grab the length and the payload we seek. - */ - fixture.return_payload_offset = 14; - return fixture; -} - -/* Needed by ssl3_write_bytes() */ -static int dummy_handshake(SSL *s) -{ - return 1; -} - -static HEARTBEAT_TEST_FIXTURE set_up_tls(const char *const test_case_name) -{ - HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name, - TLSv1_server_method()); - fixture.process_heartbeat = tls1_process_heartbeat; - fixture.s->handshake_func = dummy_handshake; - - /* - * As per do_ssl3_write(), skipping the following from the beginning of - * the returned heartbeat message: type-1 byte; version-2 bytes; length-2 - * bytes And then skipping the 1-byte type encoded by process_heartbeat - * for a total of 6 bytes, at which point we can grab the length and the - * payload we seek. - */ - fixture.return_payload_offset = 6; - return fixture; -} - -static void tear_down(HEARTBEAT_TEST_FIXTURE fixture) -{ - ERR_print_errors_fp(stderr); - SSL_free(fixture.s); - SSL_CTX_free(fixture.ctx); -} - -static void print_payload(const char *const prefix, - const unsigned char *payload, const int n) -{ - const int end = n < MAX_PRINTABLE_CHARACTERS ? n - : MAX_PRINTABLE_CHARACTERS; - int i = 0; - - printf("%s %d character%s", prefix, n, n == 1 ? "" : "s"); - if (end != n) - printf(" (first %d shown)", end); - printf("\n \""); - - for (; i != end; ++i) { - const unsigned char c = payload[i]; - if (isprint(c)) - fputc(c, stdout); - else - printf("\\x%02x", c); - } - printf("\"\n"); -} - -static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) -{ - int result = 0; - SSL *s = fixture.s; - unsigned char *payload = fixture.payload; - unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1]; - int return_value; - unsigned const char *p; - int actual_payload_len; - - s->s3->rrec.data = payload; - s->s3->rrec.length = strlen((const char *)payload); - *payload++ = TLS1_HB_REQUEST; - s2n(fixture.sent_payload_len, payload); - - /* - * Make a local copy of the request, since it gets overwritten at some - * point - */ - memcpy((char *)sent_buf, (const char *)payload, sizeof(sent_buf)); - - return_value = fixture.process_heartbeat(s); - - if (return_value != fixture.expected_return_value) { - printf("%s failed: expected return value %d, received %d\n", - fixture.test_case_name, fixture.expected_return_value, - return_value); - result = 1; - } - - /* - * If there is any byte alignment, it will be stored in wbuf.offset. - */ - p = &(s->s3-> - wbuf.buf[fixture.return_payload_offset + s->s3->wbuf.offset]); - actual_payload_len = 0; - n2s(p, actual_payload_len); - - if (actual_payload_len != fixture.expected_payload_len) { - printf("%s failed:\n expected payload len: %d\n received: %d\n", - fixture.test_case_name, fixture.expected_payload_len, - actual_payload_len); - print_payload("sent", sent_buf, strlen((const char *)sent_buf)); - print_payload("received", p, actual_payload_len); - result = 1; - } else { - char *actual_payload = - BUF_strndup((const char *)p, actual_payload_len); - if (strcmp(actual_payload, fixture.expected_return_payload) != 0) { - printf - ("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n", - fixture.test_case_name, fixture.expected_return_payload, - actual_payload); - result = 1; - } - OPENSSL_free(actual_payload); - } - - if (result != 0) { - printf("** %s failed **\n--------\n", fixture.test_case_name); - } - return result; -} - -static int honest_payload_size(unsigned char payload_buf[]) -{ - /* Omit three-byte pad at the beginning for type and payload length */ - return strlen((const char *)&payload_buf[3]) - MIN_PADDING_SIZE; -} - -# define SETUP_HEARTBEAT_TEST_FIXTURE(type)\ - SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type) - -# define EXECUTE_HEARTBEAT_TEST()\ - EXECUTE_TEST(execute_heartbeat, tear_down) - -static int test_dtls1_not_bleeding() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(dtls); - /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] = - " Not bleeding, sixteen spaces of padding" " "; - const int payload_buf_len = honest_payload_size(payload_buf); - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = payload_buf_len; - fixture.expected_return_value = 0; - fixture.expected_payload_len = payload_buf_len; - fixture.expected_return_payload = - "Not bleeding, sixteen spaces of padding"; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_dtls1_not_bleeding_empty_payload() -{ - int payload_buf_len; - - SETUP_HEARTBEAT_TEST_FIXTURE(dtls); - /* - * Three-byte pad at the beginning for type and payload length, plus a - * NUL at the end - */ - unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS]; - memset(payload_buf, ' ', MIN_PADDING_SIZE + 3); - payload_buf[MIN_PADDING_SIZE + 3] = '\0'; - payload_buf_len = honest_payload_size(payload_buf); - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = payload_buf_len; - fixture.expected_return_value = 0; - fixture.expected_payload_len = payload_buf_len; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_dtls1_heartbleed() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(dtls); - /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS] = - " HEARTBLEED "; - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; - fixture.expected_return_value = 0; - fixture.expected_payload_len = 0; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_dtls1_heartbleed_empty_payload() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(dtls); - /* - * Excluding the NUL at the end, one byte short of type + payload length - * + minimum padding - */ - unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4]; - memset(payload_buf, ' ', MIN_PADDING_SIZE + 2); - payload_buf[MIN_PADDING_SIZE + 2] = '\0'; - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; - fixture.expected_return_value = 0; - fixture.expected_payload_len = 0; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_dtls1_heartbleed_excessive_plaintext_length() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(dtls); - /* - * Excluding the NUL at the end, one byte in excess of maximum allowed - * heartbeat message length - */ - unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = honest_payload_size(payload_buf); - fixture.expected_return_value = 0; - fixture.expected_payload_len = 0; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_tls1_not_bleeding() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(tls); - /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] = - " Not bleeding, sixteen spaces of padding" " "; - const int payload_buf_len = honest_payload_size(payload_buf); - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = payload_buf_len; - fixture.expected_return_value = 0; - fixture.expected_payload_len = payload_buf_len; - fixture.expected_return_payload = - "Not bleeding, sixteen spaces of padding"; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_tls1_not_bleeding_empty_payload() -{ - int payload_buf_len; - - SETUP_HEARTBEAT_TEST_FIXTURE(tls); - /* - * Three-byte pad at the beginning for type and payload length, plus a - * NUL at the end - */ - unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS]; - memset(payload_buf, ' ', MIN_PADDING_SIZE + 3); - payload_buf[MIN_PADDING_SIZE + 3] = '\0'; - payload_buf_len = honest_payload_size(payload_buf); - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = payload_buf_len; - fixture.expected_return_value = 0; - fixture.expected_payload_len = payload_buf_len; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_tls1_heartbleed() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(tls); - /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] = - " HEARTBLEED "; - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; - fixture.expected_return_value = 0; - fixture.expected_payload_len = 0; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -static int test_tls1_heartbleed_empty_payload() -{ - SETUP_HEARTBEAT_TEST_FIXTURE(tls); - /* - * Excluding the NUL at the end, one byte short of type + payload length - * + minimum padding - */ - unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4]; - memset(payload_buf, ' ', MIN_PADDING_SIZE + 2); - payload_buf[MIN_PADDING_SIZE + 2] = '\0'; - - fixture.payload = &payload_buf[0]; - fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; - fixture.expected_return_value = 0; - fixture.expected_payload_len = 0; - fixture.expected_return_payload = ""; - EXECUTE_HEARTBEAT_TEST(); -} - -# undef EXECUTE_HEARTBEAT_TEST -# undef SETUP_HEARTBEAT_TEST_FIXTURE - -int main(int argc, char *argv[]) -{ - int num_failed; - - SSL_library_init(); - SSL_load_error_strings(); - - num_failed = test_dtls1_not_bleeding() + - test_dtls1_not_bleeding_empty_payload() + - test_dtls1_heartbleed() + test_dtls1_heartbleed_empty_payload() + - /* - * The following test causes an assertion failure at - * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g: - */ - (OPENSSL_VERSION_NUMBER >= 0x1000107fL ? - test_dtls1_heartbleed_excessive_plaintext_length() : 0) + - test_tls1_not_bleeding() + - test_tls1_not_bleeding_empty_payload() + - test_tls1_heartbleed() + test_tls1_heartbleed_empty_payload() + 0; - - ERR_print_errors_fp(stderr); - - if (num_failed != 0) { - printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : ""); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - -#else /* OPENSSL_NO_HEARTBEATS */ - -int main(int argc, char *argv[]) -{ - return EXIT_SUCCESS; -} -#endif /* OPENSSL_NO_HEARTBEATS */ diff --git a/ssl/kssl.c b/ssl/kssl.c deleted file mode 100644 index 18e5f1dcc2b0..000000000000 --- a/ssl/kssl.c +++ /dev/null @@ -1,2271 +0,0 @@ -/* ssl/kssl.c */ -/* - * Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project - * 2000. - */ -/* ==================================================================== - * Copyright (c) 2000-2018 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 "o_time.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; - - fprintf(stderr, "%s[%d] ", label, kdata->length); - for (i = 0; i < (int)kdata->length; i++) { - if (0 && isprint((int)kdata->data[i])) - fprintf(stderr, "%c ", kdata->data[i]); - else - fprintf(stderr, "%02x ", (unsigned char)kdata->data[i]); - } - fprintf(stderr, "\n"); -} - -/* - * Display contents of krb5_authdata struct, for debugging - */ -void print_krb5_authdata(char *label, krb5_authdata **adata) -{ - if (adata == NULL) { - fprintf(stderr, "%s, authdata==0\n", label); - return; - } - fprintf(stderr, "%s [%p]\n", label, (void *)adata); -# if 0 - { - int i; - fprintf(stderr, "%s[at%d:%d] ", label, adata->ad_type, adata->length); - for (i = 0; i < adata->length; i++) { - fprintf(stderr, (isprint(adata->contents[i])) ? "%c " : "%02x", - adata->contents[i]); - } - fprintf(stderr, "\n"); - } -# endif -} - -/* - * Display contents of krb5_keyblock struct, for debugging - */ -void print_krb5_keyblock(char *label, krb5_keyblock *keyblk) -{ - int i; - - if (keyblk == NULL) { - fprintf(stderr, "%s, keyblk==0\n", label); - return; - } -# ifdef KRB5_HEIMDAL - fprintf(stderr, "%s\n\t[et%d:%d]: ", label, keyblk->keytype, - keyblk->keyvalue->length); - for (i = 0; i < (int)keyblk->keyvalue->length; i++) { - fprintf(stderr, "%02x", - (unsigned char *)(keyblk->keyvalue->contents)[i]); - } - fprintf(stderr, "\n"); -# else - fprintf(stderr, "%s\n\t[et%d:%d]: ", label, keyblk->enctype, - keyblk->length); - for (i = 0; i < (int)keyblk->length; i++) { - fprintf(stderr, "%02x", keyblk->contents[i]); - } - fprintf(stderr, "\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; - - fprintf(stderr, "%s principal Realm: ", label); - if (princ == NULL) - return; - for (ui = 0; ui < (int)princ->realm.length; ui++) - putchar(princ->realm.data[ui]); - fprintf(stderr, " (nametype %d) has %d strings:\n", princ->type, - princ->length); - for (i = 0; i < (int)princ->length; i++) { - fprintf(stderr, "\t%d [%d]: ", i, princ->data[i].length); - for (uj = 0; uj < (int)princ->data[i].length; uj++) { - putchar(princ->data[i].data[uj]); - } - fprintf(stderr, "\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 - fprintf(stderr, "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; - fprintf(stderr, "Decrypted ticket fields:\n"); - fprintf(stderr, "\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)); - fprintf(stderr, "\tcaddrs: %p, authdata: %p\n", - krb5ticket->enc_part2->caddrs, - krb5ticket->enc_part2->authorization_data); - if (paddr) { - fprintf(stderr, "\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); - } - } - fprintf(stderr, "\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, - /* IGNORE_VNO */ - 0, - /* IGNORE_ENCTYPE */ - 0, &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 - fprintf(stderr, "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; - struct tm gmt_result = {0}; - struct tm lt_result = {0}; - - 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; - fprintf(stderr, "kssl_check_authent: authenticator[%d]:\n", - authentp->length); - p = authentp->data; - for (ui = 0; ui < authentp->length; ui++) - fprintf(stderr, "%02x ", p[ui]); - fprintf(stderr, "\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; - fprintf(stderr, "kssl_check_authent: decrypted authenticator[%d] =\n", - outl); - for (padl = 0; padl < outl; padl++) - fprintf(stderr, "%02x ", unenc_authent[padl]); - fprintf(stderr, "\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_g = OPENSSL_gmtime(&now, &gmt_result); - -# if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && \ - !defined(OPENSSL_SYS_OS2) && !defined(OPENSSL_SYS_SUNOS) && \ - (!defined(OPENSSL_SYS_VMS) || defined(localtime_r)) - tm_l = localtime_r(&now, <_result); -# else - tm_l = localtime(&now); -# endif - - tl = mktime(tm_l); - tg = mktime(tm_g); - tz_offset = tg - tl; - - *atimep = (krb5_timestamp)(tr - tz_offset); - } -# ifdef KSSL_DEBUG - fprintf(stderr, "kssl_check_authent: returns %d for client time ", - *atimep); - if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) - fprintf(stderr, "%.*s\n", auth->ctime->length, auth->ctime->data); - else - fprintf(stderr, "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 don'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; -} - -void SSL_set0_kssl_ctx(SSL *s, KSSL_CTX *kctx) -{ - s->kssl_ctx = kctx; -} - -KSSL_CTX *SSL_get0_kssl_ctx(SSL *s) -{ - return s->kssl_ctx; -} - -char *kssl_ctx_get0_client_princ(KSSL_CTX *kctx) -{ - if (kctx) - return kctx->client_princ; - return NULL; -} - -#else /* !OPENSSL_NO_KRB5 */ - -# if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) -static void *dummy = &dummy; -# endif - -#endif /* !OPENSSL_NO_KRB5 */ diff --git a/ssl/kssl.h b/ssl/kssl.h deleted file mode 100644 index ae8a51f472da..000000000000 --- a/ssl/kssl.h +++ /dev/null @@ -1,197 +0,0 @@ -/* ssl/kssl.h */ -/* - * 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 OPENSSL_SYS_WIN32 -/* - * These can sometimes get redefined indirectly by krb5 header files after - * they get undefed in ossl_typ.h - */ -# undef X509_NAME -# undef X509_EXTENSIONS -# undef OCSP_REQUEST -# undef OCSP_RESPONSE -# endif - -#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); - -void SSL_set0_kssl_ctx(SSL *s, KSSL_CTX *kctx); -KSSL_CTX *SSL_get0_kssl_ctx(SSL *s); -char *kssl_ctx_get0_client_princ(KSSL_CTX *kctx); - -#ifdef __cplusplus -} -#endif -# endif /* OPENSSL_NO_KRB5 */ -#endif /* KSSL_H */ diff --git a/ssl/kssl_lcl.h b/ssl/kssl_lcl.h deleted file mode 100644 index 8e6a6d69e949..000000000000 --- a/ssl/kssl_lcl.h +++ /dev/null @@ -1,88 +0,0 @@ -/* ssl/kssl.h */ -/* - * 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/ssl/methods.c b/ssl/methods.c new file mode 100644 index 000000000000..348efe467dbb --- /dev/null +++ b/ssl/methods.c @@ -0,0 +1,278 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <openssl/objects.h> +#include "ssl_locl.h" + +/*- + * TLS/SSLv3 methods + */ + +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, + TLS_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_2_enc_data) +IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3, + tlsv1_3_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_3_enc_data) +#ifndef OPENSSL_NO_TLS1_2_METHOD +IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2, + tlsv1_2_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_2_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_1_METHOD +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1, + tlsv1_1_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_1_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_METHOD +IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + tlsv1_method, + ossl_statem_accept, ossl_statem_connect, TLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +IMPLEMENT_ssl3_meth_func(sslv3_method, ossl_statem_accept, ossl_statem_connect) +#endif +/*- + * TLS/SSLv3 server methods + */ +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, + TLS_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_2_enc_data) +IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3, + tlsv1_3_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_3_enc_data) +#ifndef OPENSSL_NO_TLS1_2_METHOD +IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2, + tlsv1_2_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_2_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_1_METHOD +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1, + tlsv1_1_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_1_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_METHOD +IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + tlsv1_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +IMPLEMENT_ssl3_meth_func(sslv3_server_method, + ossl_statem_accept, ssl_undefined_function) +#endif +/*- + * TLS/SSLv3 client methods + */ +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, + TLS_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_2_enc_data) +IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3, + tlsv1_3_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_3_enc_data) +#ifndef OPENSSL_NO_TLS1_2_METHOD +IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2, + tlsv1_2_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_2_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_1_METHOD +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1, + tlsv1_1_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_1_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_METHOD +IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + tlsv1_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +IMPLEMENT_ssl3_meth_func(sslv3_client_method, + ssl_undefined_function, ossl_statem_connect) +#endif +/*- + * DTLS methods + */ +#ifndef OPENSSL_NO_DTLS1_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtlsv1_method, + ossl_statem_accept, + ossl_statem_connect, DTLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_DTLS1_2_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2, + dtlsv1_2_method, + ossl_statem_accept, + ossl_statem_connect, DTLSv1_2_enc_data) +#endif +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0, + DTLS_method, + ossl_statem_accept, + ossl_statem_connect, DTLSv1_2_enc_data) + +/*- + * DTLS server methods + */ +#ifndef OPENSSL_NO_DTLS1_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtlsv1_server_method, + ossl_statem_accept, + ssl_undefined_function, DTLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_DTLS1_2_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2, + dtlsv1_2_server_method, + ossl_statem_accept, + ssl_undefined_function, DTLSv1_2_enc_data) +#endif +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0, + DTLS_server_method, + ossl_statem_accept, + ssl_undefined_function, DTLSv1_2_enc_data) + +/*- + * DTLS client methods + */ +#ifndef OPENSSL_NO_DTLS1_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtlsv1_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_enc_data) +IMPLEMENT_dtls1_meth_func(DTLS1_BAD_VER, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtls_bad_ver_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_DTLS1_2_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2, + dtlsv1_2_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_2_enc_data) +#endif +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0, + DTLS_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_2_enc_data) +#if OPENSSL_API_COMPAT < 0x10100000L +# ifndef OPENSSL_NO_TLS1_2_METHOD +const SSL_METHOD *TLSv1_2_method(void) +{ + return tlsv1_2_method(); +} + +const SSL_METHOD *TLSv1_2_server_method(void) +{ + return tlsv1_2_server_method(); +} + +const SSL_METHOD *TLSv1_2_client_method(void) +{ + return tlsv1_2_client_method(); +} +# endif + +# ifndef OPENSSL_NO_TLS1_1_METHOD +const SSL_METHOD *TLSv1_1_method(void) +{ + return tlsv1_1_method(); +} + +const SSL_METHOD *TLSv1_1_server_method(void) +{ + return tlsv1_1_server_method(); +} + +const SSL_METHOD *TLSv1_1_client_method(void) +{ + return tlsv1_1_client_method(); +} +# endif + +# ifndef OPENSSL_NO_TLS1_METHOD +const SSL_METHOD *TLSv1_method(void) +{ + return tlsv1_method(); +} + +const SSL_METHOD *TLSv1_server_method(void) +{ + return tlsv1_server_method(); +} + +const SSL_METHOD *TLSv1_client_method(void) +{ + return tlsv1_client_method(); +} +# endif + +# ifndef OPENSSL_NO_SSL3_METHOD +const SSL_METHOD *SSLv3_method(void) +{ + return sslv3_method(); +} + +const SSL_METHOD *SSLv3_server_method(void) +{ + return sslv3_server_method(); +} + +const SSL_METHOD *SSLv3_client_method(void) +{ + return sslv3_client_method(); +} +# endif + +# ifndef OPENSSL_NO_DTLS1_2_METHOD +const SSL_METHOD *DTLSv1_2_method(void) +{ + return dtlsv1_2_method(); +} + +const SSL_METHOD *DTLSv1_2_server_method(void) +{ + return dtlsv1_2_server_method(); +} + +const SSL_METHOD *DTLSv1_2_client_method(void) +{ + return dtlsv1_2_client_method(); +} +# endif + +# ifndef OPENSSL_NO_DTLS1_METHOD +const SSL_METHOD *DTLSv1_method(void) +{ + return dtlsv1_method(); +} + +const SSL_METHOD *DTLSv1_server_method(void) +{ + return dtlsv1_server_method(); +} + +const SSL_METHOD *DTLSv1_client_method(void) +{ + return dtlsv1_client_method(); +} +# endif + +#endif diff --git a/ssl/packet.c b/ssl/packet.c new file mode 100644 index 000000000000..95031430ed66 --- /dev/null +++ b/ssl/packet.c @@ -0,0 +1,424 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "packet_locl.h" +#include <openssl/sslerr.h> + +#define DEFAULT_BUF_SIZE 256 + +int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) +{ + if (!WPACKET_reserve_bytes(pkt, len, allocbytes)) + return 0; + + pkt->written += len; + pkt->curr += len; + return 1; +} + +int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes) +{ + if (!WPACKET_start_sub_packet_len__(pkt, lenbytes) + || !WPACKET_allocate_bytes(pkt, len, allocbytes) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +#define GETBUF(p) (((p)->staticbuf != NULL) \ + ? (p)->staticbuf : (unsigned char *)(p)->buf->data) + +int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL && len != 0)) + return 0; + + if (pkt->maxsize - pkt->written < len) + return 0; + + if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) { + size_t newlen; + size_t reflen; + + reflen = (len > pkt->buf->length) ? len : pkt->buf->length; + + if (reflen > SIZE_MAX / 2) { + newlen = SIZE_MAX; + } else { + newlen = reflen * 2; + if (newlen < DEFAULT_BUF_SIZE) + newlen = DEFAULT_BUF_SIZE; + } + if (BUF_MEM_grow(pkt->buf, newlen) == 0) + return 0; + } + if (allocbytes != NULL) + *allocbytes = WPACKET_get_curr(pkt); + + return 1; +} + +int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes) +{ + if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes)) + return 0; + + *allocbytes += lenbytes; + + return 1; +} + +static size_t maxmaxsize(size_t lenbytes) +{ + if (lenbytes >= sizeof(size_t) || lenbytes == 0) + return SIZE_MAX; + + return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes; +} + +static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes) +{ + unsigned char *lenchars; + + pkt->curr = 0; + pkt->written = 0; + + if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) { + SSLerr(SSL_F_WPACKET_INTERN_INIT_LEN, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (lenbytes == 0) + return 1; + + pkt->subs->pwritten = lenbytes; + pkt->subs->lenbytes = lenbytes; + + if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) { + OPENSSL_free(pkt->subs); + pkt->subs = NULL; + return 0; + } + pkt->subs->packet_len = lenchars - GETBUF(pkt); + + return 1; +} + +int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, + size_t lenbytes) +{ + size_t max = maxmaxsize(lenbytes); + + /* Internal API, so should not fail */ + if (!ossl_assert(buf != NULL && len > 0)) + return 0; + + pkt->staticbuf = buf; + pkt->buf = NULL; + pkt->maxsize = (max < len) ? max : len; + + return wpacket_intern_init_len(pkt, lenbytes); +} + +int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(buf != NULL)) + return 0; + + pkt->staticbuf = NULL; + pkt->buf = buf; + pkt->maxsize = maxmaxsize(lenbytes); + + return wpacket_intern_init_len(pkt, lenbytes); +} + +int WPACKET_init(WPACKET *pkt, BUF_MEM *buf) +{ + return WPACKET_init_len(pkt, buf, 0); +} + +int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + pkt->subs->flags = flags; + + return 1; +} + +/* Store the |value| of length |len| at location |data| */ +static int put_value(unsigned char *data, size_t value, size_t len) +{ + for (data += len - 1; len > 0; len--) { + *data = (unsigned char)(value & 0xff); + data--; + value >>= 8; + } + + /* Check whether we could fit the value in the assigned number of bytes */ + if (value > 0) + return 0; + + return 1; +} + + +/* + * Internal helper function used by WPACKET_close(), WPACKET_finish() and + * WPACKET_fill_lengths() to close a sub-packet and write out its length if + * necessary. If |doclose| is 0 then it goes through the motions of closing + * (i.e. it fills in all the lengths), but doesn't actually close anything. + */ +static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose) +{ + size_t packlen = pkt->written - sub->pwritten; + + if (packlen == 0 + && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0) + return 0; + + if (packlen == 0 + && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) { + /* We can't handle this case. Return an error */ + if (!doclose) + return 0; + + /* Deallocate any bytes allocated for the length of the WPACKET */ + if ((pkt->curr - sub->lenbytes) == sub->packet_len) { + pkt->written -= sub->lenbytes; + pkt->curr -= sub->lenbytes; + } + + /* Don't write out the packet length */ + sub->packet_len = 0; + sub->lenbytes = 0; + } + + /* Write out the WPACKET length if needed */ + if (sub->lenbytes > 0 + && !put_value(&GETBUF(pkt)[sub->packet_len], packlen, + sub->lenbytes)) + return 0; + + if (doclose) { + pkt->subs = sub->parent; + OPENSSL_free(sub); + } + + return 1; +} + +int WPACKET_fill_lengths(WPACKET *pkt) +{ + WPACKET_SUB *sub; + + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + for (sub = pkt->subs; sub != NULL; sub = sub->parent) { + if (!wpacket_intern_close(pkt, sub, 0)) + return 0; + } + + return 1; +} + +int WPACKET_close(WPACKET *pkt) +{ + /* + * Internal API, so should not fail - but we do negative testing of this + * so no assert (otherwise the tests fail) + */ + if (pkt->subs == NULL || pkt->subs->parent == NULL) + return 0; + + return wpacket_intern_close(pkt, pkt->subs, 1); +} + +int WPACKET_finish(WPACKET *pkt) +{ + int ret; + + /* + * Internal API, so should not fail - but we do negative testing of this + * so no assert (otherwise the tests fail) + */ + if (pkt->subs == NULL || pkt->subs->parent != NULL) + return 0; + + ret = wpacket_intern_close(pkt, pkt->subs, 1); + if (ret) { + OPENSSL_free(pkt->subs); + pkt->subs = NULL; + } + + return ret; +} + +int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes) +{ + WPACKET_SUB *sub; + unsigned char *lenchars; + + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) { + SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE); + return 0; + } + + sub->parent = pkt->subs; + pkt->subs = sub; + sub->pwritten = pkt->written + lenbytes; + sub->lenbytes = lenbytes; + + if (lenbytes == 0) { + sub->packet_len = 0; + return 1; + } + + if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) + return 0; + /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */ + sub->packet_len = lenchars - GETBUF(pkt); + + return 1; +} + +int WPACKET_start_sub_packet(WPACKET *pkt) +{ + return WPACKET_start_sub_packet_len__(pkt, 0); +} + +int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size) +{ + unsigned char *data; + + /* Internal API, so should not fail */ + if (!ossl_assert(size <= sizeof(unsigned int)) + || !WPACKET_allocate_bytes(pkt, size, &data) + || !put_value(data, val, size)) + return 0; + + return 1; +} + +int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize) +{ + WPACKET_SUB *sub; + size_t lenbytes; + + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + /* Find the WPACKET_SUB for the top level */ + for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent) + continue; + + lenbytes = sub->lenbytes; + if (lenbytes == 0) + lenbytes = sizeof(pkt->maxsize); + + if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written) + return 0; + + pkt->maxsize = maxsize; + + return 1; +} + +int WPACKET_memset(WPACKET *pkt, int ch, size_t len) +{ + unsigned char *dest; + + if (len == 0) + return 1; + + if (!WPACKET_allocate_bytes(pkt, len, &dest)) + return 0; + + memset(dest, ch, len); + + return 1; +} + +int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len) +{ + unsigned char *dest; + + if (len == 0) + return 1; + + if (!WPACKET_allocate_bytes(pkt, len, &dest)) + return 0; + + memcpy(dest, src, len); + + return 1; +} + +int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, + size_t lenbytes) +{ + if (!WPACKET_start_sub_packet_len__(pkt, lenbytes) + || !WPACKET_memcpy(pkt, src, len) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +int WPACKET_get_total_written(WPACKET *pkt, size_t *written) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(written != NULL)) + return 0; + + *written = pkt->written; + + return 1; +} + +int WPACKET_get_length(WPACKET *pkt, size_t *len) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL && len != NULL)) + return 0; + + *len = pkt->written - pkt->subs->pwritten; + + return 1; +} + +unsigned char *WPACKET_get_curr(WPACKET *pkt) +{ + return GETBUF(pkt) + pkt->curr; +} + +void WPACKET_cleanup(WPACKET *pkt) +{ + WPACKET_SUB *sub, *parent; + + for (sub = pkt->subs; sub != NULL; sub = parent) { + parent = sub->parent; + OPENSSL_free(sub); + } + pkt->subs = NULL; +} diff --git a/ssl/packet_locl.h b/ssl/packet_locl.h new file mode 100644 index 000000000000..860360b8b231 --- /dev/null +++ b/ssl/packet_locl.h @@ -0,0 +1,874 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PACKET_LOCL_H +# define HEADER_PACKET_LOCL_H + +# include <string.h> +# include <openssl/bn.h> +# include <openssl/buffer.h> +# include <openssl/crypto.h> +# include <openssl/e_os2.h> + +# include "internal/numbers.h" + +typedef struct { + /* Pointer to where we are currently reading from */ + const unsigned char *curr; + /* Number of bytes remaining */ + size_t remaining; +} PACKET; + +/* Internal unchecked shorthand; don't use outside this file. */ +static ossl_inline void packet_forward(PACKET *pkt, size_t len) +{ + pkt->curr += len; + pkt->remaining -= len; +} + +/* + * Returns the number of bytes remaining to be read in the PACKET + */ +static ossl_inline size_t PACKET_remaining(const PACKET *pkt) +{ + return pkt->remaining; +} + +/* + * Returns a pointer to the first byte after the packet data. + * Useful for integrating with non-PACKET parsing code. + * Specifically, we use PACKET_end() to verify that a d2i_... call + * has consumed the entire packet contents. + */ +static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt) +{ + return pkt->curr + pkt->remaining; +} + +/* + * Returns a pointer to the PACKET's current position. + * For use in non-PACKETized APIs. + */ +static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt) +{ + return pkt->curr; +} + +/* + * Initialise a PACKET with |len| bytes held in |buf|. This does not make a + * copy of the data so |buf| must be present for the whole time that the PACKET + * is being used. + */ +__owur static ossl_inline int PACKET_buf_init(PACKET *pkt, + const unsigned char *buf, + size_t len) +{ + /* Sanity check for negative values. */ + if (len > (size_t)(SIZE_MAX / 2)) + return 0; + + pkt->curr = buf; + pkt->remaining = len; + return 1; +} + +/* Initialize a PACKET to hold zero bytes. */ +static ossl_inline void PACKET_null_init(PACKET *pkt) +{ + pkt->curr = NULL; + pkt->remaining = 0; +} + +/* + * Returns 1 if the packet has length |num| and its contents equal the |num| + * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal). + * If lengths are equal, performs the comparison in constant time. + */ +__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr, + size_t num) +{ + if (PACKET_remaining(pkt) != num) + return 0; + return CRYPTO_memcmp(pkt->curr, ptr, num) == 0; +} + +/* + * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + */ +__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt, + PACKET *subpkt, size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + return PACKET_buf_init(subpkt, pkt->curr, len); +} + +/* + * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not + * copied: the |subpkt| packet will share its underlying buffer with the + * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + */ +__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt, + PACKET *subpkt, size_t len) +{ + if (!PACKET_peek_sub_packet(pkt, subpkt, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Peek ahead at 2 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt, + unsigned int *data) +{ + if (PACKET_remaining(pkt) < 2) + return 0; + + *data = ((unsigned int)(*pkt->curr)) << 8; + *data |= *(pkt->curr + 1); + + return 1; +} + +/* Equivalent of n2s */ +/* Get 2 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data) +{ + if (!PACKET_peek_net_2(pkt, data)) + return 0; + + packet_forward(pkt, 2); + + return 1; +} + +/* Same as PACKET_get_net_2() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data) +{ + unsigned int i; + int ret = PACKET_get_net_2(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 3 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 3) + return 0; + + *data = ((unsigned long)(*pkt->curr)) << 16; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; + *data |= *(pkt->curr + 2); + + return 1; +} + +/* Equivalent of n2l3 */ +/* Get 3 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_net_3(pkt, data)) + return 0; + + packet_forward(pkt, 3); + + return 1; +} + +/* Same as PACKET_get_net_3() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data) +{ + unsigned long i; + int ret = PACKET_get_net_3(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 4 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 4) + return 0; + + *data = ((unsigned long)(*pkt->curr)) << 24; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 16; + *data |= ((unsigned long)(*(pkt->curr + 2))) << 8; + *data |= *(pkt->curr + 3); + + return 1; +} + +/* Equivalent of n2l */ +/* Get 4 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_net_4(pkt, data)) + return 0; + + packet_forward(pkt, 4); + + return 1; +} + +/* Same as PACKET_get_net_4() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) +{ + unsigned long i; + int ret = PACKET_get_net_4(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, + unsigned int *data) +{ + if (!PACKET_remaining(pkt)) + return 0; + + *data = *pkt->curr; + + return 1; +} + +/* Get 1 byte from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data) +{ + if (!PACKET_peek_1(pkt, data)) + return 0; + + packet_forward(pkt, 1); + + return 1; +} + +/* Same as PACKET_get_1() but for a size_t */ +__owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data) +{ + unsigned int i; + int ret = PACKET_get_1(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value + * in |*data| + */ +__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 4) + return 0; + + *data = *pkt->curr; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; + *data |= ((unsigned long)(*(pkt->curr + 2))) << 16; + *data |= ((unsigned long)(*(pkt->curr + 3))) << 24; + + return 1; +} + +/* Equivalent of c2l */ +/* + * Get 4 bytes in reverse network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_4(pkt, data)) + return 0; + + packet_forward(pkt, 4); + + return 1; +} + +/* + * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in + * |*data|. This just points at the underlying buffer that |pkt| is using. The + * caller should not free this data directly (it will be freed when the + * underlying buffer gets freed + */ +__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt, + const unsigned char **data, + size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + *data = pkt->curr; + + return 1; +} + +/* + * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This + * just points at the underlying buffer that |pkt| is using. The caller should + * not free this data directly (it will be freed when the underlying buffer gets + * freed + */ +__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt, + const unsigned char **data, + size_t len) +{ + if (!PACKET_peek_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */ +__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt, + unsigned char *data, + size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + memcpy(data, pkt->curr, len); + + return 1; +} + +/* + * Read |len| bytes from |pkt| and copy them to |data|. + * The caller is responsible for ensuring that |data| can hold |len| bytes. + */ +__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt, + unsigned char *data, size_t len) +{ + if (!PACKET_peek_copy_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Copy packet data to |dest|, and set |len| to the number of copied bytes. + * If the packet has more than |dest_len| bytes, nothing is copied. + * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing + * done with a given PACKET). + */ +__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt, + unsigned char *dest, + size_t dest_len, size_t *len) +{ + if (PACKET_remaining(pkt) > dest_len) { + *len = 0; + return 0; + } + *len = pkt->remaining; + memcpy(dest, pkt->curr, pkt->remaining); + return 1; +} + +/* + * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the + * result in |*data|, and the length in |len|. + * If |*data| is not NULL, the old data is OPENSSL_free'd. + * If the packet is empty, or malloc fails, |*data| will be set to NULL. + * Returns 1 if the malloc succeeds and 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing + * done with a given PACKET). + */ +__owur static ossl_inline int PACKET_memdup(const PACKET *pkt, + unsigned char **data, size_t *len) +{ + size_t length; + + OPENSSL_free(*data); + *data = NULL; + *len = 0; + + length = PACKET_remaining(pkt); + + if (length == 0) + return 1; + + *data = OPENSSL_memdup(pkt->curr, length); + if (*data == NULL) + return 0; + + *len = length; + return 1; +} + +/* + * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated + * buffer. Store a pointer to the result in |*data|. + * If |*data| is not NULL, the old data is OPENSSL_free'd. + * If the data in |pkt| does not contain a NUL-byte, the entire data is + * copied and NUL-terminated. + * Returns 1 if the malloc succeeds and 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing done + * with a given PACKET). + */ +__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data) +{ + OPENSSL_free(*data); + + /* This will succeed on an empty packet, unless pkt->curr == NULL. */ + *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt)); + return (*data != NULL); +} + +/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */ +static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt) +{ + return memchr(pkt->curr, 0, pkt->remaining) != NULL; +} + +/* Move the current reading position forward |len| bytes */ +__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a one-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_1(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Like PACKET_get_length_prefixed_1, but additionally, fails when there are + * leftover bytes in |pkt|. + */ +__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_1(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length) || + PACKET_remaining(&tmp) != 0) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a two-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + + if (!PACKET_get_net_2(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Like PACKET_get_length_prefixed_2, but additionally, fails when there are + * leftover bytes in |pkt|. + */ +__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + + if (!PACKET_get_net_2(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length) || + PACKET_remaining(&tmp) != 0) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a three-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt, + PACKET *subpkt) +{ + unsigned long length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_net_3(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* Writeable packets */ + +typedef struct wpacket_sub WPACKET_SUB; +struct wpacket_sub { + /* The parent WPACKET_SUB if we have one or NULL otherwise */ + WPACKET_SUB *parent; + + /* + * Offset into the buffer where the length of this WPACKET goes. We use an + * offset in case the buffer grows and gets reallocated. + */ + size_t packet_len; + + /* Number of bytes in the packet_len or 0 if we don't write the length */ + size_t lenbytes; + + /* Number of bytes written to the buf prior to this packet starting */ + size_t pwritten; + + /* Flags for this sub-packet */ + unsigned int flags; +}; + +typedef struct wpacket_st WPACKET; +struct wpacket_st { + /* The buffer where we store the output data */ + BUF_MEM *buf; + + /* Fixed sized buffer which can be used as an alternative to buf */ + unsigned char *staticbuf; + + /* + * Offset into the buffer where we are currently writing. We use an offset + * in case the buffer grows and gets reallocated. + */ + size_t curr; + + /* Number of bytes written so far */ + size_t written; + + /* Maximum number of bytes we will allow to be written to this WPACKET */ + size_t maxsize; + + /* Our sub-packets (always at least one if not finished) */ + WPACKET_SUB *subs; +}; + +/* Flags */ + +/* Default */ +#define WPACKET_FLAGS_NONE 0 + +/* Error on WPACKET_close() if no data written to the WPACKET */ +#define WPACKET_FLAGS_NON_ZERO_LENGTH 1 + +/* + * Abandon all changes on WPACKET_close() if no data written to the WPACKET, + * i.e. this does not write out a zero packet length + */ +#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2 + + +/* + * Initialise a WPACKET with the buffer in |buf|. The buffer must exist + * for the whole time that the WPACKET is being used. Additionally |lenbytes| of + * data is preallocated at the start of the buffer to store the length of the + * WPACKET once we know it. + */ +int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes); + +/* + * Same as WPACKET_init_len except there is no preallocation of the WPACKET + * length. + */ +int WPACKET_init(WPACKET *pkt, BUF_MEM *buf); + +/* + * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure. + * A fixed buffer of memory |buf| of size |len| is used instead. A failure will + * occur if you attempt to write beyond the end of the buffer + */ +int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, + size_t lenbytes); +/* + * Set the flags to be applied to the current sub-packet + */ +int WPACKET_set_flags(WPACKET *pkt, unsigned int flags); + +/* + * Closes the most recent sub-packet. It also writes out the length of the + * packet to the required location (normally the start of the WPACKET) if + * appropriate. The top level WPACKET should be closed using WPACKET_finish() + * instead of this function. + */ +int WPACKET_close(WPACKET *pkt); + +/* + * The same as WPACKET_close() but only for the top most WPACKET. Additionally + * frees memory resources for this WPACKET. + */ +int WPACKET_finish(WPACKET *pkt); + +/* + * Iterate through all the sub-packets and write out their lengths as if they + * were being closed. The lengths will be overwritten with the final lengths + * when the sub-packets are eventually closed (which may be different if more + * data is added to the WPACKET). This function fails if a sub-packet is of 0 + * length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set. + */ +int WPACKET_fill_lengths(WPACKET *pkt); + +/* + * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated + * at the start of the sub-packet to store its length once we know it. Don't + * call this directly. Use the convenience macros below instead. + */ +int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes); + +/* + * Convenience macros for calling WPACKET_start_sub_packet_len with different + * lengths + */ +#define WPACKET_start_sub_packet_u8(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 1) +#define WPACKET_start_sub_packet_u16(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 2) +#define WPACKET_start_sub_packet_u24(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 3) +#define WPACKET_start_sub_packet_u32(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 4) + +/* + * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated + * for the sub-packet length. + */ +int WPACKET_start_sub_packet(WPACKET *pkt); + +/* + * Allocate bytes in the WPACKET for the output. This reserves the bytes + * and counts them as "written", but doesn't actually do the writing. A pointer + * to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL. + * WARNING: the allocated bytes must be filled in immediately, without further + * WPACKET_* calls. If not then the underlying buffer may be realloc'd and + * change its location. + */ +int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, + unsigned char **allocbytes); + +/* + * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is + * started for the allocated bytes, and then closed immediately afterwards. The + * number of length bytes for the sub-packet is in |lenbytes|. Don't call this + * directly. Use the convenience macros below instead. + */ +int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes); + +/* + * Convenience macros for calling WPACKET_sub_allocate_bytes with different + * lengths + */ +#define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1) +#define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2) +#define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3) +#define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4) + +/* + * The same as WPACKET_allocate_bytes() except the reserved bytes are not + * actually counted as written. Typically this will be for when we don't know + * how big arbitrary data is going to be up front, but we do know what the + * maximum size will be. If this function is used, then it should be immediately + * followed by a WPACKET_allocate_bytes() call before any other WPACKET + * functions are called (unless the write to the allocated bytes is abandoned). + * + * For example: If we are generating a signature, then the size of that + * signature may not be known in advance. We can use WPACKET_reserve_bytes() to + * handle this: + * + * if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_size(pkey), &sigbytes1) + * || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0 + * || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2) + * || sigbytes1 != sigbytes2) + * goto err; + */ +int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes); + +/* + * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__() + */ +int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes); + +/* + * Convenience macros for WPACKET_sub_reserve_bytes with different lengths + */ +#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \ + WPACKET_reserve_bytes__((pkt), (len), (bytes), 1) +#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2) +#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3) +#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4) + +/* + * Write the value stored in |val| into the WPACKET. The value will consume + * |bytes| amount of storage. An error will occur if |val| cannot be + * accommodated in |bytes| storage, e.g. attempting to write the value 256 into + * 1 byte will fail. Don't call this directly. Use the convenience macros below + * instead. + */ +int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); + +/* + * Convenience macros for calling WPACKET_put_bytes with different + * lengths + */ +#define WPACKET_put_bytes_u8(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 1) +#define WPACKET_put_bytes_u16(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 2) +#define WPACKET_put_bytes_u24(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 3) +#define WPACKET_put_bytes_u32(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 4) + +/* Set a maximum size that we will not allow the WPACKET to grow beyond */ +int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); + +/* Copy |len| bytes of data from |*src| into the WPACKET. */ +int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len); + +/* Set |len| bytes of data to |ch| into the WPACKET. */ +int WPACKET_memset(WPACKET *pkt, int ch, size_t len); + +/* + * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its + * length (consuming |lenbytes| of data for the length). Don't call this + * directly. Use the convenience macros below instead. + */ +int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, + size_t lenbytes); + +/* Convenience macros for calling WPACKET_sub_memcpy with different lengths */ +#define WPACKET_sub_memcpy_u8(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 1) +#define WPACKET_sub_memcpy_u16(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 2) +#define WPACKET_sub_memcpy_u24(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 3) +#define WPACKET_sub_memcpy_u32(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 4) + +/* + * Return the total number of bytes written so far to the underlying buffer + * including any storage allocated for length bytes + */ +int WPACKET_get_total_written(WPACKET *pkt, size_t *written); + +/* + * Returns the length of the current sub-packet. This excludes any bytes + * allocated for the length itself. + */ +int WPACKET_get_length(WPACKET *pkt, size_t *len); + +/* + * Returns a pointer to the current write location, but does not allocate any + * bytes. + */ +unsigned char *WPACKET_get_curr(WPACKET *pkt); + +/* Release resources in a WPACKET if a failure has occurred. */ +void WPACKET_cleanup(WPACKET *pkt); + +#endif /* HEADER_PACKET_LOCL_H */ diff --git a/ssl/pqueue.c b/ssl/pqueue.c new file mode 100644 index 000000000000..548a7a443d91 --- /dev/null +++ b/ssl/pqueue.c @@ -0,0 +1,158 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" +#include <openssl/bn.h> + +struct pqueue_st { + pitem *items; + int count; +}; + +pitem *pitem_new(unsigned char *prio64be, void *data) +{ + pitem *item = OPENSSL_malloc(sizeof(*item)); + + if (item == NULL) { + SSLerr(SSL_F_PITEM_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(item->priority, prio64be, sizeof(item->priority)); + item->data = data; + item->next = NULL; + return item; +} + +void pitem_free(pitem *item) +{ + OPENSSL_free(item); +} + +pqueue *pqueue_new(void) +{ + pqueue *pq = OPENSSL_zalloc(sizeof(*pq)); + + if (pq == NULL) + SSLerr(SSL_F_PQUEUE_NEW, ERR_R_MALLOC_FAILURE); + + return pq; +} + +void pqueue_free(pqueue *pq) +{ + OPENSSL_free(pq); +} + +pitem *pqueue_insert(pqueue *pq, pitem *item) +{ + pitem *curr, *next; + + if (pq->items == NULL) { + pq->items = item; + return item; + } + + for (curr = NULL, next = pq->items; + next != NULL; curr = next, next = next->next) { + /* + * we can compare 64-bit value in big-endian encoding with memcmp:-) + */ + int cmp = memcmp(next->priority, item->priority, 8); + if (cmp > 0) { /* next > item */ + item->next = next; + + if (curr == NULL) + pq->items = item; + else + curr->next = item; + + return item; + } + + else if (cmp == 0) /* duplicates not allowed */ + return NULL; + } + + item->next = NULL; + curr->next = item; + + return item; +} + +pitem *pqueue_peek(pqueue *pq) +{ + return pq->items; +} + +pitem *pqueue_pop(pqueue *pq) +{ + pitem *item = pq->items; + + if (pq->items != NULL) + pq->items = pq->items->next; + + return item; +} + +pitem *pqueue_find(pqueue *pq, unsigned char *prio64be) +{ + pitem *next; + pitem *found = NULL; + + if (pq->items == NULL) + return NULL; + + for (next = pq->items; next->next != NULL; next = next->next) { + if (memcmp(next->priority, prio64be, 8) == 0) { + found = next; + break; + } + } + + /* check the one last node */ + if (memcmp(next->priority, prio64be, 8) == 0) + found = next; + + if (!found) + return NULL; + + return found; +} + +pitem *pqueue_iterator(pqueue *pq) +{ + return pqueue_peek(pq); +} + +pitem *pqueue_next(piterator *item) +{ + pitem *ret; + + if (item == NULL || *item == NULL) + return NULL; + + /* *item != NULL */ + ret = *item; + *item = (*item)->next; + + return ret; +} + +size_t pqueue_size(pqueue *pq) +{ + pitem *item = pq->items; + size_t count = 0; + + while (item != NULL) { + count++; + item = item->next; + } + return count; +} diff --git a/ssl/record/README b/ssl/record/README new file mode 100644 index 000000000000..987e9fd305d9 --- /dev/null +++ b/ssl/record/README @@ -0,0 +1,74 @@ +Record Layer Design +=================== + +This file provides some guidance on the thinking behind the design of the +record layer code to aid future maintenance. + +The record layer is divided into a number of components. At the time of writing +there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each +of these components is defined by: +1) A struct definition of the same name as the component +2) A set of source files that define the functions for that component +3) A set of accessor macros + +All struct definitions are in record.h. The functions and macros are either +defined in record.h or record_locl.h dependent on whether they are intended to +be private to the record layer, or whether they form part of the API to the rest +of libssl. + +The source files map to components as follows: + +dtls1_bitmap.c -> DTLS1_BITMAP component +ssl3_buffer.c -> SSL3_BUFFER component +ssl3_record.c -> SSL3_RECORD component +rec_layer_s3.c, rec_layer_d1.c -> RECORD_LAYER component + +The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified +interface to the record layer for the rest of libssl. The other 3 components are +entirely private to the record layer and therefore should never be accessed +directly by libssl. + +Any component can directly access its own members - they are private to that +component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct +without using a macro. No component can directly access the members of another +component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to +directly access its members. Instead components use accessor macros, so if code +in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the +RECORD_LAYER_* macros. + +Conceptually it looks like this: + + libssl + | +---------------------------|-----record.h-------------------------------------- + | + _______V______________ + | | + | RECORD_LAYER | + | | + | rec_layer_s3.c | + | ^ | + | _________|__________ | + || || + || DTLS1_RECORD_LAYER || + || || + || rec_layer_d1.c || + ||____________________|| + |______________________| + record_locl.h ^ ^ ^ + _________________| | |_________________ + | | | + _____V_________ ______V________ _______V________ + | | | | | | + | SSL3_BUFFER | | SSL3_RECORD | | DTLS1_BITMAP | + | |--->| | | | + | ssl3_buffer.c | | ssl3_record.c | | dtls1_bitmap.c | + |_______________| |_______________| |________________| + + +The two RECORD_LAYER source files build on each other, i.e. +the main one is rec_layer_s3.c which provides the core SSL/TLS layer. The second +one is rec_layer_d1.c which builds off of the SSL/TLS code to provide DTLS +specific capabilities. It uses some DTLS specific RECORD_LAYER component members +which should only be accessed from rec_layer_d1.c. These are held in the +DTLS1_RECORD_LAYER struct. diff --git a/ssl/record/dtls1_bitmap.c b/ssl/record/dtls1_bitmap.c new file mode 100644 index 000000000000..5923c53717c9 --- /dev/null +++ b/ssl/record/dtls1_bitmap.c @@ -0,0 +1,78 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../ssl_locl.h" +#include "record_locl.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) +{ + int64_t ret; + uint64_t l1, l2; + + n2l8(v1, l1); + n2l8(v2, l2); + + ret = l1 - l2; + + /* We do not permit wrap-around */ + if (l1 > l2 && ret < 0) + return 128; + else if (l2 > l1 && ret > 0) + return -128; + + if (ret > 128) + return 128; + else if (ret < -128) + return -128; + else + return (int)ret; +} + +int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap) +{ + int cmp; + unsigned int shift; + const unsigned char *seq = s->rlayer.read_sequence; + + cmp = satsub64be(seq, bitmap->max_seq_num); + if (cmp > 0) { + SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq); + 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 */ + + SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq); + return 1; +} + +void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap) +{ + int cmp; + unsigned int shift; + const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer); + + 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, SEQ_NUM_SIZE); + } else { + shift = -cmp; + if (shift < sizeof(bitmap->map) * 8) + bitmap->map |= 1UL << shift; + } +} diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c new file mode 100644 index 000000000000..43e1f9895319 --- /dev/null +++ b/ssl/record/rec_layer_d1.c @@ -0,0 +1,1075 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <errno.h> +#include "../ssl_locl.h" +#include <openssl/evp.h> +#include <openssl/buffer.h> +#include "record_locl.h" +#include "../packet_locl.h" +#include "internal/cryptlib.h" + +int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl) +{ + DTLS_RECORD_LAYER *d; + + if ((d = OPENSSL_malloc(sizeof(*d))) == NULL) { + SSLerr(SSL_F_DTLS_RECORD_LAYER_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + + rl->d = d; + + d->unprocessed_rcds.q = pqueue_new(); + d->processed_rcds.q = pqueue_new(); + d->buffered_app_data.q = pqueue_new(); + + if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL + || d->buffered_app_data.q == NULL) { + pqueue_free(d->unprocessed_rcds.q); + pqueue_free(d->processed_rcds.q); + pqueue_free(d->buffered_app_data.q); + OPENSSL_free(d); + rl->d = NULL; + return 0; + } + + return 1; +} + +void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl) +{ + DTLS_RECORD_LAYER_clear(rl); + pqueue_free(rl->d->unprocessed_rcds.q); + pqueue_free(rl->d->processed_rcds.q); + pqueue_free(rl->d->buffered_app_data.q); + OPENSSL_free(rl->d); + rl->d = NULL; +} + +void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) +{ + DTLS_RECORD_LAYER *d; + pitem *item = NULL; + DTLS1_RECORD_DATA *rdata; + pqueue *unprocessed_rcds; + pqueue *processed_rcds; + pqueue *buffered_app_data; + + d = rl->d; + + while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(item->data); + pitem_free(item); + } + + while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(item->data); + pitem_free(item); + } + + while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(item->data); + pitem_free(item); + } + + unprocessed_rcds = d->unprocessed_rcds.q; + processed_rcds = d->processed_rcds.q; + buffered_app_data = d->buffered_app_data.q; + memset(d, 0, sizeof(*d)); + d->unprocessed_rcds.q = unprocessed_rcds; + d->processed_rcds.q = processed_rcds; + d->buffered_app_data.q = buffered_app_data; +} + +void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e) +{ + if (e == rl->d->w_epoch - 1) { + memcpy(rl->d->curr_write_sequence, + rl->write_sequence, sizeof(rl->write_sequence)); + memcpy(rl->write_sequence, + rl->d->last_write_sequence, sizeof(rl->write_sequence)); + } else if (e == rl->d->w_epoch + 1) { + memcpy(rl->d->last_write_sequence, + rl->write_sequence, sizeof(unsigned char[8])); + memcpy(rl->write_sequence, + rl->d->curr_write_sequence, sizeof(rl->write_sequence)); + } + rl->d->w_epoch = e; +} + +void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq) +{ + memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE); +} + +/* 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; + + SSL3_BUFFER_release(&s->rlayer.rbuf); + + s->rlayer.packet = rdata->packet; + s->rlayer.packet_length = rdata->packet_length; + memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER)); + memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD)); + + /* Set proper sequence number for mac calculation */ + memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6); + + return 1; +} + +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(*rdata)); + item = pitem_new(priority, rdata); + if (rdata == NULL || item == NULL) { + OPENSSL_free(rdata); + pitem_free(item); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + + rdata->packet = s->rlayer.packet; + rdata->packet_length = s->rlayer.packet_length; + memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER)); + memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD)); + + item->data = rdata; + +#ifndef OPENSSL_NO_SCTP + /* Store bio_dgram_sctp_rcvinfo struct */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && + (SSL_get_state(s) == TLS_ST_SR_FINISHED + || SSL_get_state(s) == TLS_ST_CR_FINISHED)) { + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, + sizeof(rdata->recordinfo), &rdata->recordinfo); + } +#endif + + s->rlayer.packet = NULL; + s->rlayer.packet_length = 0; + memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf)); + memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec)); + + if (!ssl3_setup_buffers(s)) { + /* SSLfatal() already called */ + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(rdata); + pitem_free(item); + return -1; + } + + /* insert should not fail, since duplicates are dropped */ + if (pqueue_insert(queue->q, item) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD, + ERR_R_INTERNAL_ERROR); + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(rdata); + pitem_free(item); + return -1; + } + + return 1; +} + +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)->rlayer.d->unprocessed_rcds)) + +int dtls1_process_buffered_records(SSL *s) +{ + pitem *item; + SSL3_BUFFER *rb; + SSL3_RECORD *rr; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int replayok = 1; + + item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q); + if (item) { + /* Check if epoch is current. */ + if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch) + return 1; /* Nothing to do. */ + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + + rb = RECORD_LAYER_get_rbuf(&s->rlayer); + + if (SSL3_BUFFER_get_left(rb) > 0) { + /* + * We've still got data from the current packet to read. There could + * be a record from the new epoch in it - so don't overwrite it + * with the unprocessed records yet (we'll do it when we've + * finished reading the current packet). + */ + return 1; + } + + /* Process all the records. */ + while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) { + dtls1_get_unprocessed_record(s); + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* + * Should not happen. This will only ever be NULL when the + * current record is from a different epoch. But that cannot + * be the case because we already checked the epoch above + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_SCTP + /* Only do replay check if no SCTP bio */ + if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) +#endif + { + /* + * Check whether this is a repeat, or aged record. We did this + * check once already when we first received the record - but + * we might have updated the window since then due to + * records we subsequently processed. + */ + replayok = dtls1_record_replay_check(s, bitmap); + } + + if (!replayok || !dtls1_process_record(s, bitmap)) { + if (ossl_statem_in_error(s)) { + /* dtls1_process_record called SSLfatal() */ + return -1; + } + /* dump this record */ + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); + continue; + } + + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), + SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) { + /* SSLfatal() already called */ + return 0; + } + } + } + + /* + * sync epoch numbers once all the unprocessed records have been + * processed + */ + s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch; + s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1; + + 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) or renegotiation requests. ChangeCipherSpec + * messages are treated as if they were handshake messages *if* the |recd_type| + * argument is non NULL. + * 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, int *recvd_type, unsigned char *buf, + size_t len, int peek, size_t *readbytes) +{ + int i, j, iret; + size_t n; + SSL3_RECORD *rr; + void (*cb) (const SSL *ssl, int type2, int val) = NULL; + + if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) { + /* Not initialized yet */ + if (!ssl3_setup_buffers(s)) { + /* SSLfatal() already called */ + return -1; + } + } + + if ((type && (type != SSL3_RT_APPLICATION_DATA) && + (type != SSL3_RT_HANDSHAKE)) || + (peek && (type != SSL3_RT_APPLICATION_DATA))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) { + /* type == SSL3_RT_APPLICATION_DATA */ + i = s->handshake_func(s); + /* SSLfatal() already called if appropriate */ + if (i < 0) + return i; + if (i == 0) + 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->rlayer.rrec; + + /* + * We are not handshaking and have no data yet, so process data buffered + * during the last handshake in advance, if any. + */ + if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) { + pitem *item; + item = pqueue_pop(s->rlayer.d->buffered_app_data.q); + if (item) { +#ifndef OPENSSL_NO_SCTP + /* Restore bio_dgram_sctp_rcvinfo struct */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s))) { + DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data; + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, + sizeof(rdata->recordinfo), &rdata->recordinfo); + } +#endif + + dtls1_copy_record(s, item); + + OPENSSL_free(item->data); + pitem_free(item); + } + } + + /* Check for timeout */ + if (dtls1_handle_timeout(s) > 0) { + goto start; + } else if (ossl_statem_in_error(s)) { + /* dtls1_handle_timeout() has failed with a fatal error */ + return -1; + } + + /* get new packet if necessary */ + if ((SSL3_RECORD_get_length(rr) == 0) + || (s->rlayer.rstate == SSL_ST_READ_BODY)) { + RECORD_LAYER_set_numrpipes(&s->rlayer, 0); + iret = dtls1_get_record(s); + if (iret <= 0) { + iret = dtls1_read_failed(s, iret); + /* + * Anything other than a timeout is an error. SSLfatal() already + * called if appropriate. + */ + if (iret <= 0) + return iret; + else + goto start; + } + RECORD_LAYER_set_numrpipes(&s->rlayer, 1); + } + + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT + && SSL3_RECORD_get_length(rr) != 0) + s->rlayer.alert_count = 0; + + if (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE + && SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC + && !SSL_in_init(s) + && (s->d1->next_timeout.tv_sec != 0 + || s->d1->next_timeout.tv_usec != 0)) { + /* + * The timer is still running but we've received something that isn't + * handshake data - so the peer must have finished processing our + * last handshake flight. Stop the timer. + */ + dtls1_stop_timer(s); + } + + /* 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 */ + && (SSL3_RECORD_get_type(rr) != 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. + */ + if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), + SSL3_RECORD_get_seq_num(rr)) < 0) { + /* SSLfatal() already called */ + return -1; + } + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + goto start; + } + + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode) + */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + s->rwstate = SSL_NOTHING; + return 0; + } + + if (type == SSL3_RECORD_get_type(rr) + || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) { + /* + * SSL3_RT_APPLICATION_DATA or + * SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC + */ + /* + * 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)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_APP_DATA_IN_HANDSHAKE); + return -1; + } + + if (recvd_type != NULL) + *recvd_type = SSL3_RECORD_get_type(rr); + + if (len == 0) { + /* + * Mark a zero length record as read. This ensures multiple calls to + * SSL_read() with a zero length buffer will eventually cause + * SSL_pending() to report data as being available. + */ + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + return 0; + } + + if (len > SSL3_RECORD_get_length(rr)) + n = SSL3_RECORD_get_length(rr); + else + n = len; + + memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n); + if (peek) { + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + } else { + SSL3_RECORD_sub_length(rr, n); + SSL3_RECORD_add_off(rr, n); + if (SSL3_RECORD_get_length(rr) == 0) { + s->rlayer.rstate = SSL_ST_READ_HEADER; + SSL3_RECORD_set_off(rr, 0); + SSL3_RECORD_set_read(rr); + } + } +#ifndef OPENSSL_NO_SCTP + /* + * We might had to delay a close_notify alert because of reordered + * app data. If there was an alert and there is no message to read + * anymore, finally set shutdown. + */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && + s->d1->shutdown_received + && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } +#endif + *readbytes = n; + return 1; + } + + /* + * If we get here, then type != rr->type; if we have a handshake message, + * then it was unexpected (Hello Request or Client Hello). + */ + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { + unsigned int alert_level, alert_descr; + unsigned char *alert_bytes = SSL3_RECORD_get_data(rr) + + SSL3_RECORD_get_off(rr); + PACKET alert; + + if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr)) + || !PACKET_get_1(&alert, &alert_level) + || !PACKET_get_1(&alert, &alert_descr) + || PACKET_remaining(&alert) != 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_INVALID_ALERT); + return -1; + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 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 == SSL3_AL_WARNING) { + s->s3->warn_alert = alert_descr; + SSL3_RECORD_set_read(rr); + + s->rlayer.alert_count++; + if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_TOO_MANY_WARN_ALERTS); + return -1; + } + + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { +#ifndef OPENSSL_NO_SCTP + /* + * With SCTP and streams the socket may deliver app data + * after a close_notify alert. We have to check this first so + * that nothing gets discarded. + */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && + BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { + s->d1->shutdown_received = 1; + s->rwstate = SSL_READING; + BIO_clear_retry_flags(SSL_get_rbio(s)); + BIO_set_retry_read(SSL_get_rbio(s)); + return -1; + } +#endif + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } + } else if (alert_level == SSL3_AL_FATAL) { + char tmp[16]; + + s->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + SSLfatal(s, SSL_AD_NO_ALERT, 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; + SSL3_RECORD_set_read(rr); + SSL_CTX_remove_session(s->session_ctx, s->session); + return 0; + } else { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_READ_BYTES, + SSL_R_UNKNOWN_ALERT_TYPE); + return -1; + } + + goto start; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a + * shutdown */ + s->rwstate = SSL_NOTHING; + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + return 0; + } + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) { + /* + * We can't process a CCS now, because previous handshake messages + * are still missing, so just drop it. + */ + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + goto start; + } + + /* + * Unexpected handshake message (Client Hello, or protocol violation) + */ + if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) && + !ossl_statem_get_in_handshake(s)) { + struct hm_header_st msg_hdr; + + /* + * This may just be a stale retransmit. Also sanity check that we have + * at least enough record bytes for a message header + */ + if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch + || SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) { + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + goto start; + } + + dtls1_get_message_header(rr->data, &msg_hdr); + + /* + * 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) { + if (dtls1_check_timeout_num(s) < 0) { + /* SSLfatal) already called */ + return -1; + } + + if (dtls1_retransmit_buffered_messages(s) <= 0) { + /* Fail if we encountered a fatal error */ + if (ossl_statem_in_error(s)) + return -1; + } + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { + /* no read-ahead left? */ + BIO *bio; + + s->rwstate = SSL_READING; + bio = SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return -1; + } + } + goto start; + } + + /* + * To get here we must be trying to read app data but found handshake + * data. But if we're trying to read app data, and we're not in init + * (which is tested for at the top of this function) then init must be + * finished + */ + if (!ossl_assert(SSL_is_init_finished(s))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + /* We found handshake data, so we're going back into init */ + ossl_statem_set_in_init(s, 1); + + i = s->handshake_func(s); + /* SSLfatal() called if appropriate */ + if (i < 0) + return i; + if (i == 0) + return -1; + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 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 (SSL3_RECORD_get_type(rr)) { + default: + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_UNEXPECTED_RECORD); + return -1; + 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 ossl_statem_get_in_handshake(s) is true, but + * that should not happen when type != rr->type + */ + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + 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) && + ossl_statem_app_data_allowed(s)) { + s->s3->in_read_app_data = 2; + return -1; + } else { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_UNEXPECTED_RECORD); + return -1; + } + } + /* not reached */ +} + +/* + * 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, size_t len, + size_t *written) +{ + int i; + + if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_WRITE_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + s->rwstate = SSL_NOTHING; + i = do_dtls1_write(s, type, buf, len, 0, written); + return i; +} + +int do_dtls1_write(SSL *s, int type, const unsigned char *buf, + size_t len, int create_empty_fragment, size_t *written) +{ + unsigned char *p, *pseq; + int i, mac_size, clear = 0; + size_t prefix_len = 0; + int eivlen; + SSL3_RECORD wr; + SSL3_BUFFER *wb; + SSL_SESSION *sess; + + wb = &s->rlayer.wbuf[0]; + + /* + * first check if there is a SSL3_BUFFER still being written out. This + * will happen with non blocking IO + */ + if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* 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; + + if (len > ssl_get_max_send_fragment(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE); + return 0; + } + + 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) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE); + return -1; + } + } + + p = SSL3_BUFFER_get_buf(wb) + prefix_len; + + /* write the header */ + + *(p++) = type & 0xff; + SSL3_RECORD_set_type(&wr, type); + /* + * Special case: for hello verify request, client version 1.0 and we + * haven't decided which version to use yet send back using version 1.0 + * header: otherwise some clients will ignore it. + */ + if (s->method->version == DTLS_ANY_VERSION && + s->max_proto_version != DTLS1_BAD_VER) { + *(p++) = DTLS1_VERSION >> 8; + *(p++) = DTLS1_VERSION & 0xff; + } else { + *(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; + + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx) { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) { + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) + eivlen = 0; + } + /* Need explicit part of IV for GCM mode */ + else if (mode == EVP_CIPH_GCM_MODE) + eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + else if (mode == EVP_CIPH_CCM_MODE) + eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; + else + eivlen = 0; + } else + eivlen = 0; + + /* lets setup the record stuff. */ + SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */ + SSL3_RECORD_set_length(&wr, len); + SSL3_RECORD_set_input(&wr, (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, &wr)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + SSL_R_COMPRESSION_FAILURE); + return -1; + } + } else { + memcpy(SSL3_RECORD_get_data(&wr), SSL3_RECORD_get_input(&wr), + SSL3_RECORD_get_length(&wr)); + SSL3_RECORD_reset_input(&wr); + } + + /* + * 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 (!SSL_WRITE_ETM(s) && mac_size != 0) { + if (!s->method->ssl3_enc->mac(s, &wr, + &(p[SSL3_RECORD_get_length(&wr) + eivlen]), + 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + return -1; + } + SSL3_RECORD_add_length(&wr, mac_size); + } + + /* this is true regardless of mac size */ + SSL3_RECORD_set_data(&wr, p); + SSL3_RECORD_reset_input(&wr); + + if (eivlen) + SSL3_RECORD_add_length(&wr, eivlen); + + if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1) { + if (!ossl_statem_in_error(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + } + return -1; + } + + if (SSL_WRITE_ETM(s) && mac_size != 0) { + if (!s->method->ssl3_enc->mac(s, &wr, + &(p[SSL3_RECORD_get_length(&wr)]), 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + return -1; + } + SSL3_RECORD_add_length(&wr, mac_size); + } + + /* record length after mac and block padding */ + + /* there's only one epoch between handshake and app data */ + + s2n(s->rlayer.d->w_epoch, pseq); + + memcpy(pseq, &(s->rlayer.write_sequence[2]), 6); + pseq += 6; + s2n(SSL3_RECORD_get_length(&wr), pseq); + + if (s->msg_callback) + s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + + /* + * we should now have wr.data pointing to the encrypted data, which is + * wr->length long + */ + SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */ + SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH); + + ssl3_record_sequence_update(&(s->rlayer.write_sequence[0])); + + if (create_empty_fragment) { + /* + * we are in a recursive call; just return the length, don't write + * out anything here + */ + *written = wr.length; + return 1; + } + + /* now let's set up wb */ + SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(&wr)); + SSL3_BUFFER_set_offset(wb, 0); + + /* + * memorize arguments so that ssl3_write_pending can detect bad write + * retries later + */ + s->rlayer.wpend_tot = len; + s->rlayer.wpend_buf = buf; + s->rlayer.wpend_type = type; + s->rlayer.wpend_ret = len; + + /* we now just need to write the buffer. Calls SSLfatal() as required. */ + return ssl3_write_pending(s, type, buf, len, written); +} + +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->rlayer.d->r_epoch) + return &s->rlayer.d->bitmap; + + /* + * Only HM and ALERT messages can be from the next epoch and only if we + * have already processed all of the unprocessed records from the last + * epoch + */ + else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) && + s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch && + (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { + *is_next_epoch = 1; + return &s->rlayer.d->next_bitmap; + } + + return NULL; +} + +void dtls1_reset_seq_numbers(SSL *s, int rw) +{ + unsigned char *seq; + unsigned int seq_bytes = sizeof(s->rlayer.read_sequence); + + if (rw & SSL3_CC_READ) { + seq = s->rlayer.read_sequence; + s->rlayer.d->r_epoch++; + memcpy(&s->rlayer.d->bitmap, &s->rlayer.d->next_bitmap, + sizeof(s->rlayer.d->bitmap)); + memset(&s->rlayer.d->next_bitmap, 0, sizeof(s->rlayer.d->next_bitmap)); + + /* + * We must not use any buffered messages received from the previous + * epoch + */ + dtls1_clear_received_buffer(s); + } else { + seq = s->rlayer.write_sequence; + memcpy(s->rlayer.d->last_write_sequence, seq, + sizeof(s->rlayer.write_sequence)); + s->rlayer.d->w_epoch++; + } + + memset(seq, 0, seq_bytes); +} diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c new file mode 100644 index 000000000000..6d495715b22a --- /dev/null +++ b/ssl/record/rec_layer_s3.c @@ -0,0 +1,1763 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <limits.h> +#include <errno.h> +#include "../ssl_locl.h" +#include <openssl/evp.h> +#include <openssl/buffer.h> +#include <openssl/rand.h> +#include "record_locl.h" +#include "../packet_locl.h" + +#if defined(OPENSSL_SMALL_FOOTPRINT) || \ + !( defined(AES_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) ) \ + ) +# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0 +#endif + +void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s) +{ + rl->s = s; + RECORD_LAYER_set_first_record(&s->rlayer); + SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES); +} + +void RECORD_LAYER_clear(RECORD_LAYER *rl) +{ + rl->rstate = SSL_ST_READ_HEADER; + + /* + * Do I need to clear read_ahead? As far as I can tell read_ahead did not + * previously get reset by SSL_clear...so I'll keep it that way..but is + * that right? + */ + + rl->packet = NULL; + rl->packet_length = 0; + rl->wnum = 0; + memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment)); + rl->handshake_fragment_len = 0; + rl->wpend_tot = 0; + rl->wpend_type = 0; + rl->wpend_ret = 0; + rl->wpend_buf = NULL; + + SSL3_BUFFER_clear(&rl->rbuf); + ssl3_release_write_buffer(rl->s); + rl->numrpipes = 0; + SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES); + + RECORD_LAYER_reset_read_sequence(rl); + RECORD_LAYER_reset_write_sequence(rl); + + if (rl->d) + DTLS_RECORD_LAYER_clear(rl); +} + +void RECORD_LAYER_release(RECORD_LAYER *rl) +{ + if (SSL3_BUFFER_is_initialised(&rl->rbuf)) + ssl3_release_read_buffer(rl->s); + if (rl->numwpipes > 0) + ssl3_release_write_buffer(rl->s); + SSL3_RECORD_release(rl->rrec, SSL_MAX_PIPELINES); +} + +/* Checks if we have unprocessed read ahead data pending */ +int RECORD_LAYER_read_pending(const RECORD_LAYER *rl) +{ + return SSL3_BUFFER_get_left(&rl->rbuf) != 0; +} + +/* Checks if we have decrypted unread record data pending */ +int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl) +{ + size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl); + const SSL3_RECORD *rr = rl->rrec; + + while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec])) + curr_rec++; + + return curr_rec < num_recs; +} + +int RECORD_LAYER_write_pending(const RECORD_LAYER *rl) +{ + return (rl->numwpipes > 0) + && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes - 1]) != 0; +} + +void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl) +{ + memset(rl->read_sequence, 0, sizeof(rl->read_sequence)); +} + +void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl) +{ + memset(rl->write_sequence, 0, sizeof(rl->write_sequence)); +} + +size_t ssl3_pending(const SSL *s) +{ + size_t i, num = 0; + + if (s->rlayer.rstate == SSL_ST_READ_BODY) + return 0; + + for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) { + if (SSL3_RECORD_get_type(&s->rlayer.rrec[i]) + != SSL3_RT_APPLICATION_DATA) + return 0; + num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]); + } + + return num; +} + +void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len) +{ + ctx->default_read_buf_len = len; +} + +void SSL_set_default_read_buffer_len(SSL *s, size_t len) +{ + SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&s->rlayer), len); +} + +const char *SSL_rstate_string_long(const SSL *s) +{ + switch (s->rlayer.rstate) { + case SSL_ST_READ_HEADER: + return "read header"; + case SSL_ST_READ_BODY: + return "read body"; + case SSL_ST_READ_DONE: + return "read done"; + default: + return "unknown"; + } +} + +const char *SSL_rstate_string(const SSL *s) +{ + switch (s->rlayer.rstate) { + case SSL_ST_READ_HEADER: + return "RH"; + case SSL_ST_READ_BODY: + return "RB"; + case SSL_ST_READ_DONE: + return "RD"; + default: + return "unknown"; + } +} + +/* + * Return values are as per SSL_read() + */ +int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, + size_t *readbytes) +{ + /* + * 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->rlayer.read_ahead is set, 'max' bytes may be stored in rbuf [plus + * s->packet_length bytes if extend == 1].) + * if clearold == 1, move the packet to the start of the buffer; if + * clearold == 0 then leave any old packets where they were + */ + size_t len, left, align = 0; + unsigned char *pkt; + SSL3_BUFFER *rb; + + if (n == 0) + return 0; + + rb = &s->rlayer.rbuf; + if (rb->buf == NULL) + if (!ssl3_setup_read_buffer(s)) { + /* SSLfatal() already called */ + return -1; + } + + left = rb->left; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 + align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#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->rlayer.packet = rb->buf + rb->offset; + s->rlayer.packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } + + len = s->rlayer.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->rlayer.packet != pkt && clearold == 1) { + memmove(pkt, s->rlayer.packet, len + left); + s->rlayer.packet = pkt; + rb->offset = len + align; + } + + /* + * 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_IS_DTLS(s)) { + if (left == 0 && extend) + return 0; + if (left > 0 && n > left) + n = left; + } + + /* if there is enough in the buffer from a previous read, take some */ + if (left >= n) { + s->rlayer.packet_length += n; + rb->left = left - n; + rb->offset += n; + *readbytes = n; + return 1; + } + + /* else we need to read more data */ + + if (n > rb->len - rb->offset) { + /* does not happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N, + ERR_R_INTERNAL_ERROR); + return -1; + } + + /* We always act like read_ahead is set for DTLS */ + if (!s->rlayer.read_ahead && !SSL_IS_DTLS(s)) + /* ignore max parameter */ + max = n; + else { + if (max < n) + max = n; + if (max > rb->len - rb->offset) + max = rb->len - rb->offset; + } + + while (left < n) { + size_t bioread = 0; + int ret; + + /* + * 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; + /* TODO(size_t): Convert this function */ + ret = BIO_read(s->rbio, pkt + len + left, max - left); + if (ret >= 0) + bioread = ret; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N, + SSL_R_READ_BIO_NOT_SET); + ret = -1; + } + + if (ret <= 0) { + rb->left = left; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) + if (len + left == 0) + ssl3_release_read_buffer(s); + return ret; + } + left += bioread; + /* + * 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_IS_DTLS(s)) { + if (n > left) + n = left; /* makes the while condition false */ + } + } + + /* done reading, now the book-keeping */ + rb->offset += n; + rb->left = left - n; + s->rlayer.packet_length += n; + s->rwstate = SSL_NOTHING; + *readbytes = n; + 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_, size_t len, + size_t *written) +{ + const unsigned char *buf = buf_; + size_t tot; + size_t n, max_send_fragment, split_send_fragment, maxpipes; +#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK + size_t nw; +#endif + SSL3_BUFFER *wb = &s->rlayer.wbuf[0]; + int i; + size_t tmpwrit; + + s->rwstate = SSL_NOTHING; + tot = s->rlayer.wnum; + /* + * ensure that if we end up with a smaller value of data to write out + * than the original len from a write which didn't complete for + * non-blocking I/O and also somehow ended up avoiding the check for + * this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be + * possible to end up with (len-tot) as a large number that will then + * promptly send beyond the end of the users buffer ... so we trap and + * report the error in a way the user will notice + */ + if ((len < s->rlayer.wnum) + || ((wb->left != 0) && (len < (s->rlayer.wnum + s->rlayer.wpend_tot)))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES, + SSL_R_BAD_LENGTH); + return -1; + } + + if (s->early_data_state == SSL_EARLY_DATA_WRITING + && !early_data_count_ok(s, len, 0, 1)) { + /* SSLfatal() already called */ + return -1; + } + + s->rlayer.wnum = 0; + + /* + * When writing early data on the server side we could be "in_init" in + * between receiving the EoED and the CF - but we don't want to handle those + * messages yet. + */ + if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s) + && s->early_data_state != SSL_EARLY_DATA_UNAUTH_WRITING) { + i = s->handshake_func(s); + /* SSLfatal() already called */ + if (i < 0) + return i; + if (i == 0) { + 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) { + /* SSLfatal() already called if appropriate */ + i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot, + &tmpwrit); + if (i <= 0) { + /* XXX should we ssl3_release_write_buffer if i<0? */ + s->rlayer.wnum = tot; + return i; + } + tot += tmpwrit; /* this might be last fragment */ + } +#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK + /* + * Depending on platform multi-block can deliver several *times* + * better performance. Downside is that it has to allocate + * jumbo buffer to accommodate up to 8 records, but the + * compromise is considered worthy. + */ + if (type == SSL3_RT_APPLICATION_DATA && + len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) && + s->compress == NULL && s->msg_callback == NULL && + !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) && + EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) { + unsigned char aad[13]; + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; + size_t packlen; + int packleni; + + /* minimize address aliasing conflicts */ + if ((max_send_fragment & 0xfff) == 0) + max_send_fragment -= 512; + + if (tot == 0 || wb->buf == NULL) { /* allocate jumbo buffer */ + ssl3_release_write_buffer(s); + + packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE, + (int)max_send_fragment, NULL); + + if (len >= 8 * max_send_fragment) + packlen *= 8; + else + packlen *= 4; + + if (!ssl3_setup_write_buffer(s, 1, packlen)) { + /* SSLfatal() already called */ + return -1; + } + } else if (tot == len) { /* done? */ + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + *written = tot; + return 1; + } + + n = (len - tot); + for (;;) { + if (n < 4 * max_send_fragment) { + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + break; + } + + if (s->s3->alert_dispatch) { + i = s->method->ssl_dispatch_alert(s); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + s->rlayer.wnum = tot; + return i; + } + } + + if (n >= 8 * max_send_fragment) + nw = max_send_fragment * (mb_param.interleave = 8); + else + nw = max_send_fragment * (mb_param.interleave = 4); + + memcpy(aad, s->rlayer.write_sequence, 8); + aad[8] = type; + aad[9] = (unsigned char)(s->version >> 8); + aad[10] = (unsigned char)(s->version); + aad[11] = 0; + aad[12] = 0; + mb_param.out = NULL; + mb_param.inp = aad; + mb_param.len = nw; + + packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_AAD, + sizeof(mb_param), &mb_param); + packlen = (size_t)packleni; + if (packleni <= 0 || packlen > wb->len) { /* never happens */ + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + break; + } + + mb_param.out = wb->buf; + mb_param.inp = &buf[tot]; + mb_param.len = nw; + + if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, + sizeof(mb_param), &mb_param) <= 0) + return -1; + + s->rlayer.write_sequence[7] += mb_param.interleave; + if (s->rlayer.write_sequence[7] < mb_param.interleave) { + int j = 6; + while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ; + } + + wb->offset = 0; + wb->left = packlen; + + s->rlayer.wpend_tot = nw; + s->rlayer.wpend_buf = &buf[tot]; + s->rlayer.wpend_type = type; + s->rlayer.wpend_ret = nw; + + i = ssl3_write_pending(s, type, &buf[tot], nw, &tmpwrit); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) { + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + } + s->rlayer.wnum = tot; + return i; + } + if (tmpwrit == n) { + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + *written = tot + tmpwrit; + return 1; + } + n -= tmpwrit; + tot += tmpwrit; + } + } else +#endif /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */ + if (tot == len) { /* done? */ + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) + ssl3_release_write_buffer(s); + + *written = tot; + return 1; + } + + n = (len - tot); + + max_send_fragment = ssl_get_max_send_fragment(s); + split_send_fragment = ssl_get_split_send_fragment(s); + /* + * If max_pipelines is 0 then this means "undefined" and we default to + * 1 pipeline. Similarly if the cipher does not support pipelined + * processing then we also only use 1 pipeline, or if we're not using + * explicit IVs + */ + maxpipes = s->max_pipelines; + if (maxpipes > SSL_MAX_PIPELINES) { + /* + * We should have prevented this when we set max_pipelines so we + * shouldn't get here + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + if (maxpipes == 0 + || s->enc_write_ctx == NULL + || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) + & EVP_CIPH_FLAG_PIPELINE) + || !SSL_USE_EXPLICIT_IV(s)) + maxpipes = 1; + if (max_send_fragment == 0 || split_send_fragment == 0 + || split_send_fragment > max_send_fragment) { + /* + * We should have prevented this when we set/get the split and max send + * fragments so we shouldn't get here + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + for (;;) { + size_t pipelens[SSL_MAX_PIPELINES], tmppipelen, remain; + size_t numpipes, j; + + if (n == 0) + numpipes = 1; + else + numpipes = ((n - 1) / split_send_fragment) + 1; + if (numpipes > maxpipes) + numpipes = maxpipes; + + if (n / numpipes >= max_send_fragment) { + /* + * We have enough data to completely fill all available + * pipelines + */ + for (j = 0; j < numpipes; j++) { + pipelens[j] = max_send_fragment; + } + } else { + /* We can partially fill all available pipelines */ + tmppipelen = n / numpipes; + remain = n % numpipes; + for (j = 0; j < numpipes; j++) { + pipelens[j] = tmppipelen; + if (j < remain) + pipelens[j]++; + } + } + + i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0, + &tmpwrit); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + /* XXX should we ssl3_release_write_buffer if i<0? */ + s->rlayer.wnum = tot; + return i; + } + + if (tmpwrit == 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; + + if ((i == (int)n) && s->mode & SSL_MODE_RELEASE_BUFFERS && + !SSL_IS_DTLS(s)) + ssl3_release_write_buffer(s); + + *written = tot + tmpwrit; + return 1; + } + + n -= tmpwrit; + tot += tmpwrit; + } +} + +int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + size_t *pipelens, size_t numpipes, + int create_empty_fragment, size_t *written) +{ + WPACKET pkt[SSL_MAX_PIPELINES]; + SSL3_RECORD wr[SSL_MAX_PIPELINES]; + WPACKET *thispkt; + SSL3_RECORD *thiswr; + unsigned char *recordstart; + int i, mac_size, clear = 0; + size_t prefix_len = 0; + int eivlen = 0; + size_t align = 0; + SSL3_BUFFER *wb; + SSL_SESSION *sess; + size_t totlen = 0, len, wpinited = 0; + size_t j; + + for (j = 0; j < numpipes; j++) + totlen += pipelens[j]; + /* + * first check if there is a SSL3_BUFFER still being written out. This + * will happen with non blocking IO + */ + if (RECORD_LAYER_write_pending(&s->rlayer)) { + /* Calls SSLfatal() as required */ + return ssl3_write_pending(s, type, buf, totlen, written); + } + + /* 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) { + /* SSLfatal() already called if appropriate */ + return i; + } + /* if it went, fall through and send more stuff */ + } + + if (s->rlayer.numwpipes < numpipes) { + if (!ssl3_setup_write_buffer(s, numpipes, 0)) { + /* SSLfatal() already called */ + return -1; + } + } + + if (totlen == 0 && !create_empty_fragment) + return 0; + + sess = s->session; + + if ((sess == NULL) || + (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL)) { + clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */ + mac_size = 0; + } else { + /* TODO(siz_t): Convert me */ + mac_size = EVP_MD_CTX_size(s->write_hash); + if (mac_size < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + 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) + */ + size_t tmppipelen = 0; + int ret; + + ret = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1, &prefix_len); + if (ret <= 0) { + /* SSLfatal() already called if appropriate */ + goto err; + } + + if (prefix_len > + (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) { + /* insufficient space */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + s->s3->empty_fragment_done = 1; + } + + if (create_empty_fragment) { + wb = &s->rlayer.wbuf[0]; +#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 pretend we simply have two headers. + */ + align = (size_t)SSL3_BUFFER_get_buf(wb) + 2 * SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + SSL3_BUFFER_set_offset(wb, align); + if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0) + || !WPACKET_allocate_bytes(&pkt[0], align, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + wpinited = 1; + } else if (prefix_len) { + wb = &s->rlayer.wbuf[0]; + if (!WPACKET_init_static_len(&pkt[0], + SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0) + || !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb) + + prefix_len, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + wpinited = 1; + } else { + for (j = 0; j < numpipes; j++) { + thispkt = &pkt[j]; + + wb = &s->rlayer.wbuf[j]; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 + align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + SSL3_BUFFER_set_offset(wb, align); + if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0) + || !WPACKET_allocate_bytes(thispkt, align, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + wpinited++; + } + } + + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) { + /* TODO(size_t): Convert me */ + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) + eivlen = 0; + } else if (mode == EVP_CIPH_GCM_MODE) { + /* Need explicit part of IV for GCM mode */ + eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + } else if (mode == EVP_CIPH_CCM_MODE) { + eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; + } + } + + totlen = 0; + /* Clear our SSL3_RECORD structures */ + memset(wr, 0, sizeof(wr)); + for (j = 0; j < numpipes; j++) { + unsigned int version = (s->version == TLS1_3_VERSION) ? TLS1_2_VERSION + : s->version; + unsigned char *compressdata = NULL; + size_t maxcomplen; + unsigned int rectype; + + thispkt = &pkt[j]; + thiswr = &wr[j]; + + /* + * In TLSv1.3, once encrypting, we always use application data for the + * record type + */ + if (SSL_TREAT_AS_TLS13(s) + && s->enc_write_ctx != NULL + && (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS + || type != SSL3_RT_ALERT)) + rectype = SSL3_RT_APPLICATION_DATA; + else + rectype = type; + SSL3_RECORD_set_type(thiswr, rectype); + + /* + * Some servers hang if initial client hello is larger than 256 bytes + * and record version number > TLS 1.0 + */ + if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO + && !s->renegotiate + && TLS1_get_version(s) > TLS1_VERSION + && s->hello_retry_request == SSL_HRR_NONE) + version = TLS1_VERSION; + SSL3_RECORD_set_rec_version(thiswr, version); + + maxcomplen = pipelens[j]; + if (s->compress != NULL) + maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD; + + /* write the header */ + if (!WPACKET_put_bytes_u8(thispkt, rectype) + || !WPACKET_put_bytes_u16(thispkt, version) + || !WPACKET_start_sub_packet_u16(thispkt) + || (eivlen > 0 + && !WPACKET_allocate_bytes(thispkt, eivlen, NULL)) + || (maxcomplen > 0 + && !WPACKET_reserve_bytes(thispkt, maxcomplen, + &compressdata))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* lets setup the record stuff. */ + SSL3_RECORD_set_data(thiswr, compressdata); + SSL3_RECORD_set_length(thiswr, pipelens[j]); + SSL3_RECORD_set_input(thiswr, (unsigned char *)&buf[totlen]); + totlen += pipelens[j]; + + /* + * we now 'read' from thiswr->input, thiswr->length bytes into + * thiswr->data + */ + + /* first we compress */ + if (s->compress != NULL) { + if (!ssl3_do_compress(s, thiswr) + || !WPACKET_allocate_bytes(thispkt, thiswr->length, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + SSL_R_COMPRESSION_FAILURE); + goto err; + } + } else { + if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_reset_input(&wr[j]); + } + + if (SSL_TREAT_AS_TLS13(s) + && s->enc_write_ctx != NULL + && (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS + || type != SSL3_RT_ALERT)) { + size_t rlen, max_send_fragment; + + if (!WPACKET_put_bytes_u8(thispkt, type)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_add_length(thiswr, 1); + + /* Add TLS1.3 padding */ + max_send_fragment = ssl_get_max_send_fragment(s); + rlen = SSL3_RECORD_get_length(thiswr); + if (rlen < max_send_fragment) { + size_t padding = 0; + size_t max_padding = max_send_fragment - rlen; + if (s->record_padding_cb != NULL) { + padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg); + } else if (s->block_padding > 0) { + size_t mask = s->block_padding - 1; + size_t remainder; + + /* optimize for power of 2 */ + if ((s->block_padding & mask) == 0) + remainder = rlen & mask; + else + remainder = rlen % s->block_padding; + /* don't want to add a block of padding if we don't have to */ + if (remainder == 0) + padding = 0; + else + padding = s->block_padding - remainder; + } + if (padding > 0) { + /* do not allow the record to exceed max plaintext length */ + if (padding > max_padding) + padding = max_padding; + if (!WPACKET_memset(thispkt, 0, padding)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_add_length(thiswr, padding); + } + } + } + + /* + * we should still have the output to thiswr->data and the input from + * wr->input. Length should be thiswr->length. thiswr->data still points + * in the wb->buf + */ + + if (!SSL_WRITE_ETM(s) && mac_size != 0) { + unsigned char *mac; + + if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac) + || !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + /* + * Reserve some bytes for any growth that may occur during encryption. + * This will be at most one cipher block or the tag length if using + * AEAD. SSL_RT_MAX_CIPHER_BLOCK_SIZE covers either case. + */ + if (!WPACKET_reserve_bytes(thispkt, SSL_RT_MAX_CIPHER_BLOCK_SIZE, + NULL) + /* + * We also need next the amount of bytes written to this + * sub-packet + */ + || !WPACKET_get_length(thispkt, &len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Get a pointer to the start of this record excluding header */ + recordstart = WPACKET_get_curr(thispkt) - len; + + SSL3_RECORD_set_data(thiswr, recordstart); + SSL3_RECORD_reset_input(thiswr); + SSL3_RECORD_set_length(thiswr, len); + } + + if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) { + /* + * We haven't actually negotiated the version yet, but we're trying to + * send early data - so we need to use the tls13enc function. + */ + if (tls13_enc(s, wr, numpipes, 1) < 1) { + if (!ossl_statem_in_error(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + } + goto err; + } + } else { + if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) { + if (!ossl_statem_in_error(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + } + goto err; + } + } + + for (j = 0; j < numpipes; j++) { + size_t origlen; + + thispkt = &pkt[j]; + thiswr = &wr[j]; + + /* Allocate bytes for the encryption overhead */ + if (!WPACKET_get_length(thispkt, &origlen) + /* Encryption should never shrink the data! */ + || origlen > thiswr->length + || (thiswr->length > origlen + && !WPACKET_allocate_bytes(thispkt, + thiswr->length - origlen, NULL))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + if (SSL_WRITE_ETM(s) && mac_size != 0) { + unsigned char *mac; + + if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac) + || !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_add_length(thiswr, mac_size); + } + + if (!WPACKET_get_length(thispkt, &len) + || !WPACKET_close(thispkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (s->msg_callback) { + recordstart = WPACKET_get_curr(thispkt) - len + - SSL3_RT_HEADER_LENGTH; + s->msg_callback(1, 0, SSL3_RT_HEADER, recordstart, + SSL3_RT_HEADER_LENGTH, s, + s->msg_callback_arg); + + if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) { + unsigned char ctype = type; + + s->msg_callback(1, s->version, SSL3_RT_INNER_CONTENT_TYPE, + &ctype, 1, s, s->msg_callback_arg); + } + } + + if (!WPACKET_finish(thispkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * we should now have thiswr->data pointing to the encrypted data, which + * is thiswr->length long + */ + SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for + * debugging */ + SSL3_RECORD_add_length(thiswr, SSL3_RT_HEADER_LENGTH); + + if (create_empty_fragment) { + /* + * we are in a recursive call; just return the length, don't write + * out anything here + */ + if (j > 0) { + /* We should never be pipelining an empty fragment!! */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + *written = SSL3_RECORD_get_length(thiswr); + return 1; + } + + /* now let's set up wb */ + SSL3_BUFFER_set_left(&s->rlayer.wbuf[j], + prefix_len + SSL3_RECORD_get_length(thiswr)); + } + + /* + * memorize arguments so that ssl3_write_pending can detect bad write + * retries later + */ + s->rlayer.wpend_tot = totlen; + s->rlayer.wpend_buf = buf; + s->rlayer.wpend_type = type; + s->rlayer.wpend_ret = totlen; + + /* we now just need to write the buffer */ + return ssl3_write_pending(s, type, buf, totlen, written); + err: + for (j = 0; j < wpinited; j++) + WPACKET_cleanup(&pkt[j]); + return -1; +} + +/* if s->s3->wbuf.left != 0, we need to call this + * + * Return values are as per SSL_write() + */ +int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len, + size_t *written) +{ + int i; + SSL3_BUFFER *wb = s->rlayer.wbuf; + size_t currbuf = 0; + size_t tmpwrit = 0; + + if ((s->rlayer.wpend_tot > len) + || (!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) + && (s->rlayer.wpend_buf != buf)) + || (s->rlayer.wpend_type != type)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING, + SSL_R_BAD_WRITE_RETRY); + return -1; + } + + for (;;) { + /* Loop until we find a buffer we haven't written out yet */ + if (SSL3_BUFFER_get_left(&wb[currbuf]) == 0 + && currbuf < s->rlayer.numwpipes - 1) { + currbuf++; + continue; + } + clear_sys_error(); + if (s->wbio != NULL) { + s->rwstate = SSL_WRITING; + /* TODO(size_t): Convert this call */ + i = BIO_write(s->wbio, (char *) + &(SSL3_BUFFER_get_buf(&wb[currbuf]) + [SSL3_BUFFER_get_offset(&wb[currbuf])]), + (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf])); + if (i >= 0) + tmpwrit = i; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING, + SSL_R_BIO_NOT_SET); + i = -1; + } + if (i > 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) { + SSL3_BUFFER_set_left(&wb[currbuf], 0); + SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit); + if (currbuf + 1 < s->rlayer.numwpipes) + continue; + s->rwstate = SSL_NOTHING; + *written = s->rlayer.wpend_ret; + return 1; + } else if (i <= 0) { + if (SSL_IS_DTLS(s)) { + /* + * For DTLS, just drop it. That's kind of the whole point in + * using a datagram service + */ + SSL3_BUFFER_set_left(&wb[currbuf], 0); + } + return i; + } + SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit); + SSL3_BUFFER_sub_left(&wb[currbuf], tmpwrit); + } +} + +/*- + * 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) or renegotiation requests. ChangeCipherSpec + * messages are treated as if they were handshake messages *if* the |recd_type| + * argument is non NULL. + * 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, int *recvd_type, unsigned char *buf, + size_t len, int peek, size_t *readbytes) +{ + int i, j, ret; + size_t n, curr_rec, num_recs, totalbytes; + SSL3_RECORD *rr; + SSL3_BUFFER *rbuf; + void (*cb) (const SSL *ssl, int type2, int val) = NULL; + int is_tls13 = SSL_IS_TLS13(s); + + rbuf = &s->rlayer.rbuf; + + if (!SSL3_BUFFER_is_initialised(rbuf)) { + /* Not initialized yet */ + if (!ssl3_setup_read_buffer(s)) { + /* SSLfatal() already called */ + return -1; + } + } + + if ((type && (type != SSL3_RT_APPLICATION_DATA) + && (type != SSL3_RT_HANDSHAKE)) || (peek + && (type != + SSL3_RT_APPLICATION_DATA))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if ((type == SSL3_RT_HANDSHAKE) && (s->rlayer.handshake_fragment_len > 0)) + /* (partially) satisfy request from storage */ + { + unsigned char *src = s->rlayer.handshake_fragment; + unsigned char *dst = buf; + unsigned int k; + + /* peek == 0 */ + n = 0; + while ((len > 0) && (s->rlayer.handshake_fragment_len > 0)) { + *dst++ = *src++; + len--; + s->rlayer.handshake_fragment_len--; + n++; + } + /* move any remaining fragment bytes: */ + for (k = 0; k < s->rlayer.handshake_fragment_len; k++) + s->rlayer.handshake_fragment[k] = *src++; + + if (recvd_type != NULL) + *recvd_type = SSL3_RT_HANDSHAKE; + + *readbytes = n; + return 1; + } + + /* + * Now s->rlayer.handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. + */ + + if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) { + /* type == SSL3_RT_APPLICATION_DATA */ + i = s->handshake_func(s); + /* SSLfatal() already called */ + if (i < 0) + return i; + if (i == 0) + return -1; + } + start: + s->rwstate = SSL_NOTHING; + + /*- + * For each record 'i' up to |num_recs] + * rr[i].type - is the type of record + * rr[i].data, - data + * rr[i].off, - offset into 'data' for next read + * rr[i].length, - number of bytes. + */ + rr = s->rlayer.rrec; + num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer); + + do { + /* get new records if necessary */ + if (num_recs == 0) { + ret = ssl3_get_record(s); + if (ret <= 0) { + /* SSLfatal() already called if appropriate */ + return ret; + } + num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer); + if (num_recs == 0) { + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + } + /* Skip over any records we have already read */ + for (curr_rec = 0; + curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]); + curr_rec++) ; + if (curr_rec == num_recs) { + RECORD_LAYER_set_numrpipes(&s->rlayer, 0); + num_recs = 0; + curr_rec = 0; + } + } while (num_recs == 0); + rr = &rr[curr_rec]; + + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT + && SSL3_RECORD_get_length(rr) != 0) + s->rlayer.alert_count = 0; + + /* 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 */ + && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); + return -1; + } + + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode) + */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + SSL3_RECORD_set_length(rr, 0); + s->rwstate = SSL_NOTHING; + return 0; + } + + if (type == SSL3_RECORD_get_type(rr) + || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && type == SSL3_RT_HANDSHAKE && recvd_type != NULL + && !is_tls13)) { + /* + * SSL3_RT_APPLICATION_DATA or + * SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC + */ + /* + * 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)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_APP_DATA_IN_HANDSHAKE); + return -1; + } + + if (type == SSL3_RT_HANDSHAKE + && SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && s->rlayer.handshake_fragment_len > 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_CCS_RECEIVED_EARLY); + return -1; + } + + if (recvd_type != NULL) + *recvd_type = SSL3_RECORD_get_type(rr); + + if (len == 0) { + /* + * Mark a zero length record as read. This ensures multiple calls to + * SSL_read() with a zero length buffer will eventually cause + * SSL_pending() to report data as being available. + */ + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + return 0; + } + + totalbytes = 0; + do { + if (len - totalbytes > SSL3_RECORD_get_length(rr)) + n = SSL3_RECORD_get_length(rr); + else + n = len - totalbytes; + + memcpy(buf, &(rr->data[rr->off]), n); + buf += n; + if (peek) { + /* Mark any zero length record as consumed CVE-2016-6305 */ + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + } else { + SSL3_RECORD_sub_length(rr, n); + SSL3_RECORD_add_off(rr, n); + if (SSL3_RECORD_get_length(rr) == 0) { + s->rlayer.rstate = SSL_ST_READ_HEADER; + SSL3_RECORD_set_off(rr, 0); + SSL3_RECORD_set_read(rr); + } + } + if (SSL3_RECORD_get_length(rr) == 0 + || (peek && n == SSL3_RECORD_get_length(rr))) { + curr_rec++; + rr++; + } + totalbytes += n; + } while (type == SSL3_RT_APPLICATION_DATA && curr_rec < num_recs + && totalbytes < len); + if (totalbytes == 0) { + /* We must have read empty records. Get more data */ + goto start; + } + if (!peek && curr_rec == num_recs + && (s->mode & SSL_MODE_RELEASE_BUFFERS) + && SSL3_BUFFER_get_left(rbuf) == 0) + ssl3_release_read_buffer(s); + *readbytes = totalbytes; + return 1; + } + + /* + * If we get here, then type != rr->type; if we have a handshake message, + * then it was unexpected (Hello Request or Client Hello) or invalid (we + * were actually expecting a CCS). + */ + + /* + * Lets just double check that we've not got an SSLv2 record + */ + if (rr->rec_version == SSL2_VERSION) { + /* + * Should never happen. ssl3_get_record() should only give us an SSLv2 + * record back if this is the first packet and we are looking for an + * initial ClientHello. Therefore |type| should always be equal to + * |rr->type|. If not then something has gone horribly wrong + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (s->method->version == TLS_ANY_VERSION + && (s->server || rr->type != SSL3_RT_ALERT)) { + /* + * If we've got this far and still haven't decided on what version + * we're using then this must be a client side alert we're dealing with + * (we don't allow heartbeats yet). We shouldn't be receiving anything + * other than a ClientHello if we are a server. + */ + s->version = rr->rec_version; + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_UNEXPECTED_MESSAGE); + return -1; + } + + /*- + * s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; + * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) + */ + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { + unsigned int alert_level, alert_descr; + unsigned char *alert_bytes = SSL3_RECORD_get_data(rr) + + SSL3_RECORD_get_off(rr); + PACKET alert; + + if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr)) + || !PACKET_get_1(&alert, &alert_level) + || !PACKET_get_1(&alert, &alert_descr) + || PACKET_remaining(&alert) != 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_INVALID_ALERT); + return -1; + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 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 == SSL3_AL_WARNING + || (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED)) { + s->s3->warn_alert = alert_descr; + SSL3_RECORD_set_read(rr); + + s->rlayer.alert_count++; + if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_TOO_MANY_WARN_ALERTS); + return -1; + } + } + + /* + * Apart from close_notify the only other warning alert in TLSv1.3 + * is user_cancelled - which we just ignore. + */ + if (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED) { + goto start; + } else if (alert_descr == SSL_AD_CLOSE_NOTIFY + && (is_tls13 || alert_level == SSL3_AL_WARNING)) { + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } else if (alert_level == SSL3_AL_FATAL || is_tls13) { + char tmp[16]; + + s->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + SSLfatal(s, SSL_AD_NO_ALERT, 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; + SSL3_RECORD_set_read(rr); + SSL_CTX_remove_session(s->session_ctx, s->session); + return 0; + } else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { + /* + * 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 renegotiate 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. + */ + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL3_READ_BYTES, + SSL_R_NO_RENEGOTIATION); + return -1; + } else if (alert_level == SSL3_AL_WARNING) { + /* We ignore any other warning alert in TLSv1.2 and below */ + goto start; + } + + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_READ_BYTES, + SSL_R_UNKNOWN_ALERT_TYPE); + return -1; + } + + if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) { + if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) { + BIO *rbio; + + /* + * We ignore any handshake messages sent to us unless they are + * TLSv1.3 in which case we want to process them. For all other + * handshake messages we can't do anything reasonable with them + * because we are unable to write any response due to having already + * sent close_notify. + */ + if (!SSL_IS_TLS13(s)) { + SSL3_RECORD_set_length(rr, 0) |