diff options
Diffstat (limited to 'crypto/x509')
43 files changed, 6479 insertions, 6160 deletions
diff --git a/crypto/x509/Makefile b/crypto/x509/Makefile deleted file mode 100644 index bf197a1d932a..000000000000 --- a/crypto/x509/Makefile +++ /dev/null @@ -1,411 +0,0 @@ -# -# OpenSSL/crypto/x509/Makefile -# - -DIR= x509 -TOP= ../.. -CC= cc -INCLUDES= -I.. -I$(TOP) -I../../include -CFLAG=-g -MAKEFILE= Makefile -AR= ar r - -CFLAGS= $(INCLUDES) $(CFLAG) - -GENERAL=Makefile README -TEST=verify_extra_test.c -APPS= - -LIB=$(TOP)/libcrypto.a -LIBSRC= x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \ - x509_obj.c x509_req.c x509spki.c x509_vfy.c \ - x509_set.c x509cset.c x509rset.c x509_err.c \ - x509name.c x509_v3.c x509_ext.c x509_att.c \ - x509type.c x509_lu.c x_all.c x509_txt.c \ - x509_trs.c by_file.c by_dir.c x509_vpm.c -LIBOBJ= x509_def.o x509_d2.o x509_r2x.o x509_cmp.o \ - x509_obj.o x509_req.o x509spki.o x509_vfy.o \ - x509_set.o x509cset.o x509rset.o x509_err.o \ - x509name.o x509_v3.o x509_ext.o x509_att.o \ - x509type.o x509_lu.o x_all.o x509_txt.o \ - x509_trs.o by_file.o by_dir.o x509_vpm.o - -SRC= $(LIBSRC) - -EXHEADER= x509.h x509_vfy.h -HEADER= $(EXHEADER) vpm_int.h - -ALL= $(GENERAL) $(SRC) $(HEADER) - -top: - (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all) - -all: lib - -lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @touch lib - -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: depend - -depend: - @[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile... - $(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. - -by_dir.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h -by_dir.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -by_dir.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -by_dir.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -by_dir.o: ../../include/openssl/err.h ../../include/openssl/evp.h -by_dir.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -by_dir.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -by_dir.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -by_dir.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -by_dir.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -by_dir.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -by_dir.o: ../../include/openssl/x509_vfy.h ../cryptlib.h by_dir.c -by_file.o: ../../e_os.h ../../include/openssl/asn1.h -by_file.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -by_file.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -by_file.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -by_file.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -by_file.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -by_file.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -by_file.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -by_file.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h -by_file.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h -by_file.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h -by_file.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -by_file.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h -by_file.o: ../cryptlib.h by_file.c -x509_att.o: ../../e_os.h ../../include/openssl/asn1.h -x509_att.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_att.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_att.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_att.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_att.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_att.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_att.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_att.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_att.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_att.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_att.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_att.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_att.o: ../cryptlib.h x509_att.c -x509_cmp.o: ../../e_os.h ../../include/openssl/asn1.h -x509_cmp.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_cmp.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_cmp.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_cmp.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_cmp.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_cmp.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_cmp.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_cmp.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_cmp.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_cmp.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_cmp.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_cmp.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_cmp.o: ../cryptlib.h x509_cmp.c -x509_d2.o: ../../e_os.h ../../include/openssl/asn1.h -x509_d2.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_d2.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509_d2.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509_d2.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509_d2.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509_d2.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509_d2.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -x509_d2.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h -x509_d2.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h -x509_d2.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -x509_d2.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h -x509_d2.o: ../cryptlib.h x509_d2.c -x509_def.o: ../../e_os.h ../../include/openssl/asn1.h -x509_def.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_def.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509_def.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509_def.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509_def.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509_def.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509_def.o: ../../include/openssl/opensslconf.h -x509_def.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_def.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_def.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_def.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_def.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509_def.c -x509_err.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h -x509_err.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -x509_err.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_err.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_err.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_err.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_err.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_err.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_err.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_err.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_err.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_err.o: ../../include/openssl/x509_vfy.h x509_err.c -x509_ext.o: ../../e_os.h ../../include/openssl/asn1.h -x509_ext.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_ext.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_ext.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_ext.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_ext.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_ext.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_ext.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_ext.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_ext.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_ext.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_ext.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_ext.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_ext.o: ../cryptlib.h x509_ext.c -x509_lu.o: ../../e_os.h ../../include/openssl/asn1.h -x509_lu.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_lu.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_lu.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_lu.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_lu.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_lu.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_lu.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_lu.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_lu.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_lu.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_lu.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_lu.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_lu.o: ../cryptlib.h x509_lu.c -x509_obj.o: ../../e_os.h ../../include/openssl/asn1.h -x509_obj.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_obj.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509_obj.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509_obj.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509_obj.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509_obj.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509_obj.o: ../../include/openssl/opensslconf.h -x509_obj.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_obj.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_obj.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_obj.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_obj.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509_obj.c -x509_r2x.o: ../../e_os.h ../../include/openssl/asn1.h -x509_r2x.o: ../../include/openssl/bio.h ../../include/openssl/bn.h -x509_r2x.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -x509_r2x.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_r2x.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_r2x.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_r2x.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_r2x.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_r2x.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_r2x.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_r2x.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_r2x.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_r2x.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509_r2x.c -x509_req.o: ../../e_os.h ../../include/openssl/asn1.h -x509_req.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h -x509_req.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h -x509_req.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509_req.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509_req.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509_req.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509_req.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509_req.o: ../../include/openssl/opensslconf.h -x509_req.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_req.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h -x509_req.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_req.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_req.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_req.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509_req.c -x509_set.o: ../../e_os.h ../../include/openssl/asn1.h -x509_set.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_set.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509_set.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509_set.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509_set.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509_set.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509_set.o: ../../include/openssl/opensslconf.h -x509_set.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_set.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_set.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_set.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_set.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509_set.c -x509_trs.o: ../../e_os.h ../../include/openssl/asn1.h -x509_trs.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_trs.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_trs.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_trs.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_trs.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_trs.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_trs.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_trs.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_trs.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_trs.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_trs.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_trs.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_trs.o: ../cryptlib.h x509_trs.c -x509_txt.o: ../../e_os.h ../../include/openssl/asn1.h -x509_txt.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_txt.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509_txt.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509_txt.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509_txt.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509_txt.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509_txt.o: ../../include/openssl/opensslconf.h -x509_txt.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_txt.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_txt.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_txt.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_txt.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509_txt.c -x509_v3.o: ../../e_os.h ../../include/openssl/asn1.h -x509_v3.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_v3.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_v3.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_v3.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_v3.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_v3.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_v3.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_v3.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_v3.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_v3.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_v3.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_v3.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_v3.o: ../cryptlib.h x509_v3.c -x509_vfy.o: ../../e_os.h ../../include/openssl/asn1.h -x509_vfy.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_vfy.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_vfy.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_vfy.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_vfy.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_vfy.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_vfy.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_vfy.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_vfy.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_vfy.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_vfy.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_vfy.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_vfy.o: ../cryptlib.h vpm_int.h x509_vfy.c -x509_vpm.o: ../../e_os.h ../../include/openssl/asn1.h -x509_vpm.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509_vpm.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h -x509_vpm.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x509_vpm.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x509_vpm.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_vpm.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x509_vpm.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -x509_vpm.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509_vpm.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509_vpm.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509_vpm.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509_vpm.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x509_vpm.o: ../cryptlib.h vpm_int.h x509_vpm.c -x509cset.o: ../../e_os.h ../../include/openssl/asn1.h -x509cset.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509cset.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509cset.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509cset.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509cset.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509cset.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509cset.o: ../../include/openssl/opensslconf.h -x509cset.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509cset.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509cset.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509cset.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509cset.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509cset.c -x509name.o: ../../e_os.h ../../include/openssl/asn1.h -x509name.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509name.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509name.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509name.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509name.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509name.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509name.o: ../../include/openssl/opensslconf.h -x509name.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509name.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509name.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509name.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509name.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509name.c -x509rset.o: ../../e_os.h ../../include/openssl/asn1.h -x509rset.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509rset.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509rset.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509rset.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509rset.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509rset.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509rset.o: ../../include/openssl/opensslconf.h -x509rset.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509rset.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509rset.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509rset.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509rset.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509rset.c -x509spki.o: ../../e_os.h ../../include/openssl/asn1.h -x509spki.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509spki.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509spki.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509spki.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509spki.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509spki.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509spki.o: ../../include/openssl/opensslconf.h -x509spki.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509spki.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509spki.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509spki.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509spki.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509spki.c -x509type.o: ../../e_os.h ../../include/openssl/asn1.h -x509type.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h -x509type.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -x509type.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -x509type.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -x509type.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -x509type.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -x509type.o: ../../include/openssl/opensslconf.h -x509type.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -x509type.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -x509type.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x509type.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x509type.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x509type.c -x_all.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h -x_all.o: ../../include/openssl/buffer.h ../../include/openssl/conf.h -x_all.o: ../../include/openssl/crypto.h ../../include/openssl/dsa.h -x_all.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -x_all.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -x_all.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x_all.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -x_all.o: ../../include/openssl/objects.h ../../include/openssl/ocsp.h -x_all.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -x_all.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h -x_all.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h -x_all.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -x_all.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -x_all.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h -x_all.o: ../cryptlib.h x_all.c diff --git a/crypto/x509/build.info b/crypto/x509/build.info new file mode 100644 index 000000000000..afd0b6134e52 --- /dev/null +++ b/crypto/x509/build.info @@ -0,0 +1,10 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \ + x509_obj.c x509_req.c x509spki.c x509_vfy.c \ + x509_set.c x509cset.c x509rset.c x509_err.c \ + x509name.c x509_v3.c x509_ext.c x509_att.c \ + x509type.c x509_meth.c x509_lu.c x_all.c x509_txt.c \ + x509_trs.c by_file.c by_dir.c x509_vpm.c \ + x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \ + x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 6f0209a275ef..11ac52ce3c55 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -1,106 +1,54 @@ -/* crypto/x509/by_dir.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 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 "e_os.h" +#include "internal/cryptlib.h" #include <stdio.h> #include <time.h> #include <errno.h> +#include <sys/types.h> -#include "cryptlib.h" - -#ifndef NO_SYS_TYPES_H -# include <sys/types.h> -#endif #ifndef OPENSSL_NO_POSIX_IO # include <sys/stat.h> #endif -#include <openssl/lhash.h> #include <openssl/x509.h> +#include "internal/x509_int.h" +#include "x509_lcl.h" -typedef struct lookup_dir_hashes_st { +struct lookup_dir_hashes_st { unsigned long hash; int suffix; -} BY_DIR_HASH; +}; -typedef struct lookup_dir_entry_st { +struct lookup_dir_entry_st { char *dir; int dir_type; STACK_OF(BY_DIR_HASH) *hashes; -} BY_DIR_ENTRY; +}; typedef struct lookup_dir_st { BUF_MEM *buffer; STACK_OF(BY_DIR_ENTRY) *dirs; + CRYPTO_RWLOCK *lock; } BY_DIR; -DECLARE_STACK_OF(BY_DIR_HASH) -DECLARE_STACK_OF(BY_DIR_ENTRY) - static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret); static int new_dir(X509_LOOKUP *lu); static void free_dir(X509_LOOKUP *lu); static int add_cert_dir(BY_DIR *ctx, const char *dir, int type); -static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, - X509_OBJECT *ret); -X509_LOOKUP_METHOD x509_dir_lookup = { +static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +static X509_LOOKUP_METHOD x509_dir_lookup = { "Load certs from files in a directory", - new_dir, /* new */ + new_dir, /* new_item */ free_dir, /* free */ NULL, /* init */ NULL, /* shutdown */ @@ -113,22 +61,20 @@ X509_LOOKUP_METHOD x509_dir_lookup = { X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) { - return (&x509_dir_lookup); + return &x509_dir_lookup; } static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **retp) { int ret = 0; - BY_DIR *ld; - char *dir = NULL; - - ld = (BY_DIR *)ctx->method_data; + BY_DIR *ld = (BY_DIR *)ctx->method_data; switch (cmd) { case X509_L_ADD_DIR: if (argl == X509_FILETYPE_DEFAULT) { - dir = (char *)getenv(X509_get_default_cert_dir_env()); + const char *dir = getenv(X509_get_default_cert_dir_env()); + if (dir) ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); else @@ -141,22 +87,35 @@ static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, ret = add_cert_dir(ld, argp, (int)argl); break; } - return (ret); + return ret; } static int new_dir(X509_LOOKUP *lu) { - BY_DIR *a; + BY_DIR *a = OPENSSL_malloc(sizeof(*a)); + + if (a == NULL) { + X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE); + return 0; + } - if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL) - return (0); if ((a->buffer = BUF_MEM_new()) == NULL) { - OPENSSL_free(a); - return (0); + X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE); + goto err; } a->dirs = NULL; - lu->method_data = (char *)a; - return (1); + a->lock = CRYPTO_THREAD_lock_new(); + if (a->lock == NULL) { + BUF_MEM_free(a->buffer); + X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE); + goto err; + } + lu->method_data = a; + return 1; + + err: + OPENSSL_free(a); + return 0; } static void by_dir_hash_free(BY_DIR_HASH *hash) @@ -176,28 +135,25 @@ static int by_dir_hash_cmp(const BY_DIR_HASH *const *a, static void by_dir_entry_free(BY_DIR_ENTRY *ent) { - if (ent->dir) - OPENSSL_free(ent->dir); - if (ent->hashes) - sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); + OPENSSL_free(ent->dir); + sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); OPENSSL_free(ent); } static void free_dir(X509_LOOKUP *lu) { - BY_DIR *a; + BY_DIR *a = (BY_DIR *)lu->method_data; - a = (BY_DIR *)lu->method_data; - if (a->dirs != NULL) - sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); - if (a->buffer != NULL) - BUF_MEM_free(a->buffer); + sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); + BUF_MEM_free(a->buffer); + CRYPTO_THREAD_lock_free(a->lock); OPENSSL_free(a); } static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) { - int j, len; + int j; + size_t len; const char *s, *ss, *p; if (dir == NULL || !*dir) { @@ -210,15 +166,15 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) do { if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) { BY_DIR_ENTRY *ent; + ss = s; s = p + 1; - len = (int)(p - ss); + len = p - ss; if (len == 0) continue; for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); - if (strlen(ent->dir) == (size_t)len && - strncmp(ent->dir, ss, (unsigned int)len) == 0) + if (strlen(ent->dir) == len && strncmp(ent->dir, ss, len) == 0) break; } if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) @@ -230,20 +186,21 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) return 0; } } - ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY)); - if (!ent) + ent = OPENSSL_malloc(sizeof(*ent)); + if (ent == NULL) { + X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE); return 0; + } ent->dir_type = type; ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); - ent->dir = OPENSSL_malloc((unsigned int)len + 1); - if (!ent->dir || !ent->hashes) { + ent->dir = OPENSSL_strndup(ss, len); + if (ent->dir == NULL || ent->hashes == NULL) { by_dir_entry_free(ent); return 0; } - strncpy(ent->dir, ss, (unsigned int)len); - ent->dir[len] = '\0'; if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { by_dir_entry_free(ent); + X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE); return 0; } } @@ -251,19 +208,13 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) return 1; } -static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, - X509_OBJECT *ret) +static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) { BY_DIR *ctx; union { - struct { - X509 st_x509; - X509_CINF st_x509_cinf; - } x509; - struct { - X509_CRL st_crl; - X509_CRL_INFO st_crl_info; - } crl; + X509 st_x509; + X509_CRL crl; } data; int ok = 0; int i, j, k; @@ -273,18 +224,16 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, const char *postfix = ""; if (name == NULL) - return (0); + return 0; stmp.type = type; if (type == X509_LU_X509) { - data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; - data.x509.st_x509_cinf.subject = name; - stmp.data.x509 = &data.x509.st_x509; + data.st_x509.cert_info.subject = name; + stmp.data.x509 = &data.st_x509; postfix = ""; } else if (type == X509_LU_CRL) { - data.crl.st_crl.crl = &data.crl.st_crl_info; - data.crl.st_crl_info.issuer = name; - stmp.data.crl = &data.crl.st_crl; + data.crl.crl.issuer = name; + stmp.data.crl = &data.crl; postfix = "r"; } else { X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE); @@ -303,6 +252,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, BY_DIR_ENTRY *ent; int idx; BY_DIR_HASH htmp, *hent; + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; if (!BUF_MEM_grow(b, j)) { @@ -311,7 +261,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, } if (type == X509_LU_CRL && ent->hashes) { htmp.hash = h; - CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_read_lock(ctx->lock); idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); if (idx >= 0) { hent = sk_BY_DIR_HASH_value(ent->hashes, idx); @@ -320,7 +270,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, hent = NULL; k = 0; } - CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->lock); } else { k = 0; hent = NULL; @@ -377,47 +327,46 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, /* * we have added it to the cache so now pull it out again */ - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_write_lock(ctx->lock); j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); - if (j != -1) - tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); - else - tmp = NULL; - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); + CRYPTO_THREAD_unlock(ctx->lock); /* If a CRL, update the last file suffix added for this */ if (type == X509_LU_CRL) { - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_write_lock(ctx->lock); /* * Look for entry again in case another thread added an entry * first. */ - if (!hent) { + if (hent == NULL) { htmp.hash = h; idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); - if (idx >= 0) - hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); } - if (!hent) { - hent = OPENSSL_malloc(sizeof(BY_DIR_HASH)); + if (hent == NULL) { + hent = OPENSSL_malloc(sizeof(*hent)); if (hent == NULL) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->lock); X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE); + ok = 0; goto finish; } hent->hash = h; hent->suffix = k; if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->lock); OPENSSL_free(hent); + X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE); ok = 0; goto finish; } - } else if (hent->suffix < k) + } else if (hent->suffix < k) { hent->suffix = k; + } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->lock); } @@ -425,17 +374,17 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, ok = 1; ret->type = tmp->type; memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + /* - * If we were going to up the reference count, we would need to - * do it on a perl 'type' basis + * Clear any errors that might have been raised processing empty + * or malformed files. */ - /*- CRYPTO_add(&tmp->data.x509->references,1, - CRYPTO_LOCK_X509);*/ + ERR_clear_error(); + goto finish; } } finish: - if (b != NULL) - BUF_MEM_free(b); - return (ok); + BUF_MEM_free(b); + return ok; } diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c index 82ce4e8d87c3..78d7fbdf4488 100644 --- a/crypto/x509/by_file.c +++ b/crypto/x509/by_file.c @@ -1,78 +1,27 @@ -/* crypto/x509/by_file.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 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> #include <time.h> #include <errno.h> -#include "cryptlib.h" -#include <openssl/lhash.h> +#include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/x509.h> #include <openssl/pem.h> - -#ifndef OPENSSL_NO_STDIO +#include "x509_lcl.h" static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); -X509_LOOKUP_METHOD x509_file_lookup = { +static X509_LOOKUP_METHOD x509_file_lookup = { "Load file into cache", - NULL, /* new */ + NULL, /* new_item */ NULL, /* free */ NULL, /* init */ NULL, /* shutdown */ @@ -85,7 +34,7 @@ X509_LOOKUP_METHOD x509_file_lookup = { X509_LOOKUP_METHOD *X509_LOOKUP_file(void) { - return (&x509_file_lookup); + return &x509_file_lookup; } static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, @@ -119,7 +68,7 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, } break; } - return (ok); + return ok; } int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) @@ -129,9 +78,7 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) int i, count = 0; X509 *x = NULL; - if (file == NULL) - return (1); - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB); @@ -173,12 +120,12 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE); goto err; } + if (ret == 0) + X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND); err: - if (x != NULL) - X509_free(x); - if (in != NULL) - BIO_free(in); - return (ret); + X509_free(x); + BIO_free(in); + return ret; } int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) @@ -188,9 +135,7 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) int i, count = 0; X509_CRL *x = NULL; - if (file == NULL) - return (1); - in = BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file()); if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB); @@ -232,12 +177,12 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE); goto err; } + if (ret == 0) + X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_NO_CRL_FOUND); err: - if (x != NULL) - X509_CRL_free(x); - if (in != NULL) - BIO_free(in); - return (ret); + X509_CRL_free(x); + BIO_free(in); + return ret; } int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) @@ -246,6 +191,7 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) X509_INFO *itmp; BIO *in; int i, count = 0; + if (type != X509_FILETYPE_PEM) return X509_load_cert_file(ctx, file, type); in = BIO_new_file(file, "r"); @@ -262,16 +208,20 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) for (i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { - X509_STORE_add_cert(ctx->store_ctx, itmp->x509); + if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) + goto err; count++; } if (itmp->crl) { - X509_STORE_add_crl(ctx->store_ctx, itmp->crl); + if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) + goto err; count++; } } + if (count == 0) + X509err(X509_F_X509_LOAD_CERT_CRL_FILE, + X509_R_NO_CERTIFICATE_OR_CRL_FOUND); + err: sk_X509_INFO_pop_free(inf, X509_INFO_free); return count; } - -#endif /* OPENSSL_NO_STDIO */ diff --git a/crypto/x509/t_crl.c b/crypto/x509/t_crl.c new file mode 100644 index 000000000000..8e262912ffaa --- /dev/null +++ b/crypto/x509/t_crl.c @@ -0,0 +1,94 @@ +/* + * Copyright 1999-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 "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/bn.h> +#include <openssl/objects.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> + +#ifndef OPENSSL_NO_STDIO +int X509_CRL_print_fp(FILE *fp, X509_CRL *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + X509err(X509_F_X509_CRL_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_CRL_print(b, x); + BIO_free(b); + return ret; +} +#endif + +int X509_CRL_print(BIO *out, X509_CRL *x) +{ + return X509_CRL_print_ex(out, x, XN_FLAG_COMPAT); +} + +int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag) +{ + STACK_OF(X509_REVOKED) *rev; + X509_REVOKED *r; + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + long l; + int i; + + BIO_printf(out, "Certificate Revocation List (CRL):\n"); + l = X509_CRL_get_version(x); + if (l >= 0 && l <= 1) + BIO_printf(out, "%8sVersion %ld (0x%lx)\n", "", l + 1, (unsigned long)l); + else + BIO_printf(out, "%8sVersion unknown (%ld)\n", "", l); + X509_CRL_get0_signature(x, &sig, &sig_alg); + BIO_puts(out, " "); + X509_signature_print(out, sig_alg, NULL); + BIO_printf(out, "%8sIssuer: ", ""); + X509_NAME_print_ex(out, X509_CRL_get_issuer(x), 0, nmflag); + BIO_puts(out, "\n"); + BIO_printf(out, "%8sLast Update: ", ""); + ASN1_TIME_print(out, X509_CRL_get0_lastUpdate(x)); + BIO_printf(out, "\n%8sNext Update: ", ""); + if (X509_CRL_get0_nextUpdate(x)) + ASN1_TIME_print(out, X509_CRL_get0_nextUpdate(x)); + else + BIO_printf(out, "NONE"); + BIO_printf(out, "\n"); + + X509V3_extensions_print(out, "CRL extensions", + X509_CRL_get0_extensions(x), 0, 8); + + rev = X509_CRL_get_REVOKED(x); + + if (sk_X509_REVOKED_num(rev) > 0) + BIO_printf(out, "Revoked Certificates:\n"); + else + BIO_printf(out, "No Revoked Certificates.\n"); + + for (i = 0; i < sk_X509_REVOKED_num(rev); i++) { + r = sk_X509_REVOKED_value(rev, i); + BIO_printf(out, " Serial Number: "); + i2a_ASN1_INTEGER(out, X509_REVOKED_get0_serialNumber(r)); + BIO_printf(out, "\n Revocation Date: "); + ASN1_TIME_print(out, X509_REVOKED_get0_revocationDate(r)); + BIO_printf(out, "\n"); + X509V3_extensions_print(out, "CRL entry extensions", + X509_REVOKED_get0_extensions(r), 0, 8); + } + X509_signature_print(out, sig_alg, sig); + + return 1; + +} diff --git a/crypto/x509/t_req.c b/crypto/x509/t_req.c new file mode 100644 index 000000000000..2d4c591b7445 --- /dev/null +++ b/crypto/x509/t_req.c @@ -0,0 +1,210 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/bn.h> +#include <openssl/objects.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> + +#ifndef OPENSSL_NO_STDIO +int X509_REQ_print_fp(FILE *fp, X509_REQ *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + X509err(X509_F_X509_REQ_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_REQ_print(b, x); + BIO_free(b); + return ret; +} +#endif + +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, + unsigned long cflag) +{ + long l; + int i; + EVP_PKEY *pkey; + STACK_OF(X509_EXTENSION) *exts; + char mlch = ' '; + int nmindent = 0; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) + nmindent = 16; + + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bp, "Certificate Request:\n", 21) <= 0) + goto err; + if (BIO_write(bp, " Data:\n", 10) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_REQ_get_version(x); + if (l >= 0 && l <= 2) { + if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0) + goto err; + } else { + if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0) + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bp, " Subject:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex(bp, X509_REQ_get_subject_name(x), + nmindent, nmflags) < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + X509_PUBKEY *xpkey; + ASN1_OBJECT *koid; + if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) + goto err; + if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) + goto err; + xpkey = X509_REQ_get_X509_PUBKEY(x); + X509_PUBKEY_get0_param(&koid, NULL, NULL, NULL, xpkey); + if (i2a_ASN1_OBJECT(bp, koid) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + + pkey = X509_REQ_get0_pubkey(x); + if (pkey == NULL) { + if (BIO_printf(bp, "%12sUnable to load Public Key\n", "") <= 0) + goto err; + ERR_print_errors(bp); + } else { + if (EVP_PKEY_print_public(bp, pkey, 16, NULL) <= 0) + goto err; + } + } + + if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { + /* may not be */ + if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0) + goto err; + + if (X509_REQ_get_attr_count(x) == 0) { + if (BIO_printf(bp, "%12sa0:00\n", "") <= 0) + goto err; + } else { + for (i = 0; i < X509_REQ_get_attr_count(x); i++) { + ASN1_TYPE *at; + X509_ATTRIBUTE *a; + ASN1_BIT_STRING *bs = NULL; + ASN1_OBJECT *aobj; + int j, type = 0, count = 1, ii = 0; + + a = X509_REQ_get_attr(x, i); + aobj = X509_ATTRIBUTE_get0_object(a); + if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) + continue; + if (BIO_printf(bp, "%12s", "") <= 0) + goto err; + if ((j = i2a_ASN1_OBJECT(bp, aobj)) > 0) { + ii = 0; + count = X509_ATTRIBUTE_count(a); + get_next: + at = X509_ATTRIBUTE_get0_type(a, ii); + type = at->type; + bs = at->value.asn1_string; + } + for (j = 25 - j; j > 0; j--) + if (BIO_write(bp, " ", 1) != 1) + goto err; + if (BIO_puts(bp, ":") <= 0) + goto err; + switch (type) { + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_IA5STRING: + if (BIO_write(bp, (char *)bs->data, bs->length) + != bs->length) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + break; + default: + if (BIO_puts(bp, "unable to print attribute\n") <= 0) + goto err; + break; + } + if (++ii < count) + goto get_next; + } + } + } + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { + exts = X509_REQ_get_extensions(x); + if (exts) { + if (BIO_printf(bp, "%8sRequested Extensions:\n", "") <= 0) + goto err; + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + int critical; + ex = sk_X509_EXTENSION_value(exts, i); + if (BIO_printf(bp, "%12s", "") <= 0) + goto err; + obj = X509_EXTENSION_get_object(ex); + if (i2a_ASN1_OBJECT(bp, obj) <= 0) + goto err; + critical = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ": %s\n", critical ? "critical" : "") <= 0) + goto err; + if (!X509V3_EXT_print(bp, ex, cflag, 16)) { + if (BIO_printf(bp, "%16s", "") <= 0 + || ASN1_STRING_print(bp, + X509_EXTENSION_get_data(ex)) <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + } + } + + if (!(cflag & X509_FLAG_NO_SIGDUMP)) { + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + X509_REQ_get0_signature(x, &sig, &sig_alg); + if (!X509_signature_print(bp, sig_alg, sig)) + goto err; + } + + return 1; + err: + X509err(X509_F_X509_REQ_PRINT_EX, ERR_R_BUF_LIB); + return 0; +} + +int X509_REQ_print(BIO *bp, X509_REQ *x) +{ + return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c new file mode 100644 index 000000000000..ccacbe7cbf8f --- /dev/null +++ b/crypto/x509/t_x509.c @@ -0,0 +1,379 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/bn.h> +#include <openssl/objects.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include "internal/asn1_int.h" + +#ifndef OPENSSL_NO_STDIO +int X509_print_fp(FILE *fp, X509 *x) +{ + return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, + unsigned long cflag) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_print_ex(b, x, nmflag, cflag); + BIO_free(b); + return ret; +} +#endif + +int X509_print(BIO *bp, X509 *x) +{ + return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, + unsigned long cflag) +{ + long l; + int ret = 0, i; + char *m = NULL, mlch = ' '; + int nmindent = 0; + ASN1_INTEGER *bs; + EVP_PKEY *pkey = NULL; + const char *neg; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) + nmindent = 16; + + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bp, "Certificate:\n", 13) <= 0) + goto err; + if (BIO_write(bp, " Data:\n", 10) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_get_version(x); + if (l >= 0 && l <= 2) { + if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0) + goto err; + } else { + if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0) + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SERIAL)) { + + if (BIO_write(bp, " Serial Number:", 22) <= 0) + goto err; + + bs = X509_get_serialNumber(x); + if (bs->length <= (int)sizeof(long)) { + ERR_set_mark(); + l = ASN1_INTEGER_get(bs); + ERR_pop_to_mark(); + } else { + l = -1; + } + if (l != -1) { + unsigned long ul; + if (bs->type == V_ASN1_NEG_INTEGER) { + ul = 0 - (unsigned long)l; + neg = "-"; + } else { + ul = l; + neg = ""; + } + if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0) + goto err; + } else { + neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; + if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) + goto err; + + for (i = 0; i < bs->length; i++) { + if (BIO_printf(bp, "%02x%c", bs->data[i], + ((i + 1 == bs->length) ? '\n' : ':')) <= 0) + goto err; + } + } + + } + + if (!(cflag & X509_FLAG_NO_SIGNAME)) { + const X509_ALGOR *tsig_alg = X509_get0_tbs_sigalg(x); + + if (BIO_puts(bp, " ") <= 0) + goto err; + if (X509_signature_print(bp, tsig_alg, NULL) <= 0) + goto err; + } + + if (!(cflag & X509_FLAG_NO_ISSUER)) { + if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) + < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VALIDITY)) { + if (BIO_write(bp, " Validity\n", 17) <= 0) + goto err; + if (BIO_write(bp, " Not Before: ", 24) <= 0) + goto err; + if (!ASN1_TIME_print(bp, X509_get0_notBefore(x))) + goto err; + if (BIO_write(bp, "\n Not After : ", 25) <= 0) + goto err; + if (!ASN1_TIME_print(bp, X509_get0_notAfter(x))) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bp, " Subject:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex + (bp, X509_get_subject_name(x), nmindent, nmflags) < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + X509_PUBKEY *xpkey = X509_get_X509_PUBKEY(x); + ASN1_OBJECT *xpoid; + X509_PUBKEY_get0_param(&xpoid, NULL, NULL, NULL, xpkey); + if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) + goto err; + if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, xpoid) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + + pkey = X509_get0_pubkey(x); + if (pkey == NULL) { + BIO_printf(bp, "%12sUnable to load Public Key\n", ""); + ERR_print_errors(bp); + } else { + EVP_PKEY_print_public(bp, pkey, 16, NULL); + } + } + + if (!(cflag & X509_FLAG_NO_IDS)) { + const ASN1_BIT_STRING *iuid, *suid; + X509_get0_uids(x, &iuid, &suid); + if (iuid != NULL) { + if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) + goto err; + if (!X509_signature_dump(bp, iuid, 12)) + goto err; + } + if (suid != NULL) { + if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) + goto err; + if (!X509_signature_dump(bp, suid, 12)) + goto err; + } + } + + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) + X509V3_extensions_print(bp, "X509v3 extensions", + X509_get0_extensions(x), cflag, 8); + + if (!(cflag & X509_FLAG_NO_SIGDUMP)) { + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + X509_get0_signature(&sig, &sig_alg, x); + if (X509_signature_print(bp, sig_alg, sig) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_AUX)) { + if (!X509_aux_print(bp, x, 0)) + goto err; + } + ret = 1; + err: + OPENSSL_free(m); + return ret; +} + +int X509_ocspid_print(BIO *bp, X509 *x) +{ + unsigned char *der = NULL; + unsigned char *dertmp; + int derlen; + int i; + unsigned char SHA1md[SHA_DIGEST_LENGTH]; + ASN1_BIT_STRING *keybstr; + X509_NAME *subj; + + /* + * display the hash of the subject as it would appear in OCSP requests + */ + if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) + goto err; + subj = X509_get_subject_name(x); + derlen = i2d_X509_NAME(subj, NULL); + if ((der = dertmp = OPENSSL_malloc(derlen)) == NULL) + goto err; + i2d_X509_NAME(subj, &dertmp); + + if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL)) + goto err; + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) + goto err; + } + OPENSSL_free(der); + der = NULL; + + /* + * display the hash of the public key as it would appear in OCSP requests + */ + if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) + goto err; + + keybstr = X509_get0_pubkey_bitstr(x); + + if (keybstr == NULL) + goto err; + + if (!EVP_Digest(ASN1_STRING_get0_data(keybstr), + ASN1_STRING_length(keybstr), SHA1md, NULL, EVP_sha1(), + NULL)) + goto err; + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) + goto err; + } + BIO_printf(bp, "\n"); + + return 1; + err: + OPENSSL_free(der); + return 0; +} + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) +{ + const unsigned char *s; + int i, n; + + n = sig->length; + s = sig->data; + for (i = 0; i < n; i++) { + if ((i % 18) == 0) { + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + if (BIO_indent(bp, indent, indent) <= 0) + return 0; + } + if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0) + return 0; + } + if (BIO_write(bp, "\n", 1) != 1) + return 0; + + return 1; +} + +int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, + const ASN1_STRING *sig) +{ + int sig_nid; + if (BIO_puts(bp, " Signature Algorithm: ") <= 0) + return 0; + if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) + return 0; + + sig_nid = OBJ_obj2nid(sigalg->algorithm); + if (sig_nid != NID_undef) { + int pkey_nid, dig_nid; + const EVP_PKEY_ASN1_METHOD *ameth; + if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) { + ameth = EVP_PKEY_asn1_find(NULL, pkey_nid); + if (ameth && ameth->sig_print) + return ameth->sig_print(bp, sigalg, sig, 9, 0); + } + } + if (sig) + return X509_signature_dump(bp, sig, 9); + else if (BIO_puts(bp, "\n") <= 0) + return 0; + return 1; +} + +int X509_aux_print(BIO *out, X509 *x, int indent) +{ + char oidstr[80], first; + STACK_OF(ASN1_OBJECT) *trust, *reject; + const unsigned char *alias, *keyid; + int keyidlen; + int i; + if (X509_trusted(x) == 0) + return 1; + trust = X509_get0_trust_objects(x); + reject = X509_get0_reject_objects(x); + if (trust) { + first = 1; + BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { + if (!first) + BIO_puts(out, ", "); + else + first = 0; + OBJ_obj2txt(oidstr, sizeof(oidstr), + sk_ASN1_OBJECT_value(trust, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else + BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); + if (reject) { + first = 1; + BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { + if (!first) + BIO_puts(out, ", "); + else + first = 0; + OBJ_obj2txt(oidstr, sizeof(oidstr), + sk_ASN1_OBJECT_value(reject, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else + BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); + alias = X509_alias_get0(x, NULL); + if (alias) + BIO_printf(out, "%*sAlias: %s\n", indent, "", alias); + keyid = X509_keyid_get0(x, &keyidlen); + if (keyid) { + BIO_printf(out, "%*sKey Id: ", indent, ""); + for (i = 0; i < keyidlen; i++) + BIO_printf(out, "%s%02X", i ? ":" : "", keyid[i]); + BIO_write(out, "\n", 1); + } + return 1; +} diff --git a/crypto/x509/verify_extra_test.c b/crypto/x509/verify_extra_test.c deleted file mode 100644 index 08509f013194..000000000000 --- a/crypto/x509/verify_extra_test.c +++ /dev/null @@ -1,208 +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 <stdio.h> -#include <openssl/crypto.h> -#include <openssl/bio.h> -#include <openssl/x509.h> -#include <openssl/pem.h> -#include <openssl/err.h> - -static STACK_OF(X509) *load_certs_from_file(const char *filename) -{ - STACK_OF(X509) *certs; - BIO *bio; - X509 *x; - - bio = BIO_new_file(filename, "r"); - - if (bio == NULL) { - return NULL; - } - - certs = sk_X509_new_null(); - if (certs == NULL) { - BIO_free(bio); - return NULL; - } - - ERR_set_mark(); - do { - x = PEM_read_bio_X509(bio, NULL, 0, NULL); - if (x != NULL && !sk_X509_push(certs, x)) { - sk_X509_pop_free(certs, X509_free); - BIO_free(bio); - return NULL; - } else if (x == NULL) { - /* - * We probably just ran out of certs, so ignore any errors - * generated - */ - ERR_pop_to_mark(); - } - } while (x != NULL); - - BIO_free(bio); - - return certs; -} - -/* - * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery) - * - * Chain is as follows: - * - * rootCA (self-signed) - * | - * interCA - * | - * subinterCA subinterCA (self-signed) - * | | - * leaf ------------------ - * | - * bad - * - * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE - * leaf and bad have CA=FALSE - * - * subinterCA and subinterCA (ss) have the same subject name and keys - * - * interCA (but not rootCA) and subinterCA (ss) are in the trusted store - * (roots.pem) - * leaf and subinterCA are in the untrusted list (untrusted.pem) - * bad is the certificate being verified (bad.pem) - * - * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has - * CA=FALSE, and will therefore incorrectly verify bad - * - */ -static int test_alt_chains_cert_forgery(void) -{ - int ret = 0; - int i; - X509 *x = NULL; - STACK_OF(X509) *untrusted = NULL; - BIO *bio = NULL; - X509_STORE_CTX *sctx = NULL; - X509_STORE *store = NULL; - X509_LOOKUP *lookup = NULL; - - store = X509_STORE_new(); - if (store == NULL) - goto err; - - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if (lookup == NULL) - goto err; - if(!X509_LOOKUP_load_file(lookup, "certs/roots.pem", X509_FILETYPE_PEM)) - goto err; - - untrusted = load_certs_from_file("certs/untrusted.pem"); - - if ((bio = BIO_new_file("certs/bad.pem", "r")) == NULL) - goto err; - - if((x = PEM_read_bio_X509(bio, NULL, 0, NULL)) == NULL) - goto err; - - sctx = X509_STORE_CTX_new(); - if (sctx == NULL) - goto err; - - if (!X509_STORE_CTX_init(sctx, store, x, untrusted)) - goto err; - - i = X509_verify_cert(sctx); - - if(i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA) { - /* This is the result we were expecting: Test passed */ - ret = 1; - } - err: - X509_STORE_CTX_free(sctx); - X509_free(x); - BIO_free(bio); - sk_X509_pop_free(untrusted, X509_free); - X509_STORE_free(store); - if (ret != 1) - ERR_print_errors_fp(stderr); - return ret; -} - -int main(void) -{ - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - ERR_load_crypto_strings(); - OpenSSL_add_all_digests(); - - if (!test_alt_chains_cert_forgery()) { - fprintf(stderr, "Test alt chains cert forgery failed\n"); - return 1; - } - - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); - ERR_free_strings(); - CRYPTO_mem_leaks_fp(stderr); - - printf("PASS\n"); - return 0; -} diff --git a/crypto/x509/vpm_int.h b/crypto/x509/vpm_int.h deleted file mode 100644 index 9c55defc512a..000000000000 --- a/crypto/x509/vpm_int.h +++ /dev/null @@ -1,70 +0,0 @@ -/* vpm_int.h */ -/* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2013. - */ -/* ==================================================================== - * Copyright (c) 2013 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). - * - */ - -/* internal only structure to hold additional X509_VERIFY_PARAM data */ - -struct X509_VERIFY_PARAM_ID_st { - STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */ - unsigned int hostflags; /* Flags to control matching features */ - char *peername; /* Matching hostname in peer certificate */ - char *email; /* If not NULL email address to match */ - size_t emaillen; - unsigned char *ip; /* If not NULL IP address to match */ - size_t iplen; /* Length of IP address */ -}; diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h deleted file mode 100644 index 6fa28ebada46..000000000000 --- a/crypto/x509/x509.h +++ /dev/null @@ -1,1330 +0,0 @@ -/* crypto/x509/x509.h */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * ECDH support in OpenSSL originally developed by - * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. - */ - -#ifndef HEADER_X509_H -# define HEADER_X509_H - -# include <openssl/e_os2.h> -# include <openssl/symhacks.h> -# ifndef OPENSSL_NO_BUFFER -# include <openssl/buffer.h> -# endif -# ifndef OPENSSL_NO_EVP -# include <openssl/evp.h> -# endif -# ifndef OPENSSL_NO_BIO -# include <openssl/bio.h> -# endif -# include <openssl/stack.h> -# include <openssl/asn1.h> -# include <openssl/safestack.h> - -# ifndef OPENSSL_NO_EC -# include <openssl/ec.h> -# endif - -# ifndef OPENSSL_NO_ECDSA -# include <openssl/ecdsa.h> -# endif - -# ifndef OPENSSL_NO_ECDH -# include <openssl/ecdh.h> -# endif - -# ifndef OPENSSL_NO_DEPRECATED -# ifndef OPENSSL_NO_RSA -# include <openssl/rsa.h> -# endif -# ifndef OPENSSL_NO_DSA -# include <openssl/dsa.h> -# endif -# ifndef OPENSSL_NO_DH -# include <openssl/dh.h> -# endif -# endif - -# ifndef OPENSSL_NO_SHA -# include <openssl/sha.h> -# endif -# include <openssl/ossl_typ.h> - -#ifdef __cplusplus -extern "C" { -#endif - -# ifdef OPENSSL_SYS_WIN32 -/* Under Win32 these are defined in wincrypt.h */ -# undef X509_NAME -# undef X509_CERT_PAIR -# undef X509_EXTENSIONS -# endif - -# define X509_FILETYPE_PEM 1 -# define X509_FILETYPE_ASN1 2 -# define X509_FILETYPE_DEFAULT 3 - -# define X509v3_KU_DIGITAL_SIGNATURE 0x0080 -# define X509v3_KU_NON_REPUDIATION 0x0040 -# define X509v3_KU_KEY_ENCIPHERMENT 0x0020 -# define X509v3_KU_DATA_ENCIPHERMENT 0x0010 -# define X509v3_KU_KEY_AGREEMENT 0x0008 -# define X509v3_KU_KEY_CERT_SIGN 0x0004 -# define X509v3_KU_CRL_SIGN 0x0002 -# define X509v3_KU_ENCIPHER_ONLY 0x0001 -# define X509v3_KU_DECIPHER_ONLY 0x8000 -# define X509v3_KU_UNDEF 0xffff - -typedef struct X509_objects_st { - int nid; - int (*a2i) (void); - int (*i2a) (void); -} X509_OBJECTS; - -struct X509_algor_st { - ASN1_OBJECT *algorithm; - ASN1_TYPE *parameter; -} /* X509_ALGOR */ ; - -DECLARE_ASN1_SET_OF(X509_ALGOR) - -typedef STACK_OF(X509_ALGOR) X509_ALGORS; - -typedef struct X509_val_st { - ASN1_TIME *notBefore; - ASN1_TIME *notAfter; -} X509_VAL; - -struct X509_pubkey_st { - X509_ALGOR *algor; - ASN1_BIT_STRING *public_key; - EVP_PKEY *pkey; -}; - -typedef struct X509_sig_st { - X509_ALGOR *algor; - ASN1_OCTET_STRING *digest; -} X509_SIG; - -typedef struct X509_name_entry_st { - ASN1_OBJECT *object; - ASN1_STRING *value; - int set; - int size; /* temp variable */ -} X509_NAME_ENTRY; - -DECLARE_STACK_OF(X509_NAME_ENTRY) -DECLARE_ASN1_SET_OF(X509_NAME_ENTRY) - -/* we always keep X509_NAMEs in 2 forms. */ -struct X509_name_st { - STACK_OF(X509_NAME_ENTRY) *entries; - int modified; /* true if 'bytes' needs to be built */ -# ifndef OPENSSL_NO_BUFFER - BUF_MEM *bytes; -# else - char *bytes; -# endif -/* unsigned long hash; Keep the hash around for lookups */ - unsigned char *canon_enc; - int canon_enclen; -} /* X509_NAME */ ; - -DECLARE_STACK_OF(X509_NAME) - -# define X509_EX_V_NETSCAPE_HACK 0x8000 -# define X509_EX_V_INIT 0x0001 -typedef struct X509_extension_st { - ASN1_OBJECT *object; - ASN1_BOOLEAN critical; - ASN1_OCTET_STRING *value; -} X509_EXTENSION; - -typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; - -DECLARE_STACK_OF(X509_EXTENSION) -DECLARE_ASN1_SET_OF(X509_EXTENSION) - -/* a sequence of these are used */ -typedef struct x509_attributes_st { - ASN1_OBJECT *object; - int single; /* 0 for a set, 1 for a single item (which is - * wrong) */ - union { - char *ptr; - /* - * 0 - */ STACK_OF(ASN1_TYPE) *set; - /* - * 1 - */ ASN1_TYPE *single; - } value; -} X509_ATTRIBUTE; - -DECLARE_STACK_OF(X509_ATTRIBUTE) -DECLARE_ASN1_SET_OF(X509_ATTRIBUTE) - -typedef struct X509_req_info_st { - ASN1_ENCODING enc; - ASN1_INTEGER *version; - X509_NAME *subject; - X509_PUBKEY *pubkey; - /* d=2 hl=2 l= 0 cons: cont: 00 */ - STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ -} X509_REQ_INFO; - -typedef struct X509_req_st { - X509_REQ_INFO *req_info; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; - int references; -} X509_REQ; - -typedef struct x509_cinf_st { - ASN1_INTEGER *version; /* [ 0 ] default of v1 */ - ASN1_INTEGER *serialNumber; - X509_ALGOR *signature; - X509_NAME *issuer; - X509_VAL *validity; - X509_NAME *subject; - X509_PUBKEY *key; - ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ - ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ - STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ - ASN1_ENCODING enc; -} X509_CINF; - -/* - * This stuff is certificate "auxiliary info" it contains details which are - * useful in certificate stores and databases. When used this is tagged onto - * the end of the certificate itself - */ - -typedef struct x509_cert_aux_st { - STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ - STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ - ASN1_UTF8STRING *alias; /* "friendly name" */ - ASN1_OCTET_STRING *keyid; /* key id of private key */ - STACK_OF(X509_ALGOR) *other; /* other unspecified info */ -} X509_CERT_AUX; - -struct x509_st { - X509_CINF *cert_info; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; - int valid; - int references; - char *name; - CRYPTO_EX_DATA ex_data; - /* These contain copies of various extension values */ - long ex_pathlen; - long ex_pcpathlen; - unsigned long ex_flags; - unsigned long ex_kusage; - unsigned long ex_xkusage; - unsigned long ex_nscert; - ASN1_OCTET_STRING *skid; - AUTHORITY_KEYID *akid; - X509_POLICY_CACHE *policy_cache; - STACK_OF(DIST_POINT) *crldp; - STACK_OF(GENERAL_NAME) *altname; - NAME_CONSTRAINTS *nc; -# ifndef OPENSSL_NO_RFC3779 - STACK_OF(IPAddressFamily) *rfc3779_addr; - struct ASIdentifiers_st *rfc3779_asid; -# endif -# ifndef OPENSSL_NO_SHA - unsigned char sha1_hash[SHA_DIGEST_LENGTH]; -# endif - X509_CERT_AUX *aux; -} /* X509 */ ; - -DECLARE_STACK_OF(X509) -DECLARE_ASN1_SET_OF(X509) - -/* This is used for a table of trust checking functions */ - -typedef struct x509_trust_st { - int trust; - int flags; - int (*check_trust) (struct x509_trust_st *, X509 *, int); - char *name; - int arg1; - void *arg2; -} X509_TRUST; - -DECLARE_STACK_OF(X509_TRUST) - -typedef struct x509_cert_pair_st { - X509 *forward; - X509 *reverse; -} X509_CERT_PAIR; - -/* standard trust ids */ - -# define X509_TRUST_DEFAULT -1/* Only valid in purpose settings */ - -# define X509_TRUST_COMPAT 1 -# define X509_TRUST_SSL_CLIENT 2 -# define X509_TRUST_SSL_SERVER 3 -# define X509_TRUST_EMAIL 4 -# define X509_TRUST_OBJECT_SIGN 5 -# define X509_TRUST_OCSP_SIGN 6 -# define X509_TRUST_OCSP_REQUEST 7 -# define X509_TRUST_TSA 8 - -/* Keep these up to date! */ -# define X509_TRUST_MIN 1 -# define X509_TRUST_MAX 8 - -/* trust_flags values */ -# define X509_TRUST_DYNAMIC 1 -# define X509_TRUST_DYNAMIC_NAME 2 - -/* check_trust return codes */ - -# define X509_TRUST_TRUSTED 1 -# define X509_TRUST_REJECTED 2 -# define X509_TRUST_UNTRUSTED 3 - -/* Flags for X509_print_ex() */ - -# define X509_FLAG_COMPAT 0 -# define X509_FLAG_NO_HEADER 1L -# define X509_FLAG_NO_VERSION (1L << 1) -# define X509_FLAG_NO_SERIAL (1L << 2) -# define X509_FLAG_NO_SIGNAME (1L << 3) -# define X509_FLAG_NO_ISSUER (1L << 4) -# define X509_FLAG_NO_VALIDITY (1L << 5) -# define X509_FLAG_NO_SUBJECT (1L << 6) -# define X509_FLAG_NO_PUBKEY (1L << 7) -# define X509_FLAG_NO_EXTENSIONS (1L << 8) -# define X509_FLAG_NO_SIGDUMP (1L << 9) -# define X509_FLAG_NO_AUX (1L << 10) -# define X509_FLAG_NO_ATTRIBUTES (1L << 11) -# define X509_FLAG_NO_IDS (1L << 12) - -/* Flags specific to X509_NAME_print_ex() */ - -/* The field separator information */ - -# define XN_FLAG_SEP_MASK (0xf << 16) - -# define XN_FLAG_COMPAT 0/* Traditional SSLeay: use old - * X509_NAME_print */ -# define XN_FLAG_SEP_COMMA_PLUS (1 << 16)/* RFC2253 ,+ */ -# define XN_FLAG_SEP_CPLUS_SPC (2 << 16)/* ,+ spaced: more readable */ -# define XN_FLAG_SEP_SPLUS_SPC (3 << 16)/* ;+ spaced */ -# define XN_FLAG_SEP_MULTILINE (4 << 16)/* One line per field */ - -# define XN_FLAG_DN_REV (1 << 20)/* Reverse DN order */ - -/* How the field name is shown */ - -# define XN_FLAG_FN_MASK (0x3 << 21) - -# define XN_FLAG_FN_SN 0/* Object short name */ -# define XN_FLAG_FN_LN (1 << 21)/* Object long name */ -# define XN_FLAG_FN_OID (2 << 21)/* Always use OIDs */ -# define XN_FLAG_FN_NONE (3 << 21)/* No field names */ - -# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */ - -/* - * This determines if we dump fields we don't recognise: RFC2253 requires - * this. - */ - -# define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) - -# define XN_FLAG_FN_ALIGN (1 << 25)/* Align field names to 20 - * characters */ - -/* Complete set of RFC2253 flags */ - -# define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ - XN_FLAG_SEP_COMMA_PLUS | \ - XN_FLAG_DN_REV | \ - XN_FLAG_FN_SN | \ - XN_FLAG_DUMP_UNKNOWN_FIELDS) - -/* readable oneline form */ - -# define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ - ASN1_STRFLGS_ESC_QUOTE | \ - XN_FLAG_SEP_CPLUS_SPC | \ - XN_FLAG_SPC_EQ | \ - XN_FLAG_FN_SN) - -/* readable multiline form */ - -# define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ - ASN1_STRFLGS_ESC_MSB | \ - XN_FLAG_SEP_MULTILINE | \ - XN_FLAG_SPC_EQ | \ - XN_FLAG_FN_LN | \ - XN_FLAG_FN_ALIGN) - -struct x509_revoked_st { - ASN1_INTEGER *serialNumber; - ASN1_TIME *revocationDate; - STACK_OF(X509_EXTENSION) /* optional */ *extensions; - /* Set up if indirect CRL */ - STACK_OF(GENERAL_NAME) *issuer; - /* Revocation reason */ - int reason; - int sequence; /* load sequence */ -}; - -DECLARE_STACK_OF(X509_REVOKED) -DECLARE_ASN1_SET_OF(X509_REVOKED) - -typedef struct X509_crl_info_st { - ASN1_INTEGER *version; - X509_ALGOR *sig_alg; - X509_NAME *issuer; - ASN1_TIME *lastUpdate; - ASN1_TIME *nextUpdate; - STACK_OF(X509_REVOKED) *revoked; - STACK_OF(X509_EXTENSION) /* [0] */ *extensions; - ASN1_ENCODING enc; -} X509_CRL_INFO; - -struct X509_crl_st { - /* actual signature */ - X509_CRL_INFO *crl; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; - int references; - int flags; - /* Copies of various extensions */ - AUTHORITY_KEYID *akid; - ISSUING_DIST_POINT *idp; - /* Convenient breakdown of IDP */ - int idp_flags; - int idp_reasons; - /* CRL and base CRL numbers for delta processing */ - ASN1_INTEGER *crl_number; - ASN1_INTEGER *base_crl_number; -# ifndef OPENSSL_NO_SHA - unsigned char sha1_hash[SHA_DIGEST_LENGTH]; -# endif - STACK_OF(GENERAL_NAMES) *issuers; - const X509_CRL_METHOD *meth; - void *meth_data; -} /* X509_CRL */ ; - -DECLARE_STACK_OF(X509_CRL) -DECLARE_ASN1_SET_OF(X509_CRL) - -typedef struct private_key_st { - int version; - /* The PKCS#8 data types */ - X509_ALGOR *enc_algor; - ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ - /* When decrypted, the following will not be NULL */ - EVP_PKEY *dec_pkey; - /* used to encrypt and decrypt */ - int key_length; - char *key_data; - int key_free; /* true if we should auto free key_data */ - /* expanded version of 'enc_algor' */ - EVP_CIPHER_INFO cipher; - int references; -} X509_PKEY; - -# ifndef OPENSSL_NO_EVP -typedef struct X509_info_st { - X509 *x509; - X509_CRL *crl; - X509_PKEY *x_pkey; - EVP_CIPHER_INFO enc_cipher; - int enc_len; - char *enc_data; - int references; -} X509_INFO; - -DECLARE_STACK_OF(X509_INFO) -# endif - -/* - * The next 2 structures and their 8 routines were sent to me by Pat Richard - * <patr@x509.com> and are used to manipulate Netscapes spki structures - - * useful if you are writing a CA web page - */ -typedef struct Netscape_spkac_st { - X509_PUBKEY *pubkey; - ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ -} NETSCAPE_SPKAC; - -typedef struct Netscape_spki_st { - NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ - X509_ALGOR *sig_algor; - ASN1_BIT_STRING *signature; -} NETSCAPE_SPKI; - -/* Netscape certificate sequence structure */ -typedef struct Netscape_certificate_sequence { - ASN1_OBJECT *type; - STACK_OF(X509) *certs; -} NETSCAPE_CERT_SEQUENCE; - -/*- Unused (and iv length is wrong) -typedef struct CBCParameter_st - { - unsigned char iv[8]; - } CBC_PARAM; -*/ - -/* Password based encryption structure */ - -typedef struct PBEPARAM_st { - ASN1_OCTET_STRING *salt; - ASN1_INTEGER *iter; -} PBEPARAM; - -/* Password based encryption V2 structures */ - -typedef struct PBE2PARAM_st { - X509_ALGOR *keyfunc; - X509_ALGOR *encryption; -} PBE2PARAM; - -typedef struct PBKDF2PARAM_st { -/* Usually OCTET STRING but could be anything */ - ASN1_TYPE *salt; - ASN1_INTEGER *iter; - ASN1_INTEGER *keylength; - X509_ALGOR *prf; -} PBKDF2PARAM; - -/* PKCS#8 private key info structure */ - -struct pkcs8_priv_key_info_st { - /* Flag for various broken formats */ - int broken; -# define PKCS8_OK 0 -# define PKCS8_NO_OCTET 1 -# define PKCS8_EMBEDDED_PARAM 2 -# define PKCS8_NS_DB 3 -# define PKCS8_NEG_PRIVKEY 4 - ASN1_INTEGER *version; - X509_ALGOR *pkeyalg; - /* Should be OCTET STRING but some are broken */ - ASN1_TYPE *pkey; - STACK_OF(X509_ATTRIBUTE) *attributes; -}; - -#ifdef __cplusplus -} -#endif - -# include <openssl/x509_vfy.h> -# include <openssl/pkcs7.h> - -#ifdef __cplusplus -extern "C" { -#endif - -# define X509_EXT_PACK_UNKNOWN 1 -# define X509_EXT_PACK_STRING 2 - -# define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version) -/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */ -# define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) -# define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) -# define X509_extract_key(x) X509_get_pubkey(x)/*****/ -# define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version) -# define X509_REQ_get_subject_name(x) ((x)->req_info->subject) -# define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) -# define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) -# define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm)) - -# define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version) -# define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate) -# define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate) -# define X509_CRL_get_issuer(x) ((x)->crl->issuer) -# define X509_CRL_get_REVOKED(x) ((x)->crl->revoked) - -void X509_CRL_set_default_method(const X509_CRL_METHOD *meth); -X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), - int (*crl_free) (X509_CRL *crl), - int (*crl_lookup) (X509_CRL *crl, - X509_REVOKED **ret, - ASN1_INTEGER *ser, - X509_NAME *issuer), - int (*crl_verify) (X509_CRL *crl, - EVP_PKEY *pk)); -void X509_CRL_METHOD_free(X509_CRL_METHOD *m); - -void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); -void *X509_CRL_get_meth_data(X509_CRL *crl); - -/* - * This one is only used so that a binary form can output, as in - * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) - */ -# define X509_get_X509_PUBKEY(x) ((x)->cert_info->key) - -const char *X509_verify_cert_error_string(long n); - -# ifndef OPENSSL_NO_EVP -int X509_verify(X509 *a, EVP_PKEY *r); - -int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); -int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); -int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); - -NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len); -char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); -EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); -int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); - -int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); - -int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent); -int X509_signature_print(BIO *bp, X509_ALGOR *alg, ASN1_STRING *sig); - -int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); -int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx); -int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert); -int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); -int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx); -int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); -int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); -int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl); -int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); - -int X509_pubkey_digest(const X509 *data, const EVP_MD *type, - unsigned char *md, unsigned int *len); -int X509_digest(const X509 *data, const EVP_MD *type, - unsigned char *md, unsigned int *len); -int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, - unsigned char *md, unsigned int *len); -int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, - unsigned char *md, unsigned int *len); -int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, - unsigned char *md, unsigned int *len); -# endif - -# ifndef OPENSSL_NO_FP_API -X509 *d2i_X509_fp(FILE *fp, X509 **x509); -int i2d_X509_fp(FILE *fp, X509 *x509); -X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl); -int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl); -X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req); -int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req); -# ifndef OPENSSL_NO_RSA -RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa); -int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa); -RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa); -int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa); -RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa); -int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa); -# endif -# ifndef OPENSSL_NO_DSA -DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); -int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); -DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); -int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); -# endif -# ifndef OPENSSL_NO_EC -EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); -int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); -EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); -int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); -# endif -X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8); -int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8); -PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, - PKCS8_PRIV_KEY_INFO **p8inf); -int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf); -int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); -int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); -EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); -int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); -EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); -# endif - -# ifndef OPENSSL_NO_BIO -X509 *d2i_X509_bio(BIO *bp, X509 **x509); -int i2d_X509_bio(BIO *bp, X509 *x509); -X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl); -int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl); -X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req); -int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req); -# ifndef OPENSSL_NO_RSA -RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa); -int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa); -RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa); -int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa); -RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa); -int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa); -# endif -# ifndef OPENSSL_NO_DSA -DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); -int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); -DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); -int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); -# endif -# ifndef OPENSSL_NO_EC -EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); -int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); -EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); -int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); -# endif -X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8); -int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8); -PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, - PKCS8_PRIV_KEY_INFO **p8inf); -int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf); -int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); -int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); -EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); -int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); -EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); -# endif - -X509 *X509_dup(X509 *x509); -X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); -X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); -X509_CRL *X509_CRL_dup(X509_CRL *crl); -X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev); -X509_REQ *X509_REQ_dup(X509_REQ *req); -X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); -int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, - void *pval); -void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval, - X509_ALGOR *algor); -void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); -int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); - -X509_NAME *X509_NAME_dup(X509_NAME *xn); -X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); - -int X509_cmp_time(const ASN1_TIME *s, time_t *t); -int X509_cmp_current_time(const ASN1_TIME *s); -ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t); -ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, - int offset_day, long offset_sec, time_t *t); -ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj); - -const char *X509_get_default_cert_area(void); -const char *X509_get_default_cert_dir(void); -const char *X509_get_default_cert_file(void); -const char *X509_get_default_cert_dir_env(void); -const char *X509_get_default_cert_file_env(void); -const char *X509_get_default_private_dir(void); - -X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); -X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey); - -DECLARE_ASN1_FUNCTIONS(X509_ALGOR) -DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS) -DECLARE_ASN1_FUNCTIONS(X509_VAL) - -DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) - -int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); -EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key); -int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain); -int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp); -EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length); -# ifndef OPENSSL_NO_RSA -int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp); -RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length); -# endif -# ifndef OPENSSL_NO_DSA -int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp); -DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length); -# endif -# ifndef OPENSSL_NO_EC -int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp); -EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length); -# endif - -DECLARE_ASN1_FUNCTIONS(X509_SIG) -DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) -DECLARE_ASN1_FUNCTIONS(X509_REQ) - -DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) -X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); - -DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) -DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) - -DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY) - -DECLARE_ASN1_FUNCTIONS(X509_NAME) - -int X509_NAME_set(X509_NAME **xn, X509_NAME *name); - -DECLARE_ASN1_FUNCTIONS(X509_CINF) - -DECLARE_ASN1_FUNCTIONS(X509) -DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX) - -DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR) - -int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); -int X509_set_ex_data(X509 *r, int idx, void *arg); -void *X509_get_ex_data(X509 *r, int idx); -int i2d_X509_AUX(X509 *a, unsigned char **pp); -X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length); - -int i2d_re_X509_tbs(X509 *x, unsigned char **pp); - -void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, - const X509 *x); -int X509_get_signature_nid(const X509 *x); - -int X509_alias_set1(X509 *x, unsigned char *name, int len); -int X509_keyid_set1(X509 *x, unsigned char *id, int len); -unsigned char *X509_alias_get0(X509 *x, int *len); -unsigned char *X509_keyid_get0(X509 *x, int *len); -int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, - int); -int X509_TRUST_set(int *t, int trust); -int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); -int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj); -void X509_trust_clear(X509 *x); -void X509_reject_clear(X509 *x); - -DECLARE_ASN1_FUNCTIONS(X509_REVOKED) -DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO) -DECLARE_ASN1_FUNCTIONS(X509_CRL) - -int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); -int X509_CRL_get0_by_serial(X509_CRL *crl, - X509_REVOKED **ret, ASN1_INTEGER *serial); -int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); - -X509_PKEY *X509_PKEY_new(void); -void X509_PKEY_free(X509_PKEY *a); -int i2d_X509_PKEY(X509_PKEY *a, unsigned char **pp); -X509_PKEY *d2i_X509_PKEY(X509_PKEY **a, const unsigned char **pp, - long length); - -DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI) -DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC) -DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) - -# ifndef OPENSSL_NO_EVP -X509_INFO *X509_INFO_new(void); -void X509_INFO_free(X509_INFO *a); -char *X509_NAME_oneline(X509_NAME *a, char *buf, int size); - -int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1, - ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey); - -int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, - unsigned char *md, unsigned int *len); - -int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, - X509_ALGOR *algor2, ASN1_BIT_STRING *signature, - char *data, EVP_PKEY *pkey, const EVP_MD *type); - -int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *data, - unsigned char *md, unsigned int *len); - -int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, - ASN1_BIT_STRING *signature, void *data, EVP_PKEY *pkey); - -int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, - X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data, - EVP_PKEY *pkey, const EVP_MD *type); -int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, - X509_ALGOR *algor2, ASN1_BIT_STRING *signature, - void *asn, EVP_MD_CTX *ctx); -# endif - -int X509_set_version(X509 *x, long version); -int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); -ASN1_INTEGER *X509_get_serialNumber(X509 *x); -int X509_set_issuer_name(X509 *x, X509_NAME *name); -X509_NAME *X509_get_issuer_name(X509 *a); -int X509_set_subject_name(X509 *x, X509_NAME *name); -X509_NAME *X509_get_subject_name(X509 *a); -int X509_set_notBefore(X509 *x, const ASN1_TIME *tm); -int X509_set_notAfter(X509 *x, const ASN1_TIME *tm); -int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); -EVP_PKEY *X509_get_pubkey(X509 *x); -ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); -int X509_certificate_type(X509 *x, EVP_PKEY *pubkey /* optional */ ); - -int X509_REQ_set_version(X509_REQ *x, long version); -int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); -int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); -EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); -int X509_REQ_extension_nid(int nid); -int *X509_REQ_get_extension_nids(void); -void X509_REQ_set_extension_nids(int *nids); -STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); -int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, - int nid); -int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); -int X509_REQ_get_attr_count(const X509_REQ *req); -int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos); -int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, - int lastpos); -X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); -X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); -int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); -int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, - const ASN1_OBJECT *obj, int type, - const unsigned char *bytes, int len); -int X509_REQ_add1_attr_by_NID(X509_REQ *req, - int nid, int type, - const unsigned char *bytes, int len); -int X509_REQ_add1_attr_by_txt(X509_REQ *req, - const char *attrname, int type, - const unsigned char *bytes, int len); - -int X509_CRL_set_version(X509_CRL *x, long version); -int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); -int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); -int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); -int X509_CRL_sort(X509_CRL *crl); - -int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); -int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); - -X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, - EVP_PKEY *skey, const EVP_MD *md, unsigned int flags); - -int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey); - -int X509_check_private_key(X509 *x509, EVP_PKEY *pkey); -int X509_chain_check_suiteb(int *perror_depth, - X509 *x, STACK_OF(X509) *chain, - unsigned long flags); -int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags); -STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); - -int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); -unsigned long X509_issuer_and_serial_hash(X509 *a); - -int X509_issuer_name_cmp(const X509 *a, const X509 *b); -unsigned long X509_issuer_name_hash(X509 *a); - -int X509_subject_name_cmp(const X509 *a, const X509 *b); -unsigned long X509_subject_name_hash(X509 *x); - -# ifndef OPENSSL_NO_MD5 -unsigned long X509_issuer_name_hash_old(X509 *a); -unsigned long X509_subject_name_hash_old(X509 *x); -# endif - -int X509_cmp(const X509 *a, const X509 *b); -int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); -unsigned long X509_NAME_hash(X509_NAME *x); -unsigned long X509_NAME_hash_old(X509_NAME *x); - -int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); -int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); -# ifndef OPENSSL_NO_FP_API -int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag, - unsigned long cflag); -int X509_print_fp(FILE *bp, X509 *x); -int X509_CRL_print_fp(FILE *bp, X509_CRL *x); -int X509_REQ_print_fp(FILE *bp, X509_REQ *req); -int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, - unsigned long flags); -# endif - -# ifndef OPENSSL_NO_BIO -int X509_NAME_print(BIO *bp, X509_NAME *name, int obase); -int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, - unsigned long flags); -int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag, - unsigned long cflag); -int X509_print(BIO *bp, X509 *x); -int X509_ocspid_print(BIO *bp, X509 *x); -int X509_CERT_AUX_print(BIO *bp, X509_CERT_AUX *x, int indent); -int X509_CRL_print(BIO *bp, X509_CRL *x); -int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, - unsigned long cflag); -int X509_REQ_print(BIO *bp, X509_REQ *req); -# endif - -int X509_NAME_entry_count(X509_NAME *name); -int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len); -int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, - char *buf, int len); - -/* - * NOTE: you should be passsing -1, not 0 as lastpos. The functions that use - * lastpos, search after that position on. - */ -int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); -int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, - int lastpos); -X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); -X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); -int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, - int loc, int set); -int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, - unsigned char *bytes, int len, int loc, - int set); -int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, - unsigned char *bytes, int len, int loc, - int set); -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, - const char *field, int type, - const unsigned char *bytes, - int len); -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, - int type, unsigned char *bytes, - int len); -int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, - const unsigned char *bytes, int len, int loc, - int set); -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, - ASN1_OBJECT *obj, int type, - const unsigned char *bytes, - int len); -int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj); -int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, - const unsigned char *bytes, int len); -ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne); -ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); - -int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); -int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, - int nid, int lastpos); -int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, - ASN1_OBJECT *obj, int lastpos); -int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, - int crit, int lastpos); -X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); -X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); -STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, - X509_EXTENSION *ex, int loc); - -int X509_get_ext_count(X509 *x); -int X509_get_ext_by_NID(X509 *x, int nid, int lastpos); -int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos); -int X509_get_ext_by_critical(X509 *x, int crit, int lastpos); -X509_EXTENSION *X509_get_ext(X509 *x, int loc); -X509_EXTENSION *X509_delete_ext(X509 *x, int loc); -int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); -void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); -int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, - unsigned long flags); - -int X509_CRL_get_ext_count(X509_CRL *x); -int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos); -int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos); -int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos); -X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc); -X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); -int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); -void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx); -int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, - unsigned long flags); - -int X509_REVOKED_get_ext_count(X509_REVOKED *x); -int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos); -int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj, - int lastpos); -int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos); -X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc); -X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); -int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); -void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx); -int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, - unsigned long flags); - -X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, - int nid, int crit, - ASN1_OCTET_STRING *data); -X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, - ASN1_OBJECT *obj, int crit, - ASN1_OCTET_STRING *data); -int X509_EXTENSION_set_object(X509_EXTENSION *ex, ASN1_OBJECT *obj); -int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); -int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data); -ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex); -ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); -int X509_EXTENSION_get_critical(X509_EXTENSION *ex); - -int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); -int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, - int lastpos); -int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, - ASN1_OBJECT *obj, int lastpos); -X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); -X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, - X509_ATTRIBUTE *attr); -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) - **x, const ASN1_OBJECT *obj, - int type, - const unsigned char *bytes, - int len); -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) - **x, int nid, int type, - const unsigned char *bytes, - int len); -STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) - **x, const char *attrname, - int type, - const unsigned char *bytes, - int len); -void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, ASN1_OBJECT *obj, - int lastpos, int type); -X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, - int atrtype, const void *data, - int len); -X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, - const ASN1_OBJECT *obj, - int atrtype, const void *data, - int len); -X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, - const char *atrname, int type, - const unsigned char *bytes, - int len); -int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); -int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, - const void *data, int len); -void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype, - void *data); -int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr); -ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); -ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); - -int EVP_PKEY_get_attr_count(const EVP_PKEY *key); -int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos); -int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj, - int lastpos); -X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc); -X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc); -int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr); -int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, - const ASN1_OBJECT *obj, int type, - const unsigned char *bytes, int len); -int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, - int nid, int type, - const unsigned char *bytes, int len); -int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, - const char *attrname, int type, - const unsigned char *bytes, int len); - -int X509_verify_cert(X509_STORE_CTX *ctx); - -/* lookup a cert from a X509 STACK */ -X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, - ASN1_INTEGER *serial); -X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name); - -DECLARE_ASN1_FUNCTIONS(PBEPARAM) -DECLARE_ASN1_FUNCTIONS(PBE2PARAM) -DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM) - -int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, - const unsigned char *salt, int saltlen); - -X509_ALGOR *PKCS5_pbe_set(int alg, int iter, - const unsigned char *salt, int saltlen); -X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, - unsigned char *salt, int saltlen); -X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, - unsigned char *salt, int saltlen, - unsigned char *aiv, int prf_nid); - -X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, - int prf_nid, int keylen); - -/* PKCS#8 utilities */ - -DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) - -EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8); -PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); -PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken); -PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); - -int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, - int version, int ptype, void *pval, - unsigned char *penc, int penclen); -int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, - const unsigned char **pk, int *ppklen, - X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8); - -int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, - int ptype, void *pval, - unsigned char *penc, int penclen); -int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, - const unsigned char **pk, int *ppklen, - X509_ALGOR **pa, X509_PUBKEY *pub); - -int X509_check_trust(X509 *x, int id, int flags); -int X509_TRUST_get_count(void); -X509_TRUST *X509_TRUST_get0(int idx); -int X509_TRUST_get_by_id(int id); -int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), - char *name, int arg1, void *arg2); -void X509_TRUST_cleanup(void); -int X509_TRUST_get_flags(X509_TRUST *xp); -char *X509_TRUST_get0_name(X509_TRUST *xp); -int X509_TRUST_get_trust(X509_TRUST *xp); - -/* BEGIN ERROR CODES */ -/* - * The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. - */ - -void ERR_load_X509_strings(void); - -/* Error codes for the X509 functions. */ - -/* Function codes. */ -# define X509_F_ADD_CERT_DIR 100 -# define X509_F_BY_FILE_CTRL 101 -# define X509_F_CHECK_NAME_CONSTRAINTS 106 -# define X509_F_CHECK_POLICY 145 -# define X509_F_DIR_CTRL 102 -# define X509_F_GET_CERT_BY_SUBJECT 103 -# define X509_F_NETSCAPE_SPKI_B64_DECODE 129 -# define X509_F_NETSCAPE_SPKI_B64_ENCODE 130 -# define X509_F_X509AT_ADD1_ATTR 135 -# define X509_F_X509V3_ADD_EXT 104 -# define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136 -# define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137 -# define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140 -# define X509_F_X509_ATTRIBUTE_GET0_DATA 139 -# define X509_F_X509_ATTRIBUTE_SET1_DATA 138 -# define X509_F_X509_CHECK_PRIVATE_KEY 128 -# define X509_F_X509_CRL_DIFF 105 -# define X509_F_X509_CRL_PRINT_FP 147 -# define X509_F_X509_EXTENSION_CREATE_BY_NID 108 -# define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 -# define X509_F_X509_GET_PUBKEY_PARAMETERS 110 -# define X509_F_X509_LOAD_CERT_CRL_FILE 132 -# define X509_F_X509_LOAD_CERT_FILE 111 -# define X509_F_X509_LOAD_CRL_FILE 112 -# define X509_F_X509_NAME_ADD_ENTRY 113 -# define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114 -# define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131 -# define X509_F_X509_NAME_ENTRY_SET_OBJECT 115 -# define X509_F_X509_NAME_ONELINE 116 -# define X509_F_X509_NAME_PRINT 117 -# define X509_F_X509_PRINT_EX_FP 118 -# define X509_F_X509_PUBKEY_GET 119 -# define X509_F_X509_PUBKEY_SET 120 -# define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144 -# define X509_F_X509_REQ_PRINT_EX 121 -# define X509_F_X509_REQ_PRINT_FP 122 -# define X509_F_X509_REQ_TO_X509 123 -# define X509_F_X509_STORE_ADD_CERT 124 -# define X509_F_X509_STORE_ADD_CRL 125 -# define X509_F_X509_STORE_CTX_GET1_ISSUER 146 -# define X509_F_X509_STORE_CTX_INIT 143 -# define X509_F_X509_STORE_CTX_NEW 142 -# define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 -# define X509_F_X509_TO_X509_REQ 126 -# define X509_F_X509_TRUST_ADD 133 -# define X509_F_X509_TRUST_SET 141 -# define X509_F_X509_VERIFY_CERT 127 - -/* Reason codes. */ -# define X509_R_AKID_MISMATCH 110 -# define X509_R_BAD_X509_FILETYPE 100 -# define X509_R_BASE64_DECODE_ERROR 118 -# define X509_R_CANT_CHECK_DH_KEY 114 -# define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 -# define X509_R_CRL_ALREADY_DELTA 127 -# define X509_R_CRL_VERIFY_FAILURE 131 -# define X509_R_ERR_ASN1_LIB 102 -# define X509_R_IDP_MISMATCH 128 -# define X509_R_INVALID_DIRECTORY 113 -# define X509_R_INVALID_FIELD_NAME 119 -# define X509_R_INVALID_TRUST 123 -# define X509_R_ISSUER_MISMATCH 129 -# define X509_R_KEY_TYPE_MISMATCH 115 -# define X509_R_KEY_VALUES_MISMATCH 116 -# define X509_R_LOADING_CERT_DIR 103 -# define X509_R_LOADING_DEFAULTS 104 -# define X509_R_METHOD_NOT_SUPPORTED 124 -# define X509_R_NAME_TOO_LONG 134 -# define X509_R_NEWER_CRL_NOT_NEWER 132 -# define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 -# define X509_R_NO_CRL_NUMBER 130 -# define X509_R_PUBLIC_KEY_DECODE_ERROR 125 -# define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 -# define X509_R_SHOULD_RETRY 106 -# define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107 -# define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 -# define X509_R_UNKNOWN_KEY_TYPE 117 -# define X509_R_UNKNOWN_NID 109 -# define X509_R_UNKNOWN_PURPOSE_ID 121 -# define X509_R_UNKNOWN_TRUST_ID 120 -# define X509_R_UNSUPPORTED_ALGORITHM 111 -# define X509_R_WRONG_LOOKUP_TYPE 112 -# define X509_R_WRONG_TYPE 122 - -# ifdef __cplusplus -} -# endif -#endif diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index 25010753078c..63895efe4608 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -1,69 +1,21 @@ -/* crypto/x509/x509_att.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2017 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> -#include <openssl/stack.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" +#include <openssl/safestack.h> #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include "x509_lcl.h" int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) { @@ -73,22 +25,21 @@ int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, int lastpos) { - ASN1_OBJECT *obj; + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); - obj = OBJ_nid2obj(nid); if (obj == NULL) - return (-2); - return (X509at_get_attr_by_OBJ(x, obj, lastpos)); + return -2; + return X509at_get_attr_by_OBJ(x, obj, lastpos); } int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, - ASN1_OBJECT *obj, int lastpos) + const ASN1_OBJECT *obj, int lastpos) { int n; X509_ATTRIBUTE *ex; if (sk == NULL) - return (-1); + return -1; lastpos++; if (lastpos < 0) lastpos = 0; @@ -96,17 +47,17 @@ int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, for (; lastpos < n; lastpos++) { ex = sk_X509_ATTRIBUTE_value(sk, lastpos); if (OBJ_cmp(ex->object, obj) == 0) - return (lastpos); + return lastpos; } - return (-1); + return -1; } X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) { if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) return NULL; - else - return sk_X509_ATTRIBUTE_value(x, loc); + + return sk_X509_ATTRIBUTE_value(x, loc); } X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) @@ -114,9 +65,9 @@ X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) X509_ATTRIBUTE *ret; if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) - return (NULL); + return NULL; ret = sk_X509_ATTRIBUTE_delete(x, loc); - return (ret); + return ret; } STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, @@ -142,15 +93,13 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, goto err; if (*x == NULL) *x = sk; - return (sk); + return sk; err: X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_MALLOC_FAILURE); err2: - if (new_attr != NULL) - X509_ATTRIBUTE_free(new_attr); - if (sk != NULL) - sk_X509_ATTRIBUTE_free(sk); - return (NULL); + X509_ATTRIBUTE_free(new_attr); + sk_X509_ATTRIBUTE_free(sk); + return NULL; } STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) @@ -201,7 +150,7 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) } void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, - ASN1_OBJECT *obj, int lastpos, int type) + const ASN1_OBJECT *obj, int lastpos, int type) { int i; X509_ATTRIBUTE *at; @@ -226,12 +175,12 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, obj = OBJ_nid2obj(nid); if (obj == NULL) { X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID, X509_R_UNKNOWN_NID); - return (NULL); + return NULL; } ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); if (ret == NULL) ASN1_OBJECT_free(obj); - return (ret); + return ret; } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, @@ -245,7 +194,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, if ((ret = X509_ATTRIBUTE_new()) == NULL) { X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, ERR_R_MALLOC_FAILURE); - return (NULL); + return NULL; } } else ret = *attr; @@ -257,11 +206,11 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, if ((attr != NULL) && (*attr == NULL)) *attr = ret; - return (ret); + return ret; err: if ((attr == NULL) || (ret != *attr)) X509_ATTRIBUTE_free(ret); - return (NULL); + return NULL; } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, @@ -277,7 +226,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, X509_R_INVALID_FIELD_NAME); ERR_add_error_data(2, "name=", atrname); - return (NULL); + return NULL; } nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); ASN1_OBJECT_free(obj); @@ -287,10 +236,10 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) { if ((attr == NULL) || (obj == NULL)) - return (0); + return 0; ASN1_OBJECT_free(attr->object); attr->object = OBJ_dup(obj); - return (1); + return attr->object != NULL; } int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, @@ -310,15 +259,12 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, } atype = stmp->type; } else if (len != -1) { - if (!(stmp = ASN1_STRING_type_new(attrtype))) + if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL) goto err; if (!ASN1_STRING_set(stmp, data, len)) goto err; atype = attrtype; } - if (!(attr->value.set = sk_ASN1_TYPE_new_null())) - goto err; - attr->single = 0; /* * This is a bit naughty because the attribute should really have at * least one value but some types use and zero length SET and require @@ -328,7 +274,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, ASN1_STRING_free(stmp); return 1; } - if (!(ttmp = ASN1_TYPE_new())) + if ((ttmp = ASN1_TYPE_new()) == NULL) goto err; if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { if (!ASN1_TYPE_set1(ttmp, attrtype, data)) @@ -337,7 +283,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, ASN1_TYPE_set(ttmp, atype, stmp); stmp = NULL; } - if (!sk_ASN1_TYPE_push(attr->value.set, ttmp)) + if (!sk_ASN1_TYPE_push(attr->set, ttmp)) goto err; return 1; err: @@ -347,20 +293,18 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, return 0; } -int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) { - if (!attr->single) - return sk_ASN1_TYPE_num(attr->value.set); - if (attr->value.single) - return 1; - return 0; + if (attr == NULL) + return 0; + return sk_ASN1_TYPE_num(attr->set); } ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) { if (attr == NULL) - return (NULL); - return (attr->object); + return NULL; + return attr->object; } void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, @@ -380,11 +324,6 @@ void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) { if (attr == NULL) - return (NULL); - if (idx >= X509_ATTRIBUTE_count(attr)) return NULL; - if (!attr->single) - return sk_ASN1_TYPE_value(attr->value.set, idx); - else - return attr->value.single; + return sk_ASN1_TYPE_value(attr->set, idx); } diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 49c71b91280e..02fad0c671ce 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -1,174 +1,128 @@ -/* crypto/x509/x509_cmp.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. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * 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> -#include <ctype.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include "internal/x509_int.h" int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) { int i; - X509_CINF *ai, *bi; + const X509_CINF *ai, *bi; - ai = a->cert_info; - bi = b->cert_info; - i = M_ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber); + ai = &a->cert_info; + bi = &b->cert_info; + i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber); if (i) - return (i); - return (X509_NAME_cmp(ai->issuer, bi->issuer)); + return i; + return X509_NAME_cmp(ai->issuer, bi->issuer); } #ifndef OPENSSL_NO_MD5 unsigned long X509_issuer_and_serial_hash(X509 *a) { unsigned long ret = 0; - EVP_MD_CTX ctx; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); unsigned char md[16]; char *f; - EVP_MD_CTX_init(&ctx); - f = X509_NAME_oneline(a->cert_info->issuer, NULL, 0); - if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) + if (ctx == NULL) + goto err; + f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0); + if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) goto err; - if (!EVP_DigestUpdate(&ctx, (unsigned char *)f, strlen(f))) + if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f))) goto err; OPENSSL_free(f); if (!EVP_DigestUpdate - (&ctx, (unsigned char *)a->cert_info->serialNumber->data, - (unsigned long)a->cert_info->serialNumber->length)) + (ctx, (unsigned char *)a->cert_info.serialNumber.data, + (unsigned long)a->cert_info.serialNumber.length)) goto err; - if (!EVP_DigestFinal_ex(&ctx, &(md[0]), NULL)) + if (!EVP_DigestFinal_ex(ctx, &(md[0]), NULL)) goto err; ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) ) & 0xffffffffL; err: - EVP_MD_CTX_cleanup(&ctx); - return (ret); + EVP_MD_CTX_free(ctx); + return ret; } #endif int X509_issuer_name_cmp(const X509 *a, const X509 *b) { - return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer)); + return X509_NAME_cmp(a->cert_info.issuer, b->cert_info.issuer); } int X509_subject_name_cmp(const X509 *a, const X509 *b) { - return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject)); + return X509_NAME_cmp(a->cert_info.subject, b->cert_info.subject); } int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) { - return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer)); + return X509_NAME_cmp(a->crl.issuer, b->crl.issuer); } -#ifndef OPENSSL_NO_SHA int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) { return memcmp(a->sha1_hash, b->sha1_hash, 20); } -#endif -X509_NAME *X509_get_issuer_name(X509 *a) +X509_NAME *X509_get_issuer_name(const X509 *a) { - return (a->cert_info->issuer); + return a->cert_info.issuer; } unsigned long X509_issuer_name_hash(X509 *x) { - return (X509_NAME_hash(x->cert_info->issuer)); + return X509_NAME_hash(x->cert_info.issuer); } #ifndef OPENSSL_NO_MD5 unsigned long X509_issuer_name_hash_old(X509 *x) { - return (X509_NAME_hash_old(x->cert_info->issuer)); + return X509_NAME_hash_old(x->cert_info.issuer); } #endif -X509_NAME *X509_get_subject_name(X509 *a) +X509_NAME *X509_get_subject_name(const X509 *a) { - return (a->cert_info->subject); + return a->cert_info.subject; } ASN1_INTEGER *X509_get_serialNumber(X509 *a) { - return (a->cert_info->serialNumber); + return &a->cert_info.serialNumber; +} + +const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a) +{ + return &a->cert_info.serialNumber; } unsigned long X509_subject_name_hash(X509 *x) { - return (X509_NAME_hash(x->cert_info->subject)); + return X509_NAME_hash(x->cert_info.subject); } #ifndef OPENSSL_NO_MD5 unsigned long X509_subject_name_hash_old(X509 *x) { - return (X509_NAME_hash_old(x->cert_info->subject)); + return X509_NAME_hash_old(x->cert_info.subject); } #endif -#ifndef OPENSSL_NO_SHA /* * Compare two certificates: they must be identical for this to work. NB: * Although "cmp" operations are generally prototyped to take "const" @@ -188,16 +142,16 @@ int X509_cmp(const X509 *a, const X509 *b) if (rv) return rv; /* Check for match against stored encoding too */ - if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) { - rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len); - if (rv) - return rv; - return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc, - a->cert_info->enc.len); + if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) { + if (a->cert_info.enc.len < b->cert_info.enc.len) + return -1; + if (a->cert_info.enc.len > b->cert_info.enc.len) + return 1; + return memcmp(a->cert_info.enc.enc, b->cert_info.enc.enc, + a->cert_info.enc.len); } return rv; } -#endif int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { @@ -219,7 +173,7 @@ int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) ret = a->canon_enclen - b->canon_enclen; - if (ret) + if (ret != 0 || a->canon_enclen == 0) return ret; return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); @@ -240,7 +194,7 @@ unsigned long X509_NAME_hash(X509_NAME *x) ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) ) & 0xffffffffL; - return (ret); + return ret; } #ifndef OPENSSL_NO_MD5 @@ -251,23 +205,25 @@ unsigned long X509_NAME_hash(X509_NAME *x) unsigned long X509_NAME_hash_old(X509_NAME *x) { - EVP_MD_CTX md_ctx; + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); unsigned long ret = 0; unsigned char md[16]; + if (md_ctx == NULL) + return ret; + /* Make sure X509_NAME structure contains valid cached encoding */ i2d_X509_NAME(x, NULL); - EVP_MD_CTX_init(&md_ctx); - EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) - && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) - && EVP_DigestFinal_ex(&md_ctx, md, NULL)) + EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + if (EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL) + && EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length) + && EVP_DigestFinal_ex(md_ctx, md, NULL)) ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) ) & 0xffffffffL; - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); - return (ret); + return ret; } #endif @@ -276,22 +232,20 @@ X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, ASN1_INTEGER *serial) { int i; - X509_CINF cinf; X509 x, *x509 = NULL; if (!sk) return NULL; - x.cert_info = &cinf; - cinf.serialNumber = serial; - cinf.issuer = name; + x.cert_info.serialNumber = *serial; + x.cert_info.issuer = name; for (i = 0; i < sk_X509_num(sk); i++) { x509 = sk_X509_value(sk, i); if (X509_issuer_and_serial_cmp(x509, &x) == 0) - return (x509); + return x509; } - return (NULL); + return NULL; } X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) @@ -302,31 +256,31 @@ X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) for (i = 0; i < sk_X509_num(sk); i++) { x509 = sk_X509_value(sk, i); if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) - return (x509); + return x509; } - return (NULL); + return NULL; } -EVP_PKEY *X509_get_pubkey(X509 *x) +EVP_PKEY *X509_get0_pubkey(const X509 *x) { - if ((x == NULL) || (x->cert_info == NULL)) - return (NULL); - return (X509_PUBKEY_get(x->cert_info->key)); + if (x == NULL) + return NULL; + return X509_PUBKEY_get0(x->cert_info.key); } -ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) +EVP_PKEY *X509_get_pubkey(X509 *x) { - if (!x) + if (x == NULL) return NULL; - return x->cert_info->key->public_key; + return X509_PUBKEY_get(x->cert_info.key); } -int X509_check_private_key(X509 *x, EVP_PKEY *k) +int X509_check_private_key(const X509 *x, const EVP_PKEY *k) { - EVP_PKEY *xk; + const EVP_PKEY *xk; int ret; - xk = X509_get_pubkey(x); + xk = X509_get0_pubkey(x); if (xk) ret = EVP_PKEY_cmp(xk, k); @@ -345,8 +299,6 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k) case -2: X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE); } - if (xk) - EVP_PKEY_free(xk); if (ret > 0) return 1; return 0; @@ -364,8 +316,8 @@ static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) { const EC_GROUP *grp = NULL; int curve_nid; - if (pkey && pkey->type == EVP_PKEY_EC) - grp = EC_KEY_get0_group(pkey->pkey.ec); + if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_EC) + grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)); if (!grp) return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; curve_nid = EC_GROUP_get_curve_name(grp); @@ -395,11 +347,12 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, unsigned long flags) { int rv, i, sign_nid; - EVP_PKEY *pk = NULL; - unsigned long tflags; + EVP_PKEY *pk; + unsigned long tflags = flags; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; - tflags = flags; + /* If no EE certificate passed in must be first in chain */ if (x == NULL) { x = sk_X509_value(chain, 0); @@ -407,6 +360,17 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, } else i = 0; + pk = X509_get0_pubkey(x); + + /* + * With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build + * a chain all, just report trust success or failure, but must also report + * Suite-B errors if applicable. This is indicated via a NULL chain + * pointer. All we need to do is check the leaf key algorithm. + */ + if (chain == NULL) + return check_suite_b(pk, -1, &tflags); + if (X509_get_version(x) != 2) { rv = X509_V_ERR_SUITE_B_INVALID_VERSION; /* Correct error depth */ @@ -414,7 +378,6 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, goto end; } - pk = X509_get_pubkey(x); /* Check EE key only */ rv = check_suite_b(pk, -1, &tflags); if (rv != X509_V_OK) { @@ -429,8 +392,7 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, rv = X509_V_ERR_SUITE_B_INVALID_VERSION; goto end; } - EVP_PKEY_free(pk); - pk = X509_get_pubkey(x); + pk = X509_get0_pubkey(x); rv = check_suite_b(pk, sign_nid, &tflags); if (rv != X509_V_OK) goto end; @@ -439,8 +401,6 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, /* Final check: root CA signature */ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); end: - if (pk) - EVP_PKEY_free(pk); if (rv != X509_V_OK) { /* Invalid signature or LOS errors are for previous cert */ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM @@ -448,7 +408,7 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, i--; /* * If we have LOS error and flags changed then we are signing P-384 - * with P-256. Use more meaninggul error. + * with P-256. Use more meaningful error. */ if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; @@ -463,7 +423,7 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) int sign_nid; if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; - sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm); + sign_nid = OBJ_obj2nid(crl->crl.sig_alg.algorithm); return check_suite_b(pk, sign_nid, &flags); } @@ -492,7 +452,7 @@ STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) ret = sk_X509_dup(chain); for (i = 0; i < sk_X509_num(ret); i++) { X509 *x = sk_X509_value(ret, i); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); } return ret; } diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c index 50ca2a6d1820..099ffda1e15c 100644 --- a/crypto/x509/x509_d2.c +++ b/crypto/x509/x509_d2.c @@ -1,85 +1,35 @@ -/* crypto/x509/x509_d2.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> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/crypto.h> #include <openssl/x509.h> -#ifndef OPENSSL_NO_STDIO int X509_STORE_set_default_paths(X509_STORE *ctx) { X509_LOOKUP *lookup; lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); if (lookup == NULL) - return (0); + return 0; X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) - return (0); + return 0; X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); /* clear any errors */ ERR_clear_error(); - return (1); + return 1; } int X509_STORE_load_locations(X509_STORE *ctx, const char *file, @@ -90,20 +40,18 @@ int X509_STORE_load_locations(X509_STORE *ctx, const char *file, if (file != NULL) { lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); if (lookup == NULL) - return (0); + return 0; if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1) - return (0); + return 0; } if (path != NULL) { lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) - return (0); + return 0; if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) - return (0); + return 0; } if ((path == NULL) && (file == NULL)) - return (0); - return (1); + return 0; + return 1; } - -#endif diff --git a/crypto/x509/x509_def.c b/crypto/x509/x509_def.c index 25c553755627..bfa8d7d8522a 100644 --- a/crypto/x509/x509_def.c +++ b/crypto/x509/x509_def.c @@ -1,92 +1,43 @@ -/* crypto/x509/x509_def.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> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/crypto.h> #include <openssl/x509.h> const char *X509_get_default_private_dir(void) { - return (X509_PRIVATE_DIR); + return X509_PRIVATE_DIR; } const char *X509_get_default_cert_area(void) { - return (X509_CERT_AREA); + return X509_CERT_AREA; } const char *X509_get_default_cert_dir(void) { - return (X509_CERT_DIR); + return X509_CERT_DIR; } const char *X509_get_default_cert_file(void) { - return (X509_CERT_FILE); + return X509_CERT_FILE; } const char *X509_get_default_cert_dir_env(void) { - return (X509_CERT_DIR_EVP); + return X509_CERT_DIR_EVP; } const char *X509_get_default_cert_file_env(void) { - return (X509_CERT_FILE_EVP); + return X509_CERT_FILE_EVP; } diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index a2a8e1b08bb2..739708e24fa3 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -1,188 +1,181 @@ -/* crypto/x509/x509_err.c */ -/* ==================================================================== - * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - /* - * NOTE: this file was auto generated by the mkerr.pl script: any changes - * made to it will be overwritten when the script next updates this file, - * only reason strings will be preserved. + * Generated by util/mkerr.pl DO NOT EDIT + * 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 <openssl/err.h> -#include <openssl/x509.h> +#include <openssl/x509err.h> -/* BEGIN ERROR CODES */ #ifndef OPENSSL_NO_ERR -# define ERR_FUNC(func) ERR_PACK(ERR_LIB_X509,func,0) -# define ERR_REASON(reason) ERR_PACK(ERR_LIB_X509,0,reason) - -static ERR_STRING_DATA X509_str_functs[] = { - {ERR_FUNC(X509_F_ADD_CERT_DIR), "ADD_CERT_DIR"}, - {ERR_FUNC(X509_F_BY_FILE_CTRL), "BY_FILE_CTRL"}, - {ERR_FUNC(X509_F_CHECK_NAME_CONSTRAINTS), "CHECK_NAME_CONSTRAINTS"}, - {ERR_FUNC(X509_F_CHECK_POLICY), "CHECK_POLICY"}, - {ERR_FUNC(X509_F_DIR_CTRL), "DIR_CTRL"}, - {ERR_FUNC(X509_F_GET_CERT_BY_SUBJECT), "GET_CERT_BY_SUBJECT"}, - {ERR_FUNC(X509_F_NETSCAPE_SPKI_B64_DECODE), "NETSCAPE_SPKI_b64_decode"}, - {ERR_FUNC(X509_F_NETSCAPE_SPKI_B64_ENCODE), "NETSCAPE_SPKI_b64_encode"}, - {ERR_FUNC(X509_F_X509AT_ADD1_ATTR), "X509at_add1_attr"}, - {ERR_FUNC(X509_F_X509V3_ADD_EXT), "X509v3_add_ext"}, - {ERR_FUNC(X509_F_X509_ATTRIBUTE_CREATE_BY_NID), +static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_ADD_CERT_DIR, 0), "add_cert_dir"}, + {ERR_PACK(ERR_LIB_X509, X509_F_BUILD_CHAIN, 0), "build_chain"}, + {ERR_PACK(ERR_LIB_X509, X509_F_BY_FILE_CTRL, 0), "by_file_ctrl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_NAME_CONSTRAINTS, 0), + "check_name_constraints"}, + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0), + "get_cert_by_subject"}, + {ERR_PACK(ERR_LIB_X509, X509_F_I2D_X509_AUX, 0), "i2d_X509_AUX"}, + {ERR_PACK(ERR_LIB_X509, X509_F_LOOKUP_CERTS_SK, 0), "lookup_certs_sk"}, + {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_DECODE, 0), + "NETSCAPE_SPKI_b64_decode"}, + {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_ENCODE, 0), + "NETSCAPE_SPKI_b64_encode"}, + {ERR_PACK(ERR_LIB_X509, X509_F_NEW_DIR, 0), "new_dir"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509AT_ADD1_ATTR, 0), "X509at_add1_attr"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509V3_ADD_EXT, 0), "X509v3_add_ext"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_NID, 0), "X509_ATTRIBUTE_create_by_NID"}, - {ERR_FUNC(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, 0), "X509_ATTRIBUTE_create_by_OBJ"}, - {ERR_FUNC(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, 0), "X509_ATTRIBUTE_create_by_txt"}, - {ERR_FUNC(X509_F_X509_ATTRIBUTE_GET0_DATA), "X509_ATTRIBUTE_get0_data"}, - {ERR_FUNC(X509_F_X509_ATTRIBUTE_SET1_DATA), "X509_ATTRIBUTE_set1_data"}, - {ERR_FUNC(X509_F_X509_CHECK_PRIVATE_KEY), "X509_check_private_key"}, - {ERR_FUNC(X509_F_X509_CRL_DIFF), "X509_CRL_diff"}, - {ERR_FUNC(X509_F_X509_CRL_PRINT_FP), "X509_CRL_print_fp"}, - {ERR_FUNC(X509_F_X509_EXTENSION_CREATE_BY_NID), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_GET0_DATA, 0), + "X509_ATTRIBUTE_get0_data"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_SET1_DATA, 0), + "X509_ATTRIBUTE_set1_data"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CHECK_PRIVATE_KEY, 0), + "X509_check_private_key"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_DIFF, 0), "X509_CRL_diff"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_METHOD_NEW, 0), + "X509_CRL_METHOD_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_PRINT_FP, 0), "X509_CRL_print_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_NID, 0), "X509_EXTENSION_create_by_NID"}, - {ERR_FUNC(X509_F_X509_EXTENSION_CREATE_BY_OBJ), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_OBJ, 0), "X509_EXTENSION_create_by_OBJ"}, - {ERR_FUNC(X509_F_X509_GET_PUBKEY_PARAMETERS), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_GET_PUBKEY_PARAMETERS, 0), "X509_get_pubkey_parameters"}, - {ERR_FUNC(X509_F_X509_LOAD_CERT_CRL_FILE), "X509_load_cert_crl_file"}, - {ERR_FUNC(X509_F_X509_LOAD_CERT_FILE), "X509_load_cert_file"}, - {ERR_FUNC(X509_F_X509_LOAD_CRL_FILE), "X509_load_crl_file"}, - {ERR_FUNC(X509_F_X509_NAME_ADD_ENTRY), "X509_NAME_add_entry"}, - {ERR_FUNC(X509_F_X509_NAME_ENTRY_CREATE_BY_NID), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_CRL_FILE, 0), + "X509_load_cert_crl_file"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_FILE, 0), + "X509_load_cert_file"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CRL_FILE, 0), + "X509_load_crl_file"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_METH_NEW, 0), + "X509_LOOKUP_meth_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_NEW, 0), "X509_LOOKUP_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ADD_ENTRY, 0), + "X509_NAME_add_entry"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_CANON, 0), "x509_name_canon"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_NID, 0), "X509_NAME_ENTRY_create_by_NID"}, - {ERR_FUNC(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, 0), "X509_NAME_ENTRY_create_by_txt"}, - {ERR_FUNC(X509_F_X509_NAME_ENTRY_SET_OBJECT), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_SET_OBJECT, 0), "X509_NAME_ENTRY_set_object"}, - {ERR_FUNC(X509_F_X509_NAME_ONELINE), "X509_NAME_oneline"}, - {ERR_FUNC(X509_F_X509_NAME_PRINT), "X509_NAME_print"}, - {ERR_FUNC(X509_F_X509_PRINT_EX_FP), "X509_print_ex_fp"}, - {ERR_FUNC(X509_F_X509_PUBKEY_GET), "X509_PUBKEY_get"}, - {ERR_FUNC(X509_F_X509_PUBKEY_SET), "X509_PUBKEY_set"}, - {ERR_FUNC(X509_F_X509_REQ_CHECK_PRIVATE_KEY), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ONELINE, 0), "X509_NAME_oneline"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_PRINT, 0), "X509_NAME_print"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_OBJECT_NEW, 0), "X509_OBJECT_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PRINT_EX_FP, 0), "X509_print_ex_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_DECODE, 0), + "x509_pubkey_decode"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_GET0, 0), "X509_PUBKEY_get0"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_SET, 0), "X509_PUBKEY_set"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_CHECK_PRIVATE_KEY, 0), "X509_REQ_check_private_key"}, - {ERR_FUNC(X509_F_X509_REQ_PRINT_EX), "X509_REQ_print_ex"}, - {ERR_FUNC(X509_F_X509_REQ_PRINT_FP), "X509_REQ_print_fp"}, - {ERR_FUNC(X509_F_X509_REQ_TO_X509), "X509_REQ_to_X509"}, - {ERR_FUNC(X509_F_X509_STORE_ADD_CERT), "X509_STORE_add_cert"}, - {ERR_FUNC(X509_F_X509_STORE_ADD_CRL), "X509_STORE_add_crl"}, - {ERR_FUNC(X509_F_X509_STORE_CTX_GET1_ISSUER), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_EX, 0), "X509_REQ_print_ex"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_FP, 0), "X509_REQ_print_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_TO_X509, 0), "X509_REQ_to_X509"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CERT, 0), + "X509_STORE_add_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CRL, 0), + "X509_STORE_add_crl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_LOOKUP, 0), + "X509_STORE_add_lookup"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_GET1_ISSUER, 0), "X509_STORE_CTX_get1_issuer"}, - {ERR_FUNC(X509_F_X509_STORE_CTX_INIT), "X509_STORE_CTX_init"}, - {ERR_FUNC(X509_F_X509_STORE_CTX_NEW), "X509_STORE_CTX_new"}, - {ERR_FUNC(X509_F_X509_STORE_CTX_PURPOSE_INHERIT), + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_INIT, 0), + "X509_STORE_CTX_init"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_NEW, 0), + "X509_STORE_CTX_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_PURPOSE_INHERIT, 0), "X509_STORE_CTX_purpose_inherit"}, - {ERR_FUNC(X509_F_X509_TO_X509_REQ), "X509_to_X509_REQ"}, - {ERR_FUNC(X509_F_X509_TRUST_ADD), "X509_TRUST_add"}, - {ERR_FUNC(X509_F_X509_TRUST_SET), "X509_TRUST_set"}, - {ERR_FUNC(X509_F_X509_VERIFY_CERT), "X509_verify_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_NEW, 0), "X509_STORE_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TO_X509_REQ, 0), "X509_to_X509_REQ"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_ADD, 0), "X509_TRUST_add"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_SET, 0), "X509_TRUST_set"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_CERT, 0), "X509_verify_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_PARAM_NEW, 0), + "X509_VERIFY_PARAM_new"}, {0, NULL} }; -static ERR_STRING_DATA X509_str_reasons[] = { - {ERR_REASON(X509_R_AKID_MISMATCH), "akid mismatch"}, - {ERR_REASON(X509_R_BAD_X509_FILETYPE), "bad x509 filetype"}, - {ERR_REASON(X509_R_BASE64_DECODE_ERROR), "base64 decode error"}, - {ERR_REASON(X509_R_CANT_CHECK_DH_KEY), "cant check dh key"}, - {ERR_REASON(X509_R_CERT_ALREADY_IN_HASH_TABLE), - "cert already in hash table"}, - {ERR_REASON(X509_R_CRL_ALREADY_DELTA), "crl already delta"}, - {ERR_REASON(X509_R_CRL_VERIFY_FAILURE), "crl verify failure"}, - {ERR_REASON(X509_R_ERR_ASN1_LIB), "err asn1 lib"}, - {ERR_REASON(X509_R_IDP_MISMATCH), "idp mismatch"}, - {ERR_REASON(X509_R_INVALID_DIRECTORY), "invalid directory"}, - {ERR_REASON(X509_R_INVALID_FIELD_NAME), "invalid field name"}, - {ERR_REASON(X509_R_INVALID_TRUST), "invalid trust"}, - {ERR_REASON(X509_R_ISSUER_MISMATCH), "issuer mismatch"}, - {ERR_REASON(X509_R_KEY_TYPE_MISMATCH), "key type mismatch"}, - {ERR_REASON(X509_R_KEY_VALUES_MISMATCH), "key values mismatch"}, - {ERR_REASON(X509_R_LOADING_CERT_DIR), "loading cert dir"}, - {ERR_REASON(X509_R_LOADING_DEFAULTS), "loading defaults"}, - {ERR_REASON(X509_R_METHOD_NOT_SUPPORTED), "method not supported"}, - {ERR_REASON(X509_R_NAME_TOO_LONG), "name too long"}, - {ERR_REASON(X509_R_NEWER_CRL_NOT_NEWER), "newer crl not newer"}, - {ERR_REASON(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), - "no cert set for us to verify"}, - {ERR_REASON(X509_R_NO_CRL_NUMBER), "no crl number"}, - {ERR_REASON(X509_R_PUBLIC_KEY_DECODE_ERROR), "public key decode error"}, - {ERR_REASON(X509_R_PUBLIC_KEY_ENCODE_ERROR), "public key encode error"}, - {ERR_REASON(X509_R_SHOULD_RETRY), "should retry"}, - {ERR_REASON(X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), - "unable to find parameters in chain"}, - {ERR_REASON(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), - "unable to get certs public key"}, - {ERR_REASON(X509_R_UNKNOWN_KEY_TYPE), "unknown key type"}, - {ERR_REASON(X509_R_UNKNOWN_NID), "unknown nid"}, - {ERR_REASON(X509_R_UNKNOWN_PURPOSE_ID), "unknown purpose id"}, - {ERR_REASON(X509_R_UNKNOWN_TRUST_ID), "unknown trust id"}, - {ERR_REASON(X509_R_UNSUPPORTED_ALGORITHM), "unsupported algorithm"}, - {ERR_REASON(X509_R_WRONG_LOOKUP_TYPE), "wrong lookup type"}, - {ERR_REASON(X509_R_WRONG_TYPE), "wrong type"}, +static const ERR_STRING_DATA X509_str_reasons[] = { + {ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "akid mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_SELECTOR), "bad selector"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "bad x509 filetype"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR), + "base64 decode error"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "cant check dh key"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), + "cert already in hash table"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE), + "crl verify failure"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "idp mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "invalid directory"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME), + "invalid field name"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "invalid trust"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_ISSUER_MISMATCH), "issuer mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_TYPE_MISMATCH), "key type mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_VALUES_MISMATCH), + "key values mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_CERT_DIR), "loading cert dir"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_DEFAULTS), "loading defaults"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_METHOD_NOT_SUPPORTED), + "method not supported"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NAME_TOO_LONG), "name too long"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NEWER_CRL_NOT_NEWER), + "newer crl not newer"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATE_FOUND), + "no certificate found"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATE_OR_CRL_FOUND), + "no certificate or crl found"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), + "no cert set for us to verify"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_FOUND), "no crl found"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_NUMBER), "no crl number"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_DECODE_ERROR), + "public key decode error"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_ENCODE_ERROR), + "public key encode error"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_SHOULD_RETRY), "should retry"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), + "unable to find parameters in chain"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), + "unable to get certs public key"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_KEY_TYPE), "unknown key type"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "unknown nid"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID), + "unknown purpose id"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "unknown trust id"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM), + "unsupported algorithm"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "wrong lookup type"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "wrong type"}, {0, NULL} }; #endif -void ERR_load_X509_strings(void) +int ERR_load_X509_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(X509_str_functs[0].error) == NULL) { - ERR_load_strings(0, X509_str_functs); - ERR_load_strings(0, X509_str_reasons); + ERR_load_strings_const(X509_str_functs); + ERR_load_strings_const(X509_str_reasons); } #endif + return 1; } diff --git a/crypto/x509/x509_ext.c b/crypto/x509/x509_ext.c index fb4e311d7100..2db843760c68 100644 --- a/crypto/x509/x509_ext.c +++ b/crypto/x509/x509_ext.c @@ -1,193 +1,145 @@ -/* crypto/x509/x509_ext.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2017 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> -#include <openssl/stack.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include "internal/x509_int.h" #include <openssl/x509v3.h> -int X509_CRL_get_ext_count(X509_CRL *x) +int X509_CRL_get_ext_count(const X509_CRL *x) { - return (X509v3_get_ext_count(x->crl->extensions)); + return X509v3_get_ext_count(x->crl.extensions); } -int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos) +int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos) { - return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos)); + return X509v3_get_ext_by_NID(x->crl.extensions, nid, lastpos); } -int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos) +int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, + int lastpos) { - return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos)); + return X509v3_get_ext_by_OBJ(x->crl.extensions, obj, lastpos); } -int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos) +int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos) { - return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos)); + return X509v3_get_ext_by_critical(x->crl.extensions, crit, lastpos); } -X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc) +X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc) { - return (X509v3_get_ext(x->crl->extensions, loc)); + return X509v3_get_ext(x->crl.extensions, loc); } X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) { - return (X509v3_delete_ext(x->crl->extensions, loc)); + return X509v3_delete_ext(x->crl.extensions, loc); } -void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx) +void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx) { - return X509V3_get_d2i(x->crl->extensions, nid, crit, idx); + return X509V3_get_d2i(x->crl.extensions, nid, crit, idx); } int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, unsigned long flags) { - return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags); + return X509V3_add1_i2d(&x->crl.extensions, nid, value, crit, flags); } int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) { - return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL); + return (X509v3_add_ext(&(x->crl.extensions), ex, loc) != NULL); } -int X509_get_ext_count(X509 *x) +int X509_get_ext_count(const X509 *x) { - return (X509v3_get_ext_count(x->cert_info->extensions)); + return X509v3_get_ext_count(x->cert_info.extensions); } -int X509_get_ext_by_NID(X509 *x, int nid, int lastpos) +int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) { - return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos)); + return X509v3_get_ext_by_NID(x->cert_info.extensions, nid, lastpos); } -int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos) +int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) { - return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos)); + return X509v3_get_ext_by_OBJ(x->cert_info.extensions, obj, lastpos); } -int X509_get_ext_by_critical(X509 *x, int crit, int lastpos) +int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) { return (X509v3_get_ext_by_critical - (x->cert_info->extensions, crit, lastpos)); + (x->cert_info.extensions, crit, lastpos)); } -X509_EXTENSION *X509_get_ext(X509 *x, int loc) +X509_EXTENSION *X509_get_ext(const X509 *x, int loc) { - return (X509v3_get_ext(x->cert_info->extensions, loc)); + return X509v3_get_ext(x->cert_info.extensions, loc); } X509_EXTENSION *X509_delete_ext(X509 *x, int loc) { - return (X509v3_delete_ext(x->cert_info->extensions, loc)); + return X509v3_delete_ext(x->cert_info.extensions, loc); } int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) { - return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL); + return (X509v3_add_ext(&(x->cert_info.extensions), ex, loc) != NULL); } -void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) +void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx) { - return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx); + return X509V3_get_d2i(x->cert_info.extensions, nid, crit, idx); } int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags) { - return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, + return X509V3_add1_i2d(&x->cert_info.extensions, nid, value, crit, flags); } -int X509_REVOKED_get_ext_count(X509_REVOKED *x) +int X509_REVOKED_get_ext_count(const X509_REVOKED *x) { - return (X509v3_get_ext_count(x->extensions)); + return X509v3_get_ext_count(x->extensions); } -int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos) +int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos) { - return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos)); + return X509v3_get_ext_by_NID(x->extensions, nid, lastpos); } -int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj, +int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, int lastpos) { - return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos)); + return X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos); } -int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos) +int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, int lastpos) { - return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos)); + return X509v3_get_ext_by_critical(x->extensions, crit, lastpos); } -X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc) +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc) { - return (X509v3_get_ext(x->extensions, loc)); + return X509v3_get_ext(x->extensions, loc); } X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) { - return (X509v3_delete_ext(x->extensions, loc)); + return X509v3_delete_ext(x->extensions, loc); } int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) @@ -195,7 +147,7 @@ int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); } -void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx) +void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit, int *idx) { return X509V3_get_d2i(x->extensions, nid, crit, idx); } @@ -205,7 +157,3 @@ int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, { return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); } - -IMPLEMENT_STACK_OF(X509_EXTENSION) - -IMPLEMENT_ASN1_SET_OF(X509_EXTENSION) diff --git a/crypto/x509/x509_lcl.h b/crypto/x509/x509_lcl.h new file mode 100644 index 000000000000..c517a7745637 --- /dev/null +++ b/crypto/x509/x509_lcl.h @@ -0,0 +1,147 @@ +/* + * Copyright 2014-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/refcount.h" + +/* + * This structure holds all parameters associated with a verify operation by + * including an X509_VERIFY_PARAM structure in related structures the + * parameters used can be customized + */ + +struct X509_VERIFY_PARAM_st { + char *name; + time_t check_time; /* Time to use */ + uint32_t inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + int auth_level; /* Security level for chain verification */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + /* Peer identity details */ + STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */ + unsigned int hostflags; /* Flags to control matching features */ + char *peername; /* Matching hostname in peer certificate */ + char *email; /* If not NULL email address to match */ + size_t emaillen; + unsigned char *ip; /* If not NULL IP address to match */ + size_t iplen; /* Length of IP address */ +}; + +/* No error callback if depth < 0 */ +int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth); + +/* a sequence of these are used */ +struct x509_attributes_st { + ASN1_OBJECT *object; + STACK_OF(ASN1_TYPE) *set; +}; + +struct X509_extension_st { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING value; +}; + +/* + * Method to handle CRL access. In general a CRL could be very large (several + * Mb) and can consume large amounts of resources if stored in memory by + * multiple processes. This method allows general CRL operations to be + * redirected to more efficient callbacks: for example a CRL entry database. + */ + +#define X509_CRL_METHOD_DYNAMIC 1 + +struct x509_crl_method_st { + int flags; + int (*crl_init) (X509_CRL *crl); + int (*crl_free) (X509_CRL *crl); + int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *ser, X509_NAME *issuer); + int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk); +}; + +struct x509_lookup_method_st { + char *name; + int (*new_item) (X509_LOOKUP *ctx); + void (*free) (X509_LOOKUP *ctx); + int (*init) (X509_LOOKUP *ctx); + int (*shutdown) (X509_LOOKUP *ctx); + int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret); + int (*get_by_subject) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); + int (*get_by_issuer_serial) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, + X509_OBJECT *ret); + int (*get_by_fingerprint) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, + X509_OBJECT *ret); + int (*get_by_alias) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret); +}; + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st { + int init; /* have we been started */ + int skip; /* don't use us. */ + X509_LOOKUP_METHOD *method; /* the functions */ + void *method_data; /* method data */ + X509_STORE *store_ctx; /* who owns us */ +}; + +/* + * This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' function is + * then called to actually check the cert chain. + */ +struct x509_store_st { + /* The following is a cache of trusted certs */ + int cache; /* if true, stash any hits */ + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + X509_VERIFY_PARAM *param; + /* Callbacks for various operations */ + /* called to verify a certificate */ + int (*verify) (X509_STORE_CTX *ctx); + /* error callback */ + int (*verify_cb) (int ok, X509_STORE_CTX *ctx); + /* get issuers cert from ctx */ + int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + /* check issued */ + int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); + /* Check revocation status of chain */ + int (*check_revocation) (X509_STORE_CTX *ctx); + /* retrieve CRL */ + int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); + /* Check CRL validity */ + int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); + /* Check certificate against CRL */ + int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); + /* Check policy status of the chain */ + int (*check_policy) (X509_STORE_CTX *ctx); + STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup) (X509_STORE_CTX *ctx); + CRYPTO_EX_DATA ex_data; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +typedef struct lookup_dir_hashes_st BY_DIR_HASH; +typedef struct lookup_dir_entry_st BY_DIR_ENTRY; +DEFINE_STACK_OF(BY_DIR_HASH) +DEFINE_STACK_OF(BY_DIR_ENTRY) +typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; +DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY) + +void x509_set_signature_info(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig); diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index b7424809fdbb..be39015b0d01 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -1,81 +1,31 @@ -/* crypto/x509/x509_lu.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 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> -#include "cryptlib.h" -#include <openssl/lhash.h> +#include "internal/cryptlib.h" +#include "internal/refcount.h" #include <openssl/x509.h> +#include "internal/x509_int.h" #include <openssl/x509v3.h> +#include "x509_lcl.h" X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) { - X509_LOOKUP *ret; + X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret)); - ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP)); - if (ret == NULL) + if (ret == NULL) { + X509err(X509_F_X509_LOOKUP_NEW, ERR_R_MALLOC_FAILURE); return NULL; + } - ret->init = 0; - ret->skip = 0; ret->method = method; - ret->method_data = NULL; - ret->store_ctx = NULL; - if ((method->new_item != NULL) && !method->new_item(ret)) { + if (method->new_item != NULL && method->new_item(ret) == 0) { OPENSSL_free(ret); return NULL; } @@ -91,6 +41,16 @@ void X509_LOOKUP_free(X509_LOOKUP *ctx) OPENSSL_free(ctx); } +int X509_STORE_lock(X509_STORE *s) +{ + return CRYPTO_THREAD_write_lock(s->lock); +} + +int X509_STORE_unlock(X509_STORE *s) +{ + return CRYPTO_THREAD_unlock(s->lock); +} + int X509_LOOKUP_init(X509_LOOKUP *ctx) { if (ctx->method == NULL) @@ -122,41 +82,59 @@ int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, return 1; } -int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, - X509_OBJECT *ret) +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) - return X509_LU_FAIL; + return 0; if (ctx->skip) return 0; return ctx->method->get_by_subject(ctx, type, name, ret); } -int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial, X509_OBJECT *ret) +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, + X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) - return X509_LU_FAIL; + return 0; return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret); } -int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, - unsigned char *bytes, int len, +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) - return X509_LU_FAIL; + return 0; return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret); } -int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, - X509_OBJECT *ret) +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) - return X509_LU_FAIL; + return 0; return ctx->method->get_by_alias(ctx, type, str, len, ret); } +int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data) +{ + ctx->method_data = data; + return 1; +} + +void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx) +{ + return ctx->method_data; +} + +X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx) +{ + return ctx->store_ctx; +} + + static int x509_object_cmp(const X509_OBJECT *const *a, const X509_OBJECT *const *b) { @@ -172,7 +150,7 @@ static int x509_object_cmp(const X509_OBJECT *const *a, case X509_LU_CRL: ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); break; - default: + case X509_LU_NONE: /* abort(); */ return 0; } @@ -181,63 +159,48 @@ static int x509_object_cmp(const X509_OBJECT *const *a, X509_STORE *X509_STORE_new(void) { - X509_STORE *ret; + X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); - if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL) + if (ret == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); return NULL; - if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) - goto err0; + } + if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } ret->cache = 1; - if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) - goto err1; - ret->verify = 0; - ret->verify_cb = 0; - - if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) - goto err2; - - ret->get_issuer = 0; - ret->check_issued = 0; - ret->check_revocation = 0; - ret->get_crl = 0; - ret->check_crl = 0; - ret->cert_crl = 0; - ret->lookup_certs = 0; - ret->lookup_crls = 0; - ret->cleanup = 0; - - if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) - goto err3; + if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } ret->references = 1; return ret; - err3: +err: X509_VERIFY_PARAM_free(ret->param); - err2: - sk_X509_LOOKUP_free(ret->get_cert_methods); - err1: sk_X509_OBJECT_free(ret->objs); - err0: + sk_X509_LOOKUP_free(ret->get_cert_methods); OPENSSL_free(ret); return NULL; } -static void cleanup(X509_OBJECT *a) -{ - if (!a) - return; - if (a->type == X509_LU_X509) { - X509_free(a->data.x509); - } else if (a->type == X509_LU_CRL) { - X509_CRL_free(a->data.crl); - } else { - /* abort(); */ - } - - OPENSSL_free(a); -} - void X509_STORE_free(X509_STORE *vfy) { int i; @@ -246,19 +209,11 @@ void X509_STORE_free(X509_STORE *vfy) if (vfy == NULL) return; - - i = CRYPTO_add(&vfy->references, -1, CRYPTO_LOCK_X509_STORE); -#ifdef REF_PRINT - REF_PRINT("X509_STORE", vfy); -#endif + CRYPTO_DOWN_REF(&vfy->references, &i, vfy->lock); + REF_PRINT_COUNT("X509_STORE", vfy); if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) { - fprintf(stderr, "X509_STORE_free, bad reference count\n"); - abort(); /* ok */ - } -#endif + REF_ASSERT_ISNT(i < 0); sk = vfy->get_cert_methods; for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { @@ -267,14 +222,26 @@ void X509_STORE_free(X509_STORE *vfy) X509_LOOKUP_free(lu); } sk_X509_LOOKUP_free(sk); - sk_X509_OBJECT_pop_free(vfy->objs, cleanup); + sk_X509_OBJECT_pop_free(vfy->objs, X509_OBJECT_free); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); - if (vfy->param) - X509_VERIFY_PARAM_free(vfy->param); + X509_VERIFY_PARAM_free(vfy->param); + CRYPTO_THREAD_lock_free(vfy->lock); OPENSSL_free(vfy); } +int X509_STORE_up_ref(X509_STORE *vfy) +{ + int i; + + if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0) + return 0; + + REF_PRINT_COUNT("X509_STORE", a); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { int i; @@ -290,52 +257,63 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) } /* a new one */ lu = X509_LOOKUP_new(m); - if (lu == NULL) + if (lu == NULL) { + X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + lu->store_ctx = v; + if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) + return lu; + /* malloc failed */ + X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE); + X509_LOOKUP_free(lu); + return NULL; +} + +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + X509_OBJECT *ret = X509_OBJECT_new(); + + if (ret == NULL) + return NULL; + if (!X509_STORE_CTX_get_by_subject(vs, type, name, ret)) { + X509_OBJECT_free(ret); return NULL; - else { - lu->store_ctx = v; - if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) - return lu; - else { - X509_LOOKUP_free(lu); - return NULL; - } } + return ret; } -int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, - X509_OBJECT *ret) +int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) { X509_STORE *ctx = vs->ctx; X509_LOOKUP *lu; X509_OBJECT stmp, *tmp; int i, j; - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + if (ctx == NULL) + return 0; + + CRYPTO_THREAD_write_lock(ctx->lock); tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->lock); if (tmp == NULL || type == X509_LU_CRL) { - for (i = vs->current_method; - i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); j = X509_LOOKUP_by_subject(lu, type, name, &stmp); - if (j < 0) { - vs->current_method = j; - return j; - } else if (j) { + if (j) { tmp = &stmp; break; } } - vs->current_method = 0; if (tmp == NULL) return 0; } -/*- if (ret->data.ptr != NULL) - X509_OBJECT_free_contents(ret); */ - ret->type = tmp->type; ret->data.ptr = tmp->data.ptr; @@ -344,94 +322,111 @@ int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, return 1; } -int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) -{ +static int x509_store_add(X509_STORE *ctx, void *x, int crl) { X509_OBJECT *obj; - int ret = 1; + int ret = 0, added = 0; if (x == NULL) return 0; - obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); - if (obj == NULL) { - X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE); + obj = X509_OBJECT_new(); + if (obj == NULL) return 0; - } - obj->type = X509_LU_X509; - obj->data.x509 = x; - - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + if (crl) { + obj->type = X509_LU_CRL; + obj->data.crl = (X509_CRL *)x; + } else { + obj->type = X509_LU_X509; + obj->data.x509 = (X509 *)x; + } X509_OBJECT_up_ref_count(obj); + CRYPTO_THREAD_write_lock(ctx->lock); + if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { - X509_OBJECT_free_contents(obj); - OPENSSL_free(obj); - X509err(X509_F_X509_STORE_ADD_CERT, - X509_R_CERT_ALREADY_IN_HASH_TABLE); - ret = 0; - } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) { - X509_OBJECT_free_contents(obj); - OPENSSL_free(obj); - X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE); - ret = 0; + ret = 1; + } else { + added = sk_X509_OBJECT_push(ctx->objs, obj); + ret = added != 0; } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->lock); + + if (added == 0) /* obj not pushed */ + X509_OBJECT_free(obj); return ret; } -int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) { - X509_OBJECT *obj; - int ret = 1; - - if (x == NULL) - return 0; - obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); - if (obj == NULL) { - X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE); + if (!x509_store_add(ctx, x, 0)) { + X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE); return 0; } - obj->type = X509_LU_CRL; - obj->data.crl = x; - - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - - X509_OBJECT_up_ref_count(obj); + return 1; +} - if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { - X509_OBJECT_free_contents(obj); - OPENSSL_free(obj); - X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE); - ret = 0; - } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) { - X509_OBJECT_free_contents(obj); - OPENSSL_free(obj); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) +{ + if (!x509_store_add(ctx, x, 1)) { X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE); - ret = 0; + return 0; } - - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - - return ret; + return 1; } -void X509_OBJECT_up_ref_count(X509_OBJECT *a) +int X509_OBJECT_up_ref_count(X509_OBJECT *a) { switch (a->type) { - case X509_LU_X509: - CRYPTO_add(&a->data.x509->references, 1, CRYPTO_LOCK_X509); + case X509_LU_NONE: break; + case X509_LU_X509: + return X509_up_ref(a->data.x509); case X509_LU_CRL: - CRYPTO_add(&a->data.crl->references, 1, CRYPTO_LOCK_X509_CRL); - break; + return X509_CRL_up_ref(a->data.crl); } + return 1; +} + +X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a) +{ + if (a == NULL || a->type != X509_LU_X509) + return NULL; + return a->data.x509; } -void X509_OBJECT_free_contents(X509_OBJECT *a) +X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a) { + if (a == NULL || a->type != X509_LU_CRL) + return NULL; + return a->data.crl; +} + +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a) +{ + return a->type; +} + +X509_OBJECT *X509_OBJECT_new(void) +{ + X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + X509err(X509_F_X509_OBJECT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = X509_LU_NONE; + return ret; +} + +static void x509_object_free_internal(X509_OBJECT *a) +{ + if (a == NULL) + return; switch (a->type) { + case X509_LU_NONE: + break; case X509_LU_X509: X509_free(a->data.x509); break; @@ -441,29 +436,53 @@ void X509_OBJECT_free_contents(X509_OBJECT *a) } } -static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, +int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj) +{ + if (a == NULL || !X509_up_ref(obj)) + return 0; + + x509_object_free_internal(a); + a->type = X509_LU_X509; + a->data.x509 = obj; + return 1; +} + +int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj) +{ + if (a == NULL || !X509_CRL_up_ref(obj)) + return 0; + + x509_object_free_internal(a); + a->type = X509_LU_CRL; + a->data.crl = obj; + return 1; +} + +void X509_OBJECT_free(X509_OBJECT *a) +{ + x509_object_free_internal(a); + OPENSSL_free(a); +} + +static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, X509_NAME *name, int *pnmatch) { X509_OBJECT stmp; X509 x509_s; - X509_CINF cinf_s; X509_CRL crl_s; - X509_CRL_INFO crl_info_s; int idx; stmp.type = type; switch (type) { case X509_LU_X509: stmp.data.x509 = &x509_s; - x509_s.cert_info = &cinf_s; - cinf_s.subject = name; + x509_s.cert_info.subject = name; break; case X509_LU_CRL: stmp.data.crl = &crl_s; - crl_s.crl = &crl_info_s; - crl_info_s.issuer = name; + crl_s.crl.issuer = name; break; - default: + case X509_LU_NONE: /* abort(); */ return -1; } @@ -484,14 +503,15 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, return idx; } -int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, X509_NAME *name) { return x509_object_idx_cnt(h, type, name, NULL); } X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, - int type, X509_NAME *name) + X509_LOOKUP_TYPE type, + X509_NAME *name) { int idx; idx = X509_OBJECT_idx_by_subject(h, type, name); @@ -500,73 +520,83 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, return sk_X509_OBJECT_value(h, idx); } -STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v) +{ + return v->objs; +} + +STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) { int i, idx, cnt; - STACK_OF(X509) *sk; + STACK_OF(X509) *sk = NULL; X509 *x; X509_OBJECT *obj; - sk = sk_X509_new_null(); - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + + if (ctx->ctx == NULL) + return NULL; + + CRYPTO_THREAD_write_lock(ctx->ctx->lock); idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); if (idx < 0) { /* * Nothing found in cache: do lookup to possibly add new objects to * cache */ - X509_OBJECT xobj; - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { - sk_X509_free(sk); + X509_OBJECT *xobj = X509_OBJECT_new(); + + CRYPTO_THREAD_unlock(ctx->ctx->lock); + if (xobj == NULL) + return NULL; + if (!X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, nm, xobj)) { + X509_OBJECT_free(xobj); return NULL; } - X509_OBJECT_free_contents(&xobj); - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + X509_OBJECT_free(xobj); + CRYPTO_THREAD_write_lock(ctx->ctx->lock); idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); if (idx < 0) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - sk_X509_free(sk); + CRYPTO_THREAD_unlock(ctx->ctx->lock); return NULL; } } + + sk = sk_X509_new_null(); for (i = 0; i < cnt; i++, idx++) { obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); x = obj->data.x509; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x); if (!sk_X509_push(sk, x)) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->ctx->lock); X509_free(x); sk_X509_pop_free(sk, X509_free); return NULL; } } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->ctx->lock); return sk; - } -STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) +STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) { int i, idx, cnt; - STACK_OF(X509_CRL) *sk; + STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null(); X509_CRL *x; - X509_OBJECT *obj, xobj; - sk = sk_X509_CRL_new_null(); - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - - /* - * Always do lookup to possibly add new CRLs to cache - */ - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) { + X509_OBJECT *obj, *xobj = X509_OBJECT_new(); + + /* Always do lookup to possibly add new CRLs to cache */ + if (sk == NULL + || xobj == NULL + || ctx->ctx == NULL + || !X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, nm, xobj)) { + X509_OBJECT_free(xobj); sk_X509_CRL_free(sk); return NULL; } - X509_OBJECT_free_contents(&xobj); - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + X509_OBJECT_free(xobj); + CRYPTO_THREAD_write_lock(ctx->ctx->lock); idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); if (idx < 0) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->ctx->lock); sk_X509_CRL_free(sk); return NULL; } @@ -574,32 +604,33 @@ STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) for (i = 0; i < cnt; i++, idx++) { obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); x = obj->data.crl; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(x); if (!sk_X509_CRL_push(sk, x)) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->ctx->lock); X509_CRL_free(x); sk_X509_CRL_pop_free(sk, X509_CRL_free); return NULL; } } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->ctx->lock); return sk; } X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x) { - int idx, i; + int idx, i, num; X509_OBJECT *obj; + idx = sk_X509_OBJECT_find(h, x); - if (idx == -1) + if (idx < 0) return NULL; if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) return sk_X509_OBJECT_value(h, idx); - for (i = idx; i < sk_X509_OBJECT_num(h); i++) { + for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) { obj = sk_X509_OBJECT_value(h, i); - if (x509_object_cmp - ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x)) + if (x509_object_cmp((const X509_OBJECT **)&obj, + (const X509_OBJECT **)&x)) return NULL; if (x->type == X509_LU_X509) { if (!X509_cmp(obj->data.x509, x->data.x509)) @@ -628,32 +659,35 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { X509_NAME *xn; - X509_OBJECT obj, *pobj; + X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL; int i, ok, idx, ret; + + if (obj == NULL) + return -1; + *issuer = NULL; xn = X509_get_issuer_name(x); - ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj); - if (ok != X509_LU_X509) { - if (ok == X509_LU_RETRY) { - X509_OBJECT_free_contents(&obj); - X509err(X509_F_X509_STORE_CTX_GET1_ISSUER, X509_R_SHOULD_RETRY); - return -1; - } else if (ok != X509_LU_FAIL) { - X509_OBJECT_free_contents(&obj); - /* not good :-(, break anyway */ - return -1; - } + ok = X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, xn, obj); + if (ok != 1) { + X509_OBJECT_free(obj); return 0; } /* If certificate matches all OK */ - if (ctx->check_issued(ctx, x, obj.data.x509)) { - *issuer = obj.data.x509; - return 1; + if (ctx->check_issued(ctx, x, obj->data.x509)) { + if (x509_check_cert_time(ctx, obj->data.x509, -1)) { + *issuer = obj->data.x509; + X509_up_ref(*issuer); + X509_OBJECT_free(obj); + return 1; + } } - X509_OBJECT_free_contents(&obj); + X509_OBJECT_free(obj); + + if (ctx->ctx == NULL) + return 0; /* Else find index of first cert accepted by 'check_issued' */ ret = 0; - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_write_lock(ctx->ctx->lock); idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); if (idx != -1) { /* should be true as we've had at least one * match */ @@ -667,13 +701,22 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) break; if (ctx->check_issued(ctx, x, pobj->data.x509)) { *issuer = pobj->data.x509; - X509_OBJECT_up_ref_count(pobj); ret = 1; - break; + /* + * If times check, exit with match, + * otherwise keep looking. Leave last + * match in issuer so we return nearest + * match if no certificate time is OK. + */ + + if (x509_check_cert_time(ctx, *issuer, -1)) + break; } } } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_THREAD_unlock(ctx->ctx->lock); + if (*issuer) + X509_up_ref(*issuer); return ret; } @@ -703,25 +746,153 @@ int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) return X509_VERIFY_PARAM_set1(ctx->param, param); } +X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) +{ + return ctx->param; +} + +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) +{ + ctx->verify = verify; +} + +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx) +{ + return ctx->verify; +} + void X509_STORE_set_verify_cb(X509_STORE *ctx, - int (*verify_cb) (int, X509_STORE_CTX *)) + X509_STORE_CTX_verify_cb verify_cb) { ctx->verify_cb = verify_cb; } -void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx, - STACK_OF(X509_CRL) *(*cb) (X509_STORE_CTX - *ctx, - X509_NAME *nm)) +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx) { - ctx->lookup_crls = cb; + return ctx->verify_cb; } -X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) +void X509_STORE_set_get_issuer(X509_STORE *ctx, + X509_STORE_CTX_get_issuer_fn get_issuer) { - return ctx->ctx; + ctx->get_issuer = get_issuer; } -IMPLEMENT_STACK_OF(X509_LOOKUP) +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx) +{ + return ctx->get_issuer; +} + +void X509_STORE_set_check_issued(X509_STORE *ctx, + X509_STORE_CTX_check_issued_fn check_issued) +{ + ctx->check_issued = check_issued; +} -IMPLEMENT_STACK_OF(X509_OBJECT) +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx) +{ + return ctx->check_issued; +} + +void X509_STORE_set_check_revocation(X509_STORE *ctx, + X509_STORE_CTX_check_revocation_fn check_revocation) +{ + ctx->check_revocation = check_revocation; +} + +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx) +{ + return ctx->check_revocation; +} + +void X509_STORE_set_get_crl(X509_STORE *ctx, + X509_STORE_CTX_get_crl_fn get_crl) +{ + ctx->get_crl = get_crl; +} + +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx) +{ + return ctx->get_crl; +} + +void X509_STORE_set_check_crl(X509_STORE *ctx, + X509_STORE_CTX_check_crl_fn check_crl) +{ + ctx->check_crl = check_crl; +} + +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx) +{ + return ctx->check_crl; +} + +void X509_STORE_set_cert_crl(X509_STORE *ctx, + X509_STORE_CTX_cert_crl_fn cert_crl) +{ + ctx->cert_crl = cert_crl; +} + +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx) +{ + return ctx->cert_crl; +} + +void X509_STORE_set_check_policy(X509_STORE *ctx, + X509_STORE_CTX_check_policy_fn check_policy) +{ + ctx->check_policy = check_policy; +} + +X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx) +{ + return ctx->check_policy; +} + +void X509_STORE_set_lookup_certs(X509_STORE *ctx, + X509_STORE_CTX_lookup_certs_fn lookup_certs) +{ + ctx->lookup_certs = lookup_certs; +} + +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx) +{ + return ctx->lookup_certs; +} + +void X509_STORE_set_lookup_crls(X509_STORE *ctx, + X509_STORE_CTX_lookup_crls_fn lookup_crls) +{ + ctx->lookup_crls = lookup_crls; +} + +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx) +{ + return ctx->lookup_crls; +} + +void X509_STORE_set_cleanup(X509_STORE *ctx, + X509_STORE_CTX_cleanup_fn ctx_cleanup) +{ + ctx->cleanup = ctx_cleanup; +} + +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx) +{ + return ctx->cleanup; +} + +int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data) +{ + return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); +} + +void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx) +{ + return CRYPTO_get_ex_data(&ctx->ex_data, idx); +} + +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) +{ + return ctx->ctx; +} diff --git a/crypto/x509/x509_meth.c b/crypto/x509/x509_meth.c new file mode 100644 index 000000000000..9dc587a09212 --- /dev/null +++ b/crypto/x509/x509_meth.c @@ -0,0 +1,166 @@ +/* + * Copyright 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 <time.h> +#include <errno.h> + +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/x509.h> +#include <openssl/ossl_typ.h> +#include "x509_lcl.h" + +X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name) +{ + X509_LOOKUP_METHOD *method = OPENSSL_zalloc(sizeof(X509_LOOKUP_METHOD)); + + if (method != NULL) { + method->name = OPENSSL_strdup(name); + if (method->name == NULL) { + X509err(X509_F_X509_LOOKUP_METH_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + return method; + +err: + OPENSSL_free(method); + return NULL; +} + +void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method) +{ + if (method != NULL) + OPENSSL_free(method->name); + OPENSSL_free(method); +} + +int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method, + int (*new_item) (X509_LOOKUP *ctx)) +{ + method->new_item = new_item; + return 1; +} + +int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->new_item; +} + +int X509_LOOKUP_meth_set_free( + X509_LOOKUP_METHOD *method, + void (*free_fn) (X509_LOOKUP *ctx)) +{ + method->free = free_fn; + return 1; +} + +void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->free; +} + +int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method, + int (*init) (X509_LOOKUP *ctx)) +{ + method->init = init; + return 1; +} + +int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->init; +} + +int X509_LOOKUP_meth_set_shutdown( + X509_LOOKUP_METHOD *method, + int (*shutdown) (X509_LOOKUP *ctx)) +{ + method->shutdown = shutdown; + return 1; +} + +int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->shutdown; +} + +int X509_LOOKUP_meth_set_ctrl( + X509_LOOKUP_METHOD *method, + X509_LOOKUP_ctrl_fn ctrl) +{ + method->ctrl = ctrl; + return 1; +} + +X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method) +{ + return method->ctrl; +} + +int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_subject_fn get_by_subject) +{ + method->get_by_subject = get_by_subject; + return 1; +} + +X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject( + const X509_LOOKUP_METHOD *method) +{ + return method->get_by_subject; +} + + +int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_issuer_serial_fn get_by_issuer_serial) +{ + method->get_by_issuer_serial = get_by_issuer_serial; + return 1; +} + +X509_LOOKUP_get_by_issuer_serial_fn + X509_LOOKUP_meth_get_get_by_issuer_serial(const X509_LOOKUP_METHOD *method) +{ + return method->get_by_issuer_serial; +} + + +int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_fingerprint_fn get_by_fingerprint) +{ + method->get_by_fingerprint = get_by_fingerprint; + return 1; +} + +X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint( + const X509_LOOKUP_METHOD *method) +{ + return method->get_by_fingerprint; +} + +int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_alias_fn get_by_alias) +{ + method->get_by_alias = get_by_alias; + return 1; +} + +X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias( + const X509_LOOKUP_METHOD *method) +{ + return method->get_by_alias; +} + diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c index 0a839f3e54ce..85c39415c11e 100644 --- a/crypto/x509/x509_obj.c +++ b/crypto/x509/x509_obj.c @@ -1,78 +1,29 @@ -/* crypto/x509/x509_obj.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. +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * - * 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> -#include "cryptlib.h" -#include <openssl/lhash.h> +#include "internal/cryptlib.h" #include <openssl/objects.h> #include <openssl/x509.h> #include <openssl/buffer.h> +#include "internal/x509_int.h" /* * Limit to ensure we don't overflow: much greater than - * anything enountered in practice. + * anything encountered in practice. */ #define NAME_ONELINE_MAX (1024 * 1024) -char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) +char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) { - X509_NAME_ENTRY *ne; + const X509_NAME_ENTRY *ne; int i; int n, lold, l, l1, l2, num, j, type; const char *s; @@ -83,7 +34,7 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) int gs_doit[4]; char tmp_buf[80]; #ifdef CHARSET_EBCDIC - char ebcdic_buf[1024]; + unsigned char ebcdic_buf[1024]; #endif if (buf == NULL) { @@ -221,10 +172,10 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) p = buf; if (i == 0) *p = '\0'; - return (p); + return p; err: X509err(X509_F_X509_NAME_ONELINE, ERR_R_MALLOC_FAILURE); end: BUF_MEM_free(b); - return (NULL); + return NULL; } diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c index 2879569ead41..3d72787d3164 100644 --- a/crypto/x509/x509_r2x.c +++ b/crypto/x509/x509_r2x.c @@ -1,67 +1,19 @@ -/* crypto/x509/x509_r2x.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> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/asn1.h> #include <openssl/x509.h> +#include "internal/x509_int.h" #include <openssl/objects.h> #include <openssl/buffer.h> @@ -71,7 +23,6 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) X509_CINF *xi = NULL; X509_NAME *xn; EVP_PKEY *pubkey = NULL; - int res; if ((ret = X509_new()) == NULL) { X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE); @@ -79,10 +30,10 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) } /* duplicate the request */ - xi = ret->cert_info; + xi = &ret->cert_info; - if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) { - if ((xi->version = M_ASN1_INTEGER_new()) == NULL) + if (sk_X509_ATTRIBUTE_num(r->req_info.attributes) != 0) { + if ((xi->version = ASN1_INTEGER_new()) == NULL) goto err; if (!ASN1_INTEGER_set(xi->version, 2)) goto err; @@ -96,22 +47,21 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) if (X509_set_issuer_name(ret, xn) == 0) goto err; - if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL) + if (X509_gmtime_adj(xi->validity.notBefore, 0) == NULL) goto err; - if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) == + if (X509_gmtime_adj(xi->validity.notAfter, (long)60 * 60 * 24 * days) == NULL) goto err; - pubkey = X509_REQ_get_pubkey(r); - res = X509_set_pubkey(ret, pubkey); - EVP_PKEY_free(pubkey); + pubkey = X509_REQ_get0_pubkey(r); + if (pubkey == NULL || !X509_set_pubkey(ret, pubkey)) + goto err; - if (!res || !X509_sign(ret, pkey, EVP_md5())) + if (!X509_sign(ret, pkey, EVP_md5())) goto err; - if (0) { + return ret; + err: - X509_free(ret); - ret = NULL; - } - return (ret); + X509_free(ret); + return NULL; } diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c index 01795f4b3f37..0bdbb81db894 100644 --- a/crypto/x509/x509_req.c +++ b/crypto/x509/x509_req.c @@ -1,68 +1,20 @@ -/* crypto/x509/x509_req.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. +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * 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> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/asn1.h> #include <openssl/asn1t.h> #include <openssl/x509.h> +#include "internal/x509_int.h" #include <openssl/objects.h> #include <openssl/buffer.h> #include <openssl/pem.h> @@ -80,10 +32,10 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) goto err; } - ri = ret->req_info; + ri = &ret->req_info; ri->version->length = 1; - ri->version->data = (unsigned char *)OPENSSL_malloc(1); + ri->version->data = OPENSSL_malloc(1); if (ri->version->data == NULL) goto err; ri->version->data[0] = 0; /* version == 0 */ @@ -91,11 +43,10 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x))) goto err; - pktmp = X509_get_pubkey(x); + pktmp = X509_get0_pubkey(x); if (pktmp == NULL) goto err; i = X509_REQ_set_pubkey(ret, pktmp); - EVP_PKEY_free(pktmp); if (!i) goto err; @@ -103,17 +54,29 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) if (!X509_REQ_sign(ret, pkey, md)) goto err; } - return (ret); + return ret; err: X509_REQ_free(ret); - return (NULL); + return NULL; } EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) { - if ((req == NULL) || (req->req_info == NULL)) - return (NULL); - return (X509_PUBKEY_get(req->req_info->pubkey)); + if (req == NULL) + return NULL; + return X509_PUBKEY_get(req->req_info.pubkey); +} + +EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req) +{ + if (req == NULL) + return NULL; + return X509_PUBKEY_get0(req->req_info.pubkey); +} + +X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req) +{ + return req->req_info.pubkey; } int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) @@ -135,13 +98,13 @@ int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) break; case -2: #ifndef OPENSSL_NO_EC - if (k->type == EVP_PKEY_EC) { + if (EVP_PKEY_id(k) == EVP_PKEY_EC) { X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB); break; } #endif #ifndef OPENSSL_NO_DH - if (k->type == EVP_PKEY_DH) { + if (EVP_PKEY_id(k) == EVP_PKEY_DH) { /* No idea */ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_CANT_CHECK_DH_KEY); @@ -152,7 +115,7 @@ int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) } EVP_PKEY_free(xk); - return (ok); + return ok; } /* @@ -194,17 +157,14 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) int idx, *pnid; const unsigned char *p; - if ((req == NULL) || (req->req_info == NULL) || !ext_nids) - return (NULL); + if ((req == NULL) || !ext_nids) + return NULL; for (pnid = ext_nids; *pnid != NID_undef; pnid++) { idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); if (idx == -1) continue; attr = X509_REQ_get_attr(req, idx); - if (attr->single) - ext = attr->value.single; - else if (sk_ASN1_TYPE_num(attr->value.set)) - ext = sk_ASN1_TYPE_value(attr->value.set, 0); + ext = X509_ATTRIBUTE_get0_type(attr, 0); break; } if (!ext || (ext->type != V_ASN1_SEQUENCE)) @@ -223,37 +183,17 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, int nid) { - ASN1_TYPE *at = NULL; - X509_ATTRIBUTE *attr = NULL; - if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new())) - goto err; - - at->type = V_ASN1_SEQUENCE; + int extlen; + int rv = 0; + unsigned char *ext = NULL; /* Generate encoding of extensions */ - at->value.sequence->length = - ASN1_item_i2d((ASN1_VALUE *)exts, - &at->value.sequence->data, - ASN1_ITEM_rptr(X509_EXTENSIONS)); - if (!(attr = X509_ATTRIBUTE_new())) - goto err; - if (!(attr->value.set = sk_ASN1_TYPE_new_null())) - goto err; - if (!sk_ASN1_TYPE_push(attr->value.set, at)) - goto err; - at = NULL; - attr->single = 0; - attr->object = OBJ_nid2obj(nid); - if (!req->req_info->attributes) { - if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null())) - goto err; - } - if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) - goto err; - return 1; - err: - X509_ATTRIBUTE_free(attr); - ASN1_TYPE_free(at); - return 0; + extlen = ASN1_item_i2d((ASN1_VALUE *)exts, &ext, + ASN1_ITEM_rptr(X509_EXTENSIONS)); + if (extlen <= 0) + return 0; + rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); + OPENSSL_free(ext); + return rv; } /* This is the normal usage: use the "official" OID */ @@ -266,33 +206,33 @@ int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) int X509_REQ_get_attr_count(const X509_REQ *req) { - return X509at_get_attr_count(req->req_info->attributes); + return X509at_get_attr_count(req->req_info.attributes); } int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) { - return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); + return X509at_get_attr_by_NID(req->req_info.attributes, nid, lastpos); } -int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, int lastpos) { - return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); + return X509at_get_attr_by_OBJ(req->req_info.attributes, obj, lastpos); } X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) { - return X509at_get_attr(req->req_info->attributes, loc); + return X509at_get_attr(req->req_info.attributes, loc); } X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) { - return X509at_delete_attr(req->req_info->attributes, loc); + return X509at_delete_attr(req->req_info.attributes, loc); } int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) { - if (X509at_add1_attr(&req->req_info->attributes, attr)) + if (X509at_add1_attr(&req->req_info.attributes, attr)) return 1; return 0; } @@ -301,7 +241,7 @@ int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, const ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len) { - if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, + if (X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, type, bytes, len)) return 1; return 0; @@ -311,7 +251,7 @@ int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int type, const unsigned char *bytes, int len) { - if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, + if (X509at_add1_attr_by_NID(&req->req_info.attributes, nid, type, bytes, len)) return 1; return 0; @@ -321,8 +261,38 @@ int X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int type, const unsigned char *bytes, int len) { - if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, + if (X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, type, bytes, len)) return 1; return 0; } + +long X509_REQ_get_version(const X509_REQ *req) +{ + return ASN1_INTEGER_get(req->req_info.version); +} + +X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req) +{ + return req->req_info.subject; +} + +void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg) +{ + if (psig != NULL) + *psig = req->signature; + if (palg != NULL) + *palg = &req->sig_alg; +} + +int X509_REQ_get_signature_nid(const X509_REQ *req) +{ + return OBJ_obj2nid(req->sig_alg.algorithm); +} + +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) +{ + req->req_info.enc.modified = 1; + return i2d_X509_REQ_INFO(&req->req_info, pp); +} diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c index 5b802bd6c754..3ab6bf35115f 100644 --- a/crypto/x509/x509_set.c +++ b/crypto/x509/x509_set.c @@ -1,82 +1,38 @@ -/* crypto/x509/x509_set.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2017 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> -#include "cryptlib.h" +#include "internal/cryptlib.h" +#include "internal/refcount.h" #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include <openssl/x509v3.h> +#include "internal/asn1_int.h" +#include "internal/x509_int.h" +#include "x509_lcl.h" int X509_set_version(X509 *x, long version) { if (x == NULL) - return (0); + return 0; if (version == 0) { - M_ASN1_INTEGER_free(x->cert_info->version); - x->cert_info->version = NULL; - return (1); + ASN1_INTEGER_free(x->cert_info.version); + x->cert_info.version = NULL; + return 1; } - if (x->cert_info->version == NULL) { - if ((x->cert_info->version = M_ASN1_INTEGER_new()) == NULL) - return (0); + if (x->cert_info.version == NULL) { + if ((x->cert_info.version = ASN1_INTEGER_new()) == NULL) + return 0; } - return (ASN1_INTEGER_set(x->cert_info->version, version)); + return ASN1_INTEGER_set(x->cert_info.version, version); } int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) @@ -84,69 +40,198 @@ int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) ASN1_INTEGER *in; if (x == NULL) - return (0); - in = x->cert_info->serialNumber; - if (in != serial) { - in = M_ASN1_INTEGER_dup(serial); - if (in != NULL) { - M_ASN1_INTEGER_free(x->cert_info->serialNumber); - x->cert_info->serialNumber = in; - } - } - return (in != NULL); + return 0; + in = &x->cert_info.serialNumber; + if (in != serial) + return ASN1_STRING_copy(in, serial); + return 1; } int X509_set_issuer_name(X509 *x, X509_NAME *name) { - if ((x == NULL) || (x->cert_info == NULL)) - return (0); - return (X509_NAME_set(&x->cert_info->issuer, name)); + if (x == NULL) + return 0; + return X509_NAME_set(&x->cert_info.issuer, name); } int X509_set_subject_name(X509 *x, X509_NAME *name) { - if ((x == NULL) || (x->cert_info == NULL)) - return (0); - return (X509_NAME_set(&x->cert_info->subject, name)); + if (x == NULL) + return 0; + return X509_NAME_set(&x->cert_info.subject, name); } -int X509_set_notBefore(X509 *x, const ASN1_TIME *tm) +int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm) { ASN1_TIME *in; - - if ((x == NULL) || (x->cert_info->validity == NULL)) - return (0); - in = x->cert_info->validity->notBefore; + in = *ptm; if (in != tm) { - in = M_ASN1_TIME_dup(tm); + in = ASN1_STRING_dup(tm); if (in != NULL) { - M_ASN1_TIME_free(x->cert_info->validity->notBefore); - x->cert_info->validity->notBefore = in; + ASN1_TIME_free(*ptm); + *ptm = in; } } return (in != NULL); } -int X509_set_notAfter(X509 *x, const ASN1_TIME *tm) +int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) { - ASN1_TIME *in; + if (x == NULL) + return 0; + return x509_set1_time(&x->cert_info.validity.notBefore, tm); +} - if ((x == NULL) || (x->cert_info->validity == NULL)) - return (0); - in = x->cert_info->validity->notAfter; - if (in != tm) { - in = M_ASN1_TIME_dup(tm); - if (in != NULL) { - M_ASN1_TIME_free(x->cert_info->validity->notAfter); - x->cert_info->validity->notAfter = in; - } - } - return (in != NULL); +int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) +{ + if (x == NULL) + return 0; + return x509_set1_time(&x->cert_info.validity.notAfter, tm); } int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) { - if ((x == NULL) || (x->cert_info == NULL)) - return (0); - return (X509_PUBKEY_set(&(x->cert_info->key), pkey)); + if (x == NULL) + return 0; + return X509_PUBKEY_set(&(x->cert_info.key), pkey); +} + +int X509_up_ref(X509 *x) +{ + int i; + + if (CRYPTO_UP_REF(&x->references, &i, x->lock) <= 0) + return 0; + + REF_PRINT_COUNT("X509", x); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +long X509_get_version(const X509 *x) +{ + return ASN1_INTEGER_get(x->cert_info.version); +} + +const ASN1_TIME *X509_get0_notBefore(const X509 *x) +{ + return x->cert_info.validity.notBefore; +} + +const ASN1_TIME *X509_get0_notAfter(const X509 *x) +{ + return x->cert_info.validity.notAfter; +} + +ASN1_TIME *X509_getm_notBefore(const X509 *x) +{ + return x->cert_info.validity.notBefore; +} + +ASN1_TIME *X509_getm_notAfter(const X509 *x) +{ + return x->cert_info.validity.notAfter; +} + +int X509_get_signature_type(const X509 *x) +{ + return EVP_PKEY_type(OBJ_obj2nid(x->sig_alg.algorithm)); +} + +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x) +{ + return x->cert_info.key; +} + +const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x) +{ + return x->cert_info.extensions; +} + +void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, + const ASN1_BIT_STRING **psuid) +{ + if (piuid != NULL) + *piuid = x->cert_info.issuerUID; + if (psuid != NULL) + *psuid = x->cert_info.subjectUID; +} + +const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) +{ + return &x->cert_info.signature; +} + +int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid, + int *secbits, uint32_t *flags) +{ + if (mdnid != NULL) + *mdnid = siginf->mdnid; + if (pknid != NULL) + *pknid = siginf->pknid; + if (secbits != NULL) + *secbits = siginf->secbits; + if (flags != NULL) + *flags = siginf->flags; + return (siginf->flags & X509_SIG_INFO_VALID) != 0; +} + +void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid, + int secbits, uint32_t flags) +{ + siginf->mdnid = mdnid; + siginf->pknid = pknid; + siginf->secbits = secbits; + siginf->flags = flags; +} + +int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits, + uint32_t *flags) +{ + X509_check_purpose(x, -1, -1); + return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags); +} + +static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig) +{ + int pknid, mdnid; + const EVP_MD *md; + + siginf->mdnid = NID_undef; + siginf->pknid = NID_undef; + siginf->secbits = -1; + siginf->flags = 0; + if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid) + || pknid == NID_undef) + return; + siginf->pknid = pknid; + if (mdnid == NID_undef) { + /* If we have one, use a custom handler for this algorithm */ + const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_find(NULL, pknid); + if (ameth == NULL || ameth->siginf_set == NULL + || ameth->siginf_set(siginf, alg, sig) == 0) + return; + siginf->flags |= X509_SIG_INFO_VALID; + return; + } + siginf->flags |= X509_SIG_INFO_VALID; + siginf->mdnid = mdnid; + md = EVP_get_digestbynid(mdnid); + if (md == NULL) + return; + /* Security bits: half number of bits in digest */ + siginf->secbits = EVP_MD_size(md) * 4; + switch (mdnid) { + case NID_sha1: + case NID_sha256: + case NID_sha384: + case NID_sha512: + siginf->flags |= X509_SIG_INFO_TLS; + } +} + +void x509_init_sig_info(X509 *x) +{ + x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature); } diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c index 11e0763403ae..d749af4d590a 100644 --- a/crypto/x509/x509_trs.c +++ b/crypto/x509/x509_trs.c @@ -1,65 +1,16 @@ -/* x509_trs.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 1999. - */ -/* ==================================================================== - * Copyright (c) 1999 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). + * Copyright 1999-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 "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/x509v3.h> +#include "internal/x509_int.h" static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b); static void trtable_free(X509_TRUST *p); @@ -94,9 +45,7 @@ static X509_TRUST trstandard[] = { {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL} }; -#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) - -IMPLEMENT_STACK_OF(X509_TRUST) +#define X509_TRUST_COUNT OSSL_NELEM(trstandard) static STACK_OF(X509_TRUST) *trtable = NULL; @@ -117,16 +66,11 @@ int X509_check_trust(X509 *x, int id, int flags) { X509_TRUST *pt; int idx; - if (id == -1) - return 1; + /* We get this as a default value */ - if (id == 0) { - int rv; - rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); - if (rv != X509_TRUST_UNTRUSTED) - return rv; - return trust_compat(NULL, x, 0); - } + if (id == X509_TRUST_DEFAULT) + return obj_trust(NID_anyExtendedKeyUsage, x, + flags | X509_TRUST_DO_SS_COMPAT); idx = X509_TRUST_get_by_id(id); if (idx == -1) return default_trust(id, x, flags); @@ -154,13 +98,14 @@ int X509_TRUST_get_by_id(int id) { X509_TRUST tmp; int idx; + if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) return id - X509_TRUST_MIN; - tmp.trust = id; - if (!trtable) + if (trtable == NULL) return -1; + tmp.trust = id; idx = sk_X509_TRUST_find(trtable, &tmp); - if (idx == -1) + if (idx < 0) return -1; return idx + X509_TRUST_COUNT; } @@ -176,7 +121,7 @@ int X509_TRUST_set(int *t, int trust) } int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), - char *name, int arg1, void *arg2) + const char *name, int arg1, void *arg2) { int idx; X509_TRUST *trtmp; @@ -190,7 +135,7 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), idx = X509_TRUST_get_by_id(id); /* Need a new entry */ if (idx == -1) { - if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { + if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) { X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); return 0; } @@ -202,9 +147,9 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name); /* dup supplied name */ - if (!(trtmp->name = BUF_strdup(name))) { + if ((trtmp->name = OPENSSL_strdup(name)) == NULL) { X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); - return 0; + goto err; } /* Keep the dynamic flag of existing entry */ trtmp->flags &= X509_TRUST_DYNAMIC; @@ -218,16 +163,23 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), /* If its a new entry manage the dynamic table */ if (idx == -1) { - if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { + if (trtable == NULL + && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) { X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); - return 0; + goto err;; } if (!sk_X509_TRUST_push(trtable, trtmp)) { X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); - return 0; + goto err; } } return 1; + err: + if (idx == -1) { + OPENSSL_free(trtmp->name); + OPENSSL_free(trtmp); + } + return 0; } static void trtable_free(X509_TRUST *p) @@ -243,50 +195,53 @@ static void trtable_free(X509_TRUST *p) void X509_TRUST_cleanup(void) { - unsigned int i; - for (i = 0; i < X509_TRUST_COUNT; i++) - trtable_free(trstandard + i); sk_X509_TRUST_pop_free(trtable, trtable_free); trtable = NULL; } -int X509_TRUST_get_flags(X509_TRUST *xp) +int X509_TRUST_get_flags(const X509_TRUST *xp) { return xp->flags; } -char *X509_TRUST_get0_name(X509_TRUST *xp) +char *X509_TRUST_get0_name(const X509_TRUST *xp) { return xp->name; } -int X509_TRUST_get_trust(X509_TRUST *xp) +int X509_TRUST_get_trust(const X509_TRUST *xp) { return xp->trust; } static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) { - if (x->aux && (x->aux->trust || x->aux->reject)) - return obj_trust(trust->arg1, x, flags); /* - * we don't have any trust settings: for compatibility we return trusted - * if it is self signed + * Declare the chain verified if the desired trust OID is not rejected in + * any auxiliary trust info for this certificate, and the OID is either + * expressly trusted, or else either "anyEKU" is trusted, or the + * certificate is self-signed. */ - return trust_compat(trust, x, flags); + flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU; + return obj_trust(trust->arg1, x, flags); } static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) { - if (x->aux) - return obj_trust(trust->arg1, x, flags); - return X509_TRUST_UNTRUSTED; + /* + * Declare the chain verified only if the desired trust OID is not + * rejected and is expressly trusted. Neither "anyEKU" nor "compat" + * trust in self-signed certificates apply. + */ + flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU); + return obj_trust(trust->arg1, x, flags); } static int trust_compat(X509_TRUST *trust, X509 *x, int flags) { + /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(x, -1, 0); - if (x->ex_flags & EXFLAG_SS) + if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED; else return X509_TRUST_UNTRUSTED; @@ -294,25 +249,51 @@ static int trust_compat(X509_TRUST *trust, X509 *x, int flags) static int obj_trust(int id, X509 *x, int flags) { - ASN1_OBJECT *obj; + X509_CERT_AUX *ax = x->aux; int i; - X509_CERT_AUX *ax; - ax = x->aux; - if (!ax) - return X509_TRUST_UNTRUSTED; - if (ax->reject) { + + if (ax && ax->reject) { for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { - obj = sk_ASN1_OBJECT_value(ax->reject, i); - if (OBJ_obj2nid(obj) == id) + ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i); + int nid = OBJ_obj2nid(obj); + + if (nid == id || (nid == NID_anyExtendedKeyUsage && + (flags & X509_TRUST_OK_ANY_EKU))) return X509_TRUST_REJECTED; } } - if (ax->trust) { + + if (ax && ax->trust) { for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { - obj = sk_ASN1_OBJECT_value(ax->trust, i); - if (OBJ_obj2nid(obj) == id) + ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i); + int nid = OBJ_obj2nid(obj); + + if (nid == id || (nid == NID_anyExtendedKeyUsage && + (flags & X509_TRUST_OK_ANY_EKU))) return X509_TRUST_TRUSTED; } + /* + * Reject when explicit trust EKU are set and none match. + * + * Returning untrusted is enough for for full chains that end in + * self-signed roots, because when explicit trust is specified it + * suppresses the default blanket trust of self-signed objects. + * + * But for partial chains, this is not enough, because absent a similar + * trust-self-signed policy, non matching EKUs are indistinguishable + * from lack of EKU constraints. + * + * Therefore, failure to match any trusted purpose must trigger an + * explicit reject. + */ + return X509_TRUST_REJECTED; } - return X509_TRUST_UNTRUSTED; + + if ((flags & X509_TRUST_DO_SS_COMPAT) == 0) + return X509_TRUST_UNTRUSTED; + + /* + * Not rejected, and there is no list of accepted uses, try compat. + */ + return trust_compat(NULL, x, flags); } diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index 594031e7722d..4755b39eb4eb 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -1,67 +1,17 @@ -/* crypto/x509/x509_txt.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2017 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> #include <time.h> #include <errno.h> -#include "cryptlib.h" -#include <openssl/lhash.h> +#include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/evp.h> #include <openssl/asn1.h> @@ -70,149 +20,163 @@ const char *X509_verify_cert_error_string(long n) { - static char buf[100]; - switch ((int)n) { case X509_V_OK: - return ("ok"); + return "ok"; + case X509_V_ERR_UNSPECIFIED: + return "unspecified certificate verification error"; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - return ("unable to get issuer certificate"); + return "unable to get issuer certificate"; case X509_V_ERR_UNABLE_TO_GET_CRL: - return ("unable to get certificate CRL"); + return "unable to get certificate CRL"; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - return ("unable to decrypt certificate's signature"); + return "unable to decrypt certificate's signature"; case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - return ("unable to decrypt CRL's signature"); + return "unable to decrypt CRL's signature"; case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - return ("unable to decode issuer public key"); + return "unable to decode issuer public key"; case X509_V_ERR_CERT_SIGNATURE_FAILURE: - return ("certificate signature failure"); + return "certificate signature failure"; case X509_V_ERR_CRL_SIGNATURE_FAILURE: - return ("CRL signature failure"); + return "CRL signature failure"; case X509_V_ERR_CERT_NOT_YET_VALID: - return ("certificate is not yet valid"); - case X509_V_ERR_CRL_NOT_YET_VALID: - return ("CRL is not yet valid"); + return "certificate is not yet valid"; case X509_V_ERR_CERT_HAS_EXPIRED: - return ("certificate has expired"); + return "certificate has expired"; + case X509_V_ERR_CRL_NOT_YET_VALID: + return "CRL is not yet valid"; case X509_V_ERR_CRL_HAS_EXPIRED: - return ("CRL has expired"); + return "CRL has expired"; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - return ("format error in certificate's notBefore field"); + return "format error in certificate's notBefore field"; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - return ("format error in certificate's notAfter field"); + return "format error in certificate's notAfter field"; case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - return ("format error in CRL's lastUpdate field"); + return "format error in CRL's lastUpdate field"; case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - return ("format error in CRL's nextUpdate field"); + return "format error in CRL's nextUpdate field"; case X509_V_ERR_OUT_OF_MEM: - return ("out of memory"); + return "out of memory"; case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - return ("self signed certificate"); + return "self signed certificate"; case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - return ("self signed certificate in certificate chain"); + return "self signed certificate in certificate chain"; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - return ("unable to get local issuer certificate"); + return "unable to get local issuer certificate"; case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - return ("unable to verify the first certificate"); + return "unable to verify the first certificate"; case X509_V_ERR_CERT_CHAIN_TOO_LONG: - return ("certificate chain too long"); + return "certificate chain too long"; case X509_V_ERR_CERT_REVOKED: - return ("certificate revoked"); + return "certificate revoked"; case X509_V_ERR_INVALID_CA: - return ("invalid CA certificate"); - case X509_V_ERR_INVALID_NON_CA: - return ("invalid non-CA certificate (has CA markings)"); + return "invalid CA certificate"; case X509_V_ERR_PATH_LENGTH_EXCEEDED: - return ("path length constraint exceeded"); - case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: - return ("proxy path length constraint exceeded"); - case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: - return - ("proxy certificates not allowed, please set the appropriate flag"); + return "path length constraint exceeded"; case X509_V_ERR_INVALID_PURPOSE: - return ("unsupported certificate purpose"); + return "unsupported certificate purpose"; case X509_V_ERR_CERT_UNTRUSTED: - return ("certificate not trusted"); + return "certificate not trusted"; case X509_V_ERR_CERT_REJECTED: - return ("certificate rejected"); - case X509_V_ERR_APPLICATION_VERIFICATION: - return ("application verification failure"); + return "certificate rejected"; case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - return ("subject issuer mismatch"); + return "subject issuer mismatch"; case X509_V_ERR_AKID_SKID_MISMATCH: - return ("authority and subject key identifier mismatch"); + return "authority and subject key identifier mismatch"; case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: - return ("authority and issuer serial number mismatch"); + return "authority and issuer serial number mismatch"; case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: - return ("key usage does not include certificate signing"); + return "key usage does not include certificate signing"; case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: - return ("unable to get CRL issuer certificate"); + return "unable to get CRL issuer certificate"; case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: - return ("unhandled critical extension"); + return "unhandled critical extension"; case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: - return ("key usage does not include CRL signing"); - case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: - return ("key usage does not include digital signature"); + return "key usage does not include CRL signing"; case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: - return ("unhandled critical CRL extension"); + return "unhandled critical CRL extension"; + case X509_V_ERR_INVALID_NON_CA: + return "invalid non-CA certificate (has CA markings)"; + case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: + return "proxy path length constraint exceeded"; + case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: + return "key usage does not include digital signature"; + case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: + return + "proxy certificates not allowed, please set the appropriate flag"; case X509_V_ERR_INVALID_EXTENSION: - return ("invalid or inconsistent certificate extension"); + return "invalid or inconsistent certificate extension"; case X509_V_ERR_INVALID_POLICY_EXTENSION: - return ("invalid or inconsistent certificate policy extension"); + return "invalid or inconsistent certificate policy extension"; case X509_V_ERR_NO_EXPLICIT_POLICY: - return ("no explicit policy"); + return "no explicit policy"; case X509_V_ERR_DIFFERENT_CRL_SCOPE: - return ("Different CRL scope"); + return "Different CRL scope"; case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: - return ("Unsupported extension feature"); + return "Unsupported extension feature"; case X509_V_ERR_UNNESTED_RESOURCE: - return ("RFC 3779 resource not subset of parent's resources"); - + return "RFC 3779 resource not subset of parent's resources"; case X509_V_ERR_PERMITTED_VIOLATION: - return ("permitted subtree violation"); + return "permitted subtree violation"; case X509_V_ERR_EXCLUDED_VIOLATION: - return ("excluded subtree violation"); + return "excluded subtree violation"; case X509_V_ERR_SUBTREE_MINMAX: - return ("name constraints minimum and maximum not supported"); + return "name constraints minimum and maximum not supported"; + case X509_V_ERR_APPLICATION_VERIFICATION: + return "application verification failure"; case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: - return ("unsupported name constraint type"); + return "unsupported name constraint type"; case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: - return ("unsupported or invalid name constraint syntax"); + return "unsupported or invalid name constraint syntax"; case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: - return ("unsupported or invalid name syntax"); + return "unsupported or invalid name syntax"; case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: - return ("CRL path validation error"); - + return "CRL path validation error"; + case X509_V_ERR_PATH_LOOP: + return "Path Loop"; case X509_V_ERR_SUITE_B_INVALID_VERSION: - return ("Suite B: certificate version invalid"); + return "Suite B: certificate version invalid"; case X509_V_ERR_SUITE_B_INVALID_ALGORITHM: - return ("Suite B: invalid public key algorithm"); + return "Suite B: invalid public key algorithm"; case X509_V_ERR_SUITE_B_INVALID_CURVE: - return ("Suite B: invalid ECC curve"); + return "Suite B: invalid ECC curve"; case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: - return ("Suite B: invalid signature algorithm"); + return "Suite B: invalid signature algorithm"; case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: - return ("Suite B: curve not allowed for this LOS"); + return "Suite B: curve not allowed for this LOS"; case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: - return ("Suite B: cannot sign P-384 with P-256"); - + return "Suite B: cannot sign P-384 with P-256"; case X509_V_ERR_HOSTNAME_MISMATCH: - return ("Hostname mismatch"); + return "Hostname mismatch"; case X509_V_ERR_EMAIL_MISMATCH: - return ("Email address mismatch"); + return "Email address mismatch"; case X509_V_ERR_IP_ADDRESS_MISMATCH: - return ("IP address mismatch"); - + return "IP address mismatch"; + case X509_V_ERR_DANE_NO_MATCH: + return "No matching DANE TLSA records"; + case X509_V_ERR_EE_KEY_TOO_SMALL: + return "EE certificate key too weak"; + case X509_V_ERR_CA_KEY_TOO_SMALL: + return "CA certificate key too weak"; + case X509_V_ERR_CA_MD_TOO_WEAK: + return "CA signature digest algorithm too weak"; case X509_V_ERR_INVALID_CALL: - return ("Invalid certificate verification context"); + return "Invalid certificate verification context"; case X509_V_ERR_STORE_LOOKUP: - return ("Issuer certificate lookup error"); + return "Issuer certificate lookup error"; + case X509_V_ERR_NO_VALID_SCTS: + return "Certificate Transparency required, but no valid SCTs found"; case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION: - return ("proxy subject name violation"); + return "proxy subject name violation"; + case X509_V_ERR_OCSP_VERIFY_NEEDED: + return "OCSP verification needed"; + case X509_V_ERR_OCSP_VERIFY_FAILED: + return "OCSP verification failed"; + case X509_V_ERR_OCSP_CERT_UNKNOWN: + return "OCSP unknown cert"; default: - BIO_snprintf(buf, sizeof(buf), "error number %ld", n); - return (buf); + /* Printing an error number into a static buffer is not thread-safe */ + return "unknown certificate verification error"; } } diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c index 9a3517e02af1..75ae767d608c 100644 --- a/crypto/x509/x509_v3.c +++ b/crypto/x509/x509_v3.c @@ -1,75 +1,27 @@ -/* crypto/x509/x509_v3.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 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> -#include <openssl/stack.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" +#include <openssl/safestack.h> #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include "x509_lcl.h" int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) { if (x == NULL) - return (0); - return (sk_X509_EXTENSION_num(x)); + return 0; + return sk_X509_EXTENSION_num(x); } int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, @@ -79,18 +31,18 @@ int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, obj = OBJ_nid2obj(nid); if (obj == NULL) - return (-2); - return (X509v3_get_ext_by_OBJ(x, obj, lastpos)); + return -2; + return X509v3_get_ext_by_OBJ(x, obj, lastpos); } int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, - ASN1_OBJECT *obj, int lastpos) + const ASN1_OBJECT *obj, int lastpos) { int n; X509_EXTENSION *ex; if (sk == NULL) - return (-1); + return -1; lastpos++; if (lastpos < 0) lastpos = 0; @@ -98,9 +50,9 @@ int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, for (; lastpos < n; lastpos++) { ex = sk_X509_EXTENSION_value(sk, lastpos); if (OBJ_cmp(ex->object, obj) == 0) - return (lastpos); + return lastpos; } - return (-1); + return -1; } int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, @@ -110,7 +62,7 @@ int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, X509_EXTENSION *ex; if (sk == NULL) - return (-1); + return -1; lastpos++; if (lastpos < 0) lastpos = 0; @@ -118,9 +70,9 @@ int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, for (; lastpos < n; lastpos++) { ex = sk_X509_EXTENSION_value(sk, lastpos); if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit)) - return (lastpos); + return lastpos; } - return (-1); + return -1; } X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) @@ -136,9 +88,9 @@ X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) X509_EXTENSION *ret; if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) - return (NULL); + return NULL; ret = sk_X509_EXTENSION_delete(x, loc); - return (ret); + return ret; } STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, @@ -171,15 +123,14 @@ STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, goto err; if (*x == NULL) *x = sk; - return (sk); + return sk; err: X509err(X509_F_X509V3_ADD_EXT, ERR_R_MALLOC_FAILURE); err2: - if (new_ex != NULL) - X509_EXTENSION_free(new_ex); - if (x != NULL && *x == NULL && sk != NULL) + X509_EXTENSION_free(new_ex); + if (x != NULL && *x == NULL) sk_X509_EXTENSION_free(sk); - return (NULL); + return NULL; } X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, @@ -192,16 +143,16 @@ X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, obj = OBJ_nid2obj(nid); if (obj == NULL) { X509err(X509_F_X509_EXTENSION_CREATE_BY_NID, X509_R_UNKNOWN_NID); - return (NULL); + return NULL; } ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data); if (ret == NULL) ASN1_OBJECT_free(obj); - return (ret); + return ret; } X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, - ASN1_OBJECT *obj, int crit, + const ASN1_OBJECT *obj, int crit, ASN1_OCTET_STRING *data) { X509_EXTENSION *ret; @@ -210,7 +161,7 @@ X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, if ((ret = X509_EXTENSION_new()) == NULL) { X509err(X509_F_X509_EXTENSION_CREATE_BY_OBJ, ERR_R_MALLOC_FAILURE); - return (NULL); + return NULL; } } else ret = *ex; @@ -224,28 +175,28 @@ X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, if ((ex != NULL) && (*ex == NULL)) *ex = ret; - return (ret); + return ret; err: if ((ex == NULL) || (ret != *ex)) X509_EXTENSION_free(ret); - return (NULL); + return NULL; } -int X509_EXTENSION_set_object(X509_EXTENSION *ex, ASN1_OBJECT *obj) +int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj) { if ((ex == NULL) || (obj == NULL)) - return (0); + return 0; ASN1_OBJECT_free(ex->object); ex->object = OBJ_dup(obj); - return (1); + return ex->object != NULL; } int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) { if (ex == NULL) - return (0); + return 0; ex->critical = (crit) ? 0xFF : -1; - return (1); + return 1; } int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data) @@ -253,31 +204,31 @@ int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data) int i; if (ex == NULL) - return (0); - i = M_ASN1_OCTET_STRING_set(ex->value, data->data, data->length); + return 0; + i = ASN1_OCTET_STRING_set(&ex->value, data->data, data->length); if (!i) - return (0); - return (1); + return 0; + return 1; } ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) { if (ex == NULL) - return (NULL); - return (ex->object); + return NULL; + return ex->object; } ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) { if (ex == NULL) - return (NULL); - return (ex->value); + return NULL; + return &ex->value; } -int X509_EXTENSION_get_critical(X509_EXTENSION *ex) +int X509_EXTENSION_get_critical(const X509_EXTENSION *ex) { if (ex == NULL) - return (0); + return 0; if (ex->critical > 0) return 1; return 0; diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index b1472018baf7..3a60d412daf8 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1,75 +1,29 @@ -/* crypto/x509/x509_vfy.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. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * 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> #include <time.h> #include <errno.h> +#include <limits.h> -#include "cryptlib.h" +#include "internal/ctype.h" +#include "internal/cryptlib.h" #include <openssl/crypto.h> -#include <openssl/lhash.h> #include <openssl/buffer.h> #include <openssl/evp.h> #include <openssl/asn1.h> #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/objects.h> -#include "vpm_int.h" +#include "internal/dane.h" +#include "internal/x509_int.h" +#include "x509_lcl.h" /* CRL score values */ @@ -109,16 +63,23 @@ #define CRL_SCORE_TIME_DELTA 0x002 +static int build_chain(X509_STORE_CTX *ctx); +static int verify_chain(X509_STORE_CTX *ctx); +static int dane_verify(X509_STORE_CTX *ctx); static int null_callback(int ok, X509_STORE_CTX *e); static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); static int check_chain_extensions(X509_STORE_CTX *ctx); static int check_name_constraints(X509_STORE_CTX *ctx); static int check_id(X509_STORE_CTX *ctx); -static int check_trust(X509_STORE_CTX *ctx); +static int check_trust(X509_STORE_CTX *ctx, int num_untrusted); static int check_revocation(X509_STORE_CTX *ctx); static int check_cert(X509_STORE_CTX *ctx); static int check_policy(X509_STORE_CTX *ctx); +static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); +static int check_dane_issuer(X509_STORE_CTX *ctx, int depth); +static int check_key_level(X509_STORE_CTX *ctx, X509 *cert); +static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert); static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, unsigned int *preasons, X509_CRL *crl, X509 *x); @@ -137,22 +98,20 @@ static int check_crl_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *crl_path); static int internal_verify(X509_STORE_CTX *ctx); -const char X509_version[] = "X.509" OPENSSL_VERSION_PTEXT; static int null_callback(int ok, X509_STORE_CTX *e) { return ok; } -#if 0 -static int x509_subject_cmp(X509 **a, X509 **b) -{ - return X509_subject_name_cmp(*a, *b); -} -#endif /* Return 1 is a certificate is self signed */ static int cert_self_signed(X509 *x) { + /* + * FIXME: x509v3_cache_extensions() needs to detect more failures and not + * set EXFLAG_SET when that happens. Especially, if the failures are + * parse errors, rather than memory pressure! + */ X509_check_purpose(x, -1, 0); if (x->ex_flags & EXFLAG_SS) return 1; @@ -178,30 +137,130 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) break; } if (i < sk_X509_num(certs)) - CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(xtmp); else xtmp = NULL; sk_X509_pop_free(certs, X509_free); return xtmp; } -int X509_verify_cert(X509_STORE_CTX *ctx) +/*- + * Inform the verify callback of an error. + * If B<x> is not NULL it is the error cert, otherwise use the chain cert at + * B<depth>. + * If B<err> is not X509_V_OK, that's the error value, otherwise leave + * unchanged (presumably set by the caller). + * + * Returns 0 to abort verification with an error, non-zero to continue. + */ +static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) +{ + ctx->error_depth = depth; + ctx->current_cert = (x != NULL) ? x : sk_X509_value(ctx->chain, depth); + if (err != X509_V_OK) + ctx->error = err; + return ctx->verify_cb(0, ctx); +} + +/*- + * Inform the verify callback of an error, CRL-specific variant. Here, the + * error depth and certificate are already set, we just specify the error + * number. + * + * Returns 0 to abort verification with an error, non-zero to continue. + */ +static int verify_cb_crl(X509_STORE_CTX *ctx, int err) +{ + ctx->error = err; + return ctx->verify_cb(0, ctx); +} + +static int check_auth_level(X509_STORE_CTX *ctx) +{ + int i; + int num = sk_X509_num(ctx->chain); + + if (ctx->param->auth_level <= 0) + return 1; + + for (i = 0; i < num; ++i) { + X509 *cert = sk_X509_value(ctx->chain, i); + + /* + * We've already checked the security of the leaf key, so here we only + * check the security of issuer keys. + */ + if (i > 0 && !check_key_level(ctx, cert) && + verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL) == 0) + return 0; + /* + * We also check the signature algorithm security of all certificates + * except those of the trust anchor at index num-1. + */ + if (i < num - 1 && !check_sig_level(ctx, cert) && + verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK) == 0) + return 0; + } + return 1; +} + +static int verify_chain(X509_STORE_CTX *ctx) { - X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; - int bad_chain = 0; - X509_VERIFY_PARAM *param = ctx->param; - int depth, i, ok = 0; - int num, j, retry; - int (*cb) (int xok, X509_STORE_CTX *xctx); - STACK_OF(X509) *sktmp = NULL; - int trust = X509_TRUST_UNTRUSTED; int err; + int ok; + + /* + * Before either returning with an error, or continuing with CRL checks, + * instantiate chain public key parameters. + */ + if ((ok = build_chain(ctx)) == 0 || + (ok = check_chain_extensions(ctx)) == 0 || + (ok = check_auth_level(ctx)) == 0 || + (ok = check_id(ctx)) == 0 || 1) + X509_get_pubkey_parameters(NULL, ctx->chain); + if (ok == 0 || (ok = ctx->check_revocation(ctx)) == 0) + return ok; + + err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, + ctx->param->flags); + if (err != X509_V_OK) { + if ((ok = verify_cb_cert(ctx, NULL, ctx->error_depth, err)) == 0) + return ok; + } + + /* Verify chain signatures and expiration times */ + ok = (ctx->verify != NULL) ? ctx->verify(ctx) : internal_verify(ctx); + if (!ok) + return ok; + + if ((ok = check_name_constraints(ctx)) == 0) + return ok; + +#ifndef OPENSSL_NO_RFC3779 + /* RFC 3779 path validation, now that CRL check has been done */ + if ((ok = X509v3_asid_validate_path(ctx)) == 0) + return ok; + if ((ok = X509v3_addr_validate_path(ctx)) == 0) + return ok; +#endif + + /* If we get this far evaluate policies */ + if (ctx->param->flags & X509_V_FLAG_POLICY_CHECK) + ok = ctx->check_policy(ctx); + return ok; +} + +int X509_verify_cert(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + int ret; if (ctx->cert == NULL) { X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); ctx->error = X509_V_ERR_INVALID_CALL; return -1; } + if (ctx->chain != NULL) { /* * This X509_STORE_CTX has already been used to verify a cert. We @@ -212,8 +271,6 @@ int X509_verify_cert(X509_STORE_CTX *ctx) return -1; } - cb = ctx->verify_cb; - /* * first we make sure the chain we are going to build is present and that * the first entry is in place @@ -222,332 +279,48 @@ int X509_verify_cert(X509_STORE_CTX *ctx) (!sk_X509_push(ctx->chain, ctx->cert))) { X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); ctx->error = X509_V_ERR_OUT_OF_MEM; - ok = -1; - goto err; - } - CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509); - ctx->last_untrusted = 1; - - /* We use a temporary STACK so we can chop and hack at it */ - if (ctx->untrusted != NULL - && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - ok = -1; - goto err; - } - - num = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, num - 1); - depth = param->depth; - - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; /* FIXME: If this happens, we should take - * note of it and, if appropriate, use the - * X509_V_ERR_CERT_CHAIN_TOO_LONG error code - * later. */ - - /* If we are self signed, we break */ - if (cert_self_signed(x)) - break; - /* - * If asked see if we can find issuer in trusted store first - */ - if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) { - ok = ctx->get_issuer(&xtmp, ctx, x); - if (ok < 0) { - ctx->error = X509_V_ERR_STORE_LOOKUP; - goto err; - } - /* - * If successful for now free up cert so it will be picked up - * again later. - */ - if (ok > 0) { - X509_free(xtmp); - break; - } - } - - /* If we were passed a cert chain, use it first */ - if (ctx->untrusted != NULL) { - xtmp = find_issuer(ctx, sktmp, x); - if (xtmp != NULL) { - if (!sk_X509_push(ctx->chain, xtmp)) { - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - ok = -1; - goto err; - } - CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509); - (void)sk_X509_delete_ptr(sktmp, xtmp); - ctx->last_untrusted++; - x = xtmp; - num++; - /* - * reparse the full chain for the next one - */ - continue; - } - } - break; - } - - /* Remember how many untrusted certs we have */ - j = num; - /* - * at this point, chain should contain a list of untrusted certificates. - * We now need to add at least one trusted one, if possible, otherwise we - * complain. - */ - - do { - /* - * Examine last certificate in chain and see if it is self signed. - */ - i = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, i - 1); - if (cert_self_signed(x)) { - /* we have a self signed certificate */ - if (sk_X509_num(ctx->chain) == 1) { - /* - * We have a single self signed certificate: see if we can - * find it in the store. We must have an exact match to avoid - * possible impersonation. - */ - ok = ctx->get_issuer(&xtmp, ctx, x); - if ((ok <= 0) || X509_cmp(x, xtmp)) { - ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert = x; - ctx->error_depth = i - 1; - if (ok == 1) - X509_free(xtmp); - bad_chain = 1; - ok = cb(0, ctx); - if (!ok) - goto err; - } else { - /* - * We have a match: replace certificate with store - * version so we get any trust settings. - */ - X509_free(x); - x = xtmp; - (void)sk_X509_set(ctx->chain, i - 1, x); - ctx->last_untrusted = 0; - } - } else { - /* - * extract and save self signed certificate for later use - */ - chain_ss = sk_X509_pop(ctx->chain); - ctx->last_untrusted--; - num--; - j--; - x = sk_X509_value(ctx->chain, num - 1); - } - } - /* We now lookup certs from the certificate store */ - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; - /* If we are self signed, we break */ - if (cert_self_signed(x)) - break; - ok = ctx->get_issuer(&xtmp, ctx, x); - - if (ok < 0) { - ctx->error = X509_V_ERR_STORE_LOOKUP; - goto err; - } - if (ok == 0) - break; - x = xtmp; - if (!sk_X509_push(ctx->chain, x)) { - X509_free(xtmp); - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - ok = -1; - goto err; - } - num++; - } - - /* we now have our chain, lets check it... */ - if ((trust = check_trust(ctx)) == X509_TRUST_REJECTED) { - /* Callback already issued */ - ok = 0; - goto err; - } - - /* - * If it's not explicitly trusted then check if there is an alternative - * chain that could be used. We only do this if we haven't already - * checked via TRUSTED_FIRST and the user hasn't switched off alternate - * chain checking - */ - retry = 0; - if (trust != X509_TRUST_TRUSTED - && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) - && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { - while (j-- > 1) { - xtmp2 = sk_X509_value(ctx->chain, j - 1); - ok = ctx->get_issuer(&xtmp, ctx, xtmp2); - if (ok < 0) { - ctx->error = X509_V_ERR_STORE_LOOKUP; - goto err; - } - /* Check if we found an alternate chain */ - if (ok > 0) { - /* - * Free up the found cert we'll add it again later - */ - X509_free(xtmp); - - /* - * Dump all the certs above this point - we've found an - * alternate chain - */ - while (num > j) { - xtmp = sk_X509_pop(ctx->chain); - X509_free(xtmp); - num--; - } - ctx->last_untrusted = sk_X509_num(ctx->chain); - retry = 1; - break; - } - } - } - } while (retry); - - /* - * If not explicitly trusted then indicate error unless it's a single - * self signed certificate in which case we've indicated an error already - * and set bad_chain == 1 - */ - if (trust != X509_TRUST_TRUSTED && !bad_chain) { - if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { - if (ctx->last_untrusted >= num) - ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; - else - ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; - ctx->current_cert = x; - } else { - - sk_X509_push(ctx->chain, chain_ss); - num++; - ctx->last_untrusted = num; - ctx->current_cert = chain_ss; - ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; - chain_ss = NULL; - } - - ctx->error_depth = num - 1; - bad_chain = 1; - ok = cb(0, ctx); - if (!ok) - goto err; + return -1; } + X509_up_ref(ctx->cert); + ctx->num_untrusted = 1; - /* We have the chain complete: now we need to check its purpose */ - ok = check_chain_extensions(ctx); - - if (!ok) - goto err; - - /* Check name constraints */ - - ok = check_name_constraints(ctx); - - if (!ok) - goto err; - - ok = check_id(ctx); - - if (!ok) - goto err; + /* If the peer's public key is too weak, we can stop early. */ + if (!check_key_level(ctx, ctx->cert) && + !verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL)) + return 0; - /* We may as well copy down any DSA parameters that are required */ - X509_get_pubkey_parameters(NULL, ctx->chain); + if (DANETLS_ENABLED(dane)) + ret = dane_verify(ctx); + else + ret = verify_chain(ctx); /* - * Check revocation status: we do this after copying parameters because - * they may be needed for CRL signature verification. + * Safety-net. If we are returning an error, we must also set ctx->error, + * so that the chain is not considered verified should the error be ignored + * (e.g. TLS with SSL_VERIFY_NONE). */ - - ok = ctx->check_revocation(ctx); - if (!ok) - goto err; - - err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, - ctx->param->flags); - if (err != X509_V_OK) { - ctx->error = err; - ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); - ok = cb(0, ctx); - if (!ok) - goto err; - } - - /* At this point, we have a chain and need to verify it */ - if (ctx->verify != NULL) - ok = ctx->verify(ctx); - else - ok = internal_verify(ctx); - if (!ok) - goto err; - -#ifndef OPENSSL_NO_RFC3779 - /* RFC 3779 path validation, now that CRL check has been done */ - ok = v3_asid_validate_path(ctx); - if (!ok) - goto err; - ok = v3_addr_validate_path(ctx); - if (!ok) - goto err; -#endif - - /* If we get this far evaluate policies */ - if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) - ok = ctx->check_policy(ctx); - if (!ok) - goto err; - if (0) { - err: - /* Ensure we return an error */ - if (ok > 0) - ok = 0; - X509_get_pubkey_parameters(NULL, ctx->chain); - } - if (sktmp != NULL) - sk_X509_free(sktmp); - if (chain_ss != NULL) - X509_free(chain_ss); - - /* Safety net, error returns must set ctx->error */ - if (ok <= 0 && ctx->error == X509_V_OK) + if (ret <= 0 && ctx->error == X509_V_OK) ctx->error = X509_V_ERR_UNSPECIFIED; - return ok; + return ret; } /* * Given a STACK_OF(X509) find the issuer of cert (if any) */ - static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) { int i; - X509 *issuer; + X509 *issuer, *rv = NULL; + for (i = 0; i < sk_X509_num(sk); i++) { issuer = sk_X509_value(sk, i); - if (ctx->check_issued(ctx, x, issuer)) - return issuer; + if (ctx->check_issued(ctx, x, issuer)) { + rv = issuer; + if (x509_check_cert_time(ctx, rv, -1)) + break; + } } - return NULL; + return rv; } /* Given a possible certificate and issuer check them */ @@ -555,17 +328,25 @@ static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) { int ret; + if (x == issuer) + return cert_self_signed(x); ret = X509_check_issued(issuer, x); - if (ret == X509_V_OK) - return 1; - /* If we haven't asked for issuer errors don't set ctx */ - if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) - return 0; + if (ret == X509_V_OK) { + int i; + X509 *ch; + /* Special case: single self signed certificate */ + if (cert_self_signed(x) && sk_X509_num(ctx->chain) == 1) + return 1; + for (i = 0; i < sk_X509_num(ctx->chain); i++) { + ch = sk_X509_value(ctx->chain, i); + if (ch == issuer || !X509_cmp(ch, issuer)) { + ret = X509_V_ERR_PATH_LOOP; + break; + } + } + } - ctx->error = ret; - ctx->current_cert = x; - ctx->current_issuer = issuer; - return ctx->verify_cb(0, ctx); + return (ret == X509_V_OK); } /* Alternative lookup method: look from a STACK stored in other_ctx */ @@ -574,12 +355,86 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { *issuer = find_issuer(ctx, ctx->other_ctx, x); if (*issuer) { - CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(*issuer); return 1; } else return 0; } +static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + STACK_OF(X509) *sk = NULL; + X509 *x; + int i; + + for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) { + x = sk_X509_value(ctx->other_ctx, i); + if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) { + if (sk == NULL) + sk = sk_X509_new_null(); + if (sk == NULL || sk_X509_push(sk, x) == 0) { + sk_X509_pop_free(sk, X509_free); + X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return NULL; + } + X509_up_ref(x); + } + } + return sk; +} + +/* + * Check EE or CA certificate purpose. For trusted certificates explicit local + * auxiliary trust can be used to override EKU-restrictions. + */ +static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, + int must_be_ca) +{ + int tr_ok = X509_TRUST_UNTRUSTED; + + /* + * For trusted certificates we want to see whether any auxiliary trust + * settings trump the purpose constraints. + * + * This is complicated by the fact that the trust ordinals in + * ctx->param->trust are entirely independent of the purpose ordinals in + * ctx->param->purpose! + * + * What connects them is their mutual initialization via calls from + * X509_STORE_CTX_set_default() into X509_VERIFY_PARAM_lookup() which sets + * related values of both param->trust and param->purpose. It is however + * typically possible to infer associated trust values from a purpose value + * via the X509_PURPOSE API. + * + * Therefore, we can only check for trust overrides when the purpose we're + * checking is the same as ctx->param->purpose and ctx->param->trust is + * also set. + */ + if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose) + tr_ok = X509_check_trust(x, ctx->param->trust, X509_TRUST_NO_SS_COMPAT); + + switch (tr_ok) { + case X509_TRUST_TRUSTED: + return 1; + case X509_TRUST_REJECTED: + break; + default: + switch (X509_check_purpose(x, purpose, must_be_ca > 0)) { + case 1: + return 1; + case 0: + break; + default: + if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0) + return 1; + } + break; + } + + return verify_cb_cert(ctx, x, depth, X509_V_ERR_INVALID_PURPOSE); +} + /* * Check a certificate chains extensions for consistency with the supplied * purpose @@ -587,16 +442,12 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) static int check_chain_extensions(X509_STORE_CTX *ctx) { -#ifdef OPENSSL_NO_CHAIN_VERIFY - return 1; -#else - int i, ok = 0, must_be_ca, plen = 0; + int i, must_be_ca, plen = 0; X509 *x; - int (*cb) (int xok, X509_STORE_CTX *xctx); int proxy_path_length = 0; int purpose; int allow_proxy_certs; - cb = ctx->verify_cb; + int num = sk_X509_num(ctx->chain); /*- * must_be_ca can have 1 of 3 values: @@ -616,35 +467,22 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) } else { allow_proxy_certs = ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS); - /* - * A hack to keep people who don't want to modify their software - * happy - */ - if (getenv("OPENSSL_ALLOW_PROXY_CERTS")) - allow_proxy_certs = 1; purpose = ctx->param->purpose; } - /* Check all untrusted certificates */ - for (i = 0; i < ctx->last_untrusted; i++) { + for (i = 0; i < num; i++) { int ret; x = sk_X509_value(ctx->chain, i); if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && (x->ex_flags & EXFLAG_CRITICAL)) { - ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; - ctx->error_depth = i; - ctx->current_cert = x; - ok = cb(0, ctx); - if (!ok) - goto end; + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)) + return 0; } if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) { - ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED; - ctx->error_depth = i; - ctx->current_cert = x; - ok = cb(0, ctx); - if (!ok) - goto end; + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)) + return 0; } ret = X509_check_ca(x); switch (must_be_ca) { @@ -664,8 +502,9 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ret = 1; break; default: + /* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */ if ((ret == 0) - || ((ctx->param->flags & X509_V_FLAG_X509_STRICT) + || ((i + 1 < num || ctx->param->flags & X509_V_FLAG_X509_STRICT) && (ret != 1))) { ret = 0; ctx->error = X509_V_ERR_INVALID_CA; @@ -673,36 +512,17 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ret = 1; break; } - if (ret == 0) { - ctx->error_depth = i; - ctx->current_cert = x; - ok = cb(0, ctx); - if (!ok) - goto end; - } - if (ctx->param->purpose > 0) { - ret = X509_check_purpose(x, purpose, must_be_ca > 0); - if ((ret == 0) - || ((ctx->param->flags & X509_V_FLAG_X509_STRICT) - && (ret != 1))) { - ctx->error = X509_V_ERR_INVALID_PURPOSE; - ctx->error_depth = i; - ctx->current_cert = x; - ok = cb(0, ctx); - if (!ok) - goto end; - } - } + if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK)) + return 0; + /* check_purpose() makes the callback as needed */ + if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca)) + return 0; /* Check pathlen if not self issued */ if ((i > 1) && !(x->ex_flags & EXFLAG_SI) && (x->ex_pathlen != -1) && (plen > (x->ex_pathlen + proxy_path_length + 1))) { - ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; - ctx->error_depth = i; - ctx->current_cert = x; - ok = cb(0, ctx); - if (!ok) - goto end; + if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED)) + return 0; } /* Increment path length if not self issued */ if (!(x->ex_flags & EXFLAG_SI)) @@ -726,12 +546,9 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) */ if (x->ex_pcpathlen != -1) { if (proxy_path_length > x->ex_pcpathlen) { - ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED; - ctx->error_depth = i; - ctx->current_cert = x; - ok = cb(0, ctx); - if (!ok) - goto end; + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)) + return 0; } proxy_path_length = x->ex_pcpathlen; } @@ -740,19 +557,39 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) } else must_be_ca = 1; } - ok = 1; - end: - return ok; -#endif + return 1; +} + +static int has_san_id(X509 *x, int gtype) +{ + int i; + int ret = 0; + GENERAL_NAMES *gs = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + + if (gs == NULL) + return 0; + + for (i = 0; i < sk_GENERAL_NAME_num(gs); i++) { + GENERAL_NAME *g = sk_GENERAL_NAME_value(gs, i); + + if (g->type == gtype) { + ret = 1; + break; + } + } + GENERAL_NAMES_free(gs); + return ret; } static int check_name_constraints(X509_STORE_CTX *ctx) { - X509 *x; - int i, j, rv; + int i; + /* Check name constraints for all certificates */ for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) { - x = sk_X509_value(ctx->chain, i); + X509 *x = sk_X509_value(ctx->chain, i); + int j; + /* Ignore self issued certs unless last in chain */ if (i && (x->ex_flags & EXFLAG_SI)) continue; @@ -791,8 +628,10 @@ static int check_name_constraints(X509_STORE_CTX *ctx) * Check that the last subject component isn't part of a * multivalued RDN */ - if (X509_NAME_get_entry(tmpsubject, last_object_loc)->set - == X509_NAME_get_entry(tmpsubject, last_object_loc - 1)->set) { + if (X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject, + last_object_loc)) + == X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject, + last_object_loc - 1))) { err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION; goto proxy_name_done; } @@ -822,13 +661,9 @@ static int check_name_constraints(X509_STORE_CTX *ctx) X509_NAME_free(tmpsubject); proxy_name_done: - if (err != X509_V_OK) { - ctx->error = err; - ctx->error_depth = i; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; - } + if (err != X509_V_OK + && !verify_cb_cert(ctx, x, i, err)) + return 0; } /* @@ -839,19 +674,26 @@ static int check_name_constraints(X509_STORE_CTX *ctx) */ for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) { NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc; + if (nc) { - rv = NAME_CONSTRAINTS_check(x, nc); + int rv = NAME_CONSTRAINTS_check(x, nc); + + /* If EE certificate check commonName too */ + if (rv == X509_V_OK && i == 0 + && (ctx->param->hostflags + & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0 + && ((ctx->param->hostflags + & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0 + || !has_san_id(x, GEN_DNS))) + rv = NAME_CONSTRAINTS_check_CN(x, nc); + switch (rv) { case X509_V_OK: - continue; + break; case X509_V_ERR_OUT_OF_MEM: - ctx->error = rv; return 0; default: - ctx->error = rv; - ctx->error_depth = i; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) + if (!verify_cb_cert(ctx, x, i, rv)) return 0; break; } @@ -863,25 +705,22 @@ static int check_name_constraints(X509_STORE_CTX *ctx) static int check_id_error(X509_STORE_CTX *ctx, int errcode) { - ctx->error = errcode; - ctx->current_cert = ctx->cert; - ctx->error_depth = 0; - return ctx->verify_cb(0, ctx); + return verify_cb_cert(ctx, ctx->cert, 0, errcode); } -static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id) +static int check_hosts(X509 *x, X509_VERIFY_PARAM *vpm) { int i; - int n = sk_OPENSSL_STRING_num(id->hosts); + int n = sk_OPENSSL_STRING_num(vpm->hosts); char *name; - if (id->peername != NULL) { - OPENSSL_free(id->peername); - id->peername = NULL; + if (vpm->peername != NULL) { + OPENSSL_free(vpm->peername); + vpm->peername = NULL; } for (i = 0; i < n; ++i) { - name = sk_OPENSSL_STRING_value(id->hosts, i); - if (X509_check_host(x, name, 0, id->hostflags, &id->peername) > 0) + name = sk_OPENSSL_STRING_value(vpm->hosts, i); + if (X509_check_host(x, name, 0, vpm->hostflags, &vpm->peername) > 0) return 1; } return n == 0; @@ -890,65 +729,95 @@ static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id) static int check_id(X509_STORE_CTX *ctx) { X509_VERIFY_PARAM *vpm = ctx->param; - X509_VERIFY_PARAM_ID *id = vpm->id; X509 *x = ctx->cert; - if (id->hosts && check_hosts(x, id) <= 0) { + if (vpm->hosts && check_hosts(x, vpm) <= 0) { if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) return 0; } - if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0) { + if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) { if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) return 0; } - if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0) { + if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) { if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) return 0; } return 1; } -static int check_trust(X509_STORE_CTX *ctx) +static int check_trust(X509_STORE_CTX *ctx, int num_untrusted) { - int i, ok; + int i; X509 *x = NULL; - int (*cb) (int xok, X509_STORE_CTX *xctx); - cb = ctx->verify_cb; - /* Check all trusted certificates in chain */ - for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) { + X509 *mx; + SSL_DANE *dane = ctx->dane; + int num = sk_X509_num(ctx->chain); + int trust; + + /* + * Check for a DANE issuer at depth 1 or greater, if it is a DANE-TA(2) + * match, we're done, otherwise we'll merely record the match depth. + */ + if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) { + switch (trust = check_dane_issuer(ctx, num_untrusted)) { + case X509_TRUST_TRUSTED: + case X509_TRUST_REJECTED: + return trust; + } + } + + /* + * Check trusted certificates in chain at depth num_untrusted and up. + * Note, that depths 0..num_untrusted-1 may also contain trusted + * certificates, but the caller is expected to have already checked those, + * and wants to incrementally check just any added since. + */ + for (i = num_untrusted; i < num; i++) { x = sk_X509_value(ctx->chain, i); - ok = X509_check_trust(x, ctx->param->trust, 0); + trust = X509_check_trust(x, ctx->param->trust, 0); /* If explicitly trusted return trusted */ - if (ok == X509_TRUST_TRUSTED) - return X509_TRUST_TRUSTED; - /* - * If explicitly rejected notify callback and reject if not - * overridden. - */ - if (ok == X509_TRUST_REJECTED) { - ctx->error_depth = i; - ctx->current_cert = x; - ctx->error = X509_V_ERR_CERT_REJECTED; - ok = cb(0, ctx); - if (!ok) - return X509_TRUST_REJECTED; - } + if (trust == X509_TRUST_TRUSTED) + goto trusted; + if (trust == X509_TRUST_REJECTED) + goto rejected; } + /* - * If we accept partial chains and have at least one trusted certificate - * return success. + * If we are looking at a trusted certificate, and accept partial chains, + * the chain is PKIX trusted. */ - if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { - X509 *mx; - if (ctx->last_untrusted < sk_X509_num(ctx->chain)) - return X509_TRUST_TRUSTED; - x = sk_X509_value(ctx->chain, 0); + if (num_untrusted < num) { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) + goto trusted; + return X509_TRUST_UNTRUSTED; + } + + if (num_untrusted == num && ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + /* + * Last-resort call with no new trusted certificates, check the leaf + * for a direct trust store match. + */ + i = 0; + x = sk_X509_value(ctx->chain, i); mx = lookup_cert_match(ctx, x); - if (mx) { - (void)sk_X509_set(ctx->chain, 0, mx); - X509_free(x); - ctx->last_untrusted = 0; - return X509_TRUST_TRUSTED; + if (!mx) + return X509_TRUST_UNTRUSTED; + + /* + * Check explicit auxiliary trust/reject settings. If none are set, + * we'll accept X509_TRUST_UNTRUSTED when not self-signed. + */ + trust = X509_check_trust(mx, ctx->param->trust, 0); + if (trust == X509_TRUST_REJECTED) { + X509_free(mx); + goto rejected; } + + /* Replace leaf with trusted match */ + (void) sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->num_untrusted = 0; + goto trusted; } /* @@ -956,11 +825,26 @@ static int check_trust(X509_STORE_CTX *ctx) * standard (no issuer cert) etc errors to be indicated. */ return X509_TRUST_UNTRUSTED; + + rejected: + if (!verify_cb_cert(ctx, x, i, X509_V_ERR_CERT_REJECTED)) + return X509_TRUST_REJECTED; + return X509_TRUST_UNTRUSTED; + + trusted: + if (!DANETLS_ENABLED(dane)) + return X509_TRUST_TRUSTED; + if (dane->pdpth < 0) + dane->pdpth = num_untrusted; + /* With DANE, PKIX alone is not trusted until we have both */ + if (dane->mdpth >= 0) + return X509_TRUST_TRUSTED; + return X509_TRUST_UNTRUSTED; } static int check_revocation(X509_STORE_CTX *ctx) { - int i, last, ok; + int i = 0, last = 0, ok = 0; if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) return 1; if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) @@ -983,19 +867,21 @@ static int check_revocation(X509_STORE_CTX *ctx) static int check_cert(X509_STORE_CTX *ctx) { X509_CRL *crl = NULL, *dcrl = NULL; - X509 *x; - int ok, cnum; - unsigned int last_reasons; - cnum = ctx->error_depth; - x = sk_X509_value(ctx->chain, cnum); + int ok = 0; + int cnum = ctx->error_depth; + X509 *x = sk_X509_value(ctx->chain, cnum); + ctx->current_cert = x; ctx->current_issuer = NULL; ctx->current_crl_score = 0; ctx->current_reasons = 0; + if (x->ex_flags & EXFLAG_PROXY) return 1; + while (ctx->current_reasons != CRLDP_ALL_REASONS) { - last_reasons = ctx->current_reasons; + unsigned int last_reasons = ctx->current_reasons; + /* Try to retrieve relevant CRL */ if (ctx->get_crl) ok = ctx->get_crl(ctx, &crl, x); @@ -1005,22 +891,21 @@ static int check_cert(X509_STORE_CTX *ctx) * If error looking up CRL, nothing we can do except notify callback */ if (!ok) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; - ok = ctx->verify_cb(0, ctx); - goto err; + ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL); + goto done; } ctx->current_crl = crl; ok = ctx->check_crl(ctx, crl); if (!ok) - goto err; + goto done; if (dcrl) { ok = ctx->check_crl(ctx, dcrl); if (!ok) - goto err; + goto done; ok = ctx->cert_crl(ctx, dcrl, x); if (!ok) - goto err; + goto done; } else ok = 1; @@ -1028,7 +913,7 @@ static int check_cert(X509_STORE_CTX *ctx) if (ok != 2) { ok = ctx->cert_crl(ctx, crl, x); if (!ok) - goto err; + goto done; } X509_CRL_free(crl); @@ -1036,22 +921,20 @@ static int check_cert(X509_STORE_CTX *ctx) crl = NULL; dcrl = NULL; /* - * If reasons not updated we wont get anywhere by another iteration, + * If reasons not updated we won't get anywhere by another iteration, * so exit loop. */ if (last_reasons == ctx->current_reasons) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; - ok = ctx->verify_cb(0, ctx); - goto err; + ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL); + goto done; } } - err: + done: X509_CRL_free(crl); X509_CRL_free(dcrl); ctx->current_crl = NULL; return ok; - } /* Check CRL times against values in X509_STORE_CTX */ @@ -1060,46 +943,45 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) { time_t *ptime; int i; + if (notify) ctx->current_crl = crl; if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; else ptime = NULL; - i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); + i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); if (i == 0) { if (!notify) return 0; - ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; - if (!ctx->verify_cb(0, ctx)) + if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD)) return 0; } if (i > 0) { if (!notify) return 0; - ctx->error = X509_V_ERR_CRL_NOT_YET_VALID; - if (!ctx->verify_cb(0, ctx)) + if (!verify_cb_crl(ctx, X509_V_ERR_CRL_NOT_YET_VALID)) return 0; } - if (X509_CRL_get_nextUpdate(crl)) { - i = X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime); + if (X509_CRL_get0_nextUpdate(crl)) { + i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime); if (i == 0) { if (!notify) return 0; - ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; - if (!ctx->verify_cb(0, ctx)) + if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD)) return 0; } /* Ignore expiry of base CRL is delta is valid */ if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) { if (!notify) return 0; - ctx->error = X509_V_ERR_CRL_HAS_EXPIRED; - if (!ctx->verify_cb(0, ctx)) + if (!verify_cb_crl(ctx, X509_V_ERR_CRL_HAS_EXPIRED)) return 0; } } @@ -1129,8 +1011,8 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, /* If current CRL is equivalent use it if it is newer */ if (crl_score == best_score && best_crl != NULL) { int day, sec; - if (ASN1_TIME_diff(&day, &sec, X509_CRL_get_lastUpdate(best_crl), - X509_CRL_get_lastUpdate(crl)) == 0) + if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl), + X509_CRL_get0_lastUpdate(crl)) == 0) continue; /* * ASN1_TIME_diff never returns inconsistent signs for |day| @@ -1146,17 +1028,14 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, } if (best_crl) { - if (*pcrl) - X509_CRL_free(*pcrl); + X509_CRL_free(*pcrl); *pcrl = best_crl; *pissuer = best_crl_issuer; *pscore = best_score; *preasons = best_reasons; - CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509_CRL); - if (*pdcrl) { - X509_CRL_free(*pdcrl); - *pdcrl = NULL; - } + X509_CRL_up_ref(best_crl); + X509_CRL_free(*pdcrl); + *pdcrl = NULL; get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); } @@ -1252,7 +1131,7 @@ static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, if (check_delta_base(delta, base)) { if (check_crl_time(ctx, delta, 0)) *pscore |= CRL_SCORE_TIME_DELTA; - CRYPTO_add(&delta->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(delta); *dcrl = delta; return; } @@ -1394,6 +1273,7 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) { X509_STORE_CTX crl_ctx; int ret; + /* Don't allow recursive CRL path validation */ if (ctx->parent) return 0; @@ -1409,12 +1289,10 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) /* Verify CRL issuer */ ret = X509_verify_cert(&crl_ctx); - if (ret <= 0) goto err; /* Check chain is acceptable */ - ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); err: X509_STORE_CTX_cleanup(&crl_ctx); @@ -1571,10 +1449,10 @@ static int get_crl_delta(X509_STORE_CTX *ctx, X509_CRL *crl = NULL, *dcrl = NULL; STACK_OF(X509_CRL) *skcrl; X509_NAME *nm = X509_get_issuer_name(x); + reasons = ctx->current_reasons; ok = get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, ctx->crls); - if (ok) goto done; @@ -1591,7 +1469,6 @@ static int get_crl_delta(X509_STORE_CTX *ctx, sk_X509_CRL_pop_free(skcrl, X509_CRL_free); done: - /* If we got any kind of CRL use it and return success */ if (crl) { ctx->current_issuer = issuer; @@ -1601,7 +1478,6 @@ static int get_crl_delta(X509_STORE_CTX *ctx, *pdcrl = dcrl; return 1; } - return 0; } @@ -1610,13 +1486,12 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) { X509 *issuer = NULL; EVP_PKEY *ikey = NULL; - int ok = 0, chnum, cnum; - cnum = ctx->error_depth; - chnum = sk_X509_num(ctx->chain) - 1; + int cnum = ctx->error_depth; + int chnum = sk_X509_num(ctx->chain) - 1; + /* if we have an alternative CRL issuer cert use that */ if (ctx->current_issuer) issuer = ctx->current_issuer; - /* * Else find CRL issuer: if not last certificate then issuer is next * certificate in chain. @@ -1626,121 +1501,85 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) else { issuer = sk_X509_value(ctx->chain, chnum); /* If not self signed, can't check signature */ - if (!ctx->check_issued(ctx, issuer, issuer)) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } + if (!ctx->check_issued(ctx, issuer, issuer) && + !verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)) + return 0; } - if (issuer) { - /* - * Skip most tests for deltas because they have already been done - */ - if (!crl->base_crl_number) { - /* Check for cRLSign bit if keyUsage present */ - if ((issuer->ex_flags & EXFLAG_KUSAGE) && - !(issuer->ex_kusage & KU_CRL_SIGN)) { - ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } + if (issuer == NULL) + return 1; - if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) { - ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } + /* + * Skip most tests for deltas because they have already been done + */ + if (!crl->base_crl_number) { + /* Check for cRLSign bit if keyUsage present */ + if ((issuer->ex_flags & EXFLAG_KUSAGE) && + !(issuer->ex_kusage & KU_CRL_SIGN) && + !verify_cb_crl(ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)) + return 0; - if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) { - if (check_crl_path(ctx, ctx->current_issuer) <= 0) { - ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - } + if (!(ctx->current_crl_score & CRL_SCORE_SCOPE) && + !verify_cb_crl(ctx, X509_V_ERR_DIFFERENT_CRL_SCOPE)) + return 0; - if (crl->idp_flags & IDP_INVALID) { - ctx->error = X509_V_ERR_INVALID_EXTENSION; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } + if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH) && + check_crl_path(ctx, ctx->current_issuer) <= 0 && + !verify_cb_crl(ctx, X509_V_ERR_CRL_PATH_VALIDATION_ERROR)) + return 0; - } + if ((crl->idp_flags & IDP_INVALID) && + !verify_cb_crl(ctx, X509_V_ERR_INVALID_EXTENSION)) + return 0; + } - if (!(ctx->current_crl_score & CRL_SCORE_TIME)) { - ok = check_crl_time(ctx, crl, 1); - if (!ok) - goto err; - } + if (!(ctx->current_crl_score & CRL_SCORE_TIME) && + !check_crl_time(ctx, crl, 1)) + return 0; - /* Attempt to get issuer certificate public key */ - ikey = X509_get_pubkey(issuer); + /* Attempt to get issuer certificate public key */ + ikey = X509_get0_pubkey(issuer); - if (!ikey) { - ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } else { - int rv; - rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); - if (rv != X509_V_OK) { - ctx->error = rv; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - /* Verify CRL signature */ - if (X509_CRL_verify(crl, ikey) <= 0) { - ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; - ok = ctx->verify_cb(0, ctx); - if (!ok) - goto err; - } - } - } + if (!ikey && + !verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)) + return 0; - ok = 1; + if (ikey) { + int rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); - err: - EVP_PKEY_free(ikey); - return ok; + if (rv != X509_V_OK && !verify_cb_crl(ctx, rv)) + return 0; + /* Verify CRL signature */ + if (X509_CRL_verify(crl, ikey) <= 0 && + !verify_cb_crl(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE)) + return 0; + } + return 1; } /* Check certificate against CRL */ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) { - int ok; X509_REVOKED *rev; + /* * The rules changed for this... previously if a CRL contained unhandled * critical extensions it could still be used to indicate a certificate - * was revoked. This has since been changed since critical extension can + * was revoked. This has since been changed since critical extensions can * change the meaning of CRL entries. */ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) - && (crl->flags & EXFLAG_CRITICAL)) { - ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; - ok = ctx->verify_cb(0, ctx); - if (!ok) - return 0; - } + && (crl->flags & EXFLAG_CRITICAL) && + !verify_cb_crl(ctx, X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)) + return 0; /* - * Look for serial number of certificate in CRL If found make sure reason - * is not removeFromCRL. + * Look for serial number of certificate in CRL. If found, make sure + * reason is not removeFromCRL. */ if (X509_CRL_get0_by_cert(crl, &rev, x)) { if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) return 2; - ctx->error = X509_V_ERR_CERT_REVOKED; - ok = ctx->verify_cb(0, ctx); - if (!ok) + if (!verify_cb_crl(ctx, X509_V_ERR_CERT_REVOKED)) return 0; } @@ -1750,38 +1589,60 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) static int check_policy(X509_STORE_CTX *ctx) { int ret; + if (ctx->parent) return 1; + /* + * With DANE, the trust anchor might be a bare public key, not a + * certificate! In that case our chain does not have the trust anchor + * certificate as a top-most element. This comports well with RFC5280 + * chain verification, since there too, the trust anchor is not part of the + * chain to be verified. In particular, X509_policy_check() does not look + * at the TA cert, but assumes that it is present as the top-most chain + * element. We therefore temporarily push a NULL cert onto the chain if it + * was verified via a bare public key, and pop it off right after the + * X509_policy_check() call. + */ + if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) { + X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain, ctx->param->policies, ctx->param->flags); - if (ret == 0) { + if (ctx->bare_ta_signed) + sk_X509_pop(ctx->chain); + + if (ret == X509_PCY_TREE_INTERNAL) { X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE); ctx->error = X509_V_ERR_OUT_OF_MEM; return 0; } /* Invalid or inconsistent extensions */ - if (ret == -1) { - /* - * Locate certificates with bad extensions and notify callback. - */ - X509 *x; + if (ret == X509_PCY_TREE_INVALID) { int i; + + /* Locate certificates with bad extensions and notify callback. */ for (i = 1; i < sk_X509_num(ctx->chain); i++) { - x = sk_X509_value(ctx->chain, i); + X509 *x = sk_X509_value(ctx->chain, i); + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) continue; - ctx->current_cert = x; - ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION; - if (!ctx->verify_cb(0, ctx)) + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_INVALID_POLICY_EXTENSION)) return 0; } return 1; } - if (ret == -2) { + if (ret == X509_PCY_TREE_FAILURE) { ctx->current_cert = NULL; ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY; return ctx->verify_cb(0, ctx); } + if (ret != X509_PCY_TREE_VALID) { + X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR); + return 0; + } if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) { ctx->current_cert = NULL; @@ -1798,62 +1659,61 @@ static int check_policy(X509_STORE_CTX *ctx) return 1; } -static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) +/*- + * Check certificate validity times. + * If depth >= 0, invoke verification callbacks on error, otherwise just return + * the validation status. + * + * Return 1 on success, 0 otherwise. + */ +int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) { time_t *ptime; int i; if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; else ptime = NULL; - i = X509_cmp_time(X509_get_notBefore(x), ptime); - if (i == 0) { - ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; - } - - if (i > 0) { - ctx->error = X509_V_ERR_CERT_NOT_YET_VALID; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; - } - - i = X509_cmp_time(X509_get_notAfter(x), ptime); - if (i == 0) { - ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; - } - - if (i < 0) { - ctx->error = X509_V_ERR_CERT_HAS_EXPIRED; - ctx->current_cert = x; - if (!ctx->verify_cb(0, ctx)) - return 0; - } + i = X509_cmp_time(X509_get0_notBefore(x), ptime); + if (i >= 0 && depth < 0) + return 0; + if (i == 0 && !verify_cb_cert(ctx, x, depth, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD)) + return 0; + if (i > 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID)) + return 0; + i = X509_cmp_time(X509_get0_notAfter(x), ptime); + if (i <= 0 && depth < 0) + return 0; + if (i == 0 && !verify_cb_cert(ctx, x, depth, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD)) + return 0; + if (i < 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED)) + return 0; return 1; } static int internal_verify(X509_STORE_CTX *ctx) { - int ok = 0, n; - X509 *xs, *xi; - EVP_PKEY *pkey = NULL; - int (*cb) (int xok, X509_STORE_CTX *xctx); - - cb = ctx->verify_cb; + int n = sk_X509_num(ctx->chain) - 1; + X509 *xi = sk_X509_value(ctx->chain, n); + X509 *xs; - n = sk_X509_num(ctx->chain); - ctx->error_depth = n - 1; - n--; - xi = sk_X509_value(ctx->chain, n); + /* + * With DANE-verified bare public key TA signatures, it remains only to + * check the timestamps of the top certificate. We report the issuer as + * NULL, since all we have is a bare key. + */ + if (ctx->bare_ta_signed) { + xs = xi; + xi = NULL; + goto check_cert; + } if (ctx->check_issued(ctx, xi, xi)) xs = xi; @@ -1862,72 +1722,60 @@ static int internal_verify(X509_STORE_CTX *ctx) xs = xi; goto check_cert; } - if (n <= 0) { - ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; - ctx->current_cert = xi; - ok = cb(0, ctx); - goto end; - } else { - n--; - ctx->error_depth = n; - xs = sk_X509_value(ctx->chain, n); - } + if (n <= 0) + return verify_cb_cert(ctx, xi, 0, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); + n--; + ctx->error_depth = n; + xs = sk_X509_value(ctx->chain, n); } -/* ctx->error=0; not needed */ + /* + * Do not clear ctx->error=0, it must be "sticky", only the user's callback + * is allowed to reset errors (at its own peril). + */ while (n >= 0) { - ctx->error_depth = n; + EVP_PKEY *pkey; /* - * Skip signature check for self signed certificates unless - * explicitly asked for. It doesn't add any security and just wastes - * time. + * Skip signature check for self signed certificates unless explicitly + * asked for. It doesn't add any security and just wastes time. If + * the issuer's public key is unusable, report the issuer certificate + * and its depth (rather than the depth of the subject). */ - if (!xs->valid - && (xs != xi - || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) { - if ((pkey = X509_get_pubkey(xi)) == NULL) { - ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; - ctx->current_cert = xi; - ok = (*cb) (0, ctx); - if (!ok) - goto end; + if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) { + if ((pkey = X509_get0_pubkey(xi)) == NULL) { + if (!verify_cb_cert(ctx, xi, xi != xs ? n+1 : n, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)) + return 0; } else if (X509_verify(xs, pkey) <= 0) { - ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; - ctx->current_cert = xs; - ok = (*cb) (0, ctx); - if (!ok) { - EVP_PKEY_free(pkey); - goto end; - } + if (!verify_cb_cert(ctx, xs, n, + X509_V_ERR_CERT_SIGNATURE_FAILURE)) + return 0; } - EVP_PKEY_free(pkey); - pkey = NULL; } - xs->valid = 1; - check_cert: - ok = check_cert_time(ctx, xs); - if (!ok) - goto end; + /* Calls verify callback as needed */ + if (!x509_check_cert_time(ctx, xs, n)) + return 0; - /* The last error (if any) is still in the error value */ + /* + * Signal success at this depth. However, the previous error (if any) + * is retained. + */ ctx->current_issuer = xi; ctx->current_cert = xs; - ok = (*cb) (1, ctx); - if (!ok) - goto end; + ctx->error_depth = n; + if (!ctx->verify_cb(1, ctx)) + return 0; - n--; - if (n >= 0) { + if (--n >= 0) { xi = xs; xs = sk_X509_value(ctx->chain, n); } } - ok = 1; - end: - return ok; + return 1; } int X509_cmp_current_time(const ASN1_TIME *ctm) @@ -1937,119 +1785,67 @@ int X509_cmp_current_time(const ASN1_TIME *ctm) int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) { - char *str; - ASN1_TIME atm; - long offset; - char buff1[24], buff2[24], *p; - int i, j, remaining; + static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; + static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1; + ASN1_TIME *asn1_cmp_time = NULL; + int i, day, sec, ret = 0; - p = buff1; - remaining = ctm->length; - str = (char *)ctm->data; /* - * Note that the following (historical) code allows much more slack in the - * time format than RFC5280. In RFC5280, the representation is fixed: + * Note that ASN.1 allows much more slack in the time format than RFC5280. + * In RFC5280, the representation is fixed: * UTCTime: YYMMDDHHMMSSZ * GeneralizedTime: YYYYMMDDHHMMSSZ + * + * We do NOT currently enforce the following RFC 5280 requirement: + * "CAs conforming to this profile MUST always encode certificate + * validity dates through the year 2049 as UTCTime; certificate validity + * dates in 2050 or later MUST be encoded as GeneralizedTime." */ - if (ctm->type == V_ASN1_UTCTIME) { - /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */ - int min_length = sizeof("YYMMDDHHMMZ") - 1; - int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1; - if (remaining < min_length || remaining > max_length) + switch (ctm->type) { + case V_ASN1_UTCTIME: + if (ctm->length != (int)(utctime_length)) return 0; - memcpy(p, str, 10); - p += 10; - str += 10; - remaining -= 10; - } else { - /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */ - int min_length = sizeof("YYYYMMDDHHMMZ") - 1; - int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1; - if (remaining < min_length || remaining > max_length) + break; + case V_ASN1_GENERALIZEDTIME: + if (ctm->length != (int)(generalizedtime_length)) return 0; - memcpy(p, str, 12); - p += 12; - str += 12; - remaining -= 12; + break; + default: + return 0; } - if ((*str == 'Z') || (*str == '-') || (*str == '+')) { - *(p++) = '0'; - *(p++) = '0'; - } else { - /* SS (seconds) */ - if (remaining < 2) + /** + * Verify the format: the ASN.1 functions we use below allow a more + * flexible format than what's mandated by RFC 5280. + * Digit and date ranges will be verified in the conversion methods. + */ + for (i = 0; i < ctm->length - 1; i++) { + if (!ossl_isdigit(ctm->data[i])) return 0; - *(p++) = *(str++); - *(p++) = *(str++); - remaining -= 2; - /* - * Skip any (up to three) fractional seconds... - * TODO(emilia): in RFC5280, fractional seconds are forbidden. - * Can we just kill them altogether? - */ - if (remaining && *str == '.') { - str++; - remaining--; - for (i = 0; i < 3 && remaining; i++, str++, remaining--) { - if (*str < '0' || *str > '9') - break; - } - } - } - *(p++) = 'Z'; - *(p++) = '\0'; - - /* We now need either a terminating 'Z' or an offset. */ - if (!remaining) + if (ctm->data[ctm->length - 1] != 'Z') return 0; - if (*str == 'Z') { - if (remaining != 1) - return 0; - offset = 0; - } else { - /* (+-)HHMM */ - if ((*str != '+') && (*str != '-')) - return 0; - /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */ - if (remaining != 5) - return 0; - if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' || - str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9') - return 0; - offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; - offset += (str[3] - '0') * 10 + (str[4] - '0'); - if (*str == '-') - offset = -offset; - } - atm.type = ctm->type; - atm.flags = 0; - atm.length = sizeof(buff2); - atm.data = (unsigned char *)buff2; - if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) - return 0; + /* + * There is ASN1_UTCTIME_cmp_time_t but no + * ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t, + * so we go through ASN.1 + */ + asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time); + if (asn1_cmp_time == NULL) + goto err; + if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time)) + goto err; - if (ctm->type == V_ASN1_UTCTIME) { - i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); - if (i < 50) - i += 100; /* cf. RFC 2459 */ - j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); - if (j < 50) - j += 100; - - if (i < j) - return -1; - if (i > j) - return 1; - } - i = strcmp(buff1, buff2); - if (i == 0) /* wait a second then return younger :-) */ - return -1; - else - return i; + /* + * X509_cmp_time comparison is <=. + * The return value 0 is reserved for errors. + */ + ret = (day >= 0 && sec >= 0) ? -1 : 1; + + err: + ASN1_TIME_free(asn1_cmp_time); + return ret; } ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) @@ -2090,7 +1886,7 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) return 1; for (i = 0; i < sk_X509_num(chain); i++) { - ktmp = X509_get_pubkey(sk_X509_value(chain, i)); + ktmp = X509_get0_pubkey(sk_X509_value(chain, i)); if (ktmp == NULL) { X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); @@ -2098,10 +1894,6 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) } if (!EVP_PKEY_missing_parameters(ktmp)) break; - else { - EVP_PKEY_free(ktmp); - ktmp = NULL; - } } if (ktmp == NULL) { X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, @@ -2111,14 +1903,12 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) /* first, populate the other certs */ for (j = i - 1; j >= 0; j--) { - ktmp2 = X509_get_pubkey(sk_X509_value(chain, j)); + ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j)); EVP_PKEY_copy_parameters(ktmp2, ktmp); - EVP_PKEY_free(ktmp2); } if (pkey != NULL) EVP_PKEY_copy_parameters(pkey, ktmp); - EVP_PKEY_free(ktmp); return 1; } @@ -2167,15 +1957,15 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, } /* Create new CRL */ crl = X509_CRL_new(); - if (!crl || !X509_CRL_set_version(crl, 1)) + if (crl == NULL || !X509_CRL_set_version(crl, 1)) goto memerr; /* Set issuer name */ if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) goto memerr; - if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer))) + if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer))) goto memerr; - if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer))) + if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer))) goto memerr; /* Set base CRL number: must be critical */ @@ -2206,7 +1996,7 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, * Add only if not also in base. TODO: need something cleverer here * for some more complex CRLs covering multiple CAs. */ - if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) { + if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) { rvtmp = X509_REVOKED_dup(rvn); if (!rvtmp) goto memerr; @@ -2225,24 +2015,10 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, memerr: X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE); - if (crl) - X509_CRL_free(crl); + X509_CRL_free(crl); return NULL; } -int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, - CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func, - CRYPTO_EX_free *free_func) -{ - /* - * This function is (usually) called only once, by - * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). - */ - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp, - new_func, dup_func, free_func); -} - int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) { return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); @@ -2268,12 +2044,22 @@ int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) return ctx->error_depth; } +void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth) +{ + ctx->error_depth = depth; +} + X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) { return ctx->current_cert; } -STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) +void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->current_cert = x; +} + +STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) { return ctx->chain; } @@ -2305,11 +2091,6 @@ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) ctx->cert = x; } -void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) -{ - ctx->untrusted = sk; -} - void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) { ctx->crls = sk; @@ -2317,11 +2098,20 @@ void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) { + /* + * XXX: Why isn't this function always used to set the associated trust? + * Should there even be a VPM->trust field at all? Or should the trust + * always be inferred from the purpose by X509_STORE_CTX_init(). + */ return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); } int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) { + /* + * XXX: See above, this function would only be needed when the default + * trust for the purpose needs an override in a corner case. + */ return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); } @@ -2355,6 +2145,11 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, ptmp = X509_PURPOSE_get0(idx); if (ptmp->trust == X509_TRUST_DEFAULT) { idx = X509_PURPOSE_get_by_id(def_purpose); + /* + * XXX: In the two callers above def_purpose is always 0, which is + * not a known value, so idx will always be -1. How is the + * X509_TRUST_DEFAULT case actually supposed to be handled? + */ if (idx == -1) { X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, X509_R_UNKNOWN_PURPOSE_ID); @@ -2384,20 +2179,20 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, X509_STORE_CTX *X509_STORE_CTX_new(void) { - X509_STORE_CTX *ctx; - ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); - if (!ctx) { + X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) { X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE); return NULL; } - memset(ctx, 0, sizeof(X509_STORE_CTX)); return ctx; } void X509_STORE_CTX_free(X509_STORE_CTX *ctx) { - if (!ctx) + if (ctx == NULL) return; + X509_STORE_CTX_cleanup(ctx); OPENSSL_free(ctx); } @@ -2406,12 +2201,12 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { int ret = 1; + ctx->ctx = store; - ctx->current_method = 0; ctx->cert = x509; ctx->untrusted = chain; ctx->crls = NULL; - ctx->last_untrusted = 0; + ctx->num_untrusted = 0; ctx->other_ctx = NULL; ctx->valid = 0; ctx->chain = NULL; @@ -2425,39 +2220,17 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->current_reasons = 0; ctx->tree = NULL; ctx->parent = NULL; + ctx->dane = NULL; + ctx->bare_ta_signed = 0; /* Zero ex_data to make sure we're cleanup-safe */ memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); - ctx->param = X509_VERIFY_PARAM_new(); - if (!ctx->param) { - X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - return 0; - } - - /* - * Inherit callbacks and flags from X509_STORE if not set use defaults. - */ + /* store->cleanup is always 0 in OpenSSL, if set must be idempotent */ if (store) - ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); - else - ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; - - if (store) { - ctx->verify_cb = store->verify_cb; - /* Seems to always be 0 in OpenSSL, else must be idempotent */ ctx->cleanup = store->cleanup; - } else + else ctx->cleanup = 0; - if (ret) - ret = X509_VERIFY_PARAM_inherit(ctx->param, - X509_VERIFY_PARAM_lookup("default")); - - if (ret == 0) { - X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - goto err; - } - if (store && store->check_issued) ctx->check_issued = store->check_issued; else @@ -2498,17 +2271,55 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, else ctx->cert_crl = cert_crl; + if (store && store->check_policy) + ctx->check_policy = store->check_policy; + else + ctx->check_policy = check_policy; + if (store && store->lookup_certs) ctx->lookup_certs = store->lookup_certs; else - ctx->lookup_certs = X509_STORE_get1_certs; + ctx->lookup_certs = X509_STORE_CTX_get1_certs; if (store && store->lookup_crls) ctx->lookup_crls = store->lookup_crls; else - ctx->lookup_crls = X509_STORE_get1_crls; + ctx->lookup_crls = X509_STORE_CTX_get1_crls; + + ctx->param = X509_VERIFY_PARAM_new(); + if (ctx->param == NULL) { + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * Inherit callbacks and flags from X509_STORE if not set use defaults. + */ + if (store) + ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); + else + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; + + if (ret) + ret = X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default")); + + if (ret == 0) { + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } - ctx->check_policy = check_policy; + /* + * XXX: For now, continue to inherit trust from VPM, but infer from the + * purpose if this still yields the default value. + */ + if (ctx->param->trust == X509_TRUST_DEFAULT) { + int idx = X509_PURPOSE_get_by_id(ctx->param->purpose); + X509_PURPOSE *xp = X509_PURPOSE_get0(idx); + + if (xp != NULL) + ctx->param->trust = X509_PURPOSE_get_trust(xp); + } if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data)) @@ -2528,11 +2339,11 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, * Set alternative lookup method: just a STACK of trusted certificates. This * avoids X509_STORE nastiness where it isn't needed. */ - -void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) { ctx->other_ctx = sk; ctx->get_issuer = get_issuer_sk; + ctx->lookup_certs = lookup_certs_sk; } void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) @@ -2553,16 +2364,12 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) X509_VERIFY_PARAM_free(ctx->param); ctx->param = NULL; } - if (ctx->tree != NULL) { - X509_policy_tree_free(ctx->tree); - ctx->tree = NULL; - } - if (ctx->chain != NULL) { - sk_X509_pop_free(ctx->chain, X509_free); - ctx->chain = NULL; - } + X509_policy_tree_free(ctx->tree); + ctx->tree = NULL; + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = NULL; CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data)); - memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA)); + memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); } void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) @@ -2581,12 +2388,99 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, X509_VERIFY_PARAM_set_time(ctx->param, t); } +X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) +{ + return ctx->cert; +} + +STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->untrusted; +} + +void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->untrusted = sk; +} + +void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = sk; +} + void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, - int (*verify_cb) (int, X509_STORE_CTX *)) + X509_STORE_CTX_verify_cb verify_cb) { ctx->verify_cb = verify_cb; } +X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx) +{ + return ctx->verify_cb; +} + +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_fn verify) +{ + ctx->verify = verify; +} + +X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx) +{ + return ctx->verify; +} + +X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx) +{ + return ctx->get_issuer; +} + +X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx) +{ + return ctx->check_issued; +} + +X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx) +{ + return ctx->check_revocation; +} + +X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx) +{ + return ctx->get_crl; +} + +X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx) +{ + return ctx->check_crl; +} + +X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx) +{ + return ctx->cert_crl; +} + +X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx) +{ + return ctx->check_policy; +} + +X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx) +{ + return ctx->lookup_certs; +} + +X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx) +{ + return ctx->lookup_crls; +} + +X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx) +{ + return ctx->cleanup; +} + X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) { return ctx->tree; @@ -2597,6 +2491,11 @@ int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) return ctx->explicit_policy; } +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->num_untrusted; +} + int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) { const X509_VERIFY_PARAM *param; @@ -2613,17 +2512,758 @@ X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) { - if (ctx->param) - X509_VERIFY_PARAM_free(ctx->param); + X509_VERIFY_PARAM_free(ctx->param); ctx->param = param; } -IMPLEMENT_STACK_OF(X509) +void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane) +{ + ctx->dane = dane; +} + +static unsigned char *dane_i2d( + X509 *cert, + uint8_t selector, + unsigned int *i2dlen) +{ + unsigned char *buf = NULL; + int len; + + /* + * Extract ASN.1 DER form of certificate or public key. + */ + switch (selector) { + case DANETLS_SELECTOR_CERT: + len = i2d_X509(cert, &buf); + break; + case DANETLS_SELECTOR_SPKI: + len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf); + break; + default: + X509err(X509_F_DANE_I2D, X509_R_BAD_SELECTOR); + return NULL; + } + + if (len < 0 || buf == NULL) { + X509err(X509_F_DANE_I2D, ERR_R_MALLOC_FAILURE); + return NULL; + } + + *i2dlen = (unsigned int)len; + return buf; +} + +#define DANETLS_NONE 256 /* impossible uint8_t */ + +static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth) +{ + SSL_DANE *dane = ctx->dane; + unsigned usage = DANETLS_NONE; + unsigned selector = DANETLS_NONE; + unsigned ordinal = DANETLS_NONE; + unsigned mtype = DANETLS_NONE; + unsigned char *i2dbuf = NULL; + unsigned int i2dlen = 0; + unsigned char mdbuf[EVP_MAX_MD_SIZE]; + unsigned char *cmpbuf = NULL; + unsigned int cmplen = 0; + int i; + int recnum; + int matched = 0; + danetls_record *t = NULL; + uint32_t mask; + + mask = (depth == 0) ? DANETLS_EE_MASK : DANETLS_TA_MASK; + + /* + * The trust store is not applicable with DANE-TA(2) + */ + if (depth >= ctx->num_untrusted) + mask &= DANETLS_PKIX_MASK; + + /* + * If we've previously matched a PKIX-?? record, no need to test any + * further PKIX-?? records, it remains to just build the PKIX chain. + * Had the match been a DANE-?? record, we'd be done already. + */ + if (dane->mdpth >= 0) + mask &= ~DANETLS_PKIX_MASK; + + /*- + * https://tools.ietf.org/html/rfc7671#section-5.1 + * https://tools.ietf.org/html/rfc7671#section-5.2 + * https://tools.ietf.org/html/rfc7671#section-5.3 + * https://tools.ietf.org/html/rfc7671#section-5.4 + * + * We handle DANE-EE(3) records first as they require no chain building + * and no expiration or hostname checks. We also process digests with + * higher ordinals first and ignore lower priorities except Full(0) which + * is always processed (last). If none match, we then process PKIX-EE(1). + * + * NOTE: This relies on DANE usages sorting before the corresponding PKIX + * usages in SSL_dane_tlsa_add(), and also on descending sorting of digest + * priorities. See twin comment in ssl/ssl_lib.c. + * + * We expect that most TLSA RRsets will have just a single usage, so we + * don't go out of our way to cache multiple selector-specific i2d buffers + * across usages, but if the selector happens to remain the same as switch + * usages, that's OK. Thus, a set of "3 1 1", "3 0 1", "1 1 1", "1 0 1", + * records would result in us generating each of the certificate and public + * key DER forms twice, but more typically we'd just see multiple "3 1 1" + * or multiple "3 0 1" records. + * + * As soon as we find a match at any given depth, we stop, because either + * we've matched a DANE-?? record and the peer is authenticated, or, after + * exhausting all DANE-?? records, we've matched a PKIX-?? record, which is + * sufficient for DANE, and what remains to do is ordinary PKIX validation. + */ + recnum = (dane->umask & mask) ? sk_danetls_record_num(dane->trecs) : 0; + for (i = 0; matched == 0 && i < recnum; ++i) { + t = sk_danetls_record_value(dane->trecs, i); + if ((DANETLS_USAGE_BIT(t->usage) & mask) == 0) + continue; + if (t->usage != usage) { + usage = t->usage; + + /* Reset digest agility for each usage/selector pair */ + mtype = DANETLS_NONE; + ordinal = dane->dctx->mdord[t->mtype]; + } + if (t->selector != selector) { + selector = t->selector; + + /* Update per-selector state */ + OPENSSL_free(i2dbuf); + i2dbuf = dane_i2d(cert, selector, &i2dlen); + if (i2dbuf == NULL) + return -1; + + /* Reset digest agility for each usage/selector pair */ + mtype = DANETLS_NONE; + ordinal = dane->dctx->mdord[t->mtype]; + } else if (t->mtype != DANETLS_MATCHING_FULL) { + /*- + * Digest agility: + * + * <https://tools.ietf.org/html/rfc7671#section-9> + * + * For a fixed selector, after processing all records with the + * highest mtype ordinal, ignore all mtypes with lower ordinals + * other than "Full". + */ + if (dane->dctx->mdord[t->mtype] < ordinal) + continue; + } + + /* + * Each time we hit a (new selector or) mtype, re-compute the relevant + * digest, more complex caching is not worth the code space. + */ + if (t->mtype != mtype) { + const EVP_MD *md = dane->dctx->mdevp[mtype = t->mtype]; + cmpbuf = i2dbuf; + cmplen = i2dlen; + + if (md != NULL) { + cmpbuf = mdbuf; + if (!EVP_Digest(i2dbuf, i2dlen, cmpbuf, &cmplen, md, 0)) { + matched = -1; + break; + } + } + } + + /* + * Squirrel away the certificate and depth if we have a match. Any + * DANE match is dispositive, but with PKIX we still need to build a + * full chain. + */ + if (cmplen == t->dlen && + memcmp(cmpbuf, t->data, cmplen) == 0) { + if (DANETLS_USAGE_BIT(usage) & DANETLS_DANE_MASK) + matched = 1; + if (matched || dane->mdpth < 0) { + dane->mdpth = depth; + dane->mtlsa = t; + OPENSSL_free(dane->mcert); + dane->mcert = cert; + X509_up_ref(cert); + } + break; + } + } + + /* Clear the one-element DER cache */ + OPENSSL_free(i2dbuf); + return matched; +} + +static int check_dane_issuer(X509_STORE_CTX *ctx, int depth) +{ + SSL_DANE *dane = ctx->dane; + int matched = 0; + X509 *cert; + + if (!DANETLS_HAS_TA(dane) || depth == 0) + return X509_TRUST_UNTRUSTED; + + /* + * Record any DANE trust-anchor matches, for the first depth to test, if + * there's one at that depth. (This'll be false for length 1 chains looking + * for an exact match for the leaf certificate). + */ + cert = sk_X509_value(ctx->chain, depth); + if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0) + return X509_TRUST_REJECTED; + if (matched > 0) { + ctx->num_untrusted = depth - 1; + return X509_TRUST_TRUSTED; + } + + return X509_TRUST_UNTRUSTED; +} + +static int check_dane_pkeys(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + danetls_record *t; + int num = ctx->num_untrusted; + X509 *cert = sk_X509_value(ctx->chain, num - 1); + int recnum = sk_danetls_record_num(dane->trecs); + int i; + + for (i = 0; i < recnum; ++i) { + t = sk_danetls_record_value(dane->trecs, i); + if (t->usage != DANETLS_USAGE_DANE_TA || + t->selector != DANETLS_SELECTOR_SPKI || + t->mtype != DANETLS_MATCHING_FULL || + X509_verify(cert, t->spki) <= 0) + continue; + + /* Clear any PKIX-?? matches that failed to extend to a full chain */ + X509_free(dane->mcert); + dane->mcert = NULL; + + /* Record match via a bare TA public key */ + ctx->bare_ta_signed = 1; + dane->mdpth = num - 1; + dane->mtlsa = t; + + /* Prune any excess chain certificates */ + num = sk_X509_num(ctx->chain); + for (; num > ctx->num_untrusted; --num) + X509_free(sk_X509_pop(ctx->chain)); + + return X509_TRUST_TRUSTED; + } + + return X509_TRUST_UNTRUSTED; +} + +static void dane_reset(SSL_DANE *dane) +{ + /* + * Reset state to verify another chain, or clear after failure. + */ + X509_free(dane->mcert); + dane->mcert = NULL; + dane->mtlsa = NULL; + dane->mdpth = -1; + dane->pdpth = -1; +} + +static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert) +{ + int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags); + + if (err == X509_V_OK) + return 1; + return verify_cb_cert(ctx, cert, 0, err); +} + +static int dane_verify(X509_STORE_CTX *ctx) +{ + X509 *cert = ctx->cert; + SSL_DANE *dane = ctx->dane; + int matched; + int done; + + dane_reset(dane); + + /*- + * When testing the leaf certificate, if we match a DANE-EE(3) record, + * dane_match() returns 1 and we're done. If however we match a PKIX-EE(1) + * record, the match depth and matching TLSA record are recorded, but the + * return value is 0, because we still need to find a PKIX trust-anchor. + * Therefore, when DANE authentication is enabled (required), we're done + * if: + * + matched < 0, internal error. + * + matched == 1, we matched a DANE-EE(3) record + * + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no + * DANE-TA(2) or PKIX-TA(0) to test. + */ + matched = dane_match(ctx, ctx->cert, 0); + done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0); + + if (done) + X509_get_pubkey_parameters(NULL, ctx->chain); + + if (matched > 0) { + /* Callback invoked as needed */ + if (!check_leaf_suiteb(ctx, cert)) + return 0; + /* Callback invoked as needed */ + if ((dane->flags & DANE_FLAG_NO_DANE_EE_NAMECHECKS) == 0 && + !check_id(ctx)) + return 0; + /* Bypass internal_verify(), issue depth 0 success callback */ + ctx->error_depth = 0; + ctx->current_cert = cert; + return ctx->verify_cb(1, ctx); + } + + if (matched < 0) { + ctx->error_depth = 0; + ctx->current_cert = cert; + ctx->error = X509_V_ERR_OUT_OF_MEM; + return -1; + } + + if (done) { + /* Fail early, TA-based success is not possible */ + if (!check_leaf_suiteb(ctx, cert)) + return 0; + return verify_cb_cert(ctx, cert, 0, X509_V_ERR_DANE_NO_MATCH); + } + + /* + * Chain verification for usages 0/1/2. TLSA record matching of depth > 0 + * certificates happens in-line with building the rest of the chain. + */ + return verify_chain(ctx); +} + +/* Get issuer, without duplicate suppression */ +static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert) +{ + STACK_OF(X509) *saved_chain = ctx->chain; + int ok; + + ctx->chain = NULL; + ok = ctx->get_issuer(issuer, ctx, cert); + ctx->chain = saved_chain; + + return ok; +} + +static int build_chain(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + int num = sk_X509_num(ctx->chain); + X509 *cert = sk_X509_value(ctx->chain, num - 1); + int ss = cert_self_signed(cert); + STACK_OF(X509) *sktmp = NULL; + unsigned int search; + int may_trusted = 0; + int may_alternate = 0; + int trust = X509_TRUST_UNTRUSTED; + int alt_untrusted = 0; + int depth; + int ok = 0; + int i; + + /* Our chain starts with a single untrusted element. */ + if (!ossl_assert(num == 1 && ctx->num_untrusted == num)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + +#define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */ +#define S_DOTRUSTED (1 << 1) /* Search trusted store */ +#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */ + /* + * Set up search policy, untrusted if possible, trusted-first if enabled. + * If we're doing DANE and not doing PKIX-TA/PKIX-EE, we never look in the + * trust_store, otherwise we might look there first. If not trusted-first, + * and alternate chains are not disabled, try building an alternate chain + * if no luck with untrusted first. + */ + search = (ctx->untrusted != NULL) ? S_DOUNTRUSTED : 0; + if (DANETLS_HAS_PKIX(dane) || !DANETLS_HAS_DANE(dane)) { + if (search == 0 || ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + search |= S_DOTRUSTED; + else if (!(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) + may_alternate = 1; + may_trusted = 1; + } + + /* + * Shallow-copy the stack of untrusted certificates (with TLS, this is + * typically the content of the peer's certificate message) so can make + * multiple passes over it, while free to remove elements as we go. + */ + if (ctx->untrusted && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + + /* + * If we got any "DANE-TA(2) Cert(0) Full(0)" trust-anchors from DNS, add + * them to our working copy of the untrusted certificate stack. Since the + * caller of X509_STORE_CTX_init() may have provided only a leaf cert with + * no corresponding stack of untrusted certificates, we may need to create + * an empty stack first. [ At present only the ssl library provides DANE + * support, and ssl_verify_cert_chain() always provides a non-null stack + * containing at least the leaf certificate, but we must be prepared for + * this to change. ] + */ + if (DANETLS_ENABLED(dane) && dane->certs != NULL) { + if (sktmp == NULL && (sktmp = sk_X509_new_null()) == NULL) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + for (i = 0; i < sk_X509_num(dane->certs); ++i) { + if (!sk_X509_push(sktmp, sk_X509_value(dane->certs, i))) { + sk_X509_free(sktmp); + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + } + } + + /* + * Still absurdly large, but arithmetically safe, a lower hard upper bound + * might be reasonable. + */ + if (ctx->param->depth > INT_MAX/2) + ctx->param->depth = INT_MAX/2; + + /* + * Try to Extend the chain until we reach an ultimately trusted issuer. + * Build chains up to one longer the limit, later fail if we hit the limit, + * with an X509_V_ERR_CERT_CHAIN_TOO_LONG error code. + */ + depth = ctx->param->depth + 1; + + while (search != 0) { + X509 *x; + X509 *xtmp = NULL; -IMPLEMENT_ASN1_SET_OF(X509) + /* + * Look in the trust store if enabled for first lookup, or we've run + * out of untrusted issuers and search here is not disabled. When we + * reach the depth limit, we stop extending the chain, if by that point + * we've not found a trust-anchor, any trusted chain would be too long. + * + * The error reported to the application verify callback is at the + * maximal valid depth with the current certificate equal to the last + * not ultimately-trusted issuer. For example, with verify_depth = 0, + * the callback will report errors at depth=1 when the immediate issuer + * of the leaf certificate is not a trust anchor. No attempt will be + * made to locate an issuer for that certificate, since such a chain + * would be a-priori too long. + */ + if ((search & S_DOTRUSTED) != 0) { + i = num = sk_X509_num(ctx->chain); + if ((search & S_DOALTERNATE) != 0) { + /* + * As high up the chain as we can, look for an alternative + * trusted issuer of an untrusted certificate that currently + * has an untrusted issuer. We use the alt_untrusted variable + * to track how far up the chain we find the first match. It + * is only if and when we find a match, that we prune the chain + * and reset ctx->num_untrusted to the reduced count of + * untrusted certificates. While we're searching for such a + * match (which may never be found), it is neither safe nor + * wise to preemptively modify either the chain or + * ctx->num_untrusted. + * + * Note, like ctx->num_untrusted, alt_untrusted is a count of + * untrusted certificates, not a "depth". + */ + i = alt_untrusted; + } + x = sk_X509_value(ctx->chain, i-1); -IMPLEMENT_STACK_OF(X509_NAME) + ok = (depth < num) ? 0 : get_issuer(&xtmp, ctx, x); -IMPLEMENT_STACK_OF(X509_ATTRIBUTE) + if (ok < 0) { + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_STORE_LOOKUP; + search = 0; + continue; + } -IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE) + if (ok > 0) { + /* + * Alternative trusted issuer for a mid-chain untrusted cert? + * Pop the untrusted cert's successors and retry. We might now + * be able to complete a valid chain via the trust store. Note + * that despite the current trust-store match we might still + * fail complete the chain to a suitable trust-anchor, in which + * case we may prune some more untrusted certificates and try + * again. Thus the S_DOALTERNATE bit may yet be turned on + * again with an even shorter untrusted chain! + * + * If in the process we threw away our matching PKIX-TA trust + * anchor, reset DANE trust. We might find a suitable trusted + * certificate among the ones from the trust store. + */ + if ((search & S_DOALTERNATE) != 0) { + if (!ossl_assert(num > i && i > 0 && ss == 0)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + X509_free(xtmp); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } + search &= ~S_DOALTERNATE; + for (; num > i; --num) + X509_free(sk_X509_pop(ctx->chain)); + ctx->num_untrusted = num; + + if (DANETLS_ENABLED(dane) && + dane->mdpth >= ctx->num_untrusted) { + dane->mdpth = -1; + X509_free(dane->mcert); + dane->mcert = NULL; + } + if (DANETLS_ENABLED(dane) && + dane->pdpth >= ctx->num_untrusted) + dane->pdpth = -1; + } + + /* + * Self-signed untrusted certificates get replaced by their + * trusted matching issuer. Otherwise, grow the chain. + */ + if (ss == 0) { + if (!sk_X509_push(ctx->chain, x = xtmp)) { + X509_free(xtmp); + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_OUT_OF_MEM; + search = 0; + continue; + } + ss = cert_self_signed(x); + } else if (num == ctx->num_untrusted) { + /* + * We have a self-signed certificate that has the same + * subject name (and perhaps keyid and/or serial number) as + * a trust-anchor. We must have an exact match to avoid + * possible impersonation via key substitution etc. + */ + if (X509_cmp(x, xtmp) != 0) { + /* Self-signed untrusted mimic. */ + X509_free(xtmp); + ok = 0; + } else { + X509_free(x); + ctx->num_untrusted = --num; + (void) sk_X509_set(ctx->chain, num, x = xtmp); + } + } + + /* + * We've added a new trusted certificate to the chain, recheck + * trust. If not done, and not self-signed look deeper. + * Whether or not we're doing "trusted first", we no longer + * look for untrusted certificates from the peer's chain. + * + * At this point ctx->num_trusted and num must reflect the + * correct number of untrusted certificates, since the DANE + * logic in check_trust() depends on distinguishing CAs from + * "the wire" from CAs from the trust store. In particular, the + * certificate at depth "num" should be the new trusted + * certificate with ctx->num_untrusted <= num. + */ + if (ok) { + if (!ossl_assert(ctx->num_untrusted <= num)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } + search &= ~S_DOUNTRUSTED; + switch (trust = check_trust(ctx, num)) { + case X509_TRUST_TRUSTED: + case X509_TRUST_REJECTED: + search = 0; + continue; + } + if (ss == 0) + continue; + } + } + + /* + * No dispositive decision, and either self-signed or no match, if + * we were doing untrusted-first, and alt-chains are not disabled, + * do that, by repeatedly losing one untrusted element at a time, + * and trying to extend the shorted chain. + */ + if ((search & S_DOUNTRUSTED) == 0) { + /* Continue search for a trusted issuer of a shorter chain? */ + if ((search & S_DOALTERNATE) != 0 && --alt_untrusted > 0) + continue; + /* Still no luck and no fallbacks left? */ + if (!may_alternate || (search & S_DOALTERNATE) != 0 || + ctx->num_untrusted < 2) + break; + /* Search for a trusted issuer of a shorter chain */ + search |= S_DOALTERNATE; + alt_untrusted = ctx->num_untrusted - 1; + ss = 0; + } + } + + /* + * Extend chain with peer-provided certificates + */ + if ((search & S_DOUNTRUSTED) != 0) { + num = sk_X509_num(ctx->chain); + if (!ossl_assert(num == ctx->num_untrusted)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } + x = sk_X509_value(ctx->chain, num-1); + + /* + * Once we run out of untrusted issuers, we stop looking for more + * and start looking only in the trust store if enabled. + */ + xtmp = (ss || depth < num) ? NULL : find_issuer(ctx, sktmp, x); + if (xtmp == NULL) { + search &= ~S_DOUNTRUSTED; + if (may_trusted) + search |= S_DOTRUSTED; + continue; + } + + /* Drop this issuer from future consideration */ + (void) sk_X509_delete_ptr(sktmp, xtmp); + + if (!sk_X509_push(ctx->chain, xtmp)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_OUT_OF_MEM; + search = 0; + continue; + } + + X509_up_ref(x = xtmp); + ++ctx->num_untrusted; + ss = cert_self_signed(xtmp); + + /* + * Check for DANE-TA trust of the topmost untrusted certificate. + */ + switch (trust = check_dane_issuer(ctx, ctx->num_untrusted - 1)) { + case X509_TRUST_TRUSTED: + case X509_TRUST_REJECTED: + search = 0; + continue; + } + } + } + sk_X509_free(sktmp); + + /* + * Last chance to make a trusted chain, either bare DANE-TA public-key + * signers, or else direct leaf PKIX trust. + */ + num = sk_X509_num(ctx->chain); + if (num <= depth) { + if (trust == X509_TRUST_UNTRUSTED && DANETLS_HAS_DANE_TA(dane)) + trust = check_dane_pkeys(ctx); + if (trust == X509_TRUST_UNTRUSTED && num == ctx->num_untrusted) + trust = check_trust(ctx, num); + } + + switch (trust) { + case X509_TRUST_TRUSTED: + return 1; + case X509_TRUST_REJECTED: + /* Callback already issued */ + return 0; + case X509_TRUST_UNTRUSTED: + default: + num = sk_X509_num(ctx->chain); + if (num > depth) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_CERT_CHAIN_TOO_LONG); + if (DANETLS_ENABLED(dane) && + (!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0)) + return verify_cb_cert(ctx, NULL, num-1, X509_V_ERR_DANE_NO_MATCH); + if (ss && sk_X509_num(ctx->chain) == 1) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); + if (ss) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN); + if (ctx->num_untrusted < num) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); + } +} + +static const int minbits_table[] = { 80, 112, 128, 192, 256 }; +static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table); + +/* + * Check whether the public key of ``cert`` meets the security level of + * ``ctx``. + * + * Returns 1 on success, 0 otherwise. + */ +static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) +{ + EVP_PKEY *pkey = X509_get0_pubkey(cert); + int level = ctx->param->auth_level; + + /* Unsupported or malformed keys are not secure */ + if (pkey == NULL) + return 0; + + if (level <= 0) + return 1; + if (level > NUM_AUTH_LEVELS) + level = NUM_AUTH_LEVELS; + + return EVP_PKEY_security_bits(pkey) >= minbits_table[level - 1]; +} + +/* + * Check whether the signature digest algorithm of ``cert`` meets the security + * level of ``ctx``. Should not be checked for trust anchors (whether + * self-signed or otherwise). + * + * Returns 1 on success, 0 otherwise. + */ +static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert) +{ + int secbits = -1; + int level = ctx->param->auth_level; + + if (level <= 0) + return 1; + if (level > NUM_AUTH_LEVELS) + level = NUM_AUTH_LEVELS; + + if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL)) + return 0; + + return secbits >= minbits_table[level - 1]; +} diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h deleted file mode 100644 index 50626826e0b9..000000000000 --- a/crypto/x509/x509_vfy.h +++ /dev/null @@ -1,652 +0,0 @@ -/* crypto/x509/x509_vfy.h */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#ifndef HEADER_X509_H -# include <openssl/x509.h> -/* - * openssl/x509.h ends up #include-ing this file at about the only - * appropriate moment. - */ -#endif - -#ifndef HEADER_X509_VFY_H -# define HEADER_X509_VFY_H - -# include <openssl/opensslconf.h> -# ifndef OPENSSL_NO_LHASH -# include <openssl/lhash.h> -# endif -# include <openssl/bio.h> -# include <openssl/crypto.h> -# include <openssl/symhacks.h> - -#ifdef __cplusplus -extern "C" { -#endif - -# if 0 -/* Outer object */ -typedef struct x509_hash_dir_st { - int num_dirs; - char **dirs; - int *dirs_type; - int num_dirs_alloced; -} X509_HASH_DIR_CTX; -# endif - -typedef struct x509_file_st { - int num_paths; /* number of paths to files or directories */ - int num_alloced; - char **paths; /* the list of paths or directories */ - int *path_type; -} X509_CERT_FILE_CTX; - -/*******************************/ -/*- -SSL_CTX -> X509_STORE - -> X509_LOOKUP - ->X509_LOOKUP_METHOD - -> X509_LOOKUP - ->X509_LOOKUP_METHOD - -SSL -> X509_STORE_CTX - ->X509_STORE - -The X509_STORE holds the tables etc for verification stuff. -A X509_STORE_CTX is used while validating a single certificate. -The X509_STORE has X509_LOOKUPs for looking up certs. -The X509_STORE then calls a function to actually verify the -certificate chain. -*/ - -# define X509_LU_RETRY -1 -# define X509_LU_FAIL 0 -# define X509_LU_X509 1 -# define X509_LU_CRL 2 -# define X509_LU_PKEY 3 - -typedef struct x509_object_st { - /* one of the above types */ - int type; - union { - char *ptr; - X509 *x509; - X509_CRL *crl; - EVP_PKEY *pkey; - } data; -} X509_OBJECT; - -typedef struct x509_lookup_st X509_LOOKUP; - -DECLARE_STACK_OF(X509_LOOKUP) -DECLARE_STACK_OF(X509_OBJECT) - -/* This is a static that defines the function interface */ -typedef struct x509_lookup_method_st { - const char *name; - int (*new_item) (X509_LOOKUP *ctx); - void (*free) (X509_LOOKUP *ctx); - int (*init) (X509_LOOKUP *ctx); - int (*shutdown) (X509_LOOKUP *ctx); - int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl, - char **ret); - int (*get_by_subject) (X509_LOOKUP *ctx, int type, X509_NAME *name, - X509_OBJECT *ret); - int (*get_by_issuer_serial) (X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial, X509_OBJECT *ret); - int (*get_by_fingerprint) (X509_LOOKUP *ctx, int type, - unsigned char *bytes, int len, - X509_OBJECT *ret); - int (*get_by_alias) (X509_LOOKUP *ctx, int type, char *str, int len, - X509_OBJECT *ret); -} X509_LOOKUP_METHOD; - -typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID; - -/* - * This structure hold all parameters associated with a verify operation by - * including an X509_VERIFY_PARAM structure in related structures the - * parameters used can be customized - */ - -typedef struct X509_VERIFY_PARAM_st { - char *name; - time_t check_time; /* Time to use */ - unsigned long inh_flags; /* Inheritance flags */ - unsigned long flags; /* Various verify flags */ - int purpose; /* purpose to check untrusted certificates */ - int trust; /* trust setting to check */ - int depth; /* Verify depth */ - STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ - X509_VERIFY_PARAM_ID *id; /* opaque ID data */ -} X509_VERIFY_PARAM; - -DECLARE_STACK_OF(X509_VERIFY_PARAM) - -/* - * This is used to hold everything. It is used for all certificate - * validation. Once we have a certificate chain, the 'verify' function is - * then called to actually check the cert chain. - */ -struct x509_store_st { - /* The following is a cache of trusted certs */ - int cache; /* if true, stash any hits */ - STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ - /* These are external lookup methods */ - STACK_OF(X509_LOOKUP) *get_cert_methods; - X509_VERIFY_PARAM *param; - /* Callbacks for various operations */ - /* called to verify a certificate */ - int (*verify) (X509_STORE_CTX *ctx); - /* error callback */ - int (*verify_cb) (int ok, X509_STORE_CTX *ctx); - /* get issuers cert from ctx */ - int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); - /* check issued */ - int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); - /* Check revocation status of chain */ - int (*check_revocation) (X509_STORE_CTX *ctx); - /* retrieve CRL */ - int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); - /* Check CRL validity */ - int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); - /* Check certificate against CRL */ - int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); - STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); - STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); - int (*cleanup) (X509_STORE_CTX *ctx); - CRYPTO_EX_DATA ex_data; - int references; -} /* X509_STORE */ ; - -int X509_STORE_set_depth(X509_STORE *store, int depth); - -# define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func)) -# define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) - -/* This is the functions plus an instance of the local variables. */ -struct x509_lookup_st { - int init; /* have we been started */ - int skip; /* don't use us. */ - X509_LOOKUP_METHOD *method; /* the functions */ - char *method_data; /* method data */ - X509_STORE *store_ctx; /* who owns us */ -} /* X509_LOOKUP */ ; - -/* - * This is a used when verifying cert chains. Since the gathering of the - * cert chain can take some time (and have to be 'retried', this needs to be - * kept and passed around. - */ -struct x509_store_ctx_st { /* X509_STORE_CTX */ - X509_STORE *ctx; - /* used when looking up certs */ - int current_method; - /* The following are set by the caller */ - /* The cert to check */ - X509 *cert; - /* chain of X509s - untrusted - passed in */ - STACK_OF(X509) *untrusted; - /* set of CRLs passed in */ - STACK_OF(X509_CRL) *crls; - X509_VERIFY_PARAM *param; - /* Other info for use with get_issuer() */ - void *other_ctx; - /* Callbacks for various operations */ - /* called to verify a certificate */ - int (*verify) (X509_STORE_CTX *ctx); - /* error callback */ - int (*verify_cb) (int ok, X509_STORE_CTX *ctx); - /* get issuers cert from ctx */ - int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); - /* check issued */ - int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); - /* Check revocation status of chain */ - int (*check_revocation) (X509_STORE_CTX *ctx); - /* retrieve CRL */ - int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); - /* Check CRL validity */ - int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); - /* Check certificate against CRL */ - int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); - int (*check_policy) (X509_STORE_CTX *ctx); - STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); - STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); - int (*cleanup) (X509_STORE_CTX *ctx); - /* The following is built up */ - /* if 0, rebuild chain */ - int valid; - /* index of last untrusted cert */ - int last_untrusted; - /* chain of X509s - built up and trusted */ - STACK_OF(X509) *chain; - /* Valid policy tree */ - X509_POLICY_TREE *tree; - /* Require explicit policy value */ - int explicit_policy; - /* When something goes wrong, this is why */ - int error_depth; - int error; - X509 *current_cert; - /* cert currently being tested as valid issuer */ - X509 *current_issuer; - /* current CRL */ - X509_CRL *current_crl; - /* score of current CRL */ - int current_crl_score; - /* Reason mask */ - unsigned int current_reasons; - /* For CRL path validation: parent context */ - X509_STORE_CTX *parent; - CRYPTO_EX_DATA ex_data; -} /* X509_STORE_CTX */ ; - -void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); - -# define X509_STORE_CTX_set_app_data(ctx,data) \ - X509_STORE_CTX_set_ex_data(ctx,0,data) -# define X509_STORE_CTX_get_app_data(ctx) \ - X509_STORE_CTX_get_ex_data(ctx,0) - -# define X509_L_FILE_LOAD 1 -# define X509_L_ADD_DIR 2 - -# define X509_LOOKUP_load_file(x,name,type) \ - X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) - -# define X509_LOOKUP_add_dir(x,name,type) \ - X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) - -# define X509_V_OK 0 -# define X509_V_ERR_UNSPECIFIED 1 - -# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 -# define X509_V_ERR_UNABLE_TO_GET_CRL 3 -# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 -# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 -# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 -# define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 -# define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 -# define X509_V_ERR_CERT_NOT_YET_VALID 9 -# define X509_V_ERR_CERT_HAS_EXPIRED 10 -# define X509_V_ERR_CRL_NOT_YET_VALID 11 -# define X509_V_ERR_CRL_HAS_EXPIRED 12 -# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 -# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 -# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 -# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 -# define X509_V_ERR_OUT_OF_MEM 17 -# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 -# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 -# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 -# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 -# define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 -# define X509_V_ERR_CERT_REVOKED 23 -# define X509_V_ERR_INVALID_CA 24 -# define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 -# define X509_V_ERR_INVALID_PURPOSE 26 -# define X509_V_ERR_CERT_UNTRUSTED 27 -# define X509_V_ERR_CERT_REJECTED 28 -/* These are 'informational' when looking for issuer cert */ -# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 -# define X509_V_ERR_AKID_SKID_MISMATCH 30 -# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 -# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 - -# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 -# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 -# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 -# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 -# define X509_V_ERR_INVALID_NON_CA 37 -# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 -# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 -# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 - -# define X509_V_ERR_INVALID_EXTENSION 41 -# define X509_V_ERR_INVALID_POLICY_EXTENSION 42 -# define X509_V_ERR_NO_EXPLICIT_POLICY 43 -# define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 -# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 - -# define X509_V_ERR_UNNESTED_RESOURCE 46 - -# define X509_V_ERR_PERMITTED_VIOLATION 47 -# define X509_V_ERR_EXCLUDED_VIOLATION 48 -# define X509_V_ERR_SUBTREE_MINMAX 49 -# define X509_V_ERR_APPLICATION_VERIFICATION 50 -# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 -# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 -# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 -# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 - -/* Suite B mode algorithm violation */ -# define X509_V_ERR_SUITE_B_INVALID_VERSION 56 -# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57 -# define X509_V_ERR_SUITE_B_INVALID_CURVE 58 -# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59 -# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60 -# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61 - -/* Host, email and IP check errors */ -# define X509_V_ERR_HOSTNAME_MISMATCH 62 -# define X509_V_ERR_EMAIL_MISMATCH 63 -# define X509_V_ERR_IP_ADDRESS_MISMATCH 64 - -/* Caller error */ -# define X509_V_ERR_INVALID_CALL 65 -/* Issuer lookup error */ -# define X509_V_ERR_STORE_LOOKUP 66 - -# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 67 - -/* Certificate verify flags */ - -/* Send issuer+subject checks to verify_cb */ -# define X509_V_FLAG_CB_ISSUER_CHECK 0x1 -/* Use check time instead of current time */ -# define X509_V_FLAG_USE_CHECK_TIME 0x2 -/* Lookup CRLs */ -# define X509_V_FLAG_CRL_CHECK 0x4 -/* Lookup CRLs for whole chain */ -# define X509_V_FLAG_CRL_CHECK_ALL 0x8 -/* Ignore unhandled critical extensions */ -# define X509_V_FLAG_IGNORE_CRITICAL 0x10 -/* Disable workarounds for broken certificates */ -# define X509_V_FLAG_X509_STRICT 0x20 -/* Enable proxy certificate validation */ -# define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 -/* Enable policy checking */ -# define X509_V_FLAG_POLICY_CHECK 0x80 -/* Policy variable require-explicit-policy */ -# define X509_V_FLAG_EXPLICIT_POLICY 0x100 -/* Policy variable inhibit-any-policy */ -# define X509_V_FLAG_INHIBIT_ANY 0x200 -/* Policy variable inhibit-policy-mapping */ -# define X509_V_FLAG_INHIBIT_MAP 0x400 -/* Notify callback that policy is OK */ -# define X509_V_FLAG_NOTIFY_POLICY 0x800 -/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */ -# define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 -/* Delta CRL support */ -# define X509_V_FLAG_USE_DELTAS 0x2000 -/* Check selfsigned CA signature */ -# define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 -/* Use trusted store first */ -# define X509_V_FLAG_TRUSTED_FIRST 0x8000 -/* Suite B 128 bit only mode: not normally used */ -# define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000 -/* Suite B 192 bit only mode */ -# define X509_V_FLAG_SUITEB_192_LOS 0x20000 -/* Suite B 128 bit mode allowing 192 bit algorithms */ -# define X509_V_FLAG_SUITEB_128_LOS 0x30000 - -/* Allow partial chains if at least one certificate is in trusted store */ -# define X509_V_FLAG_PARTIAL_CHAIN 0x80000 -/* - * If the initial chain is not trusted, do not attempt to build an alternative - * chain. Alternate chain checking was introduced in 1.0.2b. Setting this flag - * will force the behaviour to match that of previous versions. - */ -# define X509_V_FLAG_NO_ALT_CHAINS 0x100000 - -# define X509_VP_FLAG_DEFAULT 0x1 -# define X509_VP_FLAG_OVERWRITE 0x2 -# define X509_VP_FLAG_RESET_FLAGS 0x4 -# define X509_VP_FLAG_LOCKED 0x8 -# define X509_VP_FLAG_ONCE 0x10 - -/* Internal use: mask of policy related options */ -# define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \ - | X509_V_FLAG_EXPLICIT_POLICY \ - | X509_V_FLAG_INHIBIT_ANY \ - | X509_V_FLAG_INHIBIT_MAP) - -int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, - X509_NAME *name); -X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, - int type, X509_NAME *name); -X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, - X509_OBJECT *x); -void X509_OBJECT_up_ref_count(X509_OBJECT *a); -void X509_OBJECT_free_contents(X509_OBJECT *a); -X509_STORE *X509_STORE_new(void); -void X509_STORE_free(X509_STORE *v); - -STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); -STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); -int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); -int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); -int X509_STORE_set_trust(X509_STORE *ctx, int trust); -int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); - -void X509_STORE_set_verify_cb(X509_STORE *ctx, - int (*verify_cb) (int, X509_STORE_CTX *)); - -void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx, - STACK_OF(X509_CRL) *(*cb) (X509_STORE_CTX - *ctx, - X509_NAME *nm)); - -X509_STORE_CTX *X509_STORE_CTX_new(void); - -int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); - -void X509_STORE_CTX_free(X509_STORE_CTX *ctx); -int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, - X509 *x509, STACK_OF(X509) *chain); -void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); -void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); - -X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); - -X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); - -X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); -X509_LOOKUP_METHOD *X509_LOOKUP_file(void); - -int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); -int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); - -int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, - X509_OBJECT *ret); - -int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, - long argl, char **ret); - -# ifndef OPENSSL_NO_STDIO -int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); -int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); -int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); -# endif - -X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); -void X509_LOOKUP_free(X509_LOOKUP *ctx); -int X509_LOOKUP_init(X509_LOOKUP *ctx); -int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, - X509_OBJECT *ret); -int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, - ASN1_INTEGER *serial, X509_OBJECT *ret); -int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, - unsigned char *bytes, int len, - X509_OBJECT *ret); -int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, - X509_OBJECT *ret); -int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); - -# ifndef OPENSSL_NO_STDIO -int X509_STORE_load_locations(X509_STORE *ctx, - const char *file, const char *dir); -int X509_STORE_set_default_paths(X509_STORE *ctx); -# endif - -int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, - CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func, - CRYPTO_EX_free *free_func); -int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data); -void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx); -int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); -void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s); -int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); -X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); -X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); -X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); -X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); -STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); -STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); -void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x); -void X509_STORE_CTX_set_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk); -void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); -int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); -int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); -int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, - int purpose, int trust); -void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); -void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, - time_t t); -void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, - int (*verify_cb) (int, X509_STORE_CTX *)); - -X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx); -int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx); - -X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); -void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); -int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); - -/* X509_VERIFY_PARAM functions */ - -X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); -void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); -int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, - const X509_VERIFY_PARAM *from); -int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, - const X509_VERIFY_PARAM *from); -int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); -int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, - unsigned long flags); -int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, - unsigned long flags); -unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param); -int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); -int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); -void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); -void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); -int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, - ASN1_OBJECT *policy); -int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, - STACK_OF(ASN1_OBJECT) *policies); - -int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, - const char *name, size_t namelen); -int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, - const char *name, size_t namelen); -void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, - unsigned int flags); -char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *); -int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, - const char *email, size_t emaillen); -int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, - const unsigned char *ip, size_t iplen); -int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, - const char *ipasc); - -int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); -const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param); - -int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param); -int X509_VERIFY_PARAM_get_count(void); -const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id); -const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name); -void X509_VERIFY_PARAM_table_cleanup(void); - -int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, - STACK_OF(X509) *certs, - STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags); - -void X509_policy_tree_free(X509_POLICY_TREE *tree); - -int X509_policy_tree_level_count(const X509_POLICY_TREE *tree); -X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, - int i); - -STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const - X509_POLICY_TREE - *tree); - -STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const - X509_POLICY_TREE - *tree); - -int X509_policy_level_node_count(X509_POLICY_LEVEL *level); - -X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, - int i); - -const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node); - -STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const - X509_POLICY_NODE - *node); -const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE - *node); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 7d68a4abbc94..aea186295c2a 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -1,72 +1,22 @@ -/* x509_vpm.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2004. - */ -/* ==================================================================== - * Copyright (c) 2004 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). + * Copyright 2004-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 "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/crypto.h> -#include <openssl/lhash.h> #include <openssl/buffer.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include "internal/x509_int.h" -#include "vpm_int.h" +#include "x509_lcl.h" /* X509_VERIFY_PARAM functions */ @@ -83,9 +33,7 @@ static void str_free(char *s) OPENSSL_free(s); } -#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free) - -static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, +static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode, const char *name, size_t namelen) { char *copy; @@ -101,28 +49,28 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, if (namelen > 0 && name[namelen - 1] == '\0') --namelen; - if (mode == SET_HOST && id->hosts) { - string_stack_free(id->hosts); - id->hosts = NULL; + if (mode == SET_HOST) { + sk_OPENSSL_STRING_pop_free(vpm->hosts, str_free); + vpm->hosts = NULL; } if (name == NULL || namelen == 0) return 1; - copy = BUF_strndup(name, namelen); + copy = OPENSSL_strndup(name, namelen); if (copy == NULL) return 0; - if (id->hosts == NULL && - (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { + if (vpm->hosts == NULL && + (vpm->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { OPENSSL_free(copy); return 0; } - if (!sk_OPENSSL_STRING_push(id->hosts, copy)) { + if (!sk_OPENSSL_STRING_push(vpm->hosts, copy)) { OPENSSL_free(copy); - if (sk_OPENSSL_STRING_num(id->hosts) == 0) { - sk_OPENSSL_STRING_free(id->hosts); - id->hosts = NULL; + if (sk_OPENSSL_STRING_num(vpm->hosts) == 0) { + sk_OPENSSL_STRING_free(vpm->hosts); + vpm->hosts = NULL; } return 0; } @@ -130,68 +78,20 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, return 1; } -static void x509_verify_param_zero(X509_VERIFY_PARAM *param) -{ - X509_VERIFY_PARAM_ID *paramid; - if (!param) - return; - param->name = NULL; - param->purpose = 0; - param->trust = 0; - /* - * param->inh_flags = X509_VP_FLAG_DEFAULT; - */ - param->inh_flags = 0; - param->flags = 0; - param->depth = -1; - if (param->policies) { - sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); - param->policies = NULL; - } - paramid = param->id; - if (paramid->hosts) { - string_stack_free(paramid->hosts); - paramid->hosts = NULL; - } - if (paramid->peername) - OPENSSL_free(paramid->peername); - paramid->peername = NULL; - if (paramid->email) { - OPENSSL_free(paramid->email); - paramid->email = NULL; - paramid->emaillen = 0; - } - if (paramid->ip) { - OPENSSL_free(paramid->ip); - paramid->ip = NULL; - paramid->iplen = 0; - } -} X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) { X509_VERIFY_PARAM *param; - X509_VERIFY_PARAM_ID *paramid; - param = OPENSSL_malloc(sizeof(*param)); - if (!param) - return NULL; - memset(param, 0, sizeof(*param)); - - paramid = OPENSSL_malloc(sizeof(*paramid)); - if (!paramid) { - OPENSSL_free(param); + param = OPENSSL_zalloc(sizeof(*param)); + if (param == NULL) { + X509err(X509_F_X509_VERIFY_PARAM_NEW, ERR_R_MALLOC_FAILURE); return NULL; } - memset(paramid, 0, sizeof(*paramid)); - /* Exotic platforms may have non-zero bit representation of NULL */ - paramid->hosts = NULL; - paramid->peername = NULL; - paramid->email = NULL; - paramid->ip = NULL; - - param->id = paramid; - x509_verify_param_zero(param); + param->trust = X509_TRUST_DEFAULT; + /* param->inh_flags = X509_VP_FLAG_DEFAULT; */ + param->depth = -1; + param->auth_level = -1; /* -1 means unset, 0 is explicit */ return param; } @@ -199,8 +99,11 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) { if (param == NULL) return; - x509_verify_param_zero(param); - OPENSSL_free(param->id); + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + sk_OPENSSL_STRING_pop_free(param->hosts, str_free); + OPENSSL_free(param->peername); + OPENSSL_free(param->email); + OPENSSL_free(param->ip); OPENSSL_free(param); } @@ -242,11 +145,6 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) (to_overwrite || \ ((src->field != def) && (to_default || (dest->field == def)))) -/* As above but for ID fields */ - -#define test_x509_verify_param_copy_id(idf, def) \ - test_x509_verify_param_copy(id->idf, def) - /* Macro to test and copy a field if necessary */ #define x509_verify_param_copy(field, def) \ @@ -258,10 +156,8 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, { unsigned long inh_flags; int to_default, to_overwrite; - X509_VERIFY_PARAM_ID *id; if (!src) return 1; - id = src->id; inh_flags = dest->inh_flags | src->inh_flags; if (inh_flags & X509_VP_FLAG_ONCE) @@ -281,8 +177,9 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, to_overwrite = 0; x509_verify_param_copy(purpose, 0); - x509_verify_param_copy(trust, 0); + x509_verify_param_copy(trust, X509_TRUST_DEFAULT); x509_verify_param_copy(depth, -1); + x509_verify_param_copy(auth_level, -1); /* If overwrite or check time not set, copy across */ @@ -303,27 +200,25 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, } /* Copy the host flags if and only if we're copying the host list */ - if (test_x509_verify_param_copy_id(hosts, NULL)) { - if (dest->id->hosts) { - string_stack_free(dest->id->hosts); - dest->id->hosts = NULL; - } - if (id->hosts) { - dest->id->hosts = - sk_OPENSSL_STRING_deep_copy(id->hosts, str_copy, str_free); - if (dest->id->hosts == NULL) + if (test_x509_verify_param_copy(hosts, NULL)) { + sk_OPENSSL_STRING_pop_free(dest->hosts, str_free); + dest->hosts = NULL; + if (src->hosts) { + dest->hosts = + sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free); + if (dest->hosts == NULL) return 0; - dest->id->hostflags = id->hostflags; + dest->hostflags = src->hostflags; } } - if (test_x509_verify_param_copy_id(email, NULL)) { - if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen)) + if (test_x509_verify_param_copy(email, NULL)) { + if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) return 0; } - if (test_x509_verify_param_copy_id(ip, NULL)) { - if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen)) + if (test_x509_verify_param_copy(ip, NULL)) { + if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) return 0; } @@ -346,30 +241,27 @@ static int int_x509_param_set1(char **pdest, size_t *pdestlen, { void *tmp; if (src) { - if (srclen == 0) { - tmp = BUF_strdup(src); + if (srclen == 0) srclen = strlen(src); - } else - tmp = BUF_memdup(src, srclen); - if (!tmp) + + tmp = OPENSSL_memdup(src, srclen); + if (tmp == NULL) return 0; } else { tmp = NULL; srclen = 0; } - if (*pdest) - OPENSSL_free(*pdest); + OPENSSL_free(*pdest); *pdest = tmp; - if (pdestlen) + if (pdestlen != NULL) *pdestlen = srclen; return 1; } int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) { - if (param->name) - OPENSSL_free(param->name); - param->name = BUF_strdup(name); + OPENSSL_free(param->name); + param->name = OPENSSL_strdup(name); if (param->name) return 1; return 0; @@ -395,6 +287,17 @@ unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) return param->flags; } +uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param) +{ + return param->inh_flags; +} + +int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, uint32_t flags) +{ + param->inh_flags = flags; + return 1; +} + int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) { return X509_PURPOSE_set(¶m->purpose, purpose); @@ -410,6 +313,16 @@ void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) param->depth = depth; } +void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level) +{ + param->auth_level = auth_level; +} + +time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param) +{ + return param->check_time; +} + void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) { param->check_time = t; @@ -434,10 +347,10 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, { int i; ASN1_OBJECT *oid, *doid; + if (!param) return 0; - if (param->policies) - sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); if (!policies) { param->policies = NULL; @@ -465,30 +378,53 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, size_t namelen) { - return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen); + return int_x509_param_set_hosts(param, SET_HOST, name, namelen); } int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name, size_t namelen) { - return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen); + return int_x509_param_set_hosts(param, ADD_HOST, name, namelen); } void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags) { - param->id->hostflags = flags; + param->hostflags = flags; +} + +unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param) +{ + return param->hostflags; } char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) { - return param->id->peername; + return param->peername; +} + +/* + * Move peername from one param structure to another, freeing any name present + * at the target. If the source is a NULL parameter structure, free and zero + * the target peername. + */ +void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to, + X509_VERIFY_PARAM *from) +{ + char *peername = (from != NULL) ? from->peername : NULL; + + if (to->peername != peername) { + OPENSSL_free(to->peername); + to->peername = peername; + } + if (from) + from->peername = NULL; } int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, size_t emaillen) { - return int_x509_param_set1(¶m->id->email, ¶m->id->emaillen, + return int_x509_param_set1(¶m->email, ¶m->emaillen, email, emaillen); } @@ -497,7 +433,7 @@ int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, { if (iplen != 0 && iplen != 4 && iplen != 16) return 0; - return int_x509_param_set1((char **)¶m->id->ip, ¶m->id->iplen, + return int_x509_param_set1((char **)¶m->ip, ¶m->iplen, (char *)ip, iplen); } @@ -517,14 +453,17 @@ int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) return param->depth; } +int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param) +{ + return param->auth_level; +} + const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) { return param->name; } -static X509_VERIFY_PARAM_ID _empty_id = { NULL, 0U, NULL, NULL, 0, NULL, 0 }; - -#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id +#define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0 /* * Default verify parameters: these are used for various applications and can @@ -537,10 +476,11 @@ static const X509_VERIFY_PARAM default_table[] = { "default", /* X509 default parameters */ 0, /* Check time */ 0, /* internal flags */ - 0, /* flags */ + X509_V_FLAG_TRUSTED_FIRST, /* flags */ 0, /* purpose */ 0, /* trust */ 100, /* depth */ + -1, /* auth_level */ NULL, /* policies */ vpm_empty_id}, { @@ -551,6 +491,7 @@ static const X509_VERIFY_PARAM default_table[] = { X509_PURPOSE_SMIME_SIGN, /* purpose */ X509_TRUST_EMAIL, /* trust */ -1, /* depth */ + -1, /* auth_level */ NULL, /* policies */ vpm_empty_id}, { @@ -561,6 +502,7 @@ static const X509_VERIFY_PARAM default_table[] = { X509_PURPOSE_SMIME_SIGN, /* purpose */ X509_TRUST_EMAIL, /* trust */ -1, /* depth */ + -1, /* auth_level */ NULL, /* policies */ vpm_empty_id}, { @@ -571,6 +513,7 @@ static const X509_VERIFY_PARAM default_table[] = { X509_PURPOSE_SSL_CLIENT, /* purpose */ X509_TRUST_SSL_CLIENT, /* trust */ -1, /* depth */ + -1, /* auth_level */ NULL, /* policies */ vpm_empty_id}, { @@ -581,6 +524,7 @@ static const X509_VERIFY_PARAM default_table[] = { X509_PURPOSE_SSL_SERVER, /* purpose */ X509_TRUST_SSL_SERVER, /* trust */ -1, /* depth */ + -1, /* auth_level */ NULL, /* policies */ vpm_empty_id} }; @@ -605,16 +549,15 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) { int idx; X509_VERIFY_PARAM *ptmp; - if (!param_table) { + if (param_table == NULL) { param_table = sk_X509_VERIFY_PARAM_new(param_cmp); - if (!param_table) + if (param_table == NULL) return 0; } else { idx = sk_X509_VERIFY_PARAM_find(param_table, param); - if (idx != -1) { - ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); + if (idx >= 0) { + ptmp = sk_X509_VERIFY_PARAM_delete(param_table, idx); X509_VERIFY_PARAM_free(ptmp); - (void)sk_X509_VERIFY_PARAM_delete(param_table, idx); } } if (!sk_X509_VERIFY_PARAM_push(param_table, param)) @@ -624,7 +567,7 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) int X509_VERIFY_PARAM_get_count(void) { - int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + int num = OSSL_NELEM(default_table); if (param_table) num += sk_X509_VERIFY_PARAM_num(param_table); return num; @@ -632,7 +575,7 @@ int X509_VERIFY_PARAM_get_count(void) const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id) { - int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + int num = OSSL_NELEM(default_table); if (id < num) return default_table + id; return sk_X509_VERIFY_PARAM_value(param_table, id - num); @@ -644,19 +587,16 @@ const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) X509_VERIFY_PARAM pm; pm.name = (char *)name; - if (param_table) { + if (param_table != NULL) { idx = sk_X509_VERIFY_PARAM_find(param_table, &pm); - if (idx != -1) + if (idx >= 0) return sk_X509_VERIFY_PARAM_value(param_table, idx); } - return OBJ_bsearch_table(&pm, default_table, - sizeof(default_table) / - sizeof(X509_VERIFY_PARAM)); + return OBJ_bsearch_table(&pm, default_table, OSSL_NELEM(default_table)); } void X509_VERIFY_PARAM_table_cleanup(void) { - if (param_table) - sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); + sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); param_table = NULL; } diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c index 24ca35b58b58..7645ce375970 100644 --- a/crypto/x509/x509cset.c +++ b/crypto/x509/x509cset.c @@ -1,119 +1,51 @@ -/* crypto/x509/x509cset.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2001. - */ -/* ==================================================================== - * Copyright (c) 2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * 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). + * Copyright 2001-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 <stdio.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" +#include "internal/refcount.h" #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include "internal/x509_int.h" int X509_CRL_set_version(X509_CRL *x, long version) { if (x == NULL) - return (0); - if (x->crl->version == NULL) { - if ((x->crl->version = M_ASN1_INTEGER_new()) == NULL) - return (0); + return 0; + if (x->crl.version == NULL) { + if ((x->crl.version = ASN1_INTEGER_new()) == NULL) + return 0; } - return (ASN1_INTEGER_set(x->crl->version, version)); + return ASN1_INTEGER_set(x->crl.version, version); } int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) { - if ((x == NULL) || (x->crl == NULL)) - return (0); - return (X509_NAME_set(&x->crl->issuer, name)); + if (x == NULL) + return 0; + return X509_NAME_set(&x->crl.issuer, name); } -int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) +int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) { - ASN1_TIME *in; - if (x == NULL) - return (0); - in = x->crl->lastUpdate; - if (in != tm) { - in = M_ASN1_TIME_dup(tm); - if (in != NULL) { - M_ASN1_TIME_free(x->crl->lastUpdate); - x->crl->lastUpdate = in; - } - } - return (in != NULL); + return 0; + return x509_set1_time(&x->crl.lastUpdate, tm); } -int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) +int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) { - ASN1_TIME *in; - if (x == NULL) - return (0); - in = x->crl->nextUpdate; - if (in != tm) { - in = M_ASN1_TIME_dup(tm); - if (in != NULL) { - M_ASN1_TIME_free(x->crl->nextUpdate); - x->crl->nextUpdate = in; - } - } - return (in != NULL); + return 0; + return x509_set1_time(&x->crl.nextUpdate, tm); } int X509_CRL_sort(X509_CRL *c) @@ -123,45 +55,129 @@ int X509_CRL_sort(X509_CRL *c) /* * sort the data so it will be written in serial number order */ - sk_X509_REVOKED_sort(c->crl->revoked); - for (i = 0; i < sk_X509_REVOKED_num(c->crl->revoked); i++) { - r = sk_X509_REVOKED_value(c->crl->revoked, i); + sk_X509_REVOKED_sort(c->crl.revoked); + for (i = 0; i < sk_X509_REVOKED_num(c->crl.revoked); i++) { + r = sk_X509_REVOKED_value(c->crl.revoked, i); r->sequence = i; } - c->crl->enc.modified = 1; + c->crl.enc.modified = 1; return 1; } +int X509_CRL_up_ref(X509_CRL *crl) +{ + int i; + + if (CRYPTO_UP_REF(&crl->references, &i, crl->lock) <= 0) + return 0; + + REF_PRINT_COUNT("X509_CRL", crl); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +long X509_CRL_get_version(const X509_CRL *crl) +{ + return ASN1_INTEGER_get(crl->crl.version); +} + +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl) +{ + return crl->crl.lastUpdate; +} + +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl) +{ + return crl->crl.nextUpdate; +} + +#if OPENSSL_API_COMPAT < 0x10100000L +ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl) +{ + return crl->crl.lastUpdate; +} + +ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl) +{ + return crl->crl.nextUpdate; +} +#endif + +X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl) +{ + return crl->crl.issuer; +} + +const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl) +{ + return crl->crl.extensions; +} + +STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl) +{ + return crl->crl.revoked; +} + +void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg) +{ + if (psig != NULL) + *psig = &crl->signature; + if (palg != NULL) + *palg = &crl->sig_alg; +} + +int X509_CRL_get_signature_nid(const X509_CRL *crl) +{ + return OBJ_obj2nid(crl->sig_alg.algorithm); +} + +const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x) +{ + return x->revocationDate; +} + int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm) { ASN1_TIME *in; if (x == NULL) - return (0); + return 0; in = x->revocationDate; if (in != tm) { - in = M_ASN1_TIME_dup(tm); + in = ASN1_STRING_dup(tm); if (in != NULL) { - M_ASN1_TIME_free(x->revocationDate); + ASN1_TIME_free(x->revocationDate); x->revocationDate = in; } } return (in != NULL); } +const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x) +{ + return &x->serialNumber; +} + int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) { ASN1_INTEGER *in; if (x == NULL) - return (0); - in = x->serialNumber; - if (in != serial) { - in = M_ASN1_INTEGER_dup(serial); - if (in != NULL) { - M_ASN1_INTEGER_free(x->serialNumber); - x->serialNumber = in; - } - } - return (in != NULL); + return 0; + in = &x->serialNumber; + if (in != serial) + return ASN1_STRING_copy(in, serial); + return 1; +} + +const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *r) +{ + return r->extensions; +} + +int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp) +{ + crl->crl.enc.modified = 1; + return i2d_X509_CRL_INFO(&crl->crl, pp); } diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c index 6ea601f96228..64a73e793fdf 100644 --- a/crypto/x509/x509name.c +++ b/crypto/x509/x509name.c @@ -1,68 +1,20 @@ -/* crypto/x509/x509name.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. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * 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> -#include <openssl/stack.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" +#include <openssl/safestack.h> #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include "internal/x509_int.h" int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) { @@ -70,33 +22,35 @@ int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) obj = OBJ_nid2obj(nid); if (obj == NULL) - return (-1); - return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); + return -1; + return X509_NAME_get_text_by_OBJ(name, obj, buf, len); } -int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf, - int len) +int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + char *buf, int len) { int i; - ASN1_STRING *data; + const ASN1_STRING *data; i = X509_NAME_get_index_by_OBJ(name, obj, -1); if (i < 0) - return (-1); + return -1; data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); - i = (data->length > (len - 1)) ? (len - 1) : data->length; if (buf == NULL) - return (data->length); + return data->length; + if (len <= 0) + return 0; + i = (data->length > (len - 1)) ? (len - 1) : data->length; memcpy(buf, data->data, i); buf[i] = '\0'; - return (i); + return i; } -int X509_NAME_entry_count(X509_NAME *name) +int X509_NAME_entry_count(const X509_NAME *name) { if (name == NULL) - return (0); - return (sk_X509_NAME_ENTRY_num(name->entries)); + return 0; + return sk_X509_NAME_ENTRY_num(name->entries); } int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) @@ -105,19 +59,19 @@ int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) obj = OBJ_nid2obj(nid); if (obj == NULL) - return (-2); - return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); + return -2; + return X509_NAME_get_index_by_OBJ(name, obj, lastpos); } -/* NOTE: you should be passsing -1, not 0 as lastpos */ -int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos) +/* NOTE: you should be passing -1, not 0 as lastpos */ +int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos) { int n; X509_NAME_ENTRY *ne; STACK_OF(X509_NAME_ENTRY) *sk; if (name == NULL) - return (-1); + return -1; if (lastpos < 0) lastpos = -1; sk = name->entries; @@ -125,18 +79,18 @@ int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos) for (lastpos++; lastpos < n; lastpos++) { ne = sk_X509_NAME_ENTRY_value(sk, lastpos); if (OBJ_cmp(ne->object, obj) == 0) - return (lastpos); + return lastpos; } - return (-1); + return -1; } -X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc) +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) { if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || loc < 0) - return (NULL); - else - return (sk_X509_NAME_ENTRY_value(name->entries, loc)); + return NULL; + + return sk_X509_NAME_ENTRY_value(name->entries, loc); } X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) @@ -147,13 +101,14 @@ X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || loc < 0) - return (NULL); + return NULL; + sk = name->entries; ret = sk_X509_NAME_ENTRY_delete(sk, loc); n = sk_X509_NAME_ENTRY_num(sk); name->modified = 1; if (loc == n) - return (ret); + return ret; /* else we need to fixup the set field */ if (loc != 0) @@ -175,15 +130,16 @@ X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) if (set_prev + 1 < set_next) for (i = loc; i < n; i++) sk_X509_NAME_ENTRY_value(sk, i)->set--; - return (ret); + return ret; } -int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, - unsigned char *bytes, int len, int loc, +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len, int loc, int set) { X509_NAME_ENTRY *ne; int ret; + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); if (!ne) return 0; @@ -193,7 +149,7 @@ int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, } int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, - unsigned char *bytes, int len, int loc, + const unsigned char *bytes, int len, int loc, int set) { X509_NAME_ENTRY *ne; @@ -224,7 +180,7 @@ int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the * guy we are about to stomp on. */ -int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, +int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, int set) { X509_NAME_ENTRY *new_name = NULL; @@ -232,14 +188,14 @@ int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, STACK_OF(X509_NAME_ENTRY) *sk; if (name == NULL) - return (0); + return 0; sk = name->entries; n = sk_X509_NAME_ENTRY_num(sk); if (loc > n) loc = n; else if (loc < 0) loc = n; - + inc = (set == 0); name->modified = 1; if (set == -1) { @@ -248,7 +204,6 @@ int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, inc = 1; } else { set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; - inc = 0; } } else { /* if (set >= 0) */ @@ -259,10 +214,13 @@ int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, set = 0; } else set = sk_X509_NAME_ENTRY_value(sk, loc)->set; - inc = (set == 0) ? 1 : 0; } - if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) + /* + * X509_NAME_ENTRY_dup is ASN1 generated code, that can't be easily + * const'ified; harmless cast since dup() don't modify its input. + */ + if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL) goto err; new_name->set = set; if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { @@ -272,13 +230,12 @@ int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, if (inc) { n = sk_X509_NAME_ENTRY_num(sk); for (i = loc + 1; i < n; i++) - sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1; + sk_X509_NAME_ENTRY_value(sk, i)->set += 1; } - return (1); + return 1; err: - if (new_name != NULL) - X509_NAME_ENTRY_free(new_name); - return (0); + X509_NAME_ENTRY_free(new_name); + return 0; } X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, @@ -294,7 +251,7 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, X509_R_INVALID_FIELD_NAME); ERR_add_error_data(2, "name=", field); - return (NULL); + return NULL; } nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); ASN1_OBJECT_free(obj); @@ -302,7 +259,8 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, } X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, - int type, unsigned char *bytes, + int type, + const unsigned char *bytes, int len) { ASN1_OBJECT *obj; @@ -311,7 +269,7 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, obj = OBJ_nid2obj(nid); if (obj == NULL) { X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID); - return (NULL); + return NULL; } nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); ASN1_OBJECT_free(obj); @@ -319,7 +277,7 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, } X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, - ASN1_OBJECT *obj, int type, + const ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len) { @@ -327,7 +285,7 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, if ((ne == NULL) || (*ne == NULL)) { if ((ret = X509_NAME_ENTRY_new()) == NULL) - return (NULL); + return NULL; } else ret = *ne; @@ -338,19 +296,19 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, if ((ne != NULL) && (*ne == NULL)) *ne = ret; - return (ret); + return ret; err: if ((ne == NULL) || (ret != *ne)) X509_NAME_ENTRY_free(ret); - return (NULL); + return NULL; } -int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj) +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) { if ((ne == NULL) || (obj == NULL)) { X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT, ERR_R_PASSED_NULL_PARAMETER); - return (0); + return 0; } ASN1_OBJECT_free(ne->object); ne->object = OBJ_dup(obj); @@ -363,7 +321,7 @@ int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, int i; if ((ne == NULL) || ((bytes == NULL) && (len != 0))) - return (0); + return 0; if ((type > 0) && (type & MBSTRING_FLAG)) return ASN1_STRING_set_by_NID(&ne->value, bytes, len, type, @@ -372,26 +330,31 @@ int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, len = strlen((const char *)bytes); i = ASN1_STRING_set(ne->value, bytes, len); if (!i) - return (0); + return 0; if (type != V_ASN1_UNDEF) { if (type == V_ASN1_APP_CHOOSE) ne->value->type = ASN1_PRINTABLE_type(bytes, len); else ne->value->type = type; } - return (1); + return 1; } -ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne) +ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) { if (ne == NULL) - return (NULL); - return (ne->object); + return NULL; + return ne->object; } -ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) +ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) { if (ne == NULL) - return (NULL); - return (ne->value); + return NULL; + return ne->value; +} + +int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) +{ + return ne->set; } diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c index 80e273e64292..e8921b82a838 100644 --- a/crypto/x509/x509rset.c +++ b/crypto/x509/x509rset.c @@ -1,85 +1,40 @@ -/* crypto/x509/x509rset.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> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/asn1.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include "internal/x509_int.h" int X509_REQ_set_version(X509_REQ *x, long version) { if (x == NULL) - return (0); - return (ASN1_INTEGER_set(x->req_info->version, version)); + return 0; + x->req_info.enc.modified = 1; + return ASN1_INTEGER_set(x->req_info.version, version); } int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) { - if ((x == NULL) || (x->req_info == NULL)) - return (0); - return (X509_NAME_set(&x->req_info->subject, name)); + if (x == NULL) + return 0; + x->req_info.enc.modified = 1; + return X509_NAME_set(&x->req_info.subject, name); } int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { - if ((x == NULL) || (x->req_info == NULL)) - return (0); - return (X509_PUBKEY_set(&x->req_info->pubkey, pkey)); + if (x == NULL) + return 0; + x->req_info.enc.modified = 1; + return X509_PUBKEY_set(&x->req_info.pubkey, pkey); } diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c index 5ae5d30a3516..fd8162af6df2 100644 --- a/crypto/x509/x509spki.c +++ b/crypto/x509/x509spki.c @@ -1,78 +1,28 @@ -/* x509spki.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 1999. - */ -/* ==================================================================== - * Copyright (c) 1999 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). + * Copyright 1999-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 "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/x509.h> int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) { if ((x == NULL) || (x->spkac == NULL)) - return (0); - return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey)); + return 0; + return X509_PUBKEY_set(&(x->spkac->pubkey), pkey); } EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) { if ((x == NULL) || (x->spkac == NULL)) - return (NULL); - return (X509_PUBKEY_get(x->spkac->pubkey)); + return NULL; + return X509_PUBKEY_get(x->spkac->pubkey); } /* Load a Netscape SPKI from a base64 encoded string */ @@ -85,7 +35,7 @@ NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) NETSCAPE_SPKI *spki; if (len <= 0) len = strlen(str); - if (!(spki_der = OPENSSL_malloc(len + 1))) { + if ((spki_der = OPENSSL_malloc(len + 1)) == NULL) { X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, ERR_R_MALLOC_FAILURE); return NULL; } @@ -111,10 +61,10 @@ char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) der_len = i2d_NETSCAPE_SPKI(spki, NULL); der_spki = OPENSSL_malloc(der_len); b64_str = OPENSSL_malloc(der_len * 2); - if (!der_spki || !b64_str) { + if (der_spki == NULL || b64_str == NULL) { + X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE); OPENSSL_free(der_spki); OPENSSL_free(b64_str); - X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE); return NULL; } p = der_spki; diff --git a/crypto/x509/x509type.c b/crypto/x509/x509type.c index 9219f753bf93..0e33b424be51 100644 --- a/crypto/x509/x509type.c +++ b/crypto/x509/x509type.c @@ -1,107 +1,66 @@ -/* crypto/x509/x509type.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 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> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/evp.h> #include <openssl/objects.h> #include <openssl/x509.h> -int X509_certificate_type(X509 *x, EVP_PKEY *pkey) +int X509_certificate_type(const X509 *x, const EVP_PKEY *pkey) { - EVP_PKEY *pk; + const EVP_PKEY *pk; int ret = 0, i; if (x == NULL) - return (0); + return 0; if (pkey == NULL) - pk = X509_get_pubkey(x); + pk = X509_get0_pubkey(x); else pk = pkey; if (pk == NULL) - return (0); + return 0; - switch (pk->type) { + switch (EVP_PKEY_id(pk)) { case EVP_PKEY_RSA: ret = EVP_PK_RSA | EVP_PKT_SIGN; /* if (!sign only extension) */ ret |= EVP_PKT_ENC; break; + case EVP_PKEY_RSA_PSS: + ret = EVP_PK_RSA | EVP_PKT_SIGN; + break; case EVP_PKEY_DSA: ret = EVP_PK_DSA | EVP_PKT_SIGN; break; case EVP_PKEY_EC: ret = EVP_PK_EC | EVP_PKT_SIGN | EVP_PKT_EXCH; break; + case EVP_PKEY_ED448: + case EVP_PKEY_ED25519: + ret = EVP_PKT_SIGN; + break; case EVP_PKEY_DH: ret = EVP_PK_DH | EVP_PKT_EXCH; break; - case NID_id_GostR3410_94: case NID_id_GostR3410_2001: + case NID_id_GostR3410_2012_256: + case NID_id_GostR3410_2012_512: ret = EVP_PKT_EXCH | EVP_PKT_SIGN; break; default: break; } - i = OBJ_obj2nid(x->sig_alg->algorithm); + i = X509_get_signature_nid(x); if (i && OBJ_find_sigid_algs(i, NULL, &i)) { switch (i) { @@ -121,7 +80,5 @@ int X509_certificate_type(X509 *x, EVP_PKEY *pkey) } } - if (pkey == NULL) - EVP_PKEY_free(pk); - return (ret); + return ret; } diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 0f26c546d835..24e4114601ca 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -1,159 +1,112 @@ -/* crypto/x509/x_all.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2017 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> -#include <openssl/stack.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/asn1.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include "internal/x509_int.h" #include <openssl/ocsp.h> -#ifndef OPENSSL_NO_RSA -# include <openssl/rsa.h> -#endif -#ifndef OPENSSL_NO_DSA -# include <openssl/dsa.h> -#endif +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/x509v3.h> int X509_verify(X509 *a, EVP_PKEY *r) { - if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature)) + if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature)) return 0; - return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), a->sig_alg, - a->signature, a->cert_info, r)); + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg, + &a->signature, &a->cert_info, r)); } int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) { return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), - a->sig_alg, a->signature, a->req_info, r)); + &a->sig_alg, a->signature, &a->req_info, r)); } int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) { return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), - a->sig_algor, a->signature, a->spkac, r)); + &a->sig_algor, a->signature, a->spkac, r)); } int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { - x->cert_info->enc.modified = 1; - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, - x->sig_alg, x->signature, x->cert_info, pkey, md)); + x->cert_info.enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature, + &x->sig_alg, &x->signature, &x->cert_info, pkey, + md)); } int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) { - x->cert_info->enc.modified = 1; + x->cert_info.enc.modified = 1; return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), - x->cert_info->signature, - x->sig_alg, x->signature, x->cert_info, ctx); + &x->cert_info.signature, + &x->sig_alg, &x->signature, &x->cert_info, ctx); } +#ifndef OPENSSL_NO_OCSP int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert) { return OCSP_REQ_CTX_nbio_d2i(rctx, (ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509)); } +#endif int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, - x->signature, x->req_info, pkey, md)); + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL, + x->signature, &x->req_info, pkey, md)); } int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) { return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), - x->sig_alg, NULL, x->signature, x->req_info, + &x->sig_alg, NULL, x->signature, &x->req_info, ctx); } int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) { - x->crl->enc.modified = 1; - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, - x->sig_alg, x->signature, x->crl, pkey, md)); + x->crl.enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg, + &x->sig_alg, &x->signature, &x->crl, pkey, md)); } int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) { - x->crl->enc.modified = 1; + x->crl.enc.modified = 1; return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), - x->crl->sig_alg, x->sig_alg, x->signature, - x->crl, ctx); + &x->crl.sig_alg, &x->sig_alg, &x->signature, + &x->crl, ctx); } +#ifndef OPENSSL_NO_OCSP int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl) { return OCSP_REQ_CTX_nbio_d2i(rctx, (ASN1_VALUE **)pcrl, ASN1_ITEM_rptr(X509_CRL)); } +#endif int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { - return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL, + return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL, x->signature, x->spkac, pkey, md)); } -#ifndef OPENSSL_NO_FP_API +#ifndef OPENSSL_NO_STDIO X509 *d2i_X509_fp(FILE *fp, X509 **x509) { return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509); @@ -175,7 +128,7 @@ int i2d_X509_bio(BIO *bp, X509 *x509) return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509); } -#ifndef OPENSSL_NO_FP_API +#ifndef OPENSSL_NO_STDIO X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) { return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); @@ -197,7 +150,7 @@ int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); } -#ifndef OPENSSL_NO_FP_API +#ifndef OPENSSL_NO_STDIO PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7) { return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7); @@ -219,7 +172,7 @@ int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7) return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7); } -#ifndef OPENSSL_NO_FP_API +#ifndef OPENSSL_NO_STDIO X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) { return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); @@ -243,7 +196,7 @@ int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) #ifndef OPENSSL_NO_RSA -# ifndef OPENSSL_NO_FP_API +# ifndef OPENSSL_NO_STDIO RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa) { return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa); @@ -309,7 +262,7 @@ int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) #endif #ifndef OPENSSL_NO_DSA -# ifndef OPENSSL_NO_FP_API +# ifndef OPENSSL_NO_STDIO DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) { return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa); @@ -354,7 +307,7 @@ int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) #endif #ifndef OPENSSL_NO_EC -# ifndef OPENSSL_NO_FP_API +# ifndef OPENSSL_NO_STDIO EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey) { return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey); @@ -409,6 +362,13 @@ int X509_pubkey_digest(const X509 *data, const EVP_MD *type, int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { + if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0) { + /* Asking for SHA1 and we already computed it. */ + if (len != NULL) + *len = sizeof(data->sha1_hash); + memcpy(md, data->sha1_hash, sizeof(data->sha1_hash)); + return 1; + } return (ASN1_item_digest (ASN1_ITEM_rptr(X509), type, (char *)data, md, len)); } @@ -416,6 +376,13 @@ int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { + if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0) { + /* Asking for SHA1; always computed in CRL d2i. */ + if (len != NULL) + *len = sizeof(data->sha1_hash); + memcpy(md, data->sha1_hash, sizeof(data->sha1_hash)); + return 1; + } return (ASN1_item_digest (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len)); } @@ -442,7 +409,7 @@ int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, (char *)data, md, len)); } -#ifndef OPENSSL_NO_FP_API +#ifndef OPENSSL_NO_STDIO X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) { return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8); @@ -464,7 +431,7 @@ int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8) return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8); } -#ifndef OPENSSL_NO_FP_API +#ifndef OPENSSL_NO_STDIO PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO **p8inf) { diff --git a/crypto/x509/x_attrib.c b/crypto/x509/x_attrib.c new file mode 100644 index 000000000000..9a41e547cb2e --- /dev/null +++ b/crypto/x509/x_attrib.c @@ -0,0 +1,55 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/objects.h> +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "x509_lcl.h" + +/*- + * X509_ATTRIBUTE: this has the following form: + * + * typedef struct x509_attributes_st + * { + * ASN1_OBJECT *object; + * STACK_OF(ASN1_TYPE) *set; + * } X509_ATTRIBUTE; + * + */ + +ASN1_SEQUENCE(X509_ATTRIBUTE) = { + ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), + ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY) +} ASN1_SEQUENCE_END(X509_ATTRIBUTE) + +IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE) + +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) +{ + X509_ATTRIBUTE *ret = NULL; + ASN1_TYPE *val = NULL; + + if ((ret = X509_ATTRIBUTE_new()) == NULL) + return NULL; + ret->object = OBJ_nid2obj(nid); + if ((val = ASN1_TYPE_new()) == NULL) + goto err; + if (!sk_ASN1_TYPE_push(ret->set, val)) + goto err; + + ASN1_TYPE_set(val, atrtype, value); + return ret; + err: + X509_ATTRIBUTE_free(ret); + ASN1_TYPE_free(val); + return NULL; +} diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c new file mode 100644 index 000000000000..10733b58bca2 --- /dev/null +++ b/crypto/x509/x_crl.c @@ -0,0 +1,466 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/x509_int.h" +#include <openssl/x509v3.h> +#include "x509_lcl.h" + +static int X509_REVOKED_cmp(const X509_REVOKED *const *a, + const X509_REVOKED *const *b); +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); + +ASN1_SEQUENCE(X509_REVOKED) = { + ASN1_EMBED(X509_REVOKED,serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION) +} ASN1_SEQUENCE_END(X509_REVOKED) + +static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r); +static int def_crl_lookup(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial, + X509_NAME *issuer); + +static X509_CRL_METHOD int_crl_meth = { + 0, + 0, 0, + def_crl_lookup, + def_crl_verify +}; + +static const X509_CRL_METHOD *default_crl_method = &int_crl_meth; + +/* + * The X509_CRL_INFO structure needs a bit of customisation. Since we cache + * the original encoding the signature won't be affected by reordering of the + * revoked field. + */ +static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; + + if (!a || !a->revoked) + return 1; + switch (operation) { + /* + * Just set cmp function here. We don't sort because that would + * affect the output of X509_CRL_print(). + */ + case ASN1_OP_D2I_POST: + (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp); + break; + } + return 1; +} + + +ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = { + ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER), + ASN1_EMBED(X509_CRL_INFO, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME), + ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME), + ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0) +} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO) + +/* + * Set CRL entry issuer according to CRL certificate issuer extension. Check + * for unhandled critical CRL entry extensions. + */ + +static int crl_set_issuers(X509_CRL *crl) +{ + + int i, j; + GENERAL_NAMES *gens, *gtmp; + STACK_OF(X509_REVOKED) *revoked; + + revoked = X509_CRL_get_REVOKED(crl); + + gens = NULL; + for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { + X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i); + STACK_OF(X509_EXTENSION) *exts; + ASN1_ENUMERATED *reason; + X509_EXTENSION *ext; + gtmp = X509_REVOKED_get_ext_d2i(rev, + NID_certificate_issuer, &j, NULL); + if (!gtmp && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } + + if (gtmp) { + gens = gtmp; + if (!crl->issuers) { + crl->issuers = sk_GENERAL_NAMES_new_null(); + if (!crl->issuers) + return 0; + } + if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) + return 0; + } + rev->issuer = gens; + + reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); + if (!reason && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } + + if (reason) { + rev->reason = ASN1_ENUMERATED_get(reason); + ASN1_ENUMERATED_free(reason); + } else + rev->reason = CRL_REASON_NONE; + + /* Check for critical CRL entry extensions */ + + exts = rev->extensions; + + for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) { + ext = sk_X509_EXTENSION_value(exts, j); + if (X509_EXTENSION_get_critical(ext)) { + if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_certificate_issuer) + continue; + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + + } + + return 1; + +} + +/* + * The X509_CRL structure needs a bit of customisation. Cache some extensions + * and hash of the whole CRL. + */ +static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_CRL *crl = (X509_CRL *)*pval; + STACK_OF(X509_EXTENSION) *exts; + X509_EXTENSION *ext; + int idx; + + switch (operation) { + case ASN1_OP_NEW_POST: + crl->idp = NULL; + crl->akid = NULL; + crl->flags = 0; + crl->idp_flags = 0; + crl->idp_reasons = CRLDP_ALL_REASONS; + crl->meth = default_crl_method; + crl->meth_data = NULL; + crl->issuers = NULL; + crl->crl_number = NULL; + crl->base_crl_number = NULL; + break; + + case ASN1_OP_D2I_POST: + X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL); + crl->idp = X509_CRL_get_ext_d2i(crl, + NID_issuing_distribution_point, NULL, + NULL); + if (crl->idp) + setup_idp(crl, crl->idp); + + crl->akid = X509_CRL_get_ext_d2i(crl, + NID_authority_key_identifier, NULL, + NULL); + + crl->crl_number = X509_CRL_get_ext_d2i(crl, + NID_crl_number, NULL, NULL); + + crl->base_crl_number = X509_CRL_get_ext_d2i(crl, + NID_delta_crl, NULL, + NULL); + /* Delta CRLs must have CRL number */ + if (crl->base_crl_number && !crl->crl_number) + crl->flags |= EXFLAG_INVALID; + + /* + * See if we have any unhandled critical CRL extensions and indicate + * this in a flag. We only currently handle IDP so anything else + * critical sets the flag. This code accesses the X509_CRL structure + * directly: applications shouldn't do this. + */ + + exts = crl->crl.extensions; + + for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) { + int nid; + ext = sk_X509_EXTENSION_value(exts, idx); + nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); + if (nid == NID_freshest_crl) + crl->flags |= EXFLAG_FRESHEST; + if (X509_EXTENSION_get_critical(ext)) { + /* We handle IDP and deltas */ + if ((nid == NID_issuing_distribution_point) + || (nid == NID_authority_key_identifier) + || (nid == NID_delta_crl)) + continue; + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + + if (!crl_set_issuers(crl)) + return 0; + + if (crl->meth->crl_init) { + if (crl->meth->crl_init(crl) == 0) + return 0; + } + + crl->flags |= EXFLAG_SET; + break; + + case ASN1_OP_FREE_POST: + if (crl->meth->crl_free) { + if (!crl->meth->crl_free(crl)) + return 0; + } + AUTHORITY_KEYID_free(crl->akid); + ISSUING_DIST_POINT_free(crl->idp); + ASN1_INTEGER_free(crl->crl_number); + ASN1_INTEGER_free(crl->base_crl_number); + sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); + break; + } + return 1; +} + +/* Convert IDP into a more convenient form */ + +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) +{ + int idp_only = 0; + /* Set various flags according to IDP */ + crl->idp_flags |= IDP_PRESENT; + if (idp->onlyuser > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYUSER; + } + if (idp->onlyCA > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYCA; + } + if (idp->onlyattr > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYATTR; + } + + if (idp_only > 1) + crl->idp_flags |= IDP_INVALID; + + if (idp->indirectCRL > 0) + crl->idp_flags |= IDP_INDIRECT; + + if (idp->onlysomereasons) { + crl->idp_flags |= IDP_REASONS; + if (idp->onlysomereasons->length > 0) + crl->idp_reasons = idp->onlysomereasons->data[0]; + if (idp->onlysomereasons->length > 1) + crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8); + crl->idp_reasons &= CRLDP_ALL_REASONS; + } + + DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); +} + +ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = { + ASN1_EMBED(X509_CRL, crl, X509_CRL_INFO), + ASN1_EMBED(X509_CRL, sig_alg, X509_ALGOR), + ASN1_EMBED(X509_CRL, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL) + +static int X509_REVOKED_cmp(const X509_REVOKED *const *a, + const X509_REVOKED *const *b) +{ + return (ASN1_STRING_cmp((ASN1_STRING *)&(*a)->serialNumber, + (ASN1_STRING *)&(*b)->serialNumber)); +} + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) +{ + X509_CRL_INFO *inf; + + inf = &crl->crl; + if (inf->revoked == NULL) + inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); + if (inf->revoked == NULL || !sk_X509_REVOKED_push(inf->revoked, rev)) { + ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE); + return 0; + } + inf->enc.modified = 1; + return 1; +} + +int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r) +{ + if (crl->meth->crl_verify) + return crl->meth->crl_verify(crl, r); + return 0; +} + +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial) +{ + if (crl->meth->crl_lookup) + return crl->meth->crl_lookup(crl, ret, serial, NULL); + return 0; +} + +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) +{ + if (crl->meth->crl_lookup) + return crl->meth->crl_lookup(crl, ret, + X509_get_serialNumber(x), + X509_get_issuer_name(x)); + return 0; +} + +static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), + &crl->sig_alg, &crl->signature, &crl->crl, r)); +} + +static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, + X509_REVOKED *rev) +{ + int i; + + if (!rev->issuer) { + if (!nm) + return 1; + if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) + return 1; + return 0; + } + + if (!nm) + nm = X509_CRL_get_issuer(crl); + + for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i); + if (gen->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(nm, gen->d.directoryName)) + return 1; + } + return 0; + +} + +static int def_crl_lookup(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial, + X509_NAME *issuer) +{ + X509_REVOKED rtmp, *rev; + int idx, num; + + if (crl->crl.revoked == NULL) + return 0; + + /* + * Sort revoked into serial number order if not already sorted. Do this + * under a lock to avoid race condition. + */ + if (!sk_X509_REVOKED_is_sorted(crl->crl.revoked)) { + CRYPTO_THREAD_write_lock(crl->lock); + sk_X509_REVOKED_sort(crl->crl.revoked); + CRYPTO_THREAD_unlock(crl->lock); + } + rtmp.serialNumber = *serial; + idx = sk_X509_REVOKED_find(crl->crl.revoked, &rtmp); + if (idx < 0) + return 0; + /* Need to look for matching name */ + for (num = sk_X509_REVOKED_num(crl->crl.revoked); idx < num; idx++) { + rev = sk_X509_REVOKED_value(crl->crl.revoked, idx); + if (ASN1_INTEGER_cmp(&rev->serialNumber, serial)) + return 0; + if (crl_revoked_issuer_match(crl, issuer, rev)) { + if (ret) + *ret = rev; + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) + return 2; + return 1; + } + } + return 0; +} + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth) +{ + if (meth == NULL) + default_crl_method = &int_crl_meth; + else + default_crl_method = meth; +} + +X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), + int (*crl_free) (X509_CRL *crl), + int (*crl_lookup) (X509_CRL *crl, + X509_REVOKED **ret, + ASN1_INTEGER *ser, + X509_NAME *issuer), + int (*crl_verify) (X509_CRL *crl, + EVP_PKEY *pk)) +{ + X509_CRL_METHOD *m = OPENSSL_malloc(sizeof(*m)); + + if (m == NULL) { + X509err(X509_F_X509_CRL_METHOD_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + m->crl_init = crl_init; + m->crl_free = crl_free; + m->crl_lookup = crl_lookup; + m->crl_verify = crl_verify; + m->flags = X509_CRL_METHOD_DYNAMIC; + return m; +} + +void X509_CRL_METHOD_free(X509_CRL_METHOD *m) +{ + if (m == NULL || !(m->flags & X509_CRL_METHOD_DYNAMIC)) + return; + OPENSSL_free(m); +} + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat) +{ + crl->meth_data = dat; +} + +void *X509_CRL_get_meth_data(X509_CRL *crl) +{ + return crl->meth_data; +} diff --git a/crypto/x509/x_exten.c b/crypto/x509/x_exten.c new file mode 100644 index 000000000000..f10f4a4d8769 --- /dev/null +++ b/crypto/x509/x_exten.c @@ -0,0 +1,28 @@ +/* + * Copyright 2000-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 <stddef.h> +#include <openssl/x509.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include "x509_lcl.h" + +ASN1_SEQUENCE(X509_EXTENSION) = { + ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), + ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), + ASN1_EMBED(X509_EXTENSION, value, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_EXTENSION) + +ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION) +ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS) + +IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION) diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c new file mode 100644 index 000000000000..a1e9bbdb669d --- /dev/null +++ b/crypto/x509/x_name.c @@ -0,0 +1,551 @@ +/* + * 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 "internal/ctype.h" +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/x509_int.h" +#include "internal/asn1_int.h" +#include "x509_lcl.h" + +/* + * Maximum length of X509_NAME: much larger than anything we should + * ever see in practice. + */ + +#define X509_NAME_MAX (1024 * 1024) + +static int x509_name_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); +static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); + +static int x509_name_encode(X509_NAME *a); +static int x509_name_canon(X509_NAME *a); +static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in); +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname, + unsigned char **in); + +static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, + int indent, + const char *fname, const ASN1_PCTX *pctx); + +ASN1_SEQUENCE(X509_NAME_ENTRY) = { + ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), + ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) +} ASN1_SEQUENCE_END(X509_NAME_ENTRY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) + +/* + * For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so + * declare two template wrappers for this + */ + +ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) +static_ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) + +ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) +static_ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) + +/* + * Normally that's where it would end: we'd have two nested STACK structures + * representing the ASN1. Unfortunately X509_NAME uses a completely different + * form and caches encodings so we have to process the internal form and + * convert to the external form. + */ + +static const ASN1_EXTERN_FUNCS x509_name_ff = { + NULL, + x509_name_ex_new, + x509_name_ex_free, + 0, /* Default clear behaviour is OK */ + x509_name_ex_d2i, + x509_name_ex_i2d, + x509_name_ex_print +}; + +IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) + +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) +{ + X509_NAME *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) + goto memerr; + if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) + goto memerr; + if ((ret->bytes = BUF_MEM_new()) == NULL) + goto memerr; + ret->modified = 1; + *val = (ASN1_VALUE *)ret; + return 1; + + memerr: + ASN1err(ASN1_F_X509_NAME_EX_NEW, ERR_R_MALLOC_FAILURE); + if (ret) { + sk_X509_NAME_ENTRY_free(ret->entries); + OPENSSL_free(ret); + } + return 0; +} + +static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_NAME *a; + + if (!pval || !*pval) + return; + a = (X509_NAME *)*pval; + + BUF_MEM_free(a->bytes); + sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free); + OPENSSL_free(a->canon_enc); + OPENSSL_free(a); + *pval = NULL; +} + +static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) +{ + sk_X509_NAME_ENTRY_free(ne); +} + +static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) +{ + sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); +} + +static int x509_name_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx) +{ + const unsigned char *p = *in, *q; + union { + STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; + ASN1_VALUE *a; + } intname = { + NULL + }; + union { + X509_NAME *x; + ASN1_VALUE *a; + } nm = { + NULL + }; + int i, j, ret; + STACK_OF(X509_NAME_ENTRY) *entries; + X509_NAME_ENTRY *entry; + if (len > X509_NAME_MAX) + len = X509_NAME_MAX; + q = p; + + /* Get internal representation of Name */ + ret = ASN1_item_ex_d2i(&intname.a, + &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + tag, aclass, opt, ctx); + + if (ret <= 0) + return ret; + + if (*val) + x509_name_ex_free(val, NULL); + if (!x509_name_ex_new(&nm.a, NULL)) + goto err; + /* We've decoded it: now cache encoding */ + if (!BUF_MEM_grow(nm.x->bytes, p - q)) + goto err; + memcpy(nm.x->bytes->data, q, p - q); + + /* Convert internal representation to X509_NAME structure */ + for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) { + entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i); + for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { + entry = sk_X509_NAME_ENTRY_value(entries, j); + entry->set = i; + if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) + goto err; + sk_X509_NAME_ENTRY_set(entries, j, NULL); + } + } + ret = x509_name_canon(nm.x); + if (!ret) + goto err; + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + nm.x->modified = 0; + *val = nm.a; + *in = p; + return ret; + + err: + if (nm.x != NULL) + X509_NAME_free(nm.x); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_pop_free); + ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; +} + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + int ret; + X509_NAME *a = (X509_NAME *)*val; + if (a->modified) { + ret = x509_name_encode(a); + if (ret < 0) + return ret; + ret = x509_name_canon(a); + if (ret < 0) + return ret; + } + ret = a->bytes->length; + if (out != NULL) { + memcpy(*out, a->bytes->data, ret); + *out += ret; + } + return ret; +} + +static int x509_name_encode(X509_NAME *a) +{ + union { + STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; + ASN1_VALUE *a; + } intname = { + NULL + }; + int len; + unsigned char *p; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry; + int i, set = -1; + intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (!intname.s) + goto memerr; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (!entries) + goto memerr; + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) { + sk_X509_NAME_ENTRY_free(entries); + goto memerr; + } + set = entry->set; + } + if (!sk_X509_NAME_ENTRY_push(entries, entry)) + goto memerr; + } + len = ASN1_item_ex_i2d(&intname.a, NULL, + ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + if (!BUF_MEM_grow(a->bytes, len)) + goto memerr; + p = (unsigned char *)a->bytes->data; + ASN1_item_ex_i2d(&intname.a, + &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + a->modified = 0; + return len; + memerr: + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE); + return -1; +} + +static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, + int indent, + const char *fname, const ASN1_PCTX *pctx) +{ + if (X509_NAME_print_ex(out, (const X509_NAME *)*pval, + indent, pctx->nm_flags) <= 0) + return 0; + return 2; +} + +/* + * This function generates the canonical encoding of the Name structure. In + * it all strings are converted to UTF8, leading, trailing and multiple + * spaces collapsed, converted to lower case and the leading SEQUENCE header + * removed. In future we could also normalize the UTF8 too. By doing this + * comparison of Name structures can be rapidly performed by just using + * memcmp() of the canonical encoding. By omitting the leading SEQUENCE name + * constraints of type dirName can also be checked with a simple memcmp(). + */ + +static int x509_name_canon(X509_NAME *a) +{ + unsigned char *p; + STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry, *tmpentry = NULL; + int i, set = -1, ret = 0, len; + + OPENSSL_free(a->canon_enc); + a->canon_enc = NULL; + /* Special case: empty X509_NAME => null encoding */ + if (sk_X509_NAME_ENTRY_num(a->entries) == 0) { + a->canon_enclen = 0; + return 1; + } + intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (intname == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (entries == NULL) + goto err; + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { + sk_X509_NAME_ENTRY_free(entries); + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + set = entry->set; + } + tmpentry = X509_NAME_ENTRY_new(); + if (tmpentry == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + tmpentry->object = OBJ_dup(entry->object); + if (tmpentry->object == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!asn1_string_canon(tmpentry->value, entry->value)) + goto err; + if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + tmpentry = NULL; + } + + /* Finally generate encoding */ + len = i2d_name_canon(intname, NULL); + if (len < 0) + goto err; + a->canon_enclen = len; + + p = OPENSSL_malloc(a->canon_enclen); + if (p == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + + a->canon_enc = p; + + i2d_name_canon(intname, &p); + + ret = 1; + + err: + X509_NAME_ENTRY_free(tmpentry); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, + local_sk_X509_NAME_ENTRY_pop_free); + return ret; +} + +/* Bitmap of all the types of string that will be canonicalized. */ + +#define ASN1_MASK_CANON \ + (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \ + | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \ + | B_ASN1_VISIBLESTRING) + +static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in) +{ + unsigned char *to, *from; + int len, i; + + /* If type not in bitmask just copy string across */ + if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) { + if (!ASN1_STRING_copy(out, in)) + return 0; + return 1; + } + + out->type = V_ASN1_UTF8STRING; + out->length = ASN1_STRING_to_UTF8(&out->data, in); + if (out->length == -1) + return 0; + + to = out->data; + from = to; + + len = out->length; + + /* + * Convert string in place to canonical form. Ultimately we may need to + * handle a wider range of characters but for now ignore anything with + * MSB set and rely on the ossl_isspace() to fail on bad characters without + * needing isascii or range checks as well. + */ + + /* Ignore leading spaces */ + while (len > 0 && ossl_isspace(*from)) { + from++; + len--; + } + + to = from + len; + + /* Ignore trailing spaces */ + while (len > 0 && ossl_isspace(to[-1])) { + to--; + len--; + } + + to = out->data; + + i = 0; + while (i < len) { + /* If not ASCII set just copy across */ + if (!ossl_isascii(*from)) { + *to++ = *from++; + i++; + } + /* Collapse multiple spaces */ + else if (ossl_isspace(*from)) { + /* Copy one space across */ + *to++ = ' '; + /* + * Ignore subsequent spaces. Note: don't need to check len here + * because we know the last character is a non-space so we can't + * overflow. + */ + do { + from++; + i++; + } + while (ossl_isspace(*from)); + } else { + *to++ = ossl_tolower(*from); + from++; + i++; + } + } + + out->length = to - out->data; + + return 1; + +} + +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname, + unsigned char **in) +{ + int i, len, ltmp; + ASN1_VALUE *v; + STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; + + len = 0; + for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) { + v = sk_ASN1_VALUE_value(intname, i); + ltmp = ASN1_item_ex_i2d(&v, in, + ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1); + if (ltmp < 0) + return ltmp; + len += ltmp; + } + return len; +} + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name) +{ + if (*xn == name) + return *xn != NULL; + if ((name = X509_NAME_dup(name)) == NULL) + return 0; + X509_NAME_free(*xn); + *xn = name; + return 1; +} + +int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) +{ + char *s, *c, *b; + int l, i; + + l = 80 - 2 - obase; + + b = X509_NAME_oneline(name, NULL, 0); + if (!b) + return 0; + if (!*b) { + OPENSSL_free(b); + return 1; + } + s = b + 1; /* skip the first slash */ + + c = s; + for (;;) { + if (((*s == '/') && + (ossl_isupper(s[1]) && ((s[2] == '=') || + (ossl_isupper(s[2]) && (s[3] == '=')) + ))) || (*s == '\0')) + { + i = s - c; + if (BIO_write(bp, c, i) != i) + goto err; + c = s + 1; /* skip following slash */ + if (*s != '\0') { + if (BIO_write(bp, ", ", 2) != 2) + goto err; + } + l--; + } + if (*s == '\0') + break; + s++; + l--; + } + + OPENSSL_free(b); + return 1; + err: + X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB); + OPENSSL_free(b); + return 0; +} + +int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + size_t *pderlen) +{ + /* Make sure encoding is valid */ + if (i2d_X509_NAME(nm, NULL) <= 0) + return 0; + if (pder != NULL) + *pder = (unsigned char *)nm->bytes->data; + if (pderlen != NULL) + *pderlen = nm->bytes->length; + return 1; +} diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c new file mode 100644 index 000000000000..d050b0b4b3e2 --- /dev/null +++ b/crypto/x509/x_pubkey.c @@ -0,0 +1,374 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/x509_int.h" +#include <openssl/rsa.h> +#include <openssl/dsa.h> + +struct X509_pubkey_st { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; +}; + +static int x509_pubkey_decode(EVP_PKEY **pk, X509_PUBKEY *key); + +/* Minor tweak to operation: free up EVP_PKEY */ +static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); + } else if (operation == ASN1_OP_D2I_POST) { + /* Attempt to decode public key and cache in pubkey structure. */ + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); + /* + * Opportunistically decode the key but remove any non fatal errors + * from the queue. Subsequent explicit attempts to decode/use the key + * will return an appropriate error. + */ + ERR_set_mark(); + if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1) + return 0; + ERR_pop_to_mark(); + } + return 1; +} + +ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { + ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), + ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) +{ + X509_PUBKEY *pk = NULL; + + if (x == NULL) + return 0; + + if ((pk = X509_PUBKEY_new()) == NULL) + goto error; + + if (pkey->ameth) { + if (pkey->ameth->pub_encode) { + if (!pkey->ameth->pub_encode(pk, pkey)) { + X509err(X509_F_X509_PUBKEY_SET, + X509_R_PUBLIC_KEY_ENCODE_ERROR); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM); + goto error; + } + + X509_PUBKEY_free(*x); + *x = pk; + pk->pkey = pkey; + EVP_PKEY_up_ref(pkey); + return 1; + + error: + X509_PUBKEY_free(pk); + return 0; +} + +/* + * Attempt to decode a public key. + * Returns 1 on success, 0 for a decode failure and -1 for a fatal + * error e.g. malloc failure. + */ + + +static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key) +{ + EVP_PKEY *pkey = EVP_PKEY_new(); + + if (pkey == NULL) { + X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE); + return -1; + } + + if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) { + X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM); + goto error; + } + + if (pkey->ameth->pub_decode) { + /* + * Treat any failure of pub_decode as a decode error. In + * future we could have different return codes for decode + * errors and fatal errors such as malloc failure. + */ + if (!pkey->ameth->pub_decode(pkey, key)) { + X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED); + goto error; + } + + *ppkey = pkey; + return 1; + + error: + EVP_PKEY_free(pkey); + return 0; +} + +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key) +{ + EVP_PKEY *ret = NULL; + + if (key == NULL || key->public_key == NULL) + return NULL; + + if (key->pkey != NULL) + return key->pkey; + + /* + * When the key ASN.1 is initially parsed an attempt is made to + * decode the public key and cache the EVP_PKEY structure. If this + * operation fails the cached value will be NULL. Parsing continues + * to allow parsing of unknown key types or unsupported forms. + * We repeat the decode operation so the appropriate errors are left + * in the queue. + */ + x509_pubkey_decode(&ret, key); + /* If decode doesn't fail something bad happened */ + if (ret != NULL) { + X509err(X509_F_X509_PUBKEY_GET0, ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(ret); + } + + return NULL; +} + +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) +{ + EVP_PKEY *ret = X509_PUBKEY_get0(key); + if (ret != NULL) + EVP_PKEY_up_ref(ret); + return ret; +} + +/* + * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or + * decode as X509_PUBKEY + */ + +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) +{ + X509_PUBKEY *xpk; + EVP_PKEY *pktmp; + const unsigned char *q; + q = *pp; + xpk = d2i_X509_PUBKEY(NULL, &q, length); + if (!xpk) + return NULL; + pktmp = X509_PUBKEY_get(xpk); + X509_PUBKEY_free(xpk); + if (!pktmp) + return NULL; + *pp = q; + if (a) { + EVP_PKEY_free(*a); + *a = pktmp; + } + return pktmp; +} + +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) +{ + X509_PUBKEY *xpk = NULL; + int ret; + if (!a) + return 0; + if (!X509_PUBKEY_set(&xpk, a)) + return -1; + ret = i2d_X509_PUBKEY(xpk, pp); + X509_PUBKEY_free(xpk); + return ret; +} + +/* + * The following are equivalents but which return RSA and DSA keys + */ +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + RSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + RSA_free(*a); + *a = key; + } + return key; +} + +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return -1; + } + EVP_PKEY_set1_RSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + DSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + DSA_free(*a); + *a = key; + } + return key; +} + +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return -1; + } + EVP_PKEY_set1_DSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + EC_KEY *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + EC_KEY_free(*a); + *a = key; + } + return key; +} + +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + if ((pktmp = EVP_PKEY_new()) == NULL) { + ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); + return -1; + } + EVP_PKEY_set1_EC_KEY(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen) +{ + if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) + return 0; + if (penc) { + OPENSSL_free(pub->public_key->data); + pub->public_key->data = penc; + pub->public_key->length = penclen; + /* Set number of unused bits to zero */ + pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } + return 1; +} + +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub) +{ + if (ppkalg) + *ppkalg = pub->algor->algorithm; + if (pk) { + *pk = pub->public_key->data; + *ppklen = pub->public_key->length; + } + if (pa) + *pa = pub->algor; + return 1; +} + +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) +{ + if (x == NULL) + return NULL; + return x->cert_info.key->public_key; +} diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c new file mode 100644 index 000000000000..c2da95a73ecf --- /dev/null +++ b/crypto/x509/x_req.c @@ -0,0 +1,68 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/x509_int.h" + +/*- + * X509_REQ_INFO is handled in an unusual way to get round + * invalid encodings. Some broken certificate requests don't + * encode the attributes field if it is empty. This is in + * violation of PKCS#10 but we need to tolerate it. We do + * this by making the attributes field OPTIONAL then using + * the callback to initialise it to an empty STACK. + * + * This means that the field will be correctly encoded unless + * we NULL out the field. + * + * As a result we no longer need the req_kludge field because + * the information is now contained in the attributes field: + * 1. If it is NULL then it's the invalid omission. + * 2. If it is empty it is the correct encoding. + * 3. If it is not empty then some attributes are present. + * + */ + +static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval; + + if (operation == ASN1_OP_NEW_POST) { + rinf->attributes = sk_X509_ATTRIBUTE_new_null(); + if (!rinf->attributes) + return 0; + } + return 1; +} + +ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), + ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), + /* This isn't really OPTIONAL but it gets round invalid + * encodings + */ + ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) + +ASN1_SEQUENCE_ref(X509_REQ, 0) = { + ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO), + ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c new file mode 100644 index 000000000000..4c04f12c9494 --- /dev/null +++ b/crypto/x509/x_x509.c @@ -0,0 +1,224 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include "internal/x509_int.h" + +ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { + ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), + ASN1_EMBED(X509_CINF, serialNumber, ASN1_INTEGER), + ASN1_EMBED(X509_CINF, signature, X509_ALGOR), + ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), + ASN1_EMBED(X509_CINF, validity, X509_VAL), + ASN1_SIMPLE(X509_CINF, subject, X509_NAME), + ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), + ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), + ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3) +} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) +/* X509 top level structure needs a bit of customisation */ + +extern void policy_cache_free(X509_POLICY_CACHE *cache); + +static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509 *ret = (X509 *)*pval; + + switch (operation) { + + case ASN1_OP_NEW_POST: + ret->ex_flags = 0; + ret->ex_pathlen = -1; + ret->ex_pcpathlen = -1; + ret->skid = NULL; + ret->akid = NULL; +#ifndef OPENSSL_NO_RFC3779 + ret->rfc3779_addr = NULL; + ret->rfc3779_asid = NULL; +#endif + ret->aux = NULL; + ret->crldp = NULL; + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data)) + return 0; + break; + + case ASN1_OP_FREE_POST: + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); + X509_CERT_AUX_free(ret->aux); + ASN1_OCTET_STRING_free(ret->skid); + AUTHORITY_KEYID_free(ret->akid); + CRL_DIST_POINTS_free(ret->crldp); + policy_cache_free(ret->policy_cache); + GENERAL_NAMES_free(ret->altname); + NAME_CONSTRAINTS_free(ret->nc); +#ifndef OPENSSL_NO_RFC3779 + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); +#endif + break; + + } + + return 1; + +} + +ASN1_SEQUENCE_ref(X509, x509_cb) = { + ASN1_EMBED(X509, cert_info, X509_CINF), + ASN1_EMBED(X509, sig_alg, X509_ALGOR), + ASN1_EMBED(X509, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509, X509) + +IMPLEMENT_ASN1_FUNCTIONS(X509) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509) + +int X509_set_ex_data(X509 *r, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&r->ex_data, idx, arg); +} + +void *X509_get_ex_data(X509 *r, int idx) +{ + return CRYPTO_get_ex_data(&r->ex_data, idx); +} + +/* + * X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with + * extra info tagged on the end. Since these functions set how a certificate + * is trusted they should only be used when the certificate comes from a + * reliable source such as local storage. + */ + +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) +{ + const unsigned char *q; + X509 *ret; + int freeret = 0; + + /* Save start position */ + q = *pp; + + if (a == NULL || *a == NULL) + freeret = 1; + ret = d2i_X509(a, &q, length); + /* If certificate unreadable then forget it */ + if (ret == NULL) + return NULL; + /* update length */ + length -= q - *pp; + if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) + goto err; + *pp = q; + return ret; + err: + if (freeret) { + X509_free(ret); + if (a) + *a = NULL; + } + return NULL; +} + +/* + * Serialize trusted certificate to *pp or just return the required buffer + * length if pp == NULL. We ultimately want to avoid modifying *pp in the + * error path, but that depends on similar hygiene in lower-level functions. + * Here we avoid compounding the problem. + */ +static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) +{ + int length, tmplen; + unsigned char *start = pp != NULL ? *pp : NULL; + + /* + * This might perturb *pp on error, but fixing that belongs in i2d_X509() + * not here. It should be that if a == NULL length is zero, but we check + * both just in case. + */ + length = i2d_X509(a, pp); + if (length <= 0 || a == NULL) + return length; + + tmplen = i2d_X509_CERT_AUX(a->aux, pp); + if (tmplen < 0) { + if (start != NULL) + *pp = start; + return tmplen; + } + length += tmplen; + + return length; +} + +/* + * Serialize trusted certificate to *pp, or just return the required buffer + * length if pp == NULL. + * + * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since + * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do + * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the + * allocated buffer. + */ +int i2d_X509_AUX(X509 *a, unsigned char **pp) +{ + int length; + unsigned char *tmp; + + /* Buffer provided by caller */ + if (pp == NULL || *pp != NULL) + return i2d_x509_aux_internal(a, pp); + + /* Obtain the combined length */ + if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) + return length; + + /* Allocate requisite combined storage */ + *pp = tmp = OPENSSL_malloc(length); + if (tmp == NULL) { + X509err(X509_F_I2D_X509_AUX, ERR_R_MALLOC_FAILURE); + return -1; + } + + /* Encode, but keep *pp at the originally malloced pointer */ + length = i2d_x509_aux_internal(a, &tmp); + if (length <= 0) { + OPENSSL_free(*pp); + *pp = NULL; + } + return length; +} + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp) +{ + x->cert_info.enc.modified = 1; + return i2d_X509_CINF(&x->cert_info, pp); +} + +void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x) +{ + if (psig) + *psig = &x->signature; + if (palg) + *palg = &x->sig_alg; +} + +int X509_get_signature_nid(const X509 *x) +{ + return OBJ_obj2nid(x->sig_alg.algorithm); +} diff --git a/crypto/x509/x_x509a.c b/crypto/x509/x_x509a.c new file mode 100644 index 000000000000..8c9ad71d1b29 --- /dev/null +++ b/crypto/x509/x_x509a.c @@ -0,0 +1,169 @@ +/* + * Copyright 1999-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 "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/x509_int.h" + +/* + * X509_CERT_AUX routines. These are used to encode additional user + * modifiable data about a certificate. This data is appended to the X509 + * encoding when the *_X509_AUX routines are used. This means that the + * "traditional" X509 routines will simply ignore the extra data. + */ + +static X509_CERT_AUX *aux_get(X509 *x); + +ASN1_SEQUENCE(X509_CERT_AUX) = { + ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0), + ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING), + ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1) +} ASN1_SEQUENCE_END(X509_CERT_AUX) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX) + +int X509_trusted(const X509 *x) +{ + return x->aux ? 1 : 0; +} + +static X509_CERT_AUX *aux_get(X509 *x) +{ + if (x == NULL) + return NULL; + if (x->aux == NULL && (x->aux = X509_CERT_AUX_new()) == NULL) + return NULL; + return x->aux; +} + +int X509_alias_set1(X509 *x, const unsigned char *name, int len) +{ + X509_CERT_AUX *aux; + if (!name) { + if (!x || !x->aux || !x->aux->alias) + return 1; + ASN1_UTF8STRING_free(x->aux->alias); + x->aux->alias = NULL; + return 1; + } + if ((aux = aux_get(x)) == NULL) + return 0; + if (aux->alias == NULL && (aux->alias = ASN1_UTF8STRING_new()) == NULL) + return 0; + return ASN1_STRING_set(aux->alias, name, len); +} + +int X509_keyid_set1(X509 *x, const unsigned char *id, int len) +{ + X509_CERT_AUX *aux; + if (!id) { + if (!x || !x->aux || !x->aux->keyid) + return 1; + ASN1_OCTET_STRING_free(x->aux->keyid); + x->aux->keyid = NULL; + return 1; + } + if ((aux = aux_get(x)) == NULL) + return 0; + if (aux->keyid == NULL + && (aux->keyid = ASN1_OCTET_STRING_new()) == NULL) + return 0; + return ASN1_STRING_set(aux->keyid, id, len); +} + +unsigned char *X509_alias_get0(X509 *x, int *len) +{ + if (!x->aux || !x->aux->alias) + return NULL; + if (len) + *len = x->aux->alias->length; + return x->aux->alias->data; +} + +unsigned char *X509_keyid_get0(X509 *x, int *len) +{ + if (!x->aux || !x->aux->keyid) + return NULL; + if (len) + *len = x->aux->keyid->length; + return x->aux->keyid->data; +} + +int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj) +{ + X509_CERT_AUX *aux; + ASN1_OBJECT *objtmp = NULL; + if (obj) { + objtmp = OBJ_dup(obj); + if (!objtmp) + return 0; + } + if ((aux = aux_get(x)) == NULL) + goto err; + if (aux->trust == NULL + && (aux->trust = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + if (!objtmp || sk_ASN1_OBJECT_push(aux->trust, objtmp)) + return 1; + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj) +{ + X509_CERT_AUX *aux; + ASN1_OBJECT *objtmp; + if ((objtmp = OBJ_dup(obj)) == NULL) + return 0; + if ((aux = aux_get(x)) == NULL) + goto err; + if (aux->reject == NULL + && (aux->reject = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + return sk_ASN1_OBJECT_push(aux->reject, objtmp); + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +void X509_trust_clear(X509 *x) +{ + if (x->aux) { + sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); + x->aux->trust = NULL; + } +} + +void X509_reject_clear(X509 *x) +{ + if (x->aux) { + sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); + x->aux->reject = NULL; + } +} + +STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x) +{ + if (x->aux != NULL) + return x->aux->trust; + return NULL; +} + +STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x) +{ + if (x->aux != NULL) + return x->aux->reject; + return NULL; +} |