diff options
Diffstat (limited to 'src/openssl')
-rw-r--r-- | src/openssl/Makefile.am | 56 | ||||
-rw-r--r-- | src/openssl/Makefile.in | 790 | ||||
-rw-r--r-- | src/openssl/README | 17 | ||||
-rw-r--r-- | src/openssl/app.c | 1628 | ||||
-rw-r--r-- | src/openssl/bn.c | 163 | ||||
-rw-r--r-- | src/openssl/ciphers.c | 856 | ||||
-rw-r--r-- | src/openssl/crypto.c | 491 | ||||
-rw-r--r-- | src/openssl/digests.c | 682 | ||||
-rw-r--r-- | src/openssl/evp.c | 1559 | ||||
-rw-r--r-- | src/openssl/globals.h | 24 | ||||
-rw-r--r-- | src/openssl/hmac.c | 857 | ||||
-rw-r--r-- | src/openssl/kt_rsa.c | 876 | ||||
-rw-r--r-- | src/openssl/kw_aes.c | 513 | ||||
-rw-r--r-- | src/openssl/kw_des.c | 563 | ||||
-rw-r--r-- | src/openssl/signatures.c | 1065 | ||||
-rw-r--r-- | src/openssl/symkeys.c | 447 | ||||
-rw-r--r-- | src/openssl/x509.c | 2414 | ||||
-rw-r--r-- | src/openssl/x509vfy.c | 1284 |
18 files changed, 14285 insertions, 0 deletions
diff --git a/src/openssl/Makefile.am b/src/openssl/Makefile.am new file mode 100644 index 00000000..23c225a1 --- /dev/null +++ b/src/openssl/Makefile.am @@ -0,0 +1,56 @@ +NULL = + +EXTRA_DIST = \ + README \ + $(NULL) + +lib_LTLIBRARIES = \ + libxmlsec1-openssl.la \ + $(NULL) + +libxmlsec1_openssl_la_CPPFLAGS = \ + -DPACKAGE=\"@PACKAGE@\" \ + -I../../include \ + -I$(top_srcdir)/include \ + $(XMLSEC_DEFINES) \ + $(OPENSSL_CFLAGS) \ + $(LIBXSLT_CFLAGS) \ + $(LIBXML_CFLAGS) \ + $(NULL) + +libxmlsec1_openssl_la_SOURCES =\ + app.c \ + bn.c \ + ciphers.c \ + crypto.c \ + digests.c \ + evp.c \ + hmac.c \ + kw_aes.c \ + kw_des.c \ + kt_rsa.c \ + signatures.c \ + symkeys.c \ + x509.c \ + x509vfy.c \ + globals.h \ + $(NULL) + +if SHAREDLIB_HACK +libxmlsec1_openssl_la_SOURCES += ../strings.c +endif + +libxmlsec1_openssl_la_LIBADD = \ + $(OPENSSL_LIBS) \ + $(LIBXSLT_LIBS) \ + $(LIBXML_LIBS) \ + ../libxmlsec1.la \ + $(NULL) + +libxmlsec1_openssl_la_DEPENDENCIES = \ + $(NULL) + +libxmlsec1_openssl_la_LDFLAGS = \ + @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \ + -version-info @XMLSEC_VERSION_INFO@ \ + $(NULL) diff --git a/src/openssl/Makefile.in b/src/openssl/Makefile.in new file mode 100644 index 00000000..8f6bb8f8 --- /dev/null +++ b/src/openssl/Makefile.in @@ -0,0 +1,790 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c +subdir = src/openssl +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__libxmlsec1_openssl_la_SOURCES_DIST = app.c bn.c ciphers.c crypto.c \ + digests.c evp.c hmac.c kw_aes.c kw_des.c kt_rsa.c signatures.c \ + symkeys.c x509.c x509vfy.c globals.h ../strings.c +am__objects_1 = +@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_openssl_la-strings.lo +am_libxmlsec1_openssl_la_OBJECTS = libxmlsec1_openssl_la-app.lo \ + libxmlsec1_openssl_la-bn.lo libxmlsec1_openssl_la-ciphers.lo \ + libxmlsec1_openssl_la-crypto.lo \ + libxmlsec1_openssl_la-digests.lo libxmlsec1_openssl_la-evp.lo \ + libxmlsec1_openssl_la-hmac.lo libxmlsec1_openssl_la-kw_aes.lo \ + libxmlsec1_openssl_la-kw_des.lo \ + libxmlsec1_openssl_la-kt_rsa.lo \ + libxmlsec1_openssl_la-signatures.lo \ + libxmlsec1_openssl_la-symkeys.lo libxmlsec1_openssl_la-x509.lo \ + libxmlsec1_openssl_la-x509vfy.lo $(am__objects_1) \ + $(am__objects_2) +libxmlsec1_openssl_la_OBJECTS = $(am_libxmlsec1_openssl_la_OBJECTS) +libxmlsec1_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libxmlsec1_openssl_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libxmlsec1_openssl_la_SOURCES) +DIST_SOURCES = $(am__libxmlsec1_openssl_la_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CP = @CP@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GCRYPT_CFLAGS = @GCRYPT_CFLAGS@ +GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@ +GCRYPT_LIBS = @GCRYPT_LIBS@ +GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@ +GREP = @GREP@ +HELP2MAN = @HELP2MAN@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBXML_CFLAGS = @LIBXML_CFLAGS@ +LIBXML_CONFIG = @LIBXML_CONFIG@ +LIBXML_LIBS = @LIBXML_LIBS@ +LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@ +LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@ +LIBXSLT_CONFIG = @LIBXSLT_CONFIG@ +LIBXSLT_LIBS = @LIBXSLT_LIBS@ +LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@ +MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@ +MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@ +MSCRYPTO_LIBS = @MSCRYPTO_LIBS@ +MV = @MV@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NSPR_MIN_VERSION = @NSPR_MIN_VERSION@ +NSPR_PACKAGE = @NSPR_PACKAGE@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@ +NSS_LIBS = @NSS_LIBS@ +NSS_MIN_VERSION = @NSS_MIN_VERSION@ +NSS_PACKAGE = @NSS_PACKAGE@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TAR = @TAR@ +U = @U@ +VERSION = @VERSION@ +XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@ +XMLSEC_CFLAGS = @XMLSEC_CFLAGS@ +XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@ +XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@ +XMLSEC_CRYPTO = @XMLSEC_CRYPTO@ +XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@ +XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@ +XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ +XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@ +XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@ +XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@ +XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@ +XMLSEC_DEFINES = @XMLSEC_DEFINES@ +XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@ +XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@ +XMLSEC_DOCDIR = @XMLSEC_DOCDIR@ +XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@ +XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@ +XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@ +XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@ +XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@ +XMLSEC_LIBDIR = @XMLSEC_LIBDIR@ +XMLSEC_LIBS = @XMLSEC_LIBS@ +XMLSEC_NO_AES = @XMLSEC_NO_AES@ +XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@ +XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@ +XMLSEC_NO_DES = @XMLSEC_NO_DES@ +XMLSEC_NO_DSA = @XMLSEC_NO_DSA@ +XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@ +XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@ +XMLSEC_NO_GOST = @XMLSEC_NO_GOST@ +XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@ +XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@ +XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@ +XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@ +XMLSEC_NO_NSS = @XMLSEC_NO_NSS@ +XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@ +XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@ +XMLSEC_NO_RSA = @XMLSEC_NO_RSA@ +XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@ +XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@ +XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@ +XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@ +XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@ +XMLSEC_NO_X509 = @XMLSEC_NO_X509@ +XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@ +XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@ +XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@ +XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@ +XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@ +XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@ +XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@ +XMLSEC_PACKAGE = @XMLSEC_PACKAGE@ +XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@ +XMLSEC_VERSION = @XMLSEC_VERSION@ +XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@ +XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@ +XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@ +XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@ +XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +EXTRA_DIST = \ + README \ + $(NULL) + +lib_LTLIBRARIES = \ + libxmlsec1-openssl.la \ + $(NULL) + +libxmlsec1_openssl_la_CPPFLAGS = \ + -DPACKAGE=\"@PACKAGE@\" \ + -I../../include \ + -I$(top_srcdir)/include \ + $(XMLSEC_DEFINES) \ + $(OPENSSL_CFLAGS) \ + $(LIBXSLT_CFLAGS) \ + $(LIBXML_CFLAGS) \ + $(NULL) + +libxmlsec1_openssl_la_SOURCES = app.c bn.c ciphers.c crypto.c \ + digests.c evp.c hmac.c kw_aes.c kw_des.c kt_rsa.c signatures.c \ + symkeys.c x509.c x509vfy.c globals.h $(NULL) $(am__append_1) +libxmlsec1_openssl_la_LIBADD = \ + $(OPENSSL_LIBS) \ + $(LIBXSLT_LIBS) \ + $(LIBXML_LIBS) \ + ../libxmlsec1.la \ + $(NULL) + +libxmlsec1_openssl_la_DEPENDENCIES = \ + $(NULL) + +libxmlsec1_openssl_la_LDFLAGS = \ + @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \ + -version-info @XMLSEC_VERSION_INFO@ \ + $(NULL) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/openssl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/openssl/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libxmlsec1-openssl.la: $(libxmlsec1_openssl_la_OBJECTS) $(libxmlsec1_openssl_la_DEPENDENCIES) + $(libxmlsec1_openssl_la_LINK) -rpath $(libdir) $(libxmlsec1_openssl_la_OBJECTS) $(libxmlsec1_openssl_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-app.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-bn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-ciphers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-crypto.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-digests.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-evp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-hmac.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-kw_des.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-signatures.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-strings.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-symkeys.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-x509.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libxmlsec1_openssl_la-app.lo: app.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-app.Tpo -c -o libxmlsec1_openssl_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-app.Tpo $(DEPDIR)/libxmlsec1_openssl_la-app.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_openssl_la-app.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c + +libxmlsec1_openssl_la-bn.lo: bn.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-bn.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-bn.Tpo -c -o libxmlsec1_openssl_la-bn.lo `test -f 'bn.c' || echo '$(srcdir)/'`bn.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-bn.Tpo $(DEPDIR)/libxmlsec1_openssl_la-bn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bn.c' object='libxmlsec1_openssl_la-bn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-bn.lo `test -f 'bn.c' || echo '$(srcdir)/'`bn.c + +libxmlsec1_openssl_la-ciphers.lo: ciphers.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-ciphers.Tpo -c -o libxmlsec1_openssl_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_openssl_la-ciphers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_openssl_la-ciphers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c + +libxmlsec1_openssl_la-crypto.lo: crypto.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-crypto.Tpo -c -o libxmlsec1_openssl_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-crypto.Tpo $(DEPDIR)/libxmlsec1_openssl_la-crypto.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_openssl_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c + +libxmlsec1_openssl_la-digests.lo: digests.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-digests.Tpo -c -o libxmlsec1_openssl_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-digests.Tpo $(DEPDIR)/libxmlsec1_openssl_la-digests.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_openssl_la-digests.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c + +libxmlsec1_openssl_la-evp.lo: evp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-evp.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-evp.Tpo -c -o libxmlsec1_openssl_la-evp.lo `test -f 'evp.c' || echo '$(srcdir)/'`evp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-evp.Tpo $(DEPDIR)/libxmlsec1_openssl_la-evp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='evp.c' object='libxmlsec1_openssl_la-evp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-evp.lo `test -f 'evp.c' || echo '$(srcdir)/'`evp.c + +libxmlsec1_openssl_la-hmac.lo: hmac.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-hmac.Tpo -c -o libxmlsec1_openssl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-hmac.Tpo $(DEPDIR)/libxmlsec1_openssl_la-hmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_openssl_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c + +libxmlsec1_openssl_la-kw_aes.lo: kw_aes.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Tpo -c -o libxmlsec1_openssl_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_openssl_la-kw_aes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c + +libxmlsec1_openssl_la-kw_des.lo: kw_des.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-kw_des.Tpo -c -o libxmlsec1_openssl_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_openssl_la-kw_des.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_openssl_la-kw_des.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c + +libxmlsec1_openssl_la-kt_rsa.lo: kt_rsa.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-kt_rsa.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Tpo -c -o libxmlsec1_openssl_la-kt_rsa.lo `test -f 'kt_rsa.c' || echo '$(srcdir)/'`kt_rsa.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Tpo $(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kt_rsa.c' object='libxmlsec1_openssl_la-kt_rsa.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-kt_rsa.lo `test -f 'kt_rsa.c' || echo '$(srcdir)/'`kt_rsa.c + +libxmlsec1_openssl_la-signatures.lo: signatures.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-signatures.Tpo -c -o libxmlsec1_openssl_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-signatures.Tpo $(DEPDIR)/libxmlsec1_openssl_la-signatures.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_openssl_la-signatures.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c + +libxmlsec1_openssl_la-symkeys.lo: symkeys.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-symkeys.Tpo -c -o libxmlsec1_openssl_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_openssl_la-symkeys.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_openssl_la-symkeys.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c + +libxmlsec1_openssl_la-x509.lo: x509.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-x509.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-x509.Tpo -c -o libxmlsec1_openssl_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-x509.Tpo $(DEPDIR)/libxmlsec1_openssl_la-x509.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509.c' object='libxmlsec1_openssl_la-x509.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c + +libxmlsec1_openssl_la-x509vfy.lo: x509vfy.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-x509vfy.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Tpo -c -o libxmlsec1_openssl_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Tpo $(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509vfy.c' object='libxmlsec1_openssl_la-x509vfy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c + +libxmlsec1_openssl_la-strings.lo: ../strings.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-strings.Tpo -c -o libxmlsec1_openssl_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-strings.Tpo $(DEPDIR)/libxmlsec1_openssl_la-strings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_openssl_la-strings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/openssl/README b/src/openssl/README new file mode 100644 index 00000000..0f1c625d --- /dev/null +++ b/src/openssl/README @@ -0,0 +1,17 @@ +WHAT VERSION OF OPENSSL? +------------------------------------------------------------------------ +OpenSSL 0.9.6 is supported but some functionality requires 0.9.7 or greater. + +KEYS MANAGER +------------------------------------------------------------------------ + +OpenSSL does not have a keys or certificates storage implementation. The +default xmlsec-openssl key manager uses a simple keys store from xmlsec +core library based on plain keys list. Trusted/untrusted certificates +are stored in STACK_OF(X509) structures. + +KNOWN ISSUES. +------------------------------------------------------------------------ +1) One day we might decide to drop OpenSSL 0.9.6 supprot and remove all +these ifdef's to simplify the code. + diff --git a/src/openssl/app.c b/src/openssl/app.c new file mode 100644 index 00000000..4f8f79e6 --- /dev/null +++ b/src/openssl/app.c @@ -0,0 +1,1628 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include <libxml/tree.h> + +#include <openssl/evp.h> +#include <openssl/rand.h> +#include <openssl/pem.h> +#include <openssl/pkcs12.h> +#include <openssl/conf.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/private.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/app.h> +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> +#include <xmlsec/openssl/x509.h> + +static int xmlSecOpenSSLAppLoadRANDFile (const char *file); +static int xmlSecOpenSSLAppSaveRANDFile (const char *file); +static int xmlSecOpenSSLDefaultPasswordCallback (char *buf, + int bufsiz, + int verify, + void *userdata); +static int xmlSecOpenSSLDummyPasswordCallback (char *buf, + int bufsize, + int verify, + void *userdata); + +/* conversion from ptr to func "the right way" */ +XMLSEC_PTR_TO_FUNC_IMPL(pem_password_cb) + + +/** + * xmlSecOpenSSLAppInit: + * @config: the path to certs. + * + * General crypto engine initialization. This function is used + * by XMLSec command line utility and called before + * @xmlSecInit function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppInit(const char* config) { + ERR_load_crypto_strings(); + OPENSSL_config(NULL); + OpenSSL_add_all_algorithms(); + + if((RAND_status() != 1) && (xmlSecOpenSSLAppLoadRANDFile(NULL) != 1)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppLoadRANDFile", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if((config != NULL) && (xmlSecOpenSSLSetDefaultTrustedCertsFolder(BAD_CAST config) < 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLSetDefaultTrustedCertsFolder", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLAppShutdown: + * + * General crypto engine shutdown. This function is used + * by XMLSec command line utility and called after + * @xmlSecShutdown function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppShutdown(void) { + xmlSecOpenSSLAppSaveRANDFile(NULL); + RAND_cleanup(); + EVP_cleanup(); + +#ifndef XMLSEC_NO_X509 + X509_TRUST_cleanup(); +#endif /* XMLSEC_NO_X509 */ + +#ifndef XMLSEC_OPENSSL_096 + CRYPTO_cleanup_all_ex_data(); +#endif /* XMLSEC_OPENSSL_096 */ + + /* finally cleanup errors */ + ERR_remove_state(0); + ERR_free_strings(); + + return(0); +} + +/** + * xmlSecOpenSSLAppKeyLoad: + * @filename: the key filename. + * @format: the key file format. + * @pwd: the key file password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from the a file. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppKeyLoad(const char *filename, xmlSecKeyDataFormat format, + const char *pwd, void* pwdCallback, + void* pwdCallbackCtx) { + BIO* bio; + xmlSecKeyPtr key; + + xmlSecAssert2(filename != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + bio = BIO_new_file(filename, "rb"); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + return(NULL); + } + + key = xmlSecOpenSSLAppKeyLoadBIO (bio, format, pwd, pwdCallback, pwdCallbackCtx); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeyLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + BIO_free(bio); + return(NULL); + } + + BIO_free(bio); + return(key); +} + +/** + * xmlSecOpenSSLAppKeyLoadMemory: + * @data: the binary key data. + * @dataSize: the size of binary key. + * @format: the key file format. + * @pwd: the key file password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from the memory buffer. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, + xmlSecKeyDataFormat format, const char *pwd, + void* pwdCallback, void* pwdCallbackCtx) { + BIO* bio; + xmlSecKeyPtr key; + + xmlSecAssert2(data != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + /* this would be a read only BIO, cast from const is ok */ + bio = BIO_new_mem_buf((void*)data, dataSize); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_mem_buf", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "errno=%d", + errno); + return(NULL); + } + + key = xmlSecOpenSSLAppKeyLoadBIO (bio, format, pwd, pwdCallback, pwdCallbackCtx); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeyLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free(bio); + return(NULL); + } + + BIO_free(bio); + return(key); +} + + +/** + * xmlSecOpenSSLAppKeyLoadBIO: + * @bio: the key BIO. + * @format: the key file format. + * @pwd: the key file password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from the an OpenSSL BIO object. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppKeyLoadBIO(BIO* bio, xmlSecKeyDataFormat format, + const char *pwd, void* pwdCallback, + void* pwdCallbackCtx) { + + xmlSecKeyPtr key = NULL; + xmlSecKeyDataPtr data; + EVP_PKEY* pKey = NULL; + int ret; + + xmlSecAssert2(bio != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + switch(format) { + case xmlSecKeyDataFormatPem: + /* try to read private key first */ + if(pwd != NULL) { + pKey = PEM_read_bio_PrivateKey(bio, NULL, + xmlSecOpenSSLDummyPasswordCallback, + (void*)pwd); + } else { + pKey = PEM_read_bio_PrivateKey(bio, NULL, + XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback), + pwdCallbackCtx); + } + if(pKey == NULL) { + /* go to start of the file and try to read public key */ + BIO_reset(bio); + pKey = PEM_read_bio_PUBKEY(bio, NULL, + XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback), + pwdCallbackCtx); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PEM_read_bio_PrivateKey and PEM_read_bio_PUBKEY", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + } + break; + case xmlSecKeyDataFormatDer: + /* try to read private key first */ + pKey = d2i_PrivateKey_bio(bio, NULL); + if(pKey == NULL) { + /* go to start of the file and try to read public key */ + BIO_reset(bio); + pKey = d2i_PUBKEY_bio(bio, NULL); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "d2i_PrivateKey_bio and d2i_PUBKEY_bio", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + } + break; + case xmlSecKeyDataFormatPkcs8Pem: + /* try to read private key first */ + pKey = PEM_read_bio_PrivateKey(bio, NULL, + XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback), + pwdCallbackCtx); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PEM_read_bio_PrivateKey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; + case xmlSecKeyDataFormatPkcs8Der: + /* try to read private key first */ + pKey = d2i_PKCS8PrivateKey_bio(bio, NULL, + XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback), + pwdCallbackCtx); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "d2i_PrivateKey_bio and d2i_PUBKEY_bio", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; +#ifndef XMLSEC_NO_X509 + case xmlSecKeyDataFormatPkcs12: + key = xmlSecOpenSSLAppPkcs12LoadBIO(bio, pwd, pwdCallback, pwdCallbackCtx); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppPkcs12LoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + return(key); + + case xmlSecKeyDataFormatCertPem: + case xmlSecKeyDataFormatCertDer: + key = xmlSecOpenSSLAppKeyFromCertLoadBIO(bio, format); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeyFromCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + return(key); +#endif /* XMLSEC_NO_X509 */ + + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", format); + return(NULL); + } + + data = xmlSecOpenSSLEvpKeyAdopt(pKey); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLEvpKeyAdopt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + EVP_PKEY_free(pKey); + return(NULL); + } + + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(data); + return(NULL); + } + + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data))); + xmlSecKeyDestroy(key); + xmlSecKeyDataDestroy(data); + return(NULL); + } + + return(key); +} + + +#ifndef XMLSEC_NO_X509 +static X509* xmlSecOpenSSLAppCertLoadBIO (BIO* bio, + xmlSecKeyDataFormat format); +/** + * xmlSecOpenSSLAppKeyCertLoad: + * @key: the pointer to key. + * @filename: the certificate filename. + * @format: the certificate file format. + * + * Reads the certificate from $@filename and adds it to key. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) { + BIO* bio; + int ret; + + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(filename != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + bio = BIO_new_file(filename, "rb"); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + return(-1); + } + + ret = xmlSecOpenSSLAppKeyCertLoadBIO (key, bio, format); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeyCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + BIO_free(bio); + return(-1); + } + + BIO_free(bio); + return(0); +} + +/** + * xmlSecOpenSSLAppKeyCertLoadMemory: + * @key: the pointer to key. + * @data: the certificate binary data. + * @dataSize: the certificate binary data size. + * @format: the certificate file format. + * + * Reads the certificate from memory buffer and adds it to key. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize, + xmlSecKeyDataFormat format) { + BIO* bio; + int ret; + + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + /* this would be a read only BIO, cast from const is ok */ + bio = BIO_new_mem_buf((void*)data, dataSize); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_mem_buf", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "errno=%d", + errno); + return(-1); + } + + ret = xmlSecOpenSSLAppKeyCertLoadBIO (key, bio, format); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeyCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free(bio); + return(-1); + } + + BIO_free(bio); + return(0); +} + +/** + * xmlSecOpenSSLAppKeyCertLoadBIO: + * @key: the pointer to key. + * @bio: the certificate bio. + * @format: the certificate file format. + * + * Reads the certificate from memory buffer and adds it to key. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeyCertLoadBIO(xmlSecKeyPtr key, BIO* bio, xmlSecKeyDataFormat format) { + + xmlSecKeyDataFormat certFormat; + xmlSecKeyDataPtr data; + X509 *cert; + int ret; + + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(bio != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + data = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyEnsureData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "transform=%s", + xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecOpenSSLKeyDataX509Id))); + return(-1); + } + + /* adjust cert format */ + switch(format) { + case xmlSecKeyDataFormatPkcs8Pem: + certFormat = xmlSecKeyDataFormatPem; + break; + case xmlSecKeyDataFormatPkcs8Der: + certFormat = xmlSecKeyDataFormatDer; + break; + default: + certFormat = format; + } + + cert = xmlSecOpenSSLAppCertLoadBIO(bio, certFormat); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppCertLoad", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data))); + X509_free(cert); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLAppPkcs12Load: + * @filename: the PKCS12 key filename. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 file. + * For uniformity, call xmlSecOpenSSLAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppPkcs12Load(const char *filename, const char *pwd, + void* pwdCallback, void* pwdCallbackCtx) { + BIO* bio; + xmlSecKeyPtr key; + + xmlSecAssert2(filename != NULL, NULL); + + bio = BIO_new_file(filename, "rb"); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + return(NULL); + } + + key = xmlSecOpenSSLAppPkcs12LoadBIO (bio, pwd, pwdCallback, pwdCallbackCtx); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppPkcs12LoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + BIO_free(bio); + return(NULL); + } + + BIO_free(bio); + return(key); +} + +/** + * xmlSecOpenSSLAppPkcs12LoadMemory: + * @data: the PKCS12 binary data. + * @dataSize: the PKCS12 binary data size. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 data in memory buffer. + * For uniformity, call xmlSecOpenSSLAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, + const char *pwd, void* pwdCallback, + void* pwdCallbackCtx) { + BIO* bio; + xmlSecKeyPtr key; + + xmlSecAssert2(data != NULL, NULL); + + /* this would be a read only BIO, cast from const is ok */ + bio = BIO_new_mem_buf((void*)data, dataSize); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_mem_buf", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "errno=%d", + errno); + return(NULL); + } + + key = xmlSecOpenSSLAppPkcs12LoadBIO (bio, pwd, pwdCallback, pwdCallbackCtx); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppPkcs12LoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free(bio); + return(NULL); + } + + BIO_free(bio); + return(key); +} + +/** + * xmlSecOpenSSLAppPkcs12LoadBIO: + * @bio: the PKCS12 key bio. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 data in an OpenSSL BIO object. + * For uniformity, call xmlSecOpenSSLAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppPkcs12LoadBIO(BIO* bio, const char *pwd, + void* pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) { + + PKCS12 *p12 = NULL; + EVP_PKEY *pKey = NULL; + STACK_OF(X509) *chain = NULL; + xmlSecKeyPtr key = NULL; + xmlSecKeyDataPtr data = NULL; + xmlSecKeyDataPtr x509Data = NULL; + X509 *cert = NULL; + X509 *tmpcert = NULL; + int i; + int has_cert; + int ret; + + xmlSecAssert2(bio != NULL, NULL); + + p12 = d2i_PKCS12_bio(bio, NULL); + if(p12 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "d2i_PKCS12_fp", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = PKCS12_verify_mac(p12, pwd, (pwd != NULL) ? strlen(pwd) : 0); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PKCS12_verify_mac", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = PKCS12_parse(p12, pwd, &pKey, &cert, &chain); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PKCS12_parse", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + data = xmlSecOpenSSLEvpKeyAdopt(pKey); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLEvpKeyAdopt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + EVP_PKEY_free(pKey); + goto done; + } + + x509Data = xmlSecKeyDataCreate(xmlSecOpenSSLKeyDataX509Id); + if(x509Data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "transform=%s", + xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecOpenSSLKeyDataX509Id))); + goto done; + } + + /* starting from openssl 1.0.0 the PKCS12_parse() call will not create certs + chain object if there is no certificates in the pkcs12 file and it will be null + */ + if(chain == NULL) { + chain = sk_X509_new_null(); + if(chain == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "sk_X509_new_null", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + + /* + The documentation states (http://www.openssl.org/docs/crypto/PKCS12_parse.html): + + If successful the private key will be written to "*pkey", the + corresponding certificate to "*cert" and any additional certificates + to "*ca". + + In reality, the function sometime returns in the "ca" the certificates + including the one it is already returned in "cert". + */ + has_cert = 0; + for(i = 0; i < sk_X509_num(chain); ++i) { + xmlSecAssert2(sk_X509_value(chain, i), NULL); + + if(X509_cmp(sk_X509_value(chain, i), cert) == 0) { + has_cert = 1; + break; + } + } + + if(has_cert == 0) { + tmpcert = X509_dup(cert); + if(tmpcert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + goto done; + } + + ret = sk_X509_push(chain, tmpcert); + if(ret < 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "sk_X509_push", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + X509_free(tmpcert); + goto done; + } + } + + ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(x509Data, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKeyDataX509AdoptKeyCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + goto done; + } + cert = NULL; + + for(i = 0; i < sk_X509_num(chain); ++i) { + xmlSecAssert2(sk_X509_value(chain, i), NULL); + + tmpcert = X509_dup(sk_X509_value(chain, i)); + if(tmpcert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + X509_free(tmpcert); + goto done; + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(x509Data, tmpcert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + goto done; + } + } + + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + xmlSecKeyDestroy(key); + key = NULL; + goto done; + } + data = NULL; + + ret = xmlSecKeyAdoptData(key, x509Data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyAdoptData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + xmlSecKeyDestroy(key); + key = NULL; + goto done; + } + x509Data = NULL; + +done: + if(x509Data != NULL) { + xmlSecKeyDataDestroy(x509Data); + } + if(data != NULL) { + xmlSecKeyDataDestroy(data); + } + if(chain != NULL) { + sk_X509_pop_free(chain, X509_free); + } + if(cert != NULL) { + X509_free(cert); + } + if(p12 != NULL) { + PKCS12_free(p12); + } + return(key); +} + +/** + * xmlSecOpenSSLAppKeyFromCertLoadBIO: + * @bio: the BIO. + * @format: the cert format. + * + * Loads public key from cert. + * + * Returns: pointer to key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecOpenSSLAppKeyFromCertLoadBIO(BIO* bio, xmlSecKeyDataFormat format) { + xmlSecKeyPtr key; + xmlSecKeyDataPtr keyData; + xmlSecKeyDataPtr certData; + X509 *cert; + int ret; + + xmlSecAssert2(bio != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + /* load cert */ + cert = xmlSecOpenSSLAppCertLoadBIO(bio, format); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + /* get key value */ + keyData = xmlSecOpenSSLX509CertGetKey(cert); + if(keyData == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509CertGetKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert); + return(NULL); + } + + /* create key */ + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(keyData); + X509_free(cert); + return(NULL); + } + + /* set key value */ + ret = xmlSecKeySetValue(key, keyData); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + xmlSecKeyDataDestroy(keyData); + X509_free(cert); + return(NULL); + } + + /* create cert data */ + certData = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id); + if(certData == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyEnsureData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + X509_free(cert); + return(NULL); + } + + /* put cert in the cert data */ + ret = xmlSecOpenSSLKeyDataX509AdoptCert(certData, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + X509_free(cert); + return(NULL); + } + + return(key); +} + + +/** + * xmlSecOpenSSLAppKeysMngrCertLoad: + * @mngr: the keys manager. + * @filename: the certificate file. + * @format: the certificate file format. + * @type: the flag that indicates is the certificate in @filename + * trusted or not. + * + * Reads cert from @filename and adds to the list of trusted or known + * untrusted certs in @store. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename, + xmlSecKeyDataFormat format, xmlSecKeyDataType type) { + BIO* bio; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(filename != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + bio = BIO_new_file(filename, "rb"); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + return(-1); + } + + ret = xmlSecOpenSSLAppKeysMngrCertLoadBIO(mngr, bio, format, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeysMngrCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s;errno=%d", + xmlSecErrorsSafeString(filename), + errno); + BIO_free(bio); + return(-1); + } + + BIO_free(bio); + return(0); +} + +/** + * xmlSecOpenSSLAppKeysMngrCertLoadMemory: + * @mngr: the keys manager. + * @data: the certificate binary data. + * @dataSize: the certificate binary data size. + * @format: the certificate file format. + * @type: the flag that indicates is the certificate trusted or not. + * + * Reads cert from binary buffer @data and adds to the list of trusted or known + * untrusted certs in @store. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data, + xmlSecSize dataSize, xmlSecKeyDataFormat format, + xmlSecKeyDataType type) { + BIO* bio; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + /* this would be a read only BIO, cast from const is ok */ + bio = BIO_new_mem_buf((void*)data, dataSize); + if(bio == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new_mem_buf", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "errno=%d", + errno); + return(-1); + } + + ret = xmlSecOpenSSLAppKeysMngrCertLoadBIO(mngr, bio, format, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppKeysMngrCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free(bio); + return(-1); + } + + BIO_free(bio); + return(0); +} + +/** + * xmlSecOpenSSLAppKeysMngrCertLoadBIO: + * @mngr: the keys manager. + * @bio: the certificate BIO. + * @format: the certificate file format. + * @type: the flag that indicates is the certificate trusted or not. + * + * Reads cert from an OpenSSL BIO object and adds to the list of trusted or known + * untrusted certs in @store. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeysMngrCertLoadBIO(xmlSecKeysMngrPtr mngr, BIO* bio, + xmlSecKeyDataFormat format, xmlSecKeyDataType type) { + xmlSecKeyDataStorePtr x509Store; + X509* cert; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(bio != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecOpenSSLX509StoreId"); + return(-1); + } + + cert = xmlSecOpenSSLAppCertLoadBIO(bio, format); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLAppCertLoadBIO", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecOpenSSLX509StoreAdoptCert(x509Store, cert, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509StoreAdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLAppKeysMngrAddCertsPath: + * @mngr: the keys manager. + * @path: the path to trusted certificates. + * + * Reads cert from @path and adds to the list of trusted certificates. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeysMngrAddCertsPath(xmlSecKeysMngrPtr mngr, const char *path) { + xmlSecKeyDataStorePtr x509Store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(path != NULL, -1); + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecOpenSSLX509StoreId"); + return(-1); + } + + ret = xmlSecOpenSSLX509StoreAddCertsPath(x509Store, path); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509StoreAddCertsPath", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "path=%s", xmlSecErrorsSafeString(path)); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLAppKeysMngrAddCertsFile: + * @mngr: the keys manager. + * @file: the file containing trusted certificates. + * + * Reads certs from @file and adds to the list of trusted certificates. + * It is possible for @file to contain multiple certs. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppKeysMngrAddCertsFile(xmlSecKeysMngrPtr mngr, const char *file) { + xmlSecKeyDataStorePtr x509Store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(file != NULL, -1); + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecOpenSSLX509StoreId"); + return(-1); + } + + ret = xmlSecOpenSSLX509StoreAddCertsFile(x509Store, file); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509StoreAddCertsFile", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "file=%s", xmlSecErrorsSafeString(file)); + return(-1); + } + + return(0); +} + +static X509* +xmlSecOpenSSLAppCertLoadBIO(BIO* bio, xmlSecKeyDataFormat format) { + X509 *cert; + + xmlSecAssert2(bio != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + switch(format) { + case xmlSecKeyDataFormatPem: + case xmlSecKeyDataFormatCertPem: + cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PEM_read_bio_X509_AUX", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; + case xmlSecKeyDataFormatDer: + case xmlSecKeyDataFormatCertDer: + cert = d2i_X509_bio(bio, NULL); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "d2i_X509_bio", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", format); + return(NULL); + } + + return(cert); +} + +#endif /* XMLSEC_NO_X509 */ + +/** + * xmlSecOpenSSLAppDefaultKeysMngrInit: + * @mngr: the pointer to keys manager. + * + * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId + * and a default OpenSSL crypto key data stores. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) { + int ret; + + xmlSecAssert2(mngr != NULL, -1); + + /* create simple keys store if needed */ + if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) { + xmlSecKeyStorePtr keysStore; + + keysStore = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId); + if(keysStore == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyStoreCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecSimpleKeysStoreId"); + return(-1); + } + + ret = xmlSecKeysMngrAdoptKeysStore(mngr, keysStore); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrAdoptKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyStoreDestroy(keysStore); + return(-1); + } + } + + ret = xmlSecOpenSSLKeysMngrInit(mngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKeysMngrInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* TODO */ + mngr->getKey = xmlSecKeysMngrGetKey; + return(0); +} + +/** + * xmlSecOpenSSLAppDefaultKeysMngrAdoptKey: + * @mngr: the pointer to keys manager. + * @key: the pointer to key. + * + * Adds @key to the keys manager @mngr created with #xmlSecOpenSSLAppDefaultKeysMngrInit + * function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) { + xmlSecKeyStorePtr store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(key != NULL, -1); + + store = xmlSecKeysMngrGetKeysStore(mngr); + if(store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecSimpleKeysStoreAdoptKey(store, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSimpleKeysStoreAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLAppDefaultKeysMngrLoad: + * @mngr: the pointer to keys manager. + * @uri: the uri. + * + * Loads XML keys file from @uri to the keys manager @mngr created + * with #xmlSecOpenSSLAppDefaultKeysMngrInit function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) { + xmlSecKeyStorePtr store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(uri != NULL, -1); + + store = xmlSecKeysMngrGetKeysStore(mngr); + if(store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecSimpleKeysStoreLoad(store, uri, mngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSimpleKeysStoreLoad", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "uri=%s", xmlSecErrorsSafeString(uri)); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLAppDefaultKeysMngrSave: + * @mngr: the pointer to keys manager. + * @filename: the destination filename. + * @type: the type of keys to save (public/private/symmetric). + * + * Saves keys from @mngr to XML keys file. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename, + xmlSecKeyDataType type) { + xmlSecKeyStorePtr store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(filename != NULL, -1); + + store = xmlSecKeysMngrGetKeysStore(mngr); + if(store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecSimpleKeysStoreSave(store, filename, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSimpleKeysStoreSave", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename%s", xmlSecErrorsSafeString(filename)); + return(-1); + } + + return(0); +} + + +/* + * Random numbers initialization from openssl (apps/app_rand.c) + */ +static int seeded = 0; +static int egdsocket = 0; + +static int +xmlSecOpenSSLAppLoadRANDFile(const char *file) { + char buffer[1024]; + + if(file == NULL) { + file = RAND_file_name(buffer, sizeof(buffer)); + }else if(RAND_egd(file) > 0) { + /* we try if the given filename is an EGD socket. + * if it is, we don't write anything back to the file. */ + egdsocket = 1; + return 1; + } + + if((file == NULL) || !RAND_load_file(file, -1)) { + if(RAND_status() == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "RAND_load_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "file=%s", xmlSecErrorsSafeString(file)); + return 0; + } + } + seeded = 1; + return 1; +} + +static int +xmlSecOpenSSLAppSaveRANDFile(const char *file) { + char buffer[1024]; + + if(egdsocket || !seeded) { + /* If we did not manage to read the seed file, + * we should not write a low-entropy seed file back -- + * it would suppress a crucial warning the next time + * we want to use it. */ + return 0; + } + + if(file == NULL) { + file = RAND_file_name(buffer, sizeof(buffer)); + } + if((file == NULL) || !RAND_write_file(file)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "RAND_write_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "file=%s", + xmlSecErrorsSafeString(file)); + return 0; + } + + return 1; +} + +/** + * xmlSecOpenSSLAppGetDefaultPwdCallback: + * + * Gets default password callback. + * + * Returns: default password callback. + */ +void* +xmlSecOpenSSLAppGetDefaultPwdCallback(void) { + return XMLSEC_FUNC_TO_PTR(pem_password_cb, xmlSecOpenSSLDefaultPasswordCallback); +} + +static int +xmlSecOpenSSLDefaultPasswordCallback(char *buf, int bufsize, int verify, void *userdata) { + char* filename = (char*)userdata; + char* buf2; + xmlChar prompt[2048]; + int i, ret; + + xmlSecAssert2(buf != NULL, -1); + + /* try 3 times */ + for(i = 0; i < 3; i++) { + if(filename != NULL) { + xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password for \"%s\" file: ", filename); + } else { + xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password: "); + } + ret = EVP_read_pw_string(buf, bufsize, (char*)prompt, 0); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "EVP_read_pw_string", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* if we don't need to verify password then we are done */ + if(verify == 0) { + return(strlen(buf)); + } + + if(filename != NULL) { + xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password for \"%s\" file again: ", filename); + } else { + xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password again: "); + } + + buf2 = (char*)xmlMalloc(bufsize); + if(buf2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", bufsize); + return(-1); + } + ret = EVP_read_pw_string(buf2, bufsize, (char*)prompt, 0); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "EVP_read_pw_string", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + memset(buf2, 0, bufsize); + xmlFree(buf2); + return(-1); + } + + /* check if passwords match */ + if(strcmp(buf, buf2) == 0) { + memset(buf2, 0, bufsize); + xmlFree(buf2); + return(strlen(buf)); + } + + /* try again */ + memset(buf2, 0, bufsize); + xmlFree(buf2); + } + + return(-1); +} + +static int +xmlSecOpenSSLDummyPasswordCallback(char *buf, int bufsize, + int verify ATTRIBUTE_UNUSED, + void *userdata) { + char* password = (char*)userdata; + + if((password == NULL) || ((int)strlen(password) + 1 > bufsize)) { + return(-1); + } + + strcpy(buf, password); + return (strlen(buf)); +} + diff --git a/src/openssl/bn.c b/src/openssl/bn.c new file mode 100644 index 00000000..dfeae6ea --- /dev/null +++ b/src/openssl/bn.c @@ -0,0 +1,163 @@ +/** + * XMLSec library + * + * Reading/writing BIGNUM values + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <stdlib.h> +#include <string.h> + +#include <libxml/tree.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/buffer.h> +#include <xmlsec/base64.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/bn.h> + +/** + * xmlSecOpenSSLNodeGetBNValue: + * @cur: the poitner to an XML node. + * @a: the BIGNUM buffer. + * + * Converts the node content from CryptoBinary format + * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary) + * to a BIGNUM. If no BIGNUM buffer provided then a new + * BIGNUM is created (caller is responsible for freeing it). + * + * Returns: a pointer to BIGNUM produced from CryptoBinary string + * or NULL if an error occurs. + */ +BIGNUM* +xmlSecOpenSSLNodeGetBNValue(const xmlNodePtr cur, BIGNUM **a) { + xmlSecBuffer buf; + int ret; + + xmlSecAssert2(cur != NULL, NULL); + + ret = xmlSecBufferInitialize(&buf, 128); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + ret = xmlSecBufferBase64NodeContentRead(&buf, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferBase64NodeContentRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&buf); + return(NULL); + } + + (*a) = BN_bin2bn(xmlSecBufferGetData(&buf), xmlSecBufferGetSize(&buf), (*a)); + if( (*a) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_bin2bn", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&buf); + return(NULL); + } + xmlSecBufferFinalize(&buf); + return(*a); +} + +/** + * xmlSecOpenSSLNodeSetBNValue: + * @cur: the pointer to an XML node. + * @a: the BIGNUM. + * @addLineBreaks: if the flag is equal to 1 then + * linebreaks will be added before and after + * new buffer content. + * + * Converts BIGNUM to CryptoBinary string + * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary) + * and sets it as the content of the given node. If the + * addLineBreaks is set then line breaks are added + * before and after the CryptoBinary string. + * + * Returns: 0 on success or -1 otherwise. + */ +int +xmlSecOpenSSLNodeSetBNValue(xmlNodePtr cur, const BIGNUM *a, int addLineBreaks) { + xmlSecBuffer buf; + xmlSecSize size; + int ret; + + xmlSecAssert2(a != NULL, -1); + xmlSecAssert2(cur != NULL, -1); + + ret = xmlSecBufferInitialize(&buf, BN_num_bytes(a) + 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", BN_num_bytes(a) + 1); + return(-1); + } + + ret = BN_bn2bin(a, xmlSecBufferGetData(&buf)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_bn2bin", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&buf); + return(-1); + } + size = ret; + + ret = xmlSecBufferSetSize(&buf, size); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", size); + xmlSecBufferFinalize(&buf); + return(-1); + } + + if(addLineBreaks) { + xmlNodeSetContent(cur, xmlSecStringCR); + } else { + xmlNodeSetContent(cur, xmlSecStringEmpty); + } + + ret = xmlSecBufferBase64NodeContentWrite(&buf, cur, xmlSecBase64GetDefaultLineSize()); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferBase64NodeContentWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&buf); + return(-1); + } + + if(addLineBreaks) { + xmlNodeAddContent(cur, xmlSecStringCR); + } + + xmlSecBufferFinalize(&buf); + return(0); +} + diff --git a/src/openssl/ciphers.c b/src/openssl/ciphers.c new file mode 100644 index 00000000..1b600625 --- /dev/null +++ b/src/openssl/ciphers.c @@ -0,0 +1,856 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <openssl/evp.h> +#include <openssl/rand.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> + +/* this is not defined in OpenSSL 0.9.6 */ +#ifndef EVP_MAX_BLOCK_LENGTH +#define EVP_MAX_BLOCK_LENGTH 32 +#endif /* EVP_MAX_BLOCK_LENGTH */ + +/************************************************************************** + * + * Internal OpenSSL Block cipher CTX + * + *****************************************************************************/ +typedef struct _xmlSecOpenSSLEvpBlockCipherCtx xmlSecOpenSSLEvpBlockCipherCtx, + *xmlSecOpenSSLEvpBlockCipherCtxPtr; +struct _xmlSecOpenSSLEvpBlockCipherCtx { + const EVP_CIPHER* cipher; + xmlSecKeyDataId keyId; + EVP_CIPHER_CTX cipherCtx; + int keyInitialized; + int ctxInitialized; + xmlSecByte key[EVP_MAX_KEY_LENGTH]; + xmlSecByte iv[EVP_MAX_IV_LENGTH]; + xmlSecByte pad[EVP_MAX_BLOCK_LENGTH]; +}; +static int xmlSecOpenSSLEvpBlockCipherCtxInit (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLEvpBlockCipherCtxUpdate (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLEvpBlockCipherCtxFinal (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx, + xmlSecBufferPtr out, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int +xmlSecOpenSSLEvpBlockCipherCtxInit(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + int ivLen; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != NULL, -1); + xmlSecAssert2(ctx->keyInitialized != 0, -1); + xmlSecAssert2(ctx->ctxInitialized == 0, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ivLen = EVP_CIPHER_iv_length(ctx->cipher); + xmlSecAssert2(ivLen > 0, -1); + xmlSecAssert2((xmlSecSize)ivLen <= sizeof(ctx->iv), -1); + + if(encrypt) { + /* generate random iv */ + ret = RAND_bytes(ctx->iv, ivLen); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "RAND_bytes", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", ivLen); + return(-1); + } + + /* write iv to the output */ + ret = xmlSecBufferAppend(out, ctx->iv, ivLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferAppend", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", ivLen); + return(-1); + } + + } else { + /* if we don't have enough data, exit and hope that + * we'll have iv next time */ + if(xmlSecBufferGetSize(in) < (xmlSecSize)ivLen) { + return(0); + } + + /* copy iv to our buffer*/ + xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1); + memcpy(ctx->iv, xmlSecBufferGetData(in), ivLen); + + /* and remove from input */ + ret = xmlSecBufferRemoveHead(in, ivLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", ivLen); + return(-1); + } + } + + /* set iv */ + ret = EVP_CipherInit(&(ctx->cipherCtx), ctx->cipher, ctx->key, ctx->iv, encrypt); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "EVP_CipherInit", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ctx->ctxInitialized = 1; + + /* + * The padding used in XML Enc does not follow RFC 1423 + * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7 + * it is possible to disable padding and do it by yourself + * For OpenSSL 0.9.6 you have interop problems + */ +#ifndef XMLSEC_OPENSSL_096 + EVP_CIPHER_CTX_set_padding(&(ctx->cipherCtx), 0); +#endif /* XMLSEC_OPENSSL_096 */ + return(0); +} + +static int +xmlSecOpenSSLEvpBlockCipherCtxUpdate(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, xmlSecBufferPtr out, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + int blockLen, fixLength = 0, outLen = 0; + xmlSecSize inSize, outSize; + xmlSecByte* outBuf; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->keyInitialized != 0, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + blockLen = EVP_CIPHER_block_size(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + if(inSize == 0) { + /* wait for more data */ + return(0); + } + + /* OpenSSL docs: The amount of data written depends on the block + * alignment of the encrypted data: as a result the amount of data + * written may be anything from zero bytes to (inl + cipher_block_size - 1). + */ + ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + inSize + blockLen); + return(-1); + } + outBuf = xmlSecBufferGetData(out) + outSize; + + /* + * The padding used in XML Enc does not follow RFC 1423 + * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7 + * it is possible to disable padding and do it by yourself + * For OpenSSL 0.9.6 you have interop problems. + * + * The logic below is copied from EVP_DecryptUpdate() function. + * This is a hack but it's the only way I can provide binary + * compatibility with previous versions of xmlsec. + * This needs to be fixed in the next XMLSEC API refresh. + */ +#ifndef XMLSEC_OPENSSL_096 + if(!ctx->cipherCtx.encrypt) { + if(ctx->cipherCtx.final_used) { + memcpy(outBuf, ctx->cipherCtx.final, blockLen); + outBuf += blockLen; + fixLength = 1; + } else { + fixLength = 0; + } + } +#endif /* XMLSEC_OPENSSL_096 */ + + /* encrypt/decrypt */ + ret = EVP_CipherUpdate(&(ctx->cipherCtx), outBuf, &outLen, xmlSecBufferGetData(in), inSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "EVP_CipherUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifndef XMLSEC_OPENSSL_096 + if(!ctx->cipherCtx.encrypt) { + /* + * The logic below is copied from EVP_DecryptUpdate() function. + * This is a hack but it's the only way I can provide binary + * compatibility with previous versions of xmlsec. + * This needs to be fixed in the next XMLSEC API refresh. + */ + if (blockLen > 1 && !ctx->cipherCtx.buf_len) { + outLen -= blockLen; + ctx->cipherCtx.final_used = 1; + memcpy(ctx->cipherCtx.final, &outBuf[outLen], blockLen); + } else { + ctx->cipherCtx.final_used = 0; + } + if (fixLength) { + outLen += blockLen; + } + } +#endif /* XMLSEC_OPENSSL_096 */ + + /* set correct output buffer size */ + ret = xmlSecBufferSetSize(out, outSize + outLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + outLen); + return(-1); + } + + /* remove the processed block from input */ + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + return(0); +} + +static int +xmlSecOpenSSLEvpBlockCipherCtxFinal(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx, + xmlSecBufferPtr out, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + int blockLen, outLen = 0, outLen2 = 0; + xmlSecSize outSize; + xmlSecByte* outBuf; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->keyInitialized != 0, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + blockLen = EVP_CIPHER_block_size(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + outSize = xmlSecBufferGetSize(out); + + /* OpenSSL docs: The encrypted final data is written to out which should + * have sufficient space for one cipher block. We might have to write + * one more block with padding + */ + ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + 2 * blockLen); + return(-1); + } + outBuf = xmlSecBufferGetData(out) + outSize; + + /* + * The padding used in XML Enc does not follow RFC 1423 + * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7 + * it is possible to disable padding and do it by yourself + * For OpenSSL 0.9.6 you have interop problems. + * + * The logic below is copied from EVP_DecryptFinal() function. + * This is a hack but it's the only way I can provide binary + * compatibility with previous versions of xmlsec. + * This needs to be fixed in the next XMLSEC API refresh. + */ +#ifndef XMLSEC_OPENSSL_096 + if(ctx->cipherCtx.encrypt) { + int padLen; + + xmlSecAssert2(blockLen <= EVP_MAX_BLOCK_LENGTH, -1); + + padLen = blockLen - ctx->cipherCtx.buf_len; + xmlSecAssert2(padLen > 0, -1); + + /* generate random padding */ + if(padLen > 1) { + ret = RAND_bytes(ctx->pad, padLen - 1); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "RAND_bytes", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", padLen - 1); + return(-1); + } + } + ctx->pad[padLen - 1] = padLen; + + /* write padding */ + ret = EVP_CipherUpdate(&(ctx->cipherCtx), outBuf, &outLen, ctx->pad, padLen); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "EVP_CipherUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outBuf += outLen; + } +#endif /* XMLSEC_OPENSSL_096 */ + + /* finalize transform */ + ret = EVP_CipherFinal(&(ctx->cipherCtx), outBuf, &outLen2); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "EVP_CipherFinal", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* + * The padding used in XML Enc does not follow RFC 1423 + * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7 + * it is possible to disable padding and do it by yourself + * For OpenSSL 0.9.6 you have interop problems. + * + * The logic below is copied from EVP_DecryptFinal() function. + * This is a hack but it's the only way I can provide binary + * compatibility with previous versions of xmlsec. + * This needs to be fixed in the next XMLSEC API refresh. + */ +#ifndef XMLSEC_OPENSSL_096 + if(!ctx->cipherCtx.encrypt) { + /* we instructed openssl to do not use padding so there + * should be no final block + */ + xmlSecAssert2(outLen2 == 0, -1); + xmlSecAssert2(ctx->cipherCtx.buf_len == 0, -1); + xmlSecAssert2(ctx->cipherCtx.final_used, -1); + + if(blockLen > 1) { + outLen2 = blockLen - ctx->cipherCtx.final[blockLen - 1]; + if(outLen2 > 0) { + memcpy(outBuf, ctx->cipherCtx.final, outLen2); + } else if(outLen2 < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "padding=%d;buffer=%d", + ctx->cipherCtx.final[blockLen - 1], blockLen); + return(-1); + } + } + } +#endif /* XMLSEC_OPENSSL_096 */ + + /* set correct output buffer size */ + ret = xmlSecBufferSetSize(out, outSize + outLen + outLen2); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + outLen + outLen2); + return(-1); + } + + return(0); +} + + +/****************************************************************************** + * + * EVP Block Cipher transforms + * + * xmlSecOpenSSLEvpBlockCipherCtx block is located after xmlSecTransform structure + * + *****************************************************************************/ +#define xmlSecOpenSSLEvpBlockCipherSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLEvpBlockCipherCtx)) +#define xmlSecOpenSSLEvpBlockCipherGetCtx(transform) \ + ((xmlSecOpenSSLEvpBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecOpenSSLEvpBlockCipherInitialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLEvpBlockCipherFinalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLEvpBlockCipherSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLEvpBlockCipherSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLEvpBlockCipherExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLEvpBlockCipherCheckId (xmlSecTransformPtr transform); + + + +static int +xmlSecOpenSSLEvpBlockCipherCheckId(xmlSecTransformPtr transform) { +#ifndef XMLSEC_NO_DES + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDes3CbcId)) { + return(1); + } +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformAes128CbcId) || + xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformAes192CbcId) || + xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformAes256CbcId)) { + + return(1); + } +#endif /* XMLSEC_NO_AES */ + + return(0); +} + +static int +xmlSecOpenSSLEvpBlockCipherInitialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLEvpBlockCipherCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1); + + ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLEvpBlockCipherCtx)); + +#ifndef XMLSEC_NO_DES + if(transform->id == xmlSecOpenSSLTransformDes3CbcId) { + ctx->cipher = EVP_des_ede3_cbc(); + ctx->keyId = xmlSecOpenSSLKeyDataDesId; + } else +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(transform->id == xmlSecOpenSSLTransformAes128CbcId) { + ctx->cipher = EVP_aes_128_cbc(); + ctx->keyId = xmlSecOpenSSLKeyDataAesId; + } else if(transform->id == xmlSecOpenSSLTransformAes192CbcId) { + ctx->cipher = EVP_aes_192_cbc(); + ctx->keyId = xmlSecOpenSSLKeyDataAesId; + } else if(transform->id == xmlSecOpenSSLTransformAes256CbcId) { + ctx->cipher = EVP_aes_256_cbc(); + ctx->keyId = xmlSecOpenSSLKeyDataAesId; + } else +#endif /* XMLSEC_NO_AES */ + + if(1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + EVP_CIPHER_CTX_init(&(ctx->cipherCtx)); + return(0); +} + +static void +xmlSecOpenSSLEvpBlockCipherFinalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLEvpBlockCipherCtxPtr ctx; + + xmlSecAssert(xmlSecOpenSSLEvpBlockCipherCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize)); + + ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform); + xmlSecAssert(ctx != NULL); + + EVP_CIPHER_CTX_cleanup(&(ctx->cipherCtx)); + memset(ctx, 0, sizeof(xmlSecOpenSSLEvpBlockCipherCtx)); +} + +static int +xmlSecOpenSSLEvpBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecOpenSSLEvpBlockCipherCtxPtr ctx; + int cipherKeyLen; + + xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != NULL, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + + keyReq->keyId = ctx->keyId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + + cipherKeyLen = EVP_CIPHER_key_length(ctx->cipher); + xmlSecAssert2(cipherKeyLen > 0, -1); + + keyReq->keyBitsSize = (xmlSecSize)(8 * cipherKeyLen); + return(0); +} + +static int +xmlSecOpenSSLEvpBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLEvpBlockCipherCtxPtr ctx; + xmlSecBufferPtr buffer; + int cipherKeyLen; + + xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1); + xmlSecAssert2(key != NULL, -1); + + ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != NULL, -1); + xmlSecAssert2(ctx->keyInitialized == 0, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); + + cipherKeyLen = EVP_CIPHER_key_length(ctx->cipher); + xmlSecAssert2(cipherKeyLen > 0, -1); + xmlSecAssert2((xmlSecSize)cipherKeyLen <= sizeof(ctx->key), -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer != NULL, -1); + + if(xmlSecBufferGetSize(buffer) < (xmlSecSize)cipherKeyLen) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "keySize=%d;expected=%d", + xmlSecBufferGetSize(buffer), cipherKeyLen); + return(-1); + } + + xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1); + memcpy(ctx->key, xmlSecBufferGetData(buffer), cipherKeyLen); + + ctx->keyInitialized = 1; + return(0); +} + +static int +xmlSecOpenSSLEvpBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLEvpBlockCipherCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + if(ctx->ctxInitialized == 0) { + ret = xmlSecOpenSSLEvpBlockCipherCtxInit(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpBlockCipherCtxInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + if((ctx->ctxInitialized == 0) && (last != 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "not enough data to initialize transform"); + return(-1); + } + + if(ctx->ctxInitialized != 0) { + ret = xmlSecOpenSSLEvpBlockCipherCtxUpdate(ctx, in, out, + xmlSecTransformGetName(transform), + transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpBlockCipherCtxUpdate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + if(last != 0) { + /* by now there should be no input */ + xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); + ret = xmlSecOpenSSLEvpBlockCipherCtxFinal(ctx, out, + xmlSecTransformGetName(transform), + transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpBlockCipherCtxFinal", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + transform->status = xmlSecTransformStatusFinished; + } + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); + } else if(transform->status == xmlSecTransformStatusNone) { + /* the only way we can get here is if there is no enough data in the input */ + xmlSecAssert2(last == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + + +#ifndef XMLSEC_NO_AES +/********************************************************************* + * + * AES CBC cipher transforms + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLAes128CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes128Cbc, /* const xmlChar* name; */ + xmlSecHrefAes128Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformAes128CbcGetKlass: + * + * AES 128 CBC encryption transform klass. + * + * Returns: pointer to AES 128 CBC encryption transform. + */ +xmlSecTransformId +xmlSecOpenSSLTransformAes128CbcGetKlass(void) { + return(&xmlSecOpenSSLAes128CbcKlass); +} + +static xmlSecTransformKlass xmlSecOpenSSLAes192CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes192Cbc, /* const xmlChar* name; */ + xmlSecHrefAes192Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformAes192CbcGetKlass: + * + * AES 192 CBC encryption transform klass. + * + * Returns: pointer to AES 192 CBC encryption transform. + */ +xmlSecTransformId +xmlSecOpenSSLTransformAes192CbcGetKlass(void) { + return(&xmlSecOpenSSLAes192CbcKlass); +} + +static xmlSecTransformKlass xmlSecOpenSSLAes256CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes256Cbc, /* const xmlChar* name; */ + xmlSecHrefAes256Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformAes256CbcGetKlass: + * + * AES 256 CBC encryption transform klass. + * + * Returns: pointer to AES 256 CBC encryption transform. + */ +xmlSecTransformId +xmlSecOpenSSLTransformAes256CbcGetKlass(void) { + return(&xmlSecOpenSSLAes256CbcKlass); +} + +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES +static xmlSecTransformKlass xmlSecOpenSSLDes3CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameDes3Cbc, /* const xmlChar* name; */ + xmlSecHrefDes3Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformDes3CbcGetKlass: + * + * Triple DES CBC encryption transform klass. + * + * Returns: pointer to Triple DES encryption transform. + */ +xmlSecTransformId +xmlSecOpenSSLTransformDes3CbcGetKlass(void) { + return(&xmlSecOpenSSLDes3CbcKlass); +} +#endif /* XMLSEC_NO_DES */ + diff --git a/src/openssl/crypto.c b/src/openssl/crypto.c new file mode 100644 index 00000000..aac8d09f --- /dev/null +++ b/src/openssl/crypto.c @@ -0,0 +1,491 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <openssl/evp.h> +#include <openssl/rand.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> +#include <xmlsec/dl.h> +#include <xmlsec/private.h> + +#include <xmlsec/openssl/app.h> +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/x509.h> + +static int xmlSecOpenSSLErrorsInit (void); + +static xmlSecCryptoDLFunctionsPtr gXmlSecOpenSSLFunctions = NULL; +static xmlChar* gXmlSecOpenSSLTrustedCertsFolder = NULL; + +/** + * xmlSecCryptoGetFunctions_openssl: + * + * Gets the pointer to xmlsec-openssl functions table. + * + * Returns: the xmlsec-openssl functions table or NULL if an error occurs. + */ +xmlSecCryptoDLFunctionsPtr +xmlSecCryptoGetFunctions_openssl(void) { + static xmlSecCryptoDLFunctions functions; + + if(gXmlSecOpenSSLFunctions != NULL) { + return(gXmlSecOpenSSLFunctions); + } + + memset(&functions, 0, sizeof(functions)); + gXmlSecOpenSSLFunctions = &functions; + + /******************************************************************** + * + * Crypto Init/shutdown + * + ********************************************************************/ + gXmlSecOpenSSLFunctions->cryptoInit = xmlSecOpenSSLInit; + gXmlSecOpenSSLFunctions->cryptoShutdown = xmlSecOpenSSLShutdown; + gXmlSecOpenSSLFunctions->cryptoKeysMngrInit = xmlSecOpenSSLKeysMngrInit; + + /******************************************************************** + * + * Key data ids + * + ********************************************************************/ +#ifndef XMLSEC_NO_AES + gXmlSecOpenSSLFunctions->keyDataAesGetKlass = xmlSecOpenSSLKeyDataAesGetKlass; +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES + gXmlSecOpenSSLFunctions->keyDataDesGetKlass = xmlSecOpenSSLKeyDataDesGetKlass; +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_DSA + gXmlSecOpenSSLFunctions->keyDataDsaGetKlass = xmlSecOpenSSLKeyDataDsaGetKlass; +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_HMAC + gXmlSecOpenSSLFunctions->keyDataHmacGetKlass = xmlSecOpenSSLKeyDataHmacGetKlass; +#endif /* XMLSEC_NO_HMAC */ + +#ifndef XMLSEC_NO_RSA + gXmlSecOpenSSLFunctions->keyDataRsaGetKlass = xmlSecOpenSSLKeyDataRsaGetKlass; +#endif /* XMLSEC_NO_RSA */ + +#ifndef XMLSEC_NO_X509 + gXmlSecOpenSSLFunctions->keyDataX509GetKlass = xmlSecOpenSSLKeyDataX509GetKlass; + gXmlSecOpenSSLFunctions->keyDataRawX509CertGetKlass = xmlSecOpenSSLKeyDataRawX509CertGetKlass; +#endif /* XMLSEC_NO_X509 */ + + /******************************************************************** + * + * Key data store ids + * + ********************************************************************/ +#ifndef XMLSEC_NO_X509 + gXmlSecOpenSSLFunctions->x509StoreGetKlass = xmlSecOpenSSLX509StoreGetKlass; +#endif /* XMLSEC_NO_X509 */ + + /******************************************************************** + * + * Crypto transforms ids + * + ********************************************************************/ + + /******************************* AES ********************************/ +#ifndef XMLSEC_NO_AES + gXmlSecOpenSSLFunctions->transformAes128CbcGetKlass = xmlSecOpenSSLTransformAes128CbcGetKlass; + gXmlSecOpenSSLFunctions->transformAes192CbcGetKlass = xmlSecOpenSSLTransformAes192CbcGetKlass; + gXmlSecOpenSSLFunctions->transformAes256CbcGetKlass = xmlSecOpenSSLTransformAes256CbcGetKlass; + gXmlSecOpenSSLFunctions->transformKWAes128GetKlass = xmlSecOpenSSLTransformKWAes128GetKlass; + gXmlSecOpenSSLFunctions->transformKWAes192GetKlass = xmlSecOpenSSLTransformKWAes192GetKlass; + gXmlSecOpenSSLFunctions->transformKWAes256GetKlass = xmlSecOpenSSLTransformKWAes256GetKlass; +#endif /* XMLSEC_NO_AES */ + + /******************************* DES ********************************/ +#ifndef XMLSEC_NO_DES + gXmlSecOpenSSLFunctions->transformDes3CbcGetKlass = xmlSecOpenSSLTransformDes3CbcGetKlass; + gXmlSecOpenSSLFunctions->transformKWDes3GetKlass = xmlSecOpenSSLTransformKWDes3GetKlass; +#endif /* XMLSEC_NO_DES */ + + /******************************* DSA ********************************/ +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 + gXmlSecOpenSSLFunctions->transformDsaSha1GetKlass = xmlSecOpenSSLTransformDsaSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + + /******************************* HMAC ********************************/ +#ifndef XMLSEC_NO_HMAC + +#ifndef XMLSEC_NO_MD5 + gXmlSecOpenSSLFunctions->transformHmacMd5GetKlass = xmlSecOpenSSLTransformHmacMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + gXmlSecOpenSSLFunctions->transformHmacRipemd160GetKlass = xmlSecOpenSSLTransformHmacRipemd160GetKlass; +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + gXmlSecOpenSSLFunctions->transformHmacSha1GetKlass = xmlSecOpenSSLTransformHmacSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + gXmlSecOpenSSLFunctions->transformHmacSha224GetKlass = xmlSecOpenSSLTransformHmacSha224GetKlass; +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecOpenSSLFunctions->transformHmacSha256GetKlass = xmlSecOpenSSLTransformHmacSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecOpenSSLFunctions->transformHmacSha384GetKlass = xmlSecOpenSSLTransformHmacSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecOpenSSLFunctions->transformHmacSha512GetKlass = xmlSecOpenSSLTransformHmacSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_HMAC */ + + /******************************* MD5 ********************************/ +#ifndef XMLSEC_NO_MD5 + gXmlSecOpenSSLFunctions->transformMd5GetKlass = xmlSecOpenSSLTransformMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + + /******************************* RIPEMD160 ********************************/ +#ifndef XMLSEC_NO_RIPEMD160 + gXmlSecOpenSSLFunctions->transformRipemd160GetKlass = xmlSecOpenSSLTransformRipemd160GetKlass; +#endif /* XMLSEC_NO_RIPEMD160 */ + + /******************************* RSA ********************************/ +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + gXmlSecOpenSSLFunctions->transformRsaMd5GetKlass = xmlSecOpenSSLTransformRsaMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + gXmlSecOpenSSLFunctions->transformRsaRipemd160GetKlass = xmlSecOpenSSLTransformRsaRipemd160GetKlass; +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + gXmlSecOpenSSLFunctions->transformRsaSha1GetKlass = xmlSecOpenSSLTransformRsaSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + gXmlSecOpenSSLFunctions->transformRsaSha224GetKlass = xmlSecOpenSSLTransformRsaSha224GetKlass; +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecOpenSSLFunctions->transformRsaSha256GetKlass = xmlSecOpenSSLTransformRsaSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecOpenSSLFunctions->transformRsaSha384GetKlass = xmlSecOpenSSLTransformRsaSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecOpenSSLFunctions->transformRsaSha512GetKlass = xmlSecOpenSSLTransformRsaSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + + gXmlSecOpenSSLFunctions->transformRsaPkcs1GetKlass = xmlSecOpenSSLTransformRsaPkcs1GetKlass; + gXmlSecOpenSSLFunctions->transformRsaOaepGetKlass = xmlSecOpenSSLTransformRsaOaepGetKlass; +#endif /* XMLSEC_NO_RSA */ + + /******************************* SHA ********************************/ +#ifndef XMLSEC_NO_SHA1 + gXmlSecOpenSSLFunctions->transformSha1GetKlass = xmlSecOpenSSLTransformSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + gXmlSecOpenSSLFunctions->transformSha224GetKlass = xmlSecOpenSSLTransformSha224GetKlass; +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecOpenSSLFunctions->transformSha256GetKlass = xmlSecOpenSSLTransformSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecOpenSSLFunctions->transformSha384GetKlass = xmlSecOpenSSLTransformSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecOpenSSLFunctions->transformSha512GetKlass = xmlSecOpenSSLTransformSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + + /******************************************************************** + * + * High level routines form xmlsec command line utility + * + ********************************************************************/ + gXmlSecOpenSSLFunctions->cryptoAppInit = xmlSecOpenSSLAppInit; + gXmlSecOpenSSLFunctions->cryptoAppShutdown = xmlSecOpenSSLAppShutdown; + gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrInit = xmlSecOpenSSLAppDefaultKeysMngrInit; + gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecOpenSSLAppDefaultKeysMngrAdoptKey; + gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecOpenSSLAppDefaultKeysMngrLoad; + gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrSave = xmlSecOpenSSLAppDefaultKeysMngrSave; +#ifndef XMLSEC_NO_X509 + gXmlSecOpenSSLFunctions->cryptoAppKeysMngrCertLoad = xmlSecOpenSSLAppKeysMngrCertLoad; + gXmlSecOpenSSLFunctions->cryptoAppKeysMngrCertLoadMemory = xmlSecOpenSSLAppKeysMngrCertLoadMemory; + gXmlSecOpenSSLFunctions->cryptoAppPkcs12Load = xmlSecOpenSSLAppPkcs12Load; + gXmlSecOpenSSLFunctions->cryptoAppPkcs12LoadMemory = xmlSecOpenSSLAppPkcs12LoadMemory; + gXmlSecOpenSSLFunctions->cryptoAppKeyCertLoad = xmlSecOpenSSLAppKeyCertLoad; + gXmlSecOpenSSLFunctions->cryptoAppKeyCertLoadMemory = xmlSecOpenSSLAppKeyCertLoadMemory; +#endif /* XMLSEC_NO_X509 */ + gXmlSecOpenSSLFunctions->cryptoAppKeyLoad = xmlSecOpenSSLAppKeyLoad; + gXmlSecOpenSSLFunctions->cryptoAppKeyLoadMemory = xmlSecOpenSSLAppKeyLoadMemory; + gXmlSecOpenSSLFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecOpenSSLAppGetDefaultPwdCallback(); + + return(gXmlSecOpenSSLFunctions); +} + +/** + * xmlSecOpenSSLInit: + * + * XMLSec library specific crypto engine initialization. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLInit (void) { + /* Check loaded xmlsec library version */ + if(xmlSecCheckVersionExact() != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCheckVersionExact", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if(xmlSecOpenSSLErrorsInit() < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLErrorsInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* register our klasses */ + if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_openssl()) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLShutdown: + * + * XMLSec library specific crypto engine shutdown. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLShutdown(void) { + xmlSecOpenSSLSetDefaultTrustedCertsFolder(NULL); + return(0); +} + +/** + * xmlSecOpenSSLKeysMngrInit: + * @mngr: the pointer to keys manager. + * + * Adds OpenSSL specific key data stores in keys manager. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLKeysMngrInit(xmlSecKeysMngrPtr mngr) { + int ret; + + xmlSecAssert2(mngr != NULL, -1); + +#ifndef XMLSEC_NO_X509 + /* create x509 store if needed */ + if(xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId) == NULL) { + xmlSecKeyDataStorePtr x509Store; + + x509Store = xmlSecKeyDataStoreCreate(xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataStoreCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecOpenSSLX509StoreId"); + return(-1); + } + + ret = xmlSecKeysMngrAdoptDataStore(mngr, x509Store); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrAdoptDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataStoreDestroy(x509Store); + return(-1); + } + } +#endif /* XMLSEC_NO_X509 */ + return(0); +} + +/** + * xmlSecOpenSSLGenerateRandom: + * @buffer: the destination buffer. + * @size: the numer of bytes to generate. + * + * Generates @size random bytes and puts result in @buffer. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLGenerateRandom(xmlSecBufferPtr buffer, xmlSecSize size) { + int ret; + + xmlSecAssert2(buffer != NULL, -1); + xmlSecAssert2(size > 0, -1); + + ret = xmlSecBufferSetSize(buffer, size); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", size); + return(-1); + } + + /* get random data */ + ret = RAND_bytes((xmlSecByte*)xmlSecBufferGetData(buffer), size); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "RAND_bytes", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", size); + return(-1); + } + return(0); +} + +/** + * xmlSecOpenSSLErrorsDefaultCallback: + * @file: the error location file name (__FILE__ macro). + * @line: the error location line number (__LINE__ macro). + * @func: the error location function name (__FUNCTION__ macro). + * @errorObject: the error specific error object + * @errorSubject: the error specific error subject. + * @reason: the error code. + * @msg: the additional error message. + * + * The default OpenSSL errors reporting callback function. + */ +void +xmlSecOpenSSLErrorsDefaultCallback(const char* file, int line, const char* func, + const char* errorObject, const char* errorSubject, + int reason, const char* msg) { + + ERR_put_error(XMLSEC_OPENSSL_ERRORS_LIB, + XMLSEC_OPENSSL_ERRORS_FUNCTION, + reason, file, line); + xmlSecErrorsDefaultCallback(file, line, func, + errorObject, errorSubject, + reason, msg); +} + +static int +xmlSecOpenSSLErrorsInit(void) { + static ERR_STRING_DATA xmlSecOpenSSLStrReasons[XMLSEC_ERRORS_MAX_NUMBER + 1]; + static ERR_STRING_DATA xmlSecOpenSSLStrLib[]= { + { ERR_PACK(XMLSEC_OPENSSL_ERRORS_LIB,0,0), "xmlsec routines"}, + { 0, NULL} + }; + static ERR_STRING_DATA xmlSecOpenSSLStrDefReason[]= { + { XMLSEC_OPENSSL_ERRORS_LIB, "xmlsec lib"}, + { 0, NULL} + }; + xmlSecSize pos; + + /* initialize reasons array */ + memset(xmlSecOpenSSLStrReasons, 0, sizeof(xmlSecOpenSSLStrReasons)); + for(pos = 0; (pos < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(pos) != NULL); ++pos) { + xmlSecOpenSSLStrReasons[pos].error = xmlSecErrorsGetCode(pos); + xmlSecOpenSSLStrReasons[pos].string = xmlSecErrorsGetMsg(pos); + } + + /* finally load xmlsec strings in OpenSSL */ + ERR_load_strings(XMLSEC_OPENSSL_ERRORS_LIB, xmlSecOpenSSLStrLib); /* define xmlsec lib name */ + ERR_load_strings(XMLSEC_OPENSSL_ERRORS_LIB, xmlSecOpenSSLStrDefReason); /* define default reason */ + ERR_load_strings(XMLSEC_OPENSSL_ERRORS_LIB, xmlSecOpenSSLStrReasons); + + /* and set default errors callback for xmlsec to us */ + xmlSecErrorsSetCallback(xmlSecOpenSSLErrorsDefaultCallback); + + return(0); +} + +/** + * xmlSecOpenSSLSetDefaultTrustedCertsFolder: + * @path: the default trusted certs path. + * + * Sets the default trusted certs folder. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLSetDefaultTrustedCertsFolder(const xmlChar* path) { + if(gXmlSecOpenSSLTrustedCertsFolder != NULL) { + xmlFree(gXmlSecOpenSSLTrustedCertsFolder); + gXmlSecOpenSSLTrustedCertsFolder = NULL; + } + + if(path != NULL) { + gXmlSecOpenSSLTrustedCertsFolder = xmlStrdup(BAD_CAST path); + if(gXmlSecOpenSSLTrustedCertsFolder == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlStrdup", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + return(0); +} + +/** + * xmlSecOpenSSLGetDefaultTrustedCertsFolder: + * + * Gets the default trusted certs folder. + * + * Returns: the default trusted cert folder. + */ +const xmlChar* +xmlSecOpenSSLGetDefaultTrustedCertsFolder(void) { + return(gXmlSecOpenSSLTrustedCertsFolder); +} + + + diff --git a/src/openssl/digests.c b/src/openssl/digests.c new file mode 100644 index 00000000..2dc32369 --- /dev/null +++ b/src/openssl/digests.c @@ -0,0 +1,682 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <openssl/evp.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> + +/************************************************************************** + * + * Internal OpenSSL Digest CTX + * + *****************************************************************************/ +typedef struct _xmlSecOpenSSLDigestCtx xmlSecOpenSSLDigestCtx, *xmlSecOpenSSLDigestCtxPtr; +struct _xmlSecOpenSSLDigestCtx { + const EVP_MD* digest; + EVP_MD_CTX digestCtx; + xmlSecByte dgst[EVP_MAX_MD_SIZE]; + xmlSecSize dgstSize; /* dgst size in bytes */ +}; + +/****************************************************************************** + * + * EVP Digest transforms + * + * xmlSecOpenSSLDigestCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecOpenSSLEvpDigestSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLDigestCtx)) +#define xmlSecOpenSSLEvpDigestGetCtx(transform) \ + ((xmlSecOpenSSLDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + + +static int xmlSecOpenSSLEvpDigestInitialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLEvpDigestFinalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLEvpDigestVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLEvpDigestExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLEvpDigestCheckId (xmlSecTransformPtr transform); + +static int +xmlSecOpenSSLEvpDigestCheckId(xmlSecTransformPtr transform) { + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformMd5Id)) { + return(1); + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRipemd160Id)) { + return(1); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha224Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha256Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha384Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA512 */ + + + { + return(0); + } + + return(0); +} + +static int +xmlSecOpenSSLEvpDigestInitialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLDigestCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLEvpDigestCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize), -1); + + ctx = xmlSecOpenSSLEvpDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + /* initialize context */ + memset(ctx, 0, sizeof(xmlSecOpenSSLDigestCtx)); + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformMd5Id)) { + ctx->digest = EVP_md5(); + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRipemd160Id)) { + ctx->digest = EVP_ripemd160(); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha1Id)) { + ctx->digest = EVP_sha1(); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha224Id)) { + ctx->digest = EVP_sha224(); + } else +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha256Id)) { + ctx->digest = EVP_sha256(); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha384Id)) { + ctx->digest = EVP_sha384(); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha512Id)) { + ctx->digest = EVP_sha512(); + } else +#endif /* XMLSEC_NO_SHA512 */ + + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifndef XMLSEC_OPENSSL_096 + EVP_MD_CTX_init(&(ctx->digestCtx)); +#endif /* XMLSEC_OPENSSL_096 */ + + return(0); +} + +static void +xmlSecOpenSSLEvpDigestFinalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLDigestCtxPtr ctx; + + xmlSecAssert(xmlSecOpenSSLEvpDigestCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize)); + + ctx = xmlSecOpenSSLEvpDigestGetCtx(transform); + xmlSecAssert(ctx != NULL); + +#ifndef XMLSEC_OPENSSL_096 + EVP_MD_CTX_cleanup(&(ctx->digestCtx)); +#endif /* XMLSEC_OPENSSL_096 */ + memset(ctx, 0, sizeof(xmlSecOpenSSLDigestCtx)); +} + +static int +xmlSecOpenSSLEvpDigestVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLDigestCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLEvpDigestCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLEvpDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->dgstSize > 0, -1); + + if(dataSize != ctx->dgstSize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "data_size=%d;dgst_size=%d", + dataSize, ctx->dgstSize); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + if(memcmp(ctx->dgst, data, ctx->dgstSize) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data and digest do not match"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + transform->status = xmlSecTransformStatusOk; + return(0); +} + +static int +xmlSecOpenSSLEvpDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLDigestCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecOpenSSLEvpDigestCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + in = &(transform->inBuf); + xmlSecAssert2(in != NULL, -1); + + out = &(transform->outBuf); + xmlSecAssert2(out != NULL, -1); + + ctx = xmlSecOpenSSLEvpDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digest != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_DigestInit(&(ctx->digestCtx), ctx->digest); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_DigestInit", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_DigestInit(&(ctx->digestCtx), ctx->digest); +#endif /* XMLSEC_OPENSSL_096 */ + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + xmlSecSize inSize; + + inSize = xmlSecBufferGetSize(in); + if(inSize > 0) { +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_DigestUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_DigestUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", inSize); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_DigestUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize); +#endif /* XMLSEC_OPENSSL_096 */ + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + } + if(last) { + unsigned int dgstSize; + + xmlSecAssert2((xmlSecSize)EVP_MD_size(ctx->digest) <= sizeof(ctx->dgst), -1); + +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_DigestFinal(&(ctx->digestCtx), ctx->dgst, &dgstSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_DigestFinal", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_DigestFinal(&(ctx->digestCtx), ctx->dgst, &dgstSize); +#endif /* XMLSEC_OPENSSL_096 */ + xmlSecAssert2(dgstSize > 0, -1); + ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize); + + /* copy result to output */ + if(transform->operation == xmlSecTransformOperationSign) { + ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferAppend", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", ctx->dgstSize); + return(-1); + } + } + transform->status = xmlSecTransformStatusFinished; + } + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + + +#ifndef XMLSEC_NO_MD5 +/****************************************************************************** + * + * MD5 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLMd5Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameMd5, /* const xmlChar* name; */ + xmlSecHrefMd5, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformMd5GetKlass: + * + * MD5 digest transform klass. + * + * Returns: pointer to MD5 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformMd5GetKlass(void) { + return(&xmlSecOpenSSLMd5Klass); +} +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 +/****************************************************************************** + * + * RIPEMD160 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRipemd160Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameRipemd160, /* const xmlChar* name; */ + xmlSecHrefRipemd160, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRipemd160GetKlass: + * + * RIPEMD-160 digest transform klass. + * + * Returns: pointer to RIPEMD-160 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRipemd160GetKlass(void) { + return(&xmlSecOpenSSLRipemd160Klass); +} +#endif /* XMLSEC_NO_RIPEMD160 */ + + +#ifndef XMLSEC_NO_SHA1 +/****************************************************************************** + * + * SHA1 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameSha1, /* const xmlChar* name; */ + xmlSecHrefSha1, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformSha1GetKlass: + * + * SHA-1 digest transform klass. + * + * Returns: pointer to SHA-1 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformSha1GetKlass(void) { + return(&xmlSecOpenSSLSha1Klass); +} +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 +/****************************************************************************** + * + * SHA224 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLSha224Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameSha224, /* const xmlChar* name; */ + xmlSecHrefSha224, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformSha224GetKlass: + * + * SHA-224 digest transform klass. + * + * Returns: pointer to SHA-224 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformSha224GetKlass(void) { + return(&xmlSecOpenSSLSha224Klass); +} +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 +/****************************************************************************** + * + * SHA256 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameSha256, /* const xmlChar* name; */ + xmlSecHrefSha256, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformSha256GetKlass: + * + * SHA-256 digest transform klass. + * + * Returns: pointer to SHA-256 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformSha256GetKlass(void) { + return(&xmlSecOpenSSLSha256Klass); +} +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 +/****************************************************************************** + * + * SHA384 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLSha384Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameSha384, /* const xmlChar* name; */ + xmlSecHrefSha384, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformSha384GetKlass: + * + * SHA-384 digest transform klass. + * + * Returns: pointer to SHA-384 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformSha384GetKlass(void) { + return(&xmlSecOpenSSLSha384Klass); +} +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 +/****************************************************************************** + * + * SHA512 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLSha512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */ + + xmlSecNameSha512, /* const xmlChar* name; */ + xmlSecHrefSha512, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformSha512GetKlass: + * + * SHA-512 digest transform klass. + * + * Returns: pointer to SHA-512 digest transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformSha512GetKlass(void) { + return(&xmlSecOpenSSLSha512Klass); +} +#endif /* XMLSEC_NO_SHA512 */ + diff --git a/src/openssl/evp.c b/src/openssl/evp.c new file mode 100644 index 00000000..e48defd3 --- /dev/null +++ b/src/openssl/evp.c @@ -0,0 +1,1559 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <openssl/evp.h> +#include <openssl/rand.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/bn.h> +#include <xmlsec/openssl/evp.h> + +/************************************************************************** + * + * Internal OpenSSL EVP key CTX + * + *************************************************************************/ +typedef struct _xmlSecOpenSSLEvpKeyDataCtx xmlSecOpenSSLEvpKeyDataCtx, + *xmlSecOpenSSLEvpKeyDataCtxPtr; +struct _xmlSecOpenSSLEvpKeyDataCtx { + EVP_PKEY* pKey; +}; + +/****************************************************************************** + * + * EVP key (dsa/rsa) + * + * xmlSecOpenSSLEvpKeyDataCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecOpenSSLEvpKeyDataSize \ + (sizeof(xmlSecKeyData) + sizeof(xmlSecOpenSSLEvpKeyDataCtx)) +#define xmlSecOpenSSLEvpKeyDataGetCtx(data) \ + ((xmlSecOpenSSLEvpKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData))) + +static int xmlSecOpenSSLEvpKeyDataInitialize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLEvpKeyDataDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecOpenSSLEvpKeyDataFinalize (xmlSecKeyDataPtr data); + +/** + * xmlSecOpenSSLEvpKeyDataAdoptEvp: + * @data: the pointer to OpenSSL EVP key data. + * @pKey: the pointer to EVP key. + * + * Sets the value of key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLEvpKeyDataAdoptEvp(xmlSecKeyDataPtr data, EVP_PKEY* pKey) { + xmlSecOpenSSLEvpKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize), -1); + xmlSecAssert2(pKey != NULL, -1); + + ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + if(ctx->pKey != NULL) { + EVP_PKEY_free(ctx->pKey); + } + ctx->pKey = pKey; + return(0); +} + +/** + * xmlSecOpenSSLEvpKeyDataGetEvp: + * @data: the pointer to OpenSSL EVP data. + * + * Gets the EVP_PKEY from the key data. + * + * Returns: pointer to EVP_PKEY or NULL if an error occurs. + */ +EVP_PKEY* +xmlSecOpenSSLEvpKeyDataGetEvp(xmlSecKeyDataPtr data) { + xmlSecOpenSSLEvpKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize), NULL); + + ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, NULL); + + return(ctx->pKey); +} + +static int +xmlSecOpenSSLEvpKeyDataInitialize(xmlSecKeyDataPtr data) { + xmlSecOpenSSLEvpKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize), -1); + + ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLEvpKeyDataCtx)); + + return(0); +} + +static int +xmlSecOpenSSLEvpKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecOpenSSLEvpKeyDataCtxPtr ctxDst; + xmlSecOpenSSLEvpKeyDataCtxPtr ctxSrc; + + xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecOpenSSLEvpKeyDataSize), -1); + xmlSecAssert2(xmlSecKeyDataIsValid(src), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecOpenSSLEvpKeyDataSize), -1); + + ctxDst = xmlSecOpenSSLEvpKeyDataGetCtx(dst); + xmlSecAssert2(ctxDst != NULL, -1); + xmlSecAssert2(ctxDst->pKey == NULL, -1); + + ctxSrc = xmlSecOpenSSLEvpKeyDataGetCtx(src); + xmlSecAssert2(ctxSrc != NULL, -1); + + if(ctxSrc->pKey != NULL) { + ctxDst->pKey = xmlSecOpenSSLEvpKeyDup(ctxSrc->pKey); + if(ctxDst->pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "xmlSecOpenSSLEvpKeyDup", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + return(0); +} + +static void +xmlSecOpenSSLEvpKeyDataFinalize(xmlSecKeyDataPtr data) { + xmlSecOpenSSLEvpKeyDataCtxPtr ctx; + + xmlSecAssert(xmlSecKeyDataIsValid(data)); + xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize)); + + ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data); + xmlSecAssert(ctx != NULL); + + if(ctx->pKey != NULL) { + EVP_PKEY_free(ctx->pKey); + } + memset(ctx, 0, sizeof(xmlSecOpenSSLEvpKeyDataCtx)); +} + +/****************************************************************************** + * + * EVP helper functions + * + *****************************************************************************/ +/** + * xmlSecOpenSSLEvpKeyDup: + * @pKey: the pointer to EVP_PKEY. + * + * Duplicates @pKey. + * + * Returns: pointer to newly created EVP_PKEY object or NULL if an error occurs. + */ +EVP_PKEY* +xmlSecOpenSSLEvpKeyDup(EVP_PKEY* pKey) { + int ret; + + xmlSecAssert2(pKey != NULL, NULL); + + ret = CRYPTO_add(&pKey->references,1,CRYPTO_LOCK_EVP_PKEY); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CRYPTO_add", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + return(pKey); +} + +/** + * xmlSecOpenSSLEvpKeyAdopt: + * @pKey: the pointer to EVP_PKEY. + * + * Creates xmlsec key object from OpenSSL key object. + * + * Returns: pointer to newly created xmlsec key or NULL if an error occurs. + */ +xmlSecKeyDataPtr +xmlSecOpenSSLEvpKeyAdopt(EVP_PKEY *pKey) { + xmlSecKeyDataPtr data = NULL; + int ret; + + xmlSecAssert2(pKey != NULL, NULL); + + switch(pKey->type) { +#ifndef XMLSEC_NO_RSA + case EVP_PKEY_RSA: + data = xmlSecKeyDataCreate(xmlSecOpenSSLKeyDataRsaId); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecOpenSSLKeyDataRsaId"); + return(NULL); + } + break; +#endif /* XMLSEC_NO_RSA */ +#ifndef XMLSEC_NO_DSA + case EVP_PKEY_DSA: + data = xmlSecKeyDataCreate(xmlSecOpenSSLKeyDataDsaId); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecOpenSSLKeyDataDsaId"); + return(NULL); + } + break; +#endif /* XMLSEC_NO_DSA */ + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_TYPE, + "evp key type %d not supported", pKey->type); + return(NULL); + } + + xmlSecAssert2(data != NULL, NULL); + ret = xmlSecOpenSSLEvpKeyDataAdoptEvp(data, pKey); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLEvpKeyDataAdoptEvp", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(data); + return(NULL); + } + return(data); +} + +#ifndef XMLSEC_NO_DSA +/************************************************************************** + * + * <dsig:DSAKeyValue> processing + * + * + * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue) + * + * DSA keys and the DSA signature algorithm are specified in [DSS]. + * DSA public key values can have the following fields: + * + * * P - a prime modulus meeting the [DSS] requirements + * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime + * divisor of P-1 + * * G - an integer with certain properties with respect to P and Q + * * Y - G**X mod P (where X is part of the private key and not made + * public) + * * J - (P - 1) / Q + * * seed - a DSA prime generation seed + * * pgenCounter - a DSA prime generation counter + * + * Parameter J is available for inclusion solely for efficiency as it is + * calculatable from P and Q. Parameters seed and pgenCounter are used in the + * DSA prime number generation algorithm specified in [DSS]. As such, they are + * optional but must either both be present or both be absent. This prime + * generation algorithm is designed to provide assurance that a weak prime is + * not being used and it yields a P and Q value. Parameters P, Q, and G can be + * public and common to a group of users. They might be known from application + * context. As such, they are optional but P and Q must either both appear or + * both be absent. If all of P, Q, seed, and pgenCounter are present, + * implementations are not required to check if they are consistent and are + * free to use either P and Q or seed and pgenCounter. All parameters are + * encoded as base64 [MIME] values. + * + * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are + * represented in XML as octet strings as defined by the ds:CryptoBinary type. + * + * Schema Definition: + * + * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/> + * <complexType name="DSAKeyValueType"> + * <sequence> + * <sequence minOccurs="0"> + * <element name="P" type="ds:CryptoBinary"/> + * <element name="Q" type="ds:CryptoBinary"/> + * </sequence> + * <element name="G" type="ds:CryptoBinary" minOccurs="0"/> + * <element name="Y" type="ds:CryptoBinary"/> + * <element name="J" type="ds:CryptoBinary" minOccurs="0"/> + * <sequence minOccurs="0"> + * <element name="Seed" type="ds:CryptoBinary"/> + * <element name="PgenCounter" type="ds:CryptoBinary"/> + * </sequence> + * </sequence> + * </complexType> + * + * DTD Definition: + * + * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) > + * <!ELEMENT P (#PCDATA) > + * <!ELEMENT Q (#PCDATA) > + * <!ELEMENT G (#PCDATA) > + * <!ELEMENT Y (#PCDATA) > + * <!ELEMENT J (#PCDATA) > + * <!ELEMENT Seed (#PCDATA) > + * <!ELEMENT PgenCounter (#PCDATA) > + * + * ============================================================================ + * + * To support reading/writing private keys an X element added (before Y). + * todo: The current implementation does not support Seed and PgenCounter! + * by this the P, Q and G are *required*! + * + *************************************************************************/ +static int xmlSecOpenSSLKeyDataDsaInitialize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLKeyDataDsaDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecOpenSSLKeyDataDsaFinalize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLKeyDataDsaXmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLKeyDataDsaXmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLKeyDataDsaGenerate (xmlSecKeyDataPtr data, + xmlSecSize sizeBits, + xmlSecKeyDataType type); + +static xmlSecKeyDataType xmlSecOpenSSLKeyDataDsaGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecOpenSSLKeyDataDsaGetSize (xmlSecKeyDataPtr data); +static void xmlSecOpenSSLKeyDataDsaDebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecOpenSSLKeyDataDsaDebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); + +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataDsaKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecOpenSSLEvpKeyDataSize, + + /* data */ + xmlSecNameDSAKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefDSAKeyValue, /* const xmlChar* href; */ + xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecOpenSSLKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecOpenSSLKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecOpenSSLKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecOpenSSLKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecOpenSSLKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecOpenSSLKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecOpenSSLKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecOpenSSLKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + NULL, /* xmlSecKeyDataBinReadMethod binRead; */ + NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecOpenSSLKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecOpenSSLKeyDataDsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataDsaGetKlass: + * + * The DSA key data klass. + * + * Returns: pointer to DSA key data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataDsaGetKlass(void) { + return(&xmlSecOpenSSLKeyDataDsaKlass); +} + +/** + * xmlSecOpenSSLKeyDataDsaAdoptDsa: + * @data: the pointer to DSA key data. + * @dsa: the pointer to OpenSSL DSA key. + * + * Sets the value of DSA key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLKeyDataDsaAdoptDsa(xmlSecKeyDataPtr data, DSA* dsa) { + EVP_PKEY* pKey = NULL; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1); + + /* construct new EVP_PKEY */ + if(dsa != NULL) { + pKey = EVP_PKEY_new(); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "EVP_PKEY_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = EVP_PKEY_assign_DSA(pKey, dsa); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "EVP_PKEY_assign_DSA", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + ret = xmlSecOpenSSLKeyDataDsaAdoptEvp(data, pKey); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataDsaAdoptEvp", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + if(pKey != NULL) { + EVP_PKEY_free(pKey); + } + return(-1); + } + return(0); +} + +/** + * xmlSecOpenSSLKeyDataDsaGetDsa: + * @data: the pointer to DSA key data. + * + * Gets the OpenSSL DSA key from DSA key data. + * + * Returns: pointer to OpenSSL DSA key or NULL if an error occurs. + */ +DSA* +xmlSecOpenSSLKeyDataDsaGetDsa(xmlSecKeyDataPtr data) { + EVP_PKEY* pKey; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), NULL); + + pKey = xmlSecOpenSSLKeyDataDsaGetEvp(data); + xmlSecAssert2((pKey == NULL) || (pKey->type == EVP_PKEY_DSA), NULL); + + return((pKey != NULL) ? pKey->pkey.dsa : (DSA*)NULL); +} + +/** + * xmlSecOpenSSLKeyDataDsaAdoptEvp: + * @data: the pointer to DSA key data. + * @pKey: the pointer to OpenSSL EVP key. + * + * Sets the DSA key data value to OpenSSL EVP key. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLKeyDataDsaAdoptEvp(xmlSecKeyDataPtr data, EVP_PKEY* pKey) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1); + xmlSecAssert2(pKey != NULL, -1); + xmlSecAssert2(pKey->type == EVP_PKEY_DSA, -1); + + return(xmlSecOpenSSLEvpKeyDataAdoptEvp(data, pKey)); +} + +/** + * xmlSecOpenSSLKeyDataDsaGetEvp: + * @data: the pointer to DSA key data. + * + * Gets the OpenSSL EVP key from DSA key data. + * + * Returns: pointer to OpenSSL EVP key or NULL if an error occurs. + */ +EVP_PKEY* +xmlSecOpenSSLKeyDataDsaGetEvp(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), NULL); + + return(xmlSecOpenSSLEvpKeyDataGetEvp(data)); +} + +static int +xmlSecOpenSSLKeyDataDsaInitialize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1); + + return(xmlSecOpenSSLEvpKeyDataInitialize(data)); +} + +static int +xmlSecOpenSSLKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecOpenSSLKeyDataDsaId), -1); + xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecOpenSSLKeyDataDsaId), -1); + + return(xmlSecOpenSSLEvpKeyDataDuplicate(dst, src)); +} + +static void +xmlSecOpenSSLKeyDataDsaFinalize(xmlSecKeyDataPtr data) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId)); + + xmlSecOpenSSLEvpKeyDataFinalize(data); +} + +static int +xmlSecOpenSSLKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataPtr data; + xmlNodePtr cur; + DSA *dsa; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataDsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + if(xmlSecKeyGetValue(key) != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + dsa = DSA_new(); + if(dsa == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "DSA_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecGetNextElementNode(node->children); + + /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + DSA_free(dsa); + return(-1); + } + if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->p)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + DSA_free(dsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + DSA_free(dsa); + return(-1); + } + if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->q)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + DSA_free(dsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + DSA_free(dsa); + return(-1); + } + if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->g)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + DSA_free(dsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) { + /* next is X node. It is REQUIRED for private key but + * we are not sure exactly what do we read */ + if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->priv_key)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAX)); + DSA_free(dsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + /* next is Y node. */ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAY)); + DSA_free(dsa); + return(-1); + } + if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->pub_key)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY)); + DSA_free(dsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* todo: add support for J */ + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) { + cur = xmlSecGetNextElementNode(cur->next); + } + + /* todo: add support for seed */ + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) { + cur = xmlSecGetNextElementNode(cur->next); + } + + /* todo: add support for pgencounter */ + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) { + cur = xmlSecGetNextElementNode(cur->next); + } + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + DSA_free(dsa); + return(-1); + } + + data = xmlSecKeyDataCreate(id); + if(data == NULL ) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + DSA_free(dsa); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataDsaAdoptDsa(data, dsa); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataDsaAdoptDsa", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(data); + DSA_free(dsa); + return(-1); + } + + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(data); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlNodePtr cur; + DSA* dsa; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataDsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataDsaId), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + dsa = xmlSecOpenSSLKeyDataDsaGetDsa(xmlSecKeyGetValue(key)); + xmlSecAssert2(dsa != NULL, -1); + + if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) { + /* we can have only private key or public key */ + return(0); + } + + /* first is P node */ + xmlSecAssert2(dsa->p != NULL, -1); + cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->p, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + return(-1); + } + + /* next is Q node. */ + xmlSecAssert2(dsa->q != NULL, -1); + cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->q, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + return(-1); + } + + /* next is G node. */ + xmlSecAssert2(dsa->g != NULL, -1); + cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->g, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + return(-1); + } + + /* next is X node: write it ONLY for private keys and ONLY if it is requested */ + if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (dsa->priv_key != NULL)) { + cur = xmlSecAddChild(node, xmlSecNodeDSAX, xmlSecNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAX)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->priv_key, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAX)); + return(-1); + } + } + + /* next is Y node. */ + xmlSecAssert2(dsa->pub_key != NULL, -1); + cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAY)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->pub_key, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAY)); + return(-1); + } + return(0); +} + +static int +xmlSecOpenSSLKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + DSA* dsa; + int counter_ret; + unsigned long h_ret; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1); + xmlSecAssert2(sizeBits > 0, -1); + + dsa = DSA_generate_parameters(sizeBits, NULL, 0, &counter_ret, &h_ret, NULL, NULL); + if(dsa == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "DSA_generate_parameters", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", sizeBits); + return(-1); + } + + ret = DSA_generate_key(dsa); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "DSA_generate_key", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + DSA_free(dsa); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataDsaAdoptDsa(data, dsa); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataDsaAdoptDsa", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + DSA_free(dsa); + return(-1); + } + + return(0); +} + +static xmlSecKeyDataType +xmlSecOpenSSLKeyDataDsaGetType(xmlSecKeyDataPtr data) { + DSA* dsa; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), xmlSecKeyDataTypeUnknown); + + dsa = xmlSecOpenSSLKeyDataDsaGetDsa(data); + if((dsa != NULL) && (dsa->p != NULL) && (dsa->q != NULL) && + (dsa->g != NULL) && (dsa->pub_key != NULL)) { + + if(dsa->priv_key != NULL) { + return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic); + } else if(dsa->engine != NULL) { + /* + * !!! HACK !!! Also see RSA key + * We assume here that engine *always* has private key. + * This might be incorrect but it seems that there is no + * way to ask engine if given key is private or not. + */ + return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic); + } else { + return(xmlSecKeyDataTypePublic); + } + } + + return(xmlSecKeyDataTypeUnknown); +} + +static xmlSecSize +xmlSecOpenSSLKeyDataDsaGetSize(xmlSecKeyDataPtr data) { + DSA* dsa; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), 0); + + dsa = xmlSecOpenSSLKeyDataDsaGetDsa(data); + if((dsa != NULL) && (dsa->p != NULL)) { + return(BN_num_bits(dsa->p)); + } + return(0); +} + +static void +xmlSecOpenSSLKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "=== dsa key: size = %d\n", + xmlSecOpenSSLKeyDataDsaGetSize(data)); +} + +static void +xmlSecOpenSSLKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "<DSAKeyValue size=\"%d\" />\n", + xmlSecOpenSSLKeyDataDsaGetSize(data)); +} + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA +/************************************************************************** + * + * <dsig:RSAKeyValue> processing + * + * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue + * The RSAKeyValue Element + * + * RSA key values have two fields: Modulus and Exponent. + * + * <RSAKeyValue> + * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W + * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV + * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= + * </Modulus> + * <Exponent>AQAB</Exponent> + * </RSAKeyValue> + * + * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are + * represented in XML as octet strings as defined by the ds:CryptoBinary type. + * + * Schema Definition: + * + * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/> + * <complexType name="RSAKeyValueType"> + * <sequence> + * <element name="Modulus" type="ds:CryptoBinary"/> + * <element name="Exponent" type="ds:CryptoBinary"/> + * </sequence> + * </complexType> + * + * DTD Definition: + * + * <!ELEMENT RSAKeyValue (Modulus, Exponent) > + * <!ELEMENT Modulus (#PCDATA) > + * <!ELEMENT Exponent (#PCDATA) > + * + * ============================================================================ + * + * To support reading/writing private keys an PrivateExponent element is added + * to the end + * + *************************************************************************/ + +static int xmlSecOpenSSLKeyDataRsaInitialize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLKeyDataRsaDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecOpenSSLKeyDataRsaFinalize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLKeyDataRsaXmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLKeyDataRsaXmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLKeyDataRsaGenerate (xmlSecKeyDataPtr data, + xmlSecSize sizeBits, + xmlSecKeyDataType type); + +static xmlSecKeyDataType xmlSecOpenSSLKeyDataRsaGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecOpenSSLKeyDataRsaGetSize (xmlSecKeyDataPtr data); +static void xmlSecOpenSSLKeyDataRsaDebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecOpenSSLKeyDataRsaDebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataRsaKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecOpenSSLEvpKeyDataSize, + + /* data */ + xmlSecNameRSAKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefRSAKeyValue, /* const xmlChar* href; */ + xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecOpenSSLKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecOpenSSLKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecOpenSSLKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecOpenSSLKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecOpenSSLKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecOpenSSLKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecOpenSSLKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecOpenSSLKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + NULL, /* xmlSecKeyDataBinReadMethod binRead; */ + NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecOpenSSLKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecOpenSSLKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataRsaGetKlass: + * + * The OpenSSL RSA key data klass. + * + * Returns: pointer to OpenSSL RSA key data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataRsaGetKlass(void) { + return(&xmlSecOpenSSLKeyDataRsaKlass); +} + +/** + * xmlSecOpenSSLKeyDataRsaAdoptRsa: + * @data: the pointer to RSA key data. + * @rsa: the pointer to OpenSSL RSA key. + * + * Sets the value of RSA key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLKeyDataRsaAdoptRsa(xmlSecKeyDataPtr data, RSA* rsa) { + EVP_PKEY* pKey = NULL; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1); + + /* construct new EVP_PKEY */ + if(rsa != NULL) { + pKey = EVP_PKEY_new(); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "EVP_PKEY_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = EVP_PKEY_assign_RSA(pKey, rsa); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "EVP_PKEY_assign_RSA", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + ret = xmlSecOpenSSLKeyDataRsaAdoptEvp(data, pKey); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataRsaAdoptEvp", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + if(pKey != NULL) { + EVP_PKEY_free(pKey); + } + return(-1); + } + return(0); +} + +/** + * xmlSecOpenSSLKeyDataRsaGetRsa: + * @data: the pointer to RSA key data. + * + * Gets the OpenSSL RSA key from RSA key data. + * + * Returns: pointer to OpenSSL RSA key or NULL if an error occurs. + */ +RSA* +xmlSecOpenSSLKeyDataRsaGetRsa(xmlSecKeyDataPtr data) { + EVP_PKEY* pKey; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), NULL); + + pKey = xmlSecOpenSSLKeyDataRsaGetEvp(data); + xmlSecAssert2((pKey == NULL) || (pKey->type == EVP_PKEY_RSA), NULL); + + return((pKey != NULL) ? pKey->pkey.rsa : (RSA*)NULL); +} + +/** + * xmlSecOpenSSLKeyDataRsaAdoptEvp: + * @data: the pointer to RSA key data. + * @pKey: the pointer to OpenSSL EVP key. + * + * Sets the RSA key data value to OpenSSL EVP key. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLKeyDataRsaAdoptEvp(xmlSecKeyDataPtr data, EVP_PKEY* pKey) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1); + xmlSecAssert2(pKey != NULL, -1); + xmlSecAssert2(pKey->type == EVP_PKEY_RSA, -1); + + return(xmlSecOpenSSLEvpKeyDataAdoptEvp(data, pKey)); +} + +/** + * xmlSecOpenSSLKeyDataRsaGetEvp: + * @data: the pointer to RSA key data. + * + * Gets the OpenSSL EVP key from RSA key data. + * + * Returns: pointer to OpenSSL EVP key or NULL if an error occurs. + */ +EVP_PKEY* +xmlSecOpenSSLKeyDataRsaGetEvp(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), NULL); + + return(xmlSecOpenSSLEvpKeyDataGetEvp(data)); +} + +static int +xmlSecOpenSSLKeyDataRsaInitialize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1); + + return(xmlSecOpenSSLEvpKeyDataInitialize(data)); +} + +static int +xmlSecOpenSSLKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecOpenSSLKeyDataRsaId), -1); + xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecOpenSSLKeyDataRsaId), -1); + + return(xmlSecOpenSSLEvpKeyDataDuplicate(dst, src)); +} + +static void +xmlSecOpenSSLKeyDataRsaFinalize(xmlSecKeyDataPtr data) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId)); + + xmlSecOpenSSLEvpKeyDataFinalize(data); +} + +static int +xmlSecOpenSSLKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataPtr data; + xmlNodePtr cur; + RSA *rsa; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataRsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + if(xmlSecKeyGetValue(key) != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA, + "key already has a value"); + return(-1); + } + + rsa = RSA_new(); + if(rsa == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "RSA_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecGetNextElementNode(node->children); + + /* first is Modulus node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + RSA_free(rsa); + return(-1); + } + if(xmlSecOpenSSLNodeGetBNValue(cur, &(rsa->n)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + RSA_free(rsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is Exponent node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + RSA_free(rsa); + return(-1); + } + if(xmlSecOpenSSLNodeGetBNValue(cur, &(rsa->e)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + RSA_free(rsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) { + /* next is X node. It is REQUIRED for private key but + * we are not sure exactly what do we read */ + if(xmlSecOpenSSLNodeGetBNValue(cur, &(rsa->d)) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeGetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent)); + RSA_free(rsa); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + } + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "no nodes expected"); + RSA_free(rsa); + return(-1); + } + + data = xmlSecKeyDataCreate(id); + if(data == NULL ) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + RSA_free(rsa); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataRsaAdoptRsa(data, rsa); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLKeyDataRsaAdoptRsa", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(data); + RSA_free(rsa); + return(-1); + } + + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(data); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlNodePtr cur; + RSA* rsa; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataRsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataRsaId), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + rsa = xmlSecOpenSSLKeyDataRsaGetRsa(xmlSecKeyGetValue(key)); + xmlSecAssert2(rsa != NULL, -1); + + if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) { + /* we can have only private key or public key */ + return(0); + } + + /* first is Modulus node */ + cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, rsa->n, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + return(-1); + } + + /* next is Exponent node. */ + cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, rsa->e, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + return(-1); + } + + /* next is PrivateExponent node: write it ONLY for private keys and ONLY if it is requested */ + if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (rsa->d != NULL)) { + cur = xmlSecAddChild(node, xmlSecNodeRSAPrivateExponent, xmlSecNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent)); + return(-1); + } + ret = xmlSecOpenSSLNodeSetBNValue(cur, rsa->d, 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLNodeSetBNValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent)); + return(-1); + } + } + + return(0); +} + +static int +xmlSecOpenSSLKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + RSA* rsa; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1); + xmlSecAssert2(sizeBits > 0, -1); + + rsa = RSA_generate_key(sizeBits, 3, NULL, NULL); + if(rsa == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "RSA_generate_key", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "sizeBits=%d", sizeBits); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataRsaAdoptRsa(data, rsa); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataRsaAdoptRsa", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + RSA_free(rsa); + return(-1); + } + + return(0); +} + +static xmlSecKeyDataType +xmlSecOpenSSLKeyDataRsaGetType(xmlSecKeyDataPtr data) { + RSA* rsa; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), xmlSecKeyDataTypeUnknown); + + rsa = xmlSecOpenSSLKeyDataRsaGetRsa(data); + if((rsa != NULL) && (rsa->n != NULL) && (rsa->e != NULL)) { + if(rsa->d != NULL) { + return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic); + } else if(rsa->engine != NULL) { + /* + * !!! HACK !!! Also see DSA key + * We assume here that engine *always* has private key. + * This might be incorrect but it seems that there is no + * way to ask engine if given key is private or not. + */ + return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic); + } else { + return(xmlSecKeyDataTypePublic); + } + } + + return(xmlSecKeyDataTypeUnknown); +} + +static xmlSecSize +xmlSecOpenSSLKeyDataRsaGetSize(xmlSecKeyDataPtr data) { + RSA* rsa; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), 0); + + rsa = xmlSecOpenSSLKeyDataRsaGetRsa(data); + if((rsa != NULL) && (rsa->n != NULL)) { + return(BN_num_bits(rsa->n)); + } + return(0); +} + +static void +xmlSecOpenSSLKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "=== rsa key: size = %d\n", + xmlSecOpenSSLKeyDataRsaGetSize(data)); +} + +static void +xmlSecOpenSSLKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "<RSAKeyValue size=\"%d\" />\n", + xmlSecOpenSSLKeyDataRsaGetSize(data)); +} + +#endif /* XMLSEC_NO_RSA */ + + + diff --git a/src/openssl/globals.h b/src/openssl/globals.h new file mode 100644 index 00000000..770b6dba --- /dev/null +++ b/src/openssl/globals.h @@ -0,0 +1,24 @@ +/* + * XML Security Library + * + * globals.h: internal header only used during the compilation + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef __XMLSEC_GLOBALS_H__ +#define __XMLSEC_GLOBALS_H__ + +/** + * Use autoconf defines if present. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#define IN_XMLSEC_CRYPTO +#define XMLSEC_PRIVATE + +#endif /* ! __XMLSEC_GLOBALS_H__ */ diff --git a/src/openssl/hmac.c b/src/openssl/hmac.c new file mode 100644 index 00000000..bad1ac03 --- /dev/null +++ b/src/openssl/hmac.c @@ -0,0 +1,857 @@ +/** + * + * XMLSec library + * + * HMAC Algorithm support (http://www.w3.org/TR/xmldsig-core/#sec-HMAC): + * The HMAC algorithm (RFC2104 [HMAC]) takes the truncation length in bits + * as a parameter; if the parameter is not specified then all the bits of the + * hash are output. An example of an HMAC SignatureMethod element: + * <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"> + * <HMACOutputLength>128</HMACOutputLength> + * </SignatureMethod> + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef XMLSEC_NO_HMAC +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <openssl/hmac.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/base64.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> + +/* sizes in bits */ +#define XMLSEC_OPENSSL_MIN_HMAC_SIZE 80 +#define XMLSEC_OPENSSL_MAX_HMAC_SIZE (EVP_MAX_MD_SIZE * 8) + +/************************************************************************** + * + * Configuration + * + *****************************************************************************/ +static int g_xmlsec_openssl_hmac_min_length = XMLSEC_OPENSSL_MIN_HMAC_SIZE; + +/** + * xmlSecOpenSSLHmacGetMinOutputLength: + * + * Gets the value of min HMAC length. + * + * Returns: the min HMAC output length + */ +int xmlSecOpenSSLHmacGetMinOutputLength(void) +{ + return g_xmlsec_openssl_hmac_min_length; +} + +/** + * xmlSecOpenSSLHmacSetMinOutputLength: + * @min_length: the new min length + * + * Sets the min HMAC output length + */ +void xmlSecOpenSSLHmacSetMinOutputLength(int min_length) +{ + g_xmlsec_openssl_hmac_min_length = min_length; +} + +/************************************************************************** + * + * Internal OpenSSL HMAC CTX + * + *****************************************************************************/ +typedef struct _xmlSecOpenSSLHmacCtx xmlSecOpenSSLHmacCtx, *xmlSecOpenSSLHmacCtxPtr; +struct _xmlSecOpenSSLHmacCtx { + const EVP_MD* hmacDgst; + HMAC_CTX hmacCtx; + int ctxInitialized; + xmlSecByte dgst[XMLSEC_OPENSSL_MAX_HMAC_SIZE]; + xmlSecSize dgstSize; /* dgst size in bits */ +}; + +/************************************************************************** + * + * HMAC transforms + * + * xmlSecOpenSSLHmacCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecOpenSSLHmacGetCtx(transform) \ + ((xmlSecOpenSSLHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) +#define xmlSecOpenSSLHmacSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLHmacCtx)) + +static int xmlSecOpenSSLHmacCheckId (xmlSecTransformPtr transform); +static int xmlSecOpenSSLHmacInitialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLHmacFinalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLHmacNodeRead (xmlSecTransformPtr transform, + xmlNodePtr node, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLHmacSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLHmacSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLHmacVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLHmacExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); + + +static int +xmlSecOpenSSLHmacCheckId(xmlSecTransformPtr transform) { + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha224Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha256Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha384Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacRipemd160Id)) { + return(1); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacMd5Id)) { + return(1); + } else +#endif /* XMLSEC_NO_MD5 */ + + /* not found */ + { + return(0); + } + + /* just in case */ + return(0); +} + + + +static int +xmlSecOpenSSLHmacInitialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLHmacCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1); + + ctx = xmlSecOpenSSLHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + /* initialize context */ + memset(ctx, 0, sizeof(xmlSecOpenSSLHmacCtx)); + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha1Id)) { + ctx->hmacDgst = EVP_sha1(); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha224Id)) { + ctx->hmacDgst = EVP_sha224(); + } else +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha256Id)) { + ctx->hmacDgst = EVP_sha256(); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha384Id)) { + ctx->hmacDgst = EVP_sha384(); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha512Id)) { + ctx->hmacDgst = EVP_sha512(); + } else +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacRipemd160Id)) { + ctx->hmacDgst = EVP_ripemd160(); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacMd5Id)) { + ctx->hmacDgst = EVP_md5(); + } else +#endif /* XMLSEC_NO_MD5 */ + + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifndef XMLSEC_OPENSSL_096 + HMAC_CTX_init(&(ctx->hmacCtx)); +#endif /* XMLSEC_OPENSSL_096 */ + return(0); +} + +static void +xmlSecOpenSSLHmacFinalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLHmacCtxPtr ctx; + + xmlSecAssert(xmlSecOpenSSLHmacCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize)); + + ctx = xmlSecOpenSSLHmacGetCtx(transform); + xmlSecAssert(ctx != NULL); + +#ifndef XMLSEC_OPENSSL_096 + HMAC_CTX_cleanup(&(ctx->hmacCtx)); +#endif /* XMLSEC_OPENSSL_096 */ + memset(ctx, 0, sizeof(xmlSecOpenSSLHmacCtx)); +} + +static int +xmlSecOpenSSLHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLHmacCtxPtr ctx; + xmlNodePtr cur; + + xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1); + xmlSecAssert2(node!= NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + cur = xmlSecGetNextElementNode(node->children); + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) { + xmlChar *content; + + content = xmlNodeGetContent(cur); + if(content != NULL) { + ctx->dgstSize = atoi((char*)content); + xmlFree(content); + } + + /* Ensure that HMAC length is greater than min specified. + Otherwise, an attacker can set this length to 0 or very + small value + */ + if((int)ctx->dgstSize < xmlSecOpenSSLHmacGetMinOutputLength()) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, + "HMAC output length is too small"); + return(-1); + } + + cur = xmlSecGetNextElementNode(cur->next); + } + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + +static int +xmlSecOpenSSLHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + keyReq->keyId = xmlSecOpenSSLKeyDataHmacId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationSign) { + keyReq->keyUsage = xmlSecKeyUsageSign; + } else { + keyReq->keyUsage = xmlSecKeyUsageVerify; + } + + return(0); +} + +static int +xmlSecOpenSSLHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLHmacCtxPtr ctx; + xmlSecKeyDataPtr value; + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1); + xmlSecAssert2(key != NULL, -1); + + ctx = xmlSecOpenSSLHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->hmacDgst != NULL, -1); + xmlSecAssert2(ctx->ctxInitialized == 0, -1); + + value = xmlSecKeyGetValue(key); + xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecOpenSSLKeyDataHmacId), -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(value); + xmlSecAssert2(buffer != NULL, -1); + + if(xmlSecBufferGetSize(buffer) == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "keySize=0"); + return(-1); + } + + xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1); + HMAC_Init(&(ctx->hmacCtx), + xmlSecBufferGetData(buffer), + xmlSecBufferGetSize(buffer), + ctx->hmacDgst); + ctx->ctxInitialized = 1; + return(0); +} + +static int +xmlSecOpenSSLHmacVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + static xmlSecByte last_byte_masks[] = + { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE }; + + xmlSecOpenSSLHmacCtxPtr ctx; + xmlSecByte mask; + + xmlSecAssert2(xmlSecTransformIsValid(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->dgstSize > 0, -1); + + /* compare the digest size in bytes */ + if(dataSize != ((ctx->dgstSize + 7) / 8)){ + /* NO COMMIT */ + xmlChar* a; + mask = last_byte_masks[ctx->dgstSize % 8]; + ctx->dgst[dataSize - 1] &= mask; + a = xmlSecBase64Encode(ctx->dgst, (ctx->dgstSize + 7) / 8, -1); + fprintf(stderr, "%s\n", a); + xmlFree(a); + + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "data=%d;dgst=%d", + dataSize, ((ctx->dgstSize + 7) / 8)); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + /* we check the last byte separatelly */ + xmlSecAssert2(dataSize > 0, -1); + mask = last_byte_masks[ctx->dgstSize % 8]; + if((ctx->dgst[dataSize - 1] & mask) != (data[dataSize - 1] & mask)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_DATA_NOT_MATCH, + "data and digest do not match (last byte)"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + /* now check the rest of the digest */ + if((dataSize > 1) && (memcmp(ctx->dgst, data, dataSize - 1) != 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_DATA_NOT_MATCH, + "data and digest do not match"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + transform->status = xmlSecTransformStatusOk; + return(0); +} + +static int +xmlSecOpenSSLHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLHmacCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecTransformIsValid(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + ctx = xmlSecOpenSSLHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + + if(transform->status == xmlSecTransformStatusNone) { + /* we should be already initialized when we set key */ + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + xmlSecSize inSize; + + inSize = xmlSecBufferGetSize(in); + if(inSize > 0) { + HMAC_Update(&(ctx->hmacCtx), xmlSecBufferGetData(in), inSize); + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + } + + if(last) { + unsigned int dgstSize; + + HMAC_Final(&(ctx->hmacCtx), ctx->dgst, &dgstSize); + xmlSecAssert2(dgstSize > 0, -1); + + /* check/set the result digest size */ + if(ctx->dgstSize == 0) { + ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize * 8); /* no dgst size specified, use all we have */ + } else if(ctx->dgstSize <= XMLSEC_SIZE_BAD_CAST(8 * dgstSize)) { + dgstSize = ((ctx->dgstSize + 7) / 8); /* we need to truncate result digest */ + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "result-bits=%d;required-bits=%d", + 8 * dgstSize, ctx->dgstSize); + return(-1); + } + + /* finally write result to output */ + if(transform->operation == xmlSecTransformOperationSign) { + ret = xmlSecBufferAppend(out, ctx->dgst, dgstSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferAppend", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", dgstSize); + return(-1); + } + } + transform->status = xmlSecTransformStatusFinished; + } + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + +#ifndef XMLSEC_NO_MD5 + +/******************************************************************** + * + * HMAC MD5 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacMd5Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacMd5, /* const xmlChar* name; */ + xmlSecHrefHmacMd5, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacMd5GetKlass: + * + * The HMAC-MD5 transform klass. + * + * Returns: the HMAC-MD5 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacMd5GetKlass(void) { + return(&xmlSecOpenSSLHmacMd5Klass); +} + +#endif /* XMLSEC_NO_MD5 */ + + +#ifndef XMLSEC_NO_RIPEMD160 +/******************************************************************** + * + * HMAC RIPEMD160 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacRipemd160Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacRipemd160, /* const xmlChar* name; */ + xmlSecHrefHmacRipemd160, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacRipemd160GetKlass: + * + * The HMAC-RIPEMD160 transform klass. + * + * Returns: the HMAC-RIPEMD160 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacRipemd160GetKlass(void) { + return(&xmlSecOpenSSLHmacRipemd160Klass); +} +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 +/******************************************************************** + * + * HMAC SHA1 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha1, /* const xmlChar* name; */ + xmlSecHrefHmacSha1, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacSha1GetKlass: + * + * The HMAC-SHA1 transform klass. + * + * Returns: the HMAC-SHA1 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacSha1GetKlass(void) { + return(&xmlSecOpenSSLHmacSha1Klass); +} + +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 +/******************************************************************** + * + * HMAC SHA224 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacSha224Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha224, /* const xmlChar* name; */ + xmlSecHrefHmacSha224, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacSha224GetKlass: + * + * The HMAC-SHA224 transform klass. + * + * Returns: the HMAC-SHA224 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacSha224GetKlass(void) { + return(&xmlSecOpenSSLHmacSha224Klass); +} + +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 +/******************************************************************** + * + * HMAC SHA256 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha256, /* const xmlChar* name; */ + xmlSecHrefHmacSha256, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacSha256GetKlass: + * + * The HMAC-SHA256 transform klass. + * + * Returns: the HMAC-SHA256 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacSha256GetKlass(void) { + return(&xmlSecOpenSSLHmacSha256Klass); +} + +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 +/******************************************************************** + * + * HMAC SHA384 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacSha384Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha384, /* const xmlChar* name; */ + xmlSecHrefHmacSha384, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacSha384GetKlass: + * + * The HMAC-SHA384 transform klass. + * + * Returns: the HMAC-SHA384 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacSha384GetKlass(void) { + return(&xmlSecOpenSSLHmacSha384Klass); +} + +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 +/******************************************************************** + * + * HMAC SHA512 + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLHmacSha512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha512, /* const xmlChar* name; */ + xmlSecHrefHmacSha512, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformHmacSha512GetKlass: + * + * The HMAC-SHA512 transform klass. + * + * Returns: the HMAC-SHA512 transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformHmacSha512GetKlass(void) { + return(&xmlSecOpenSSLHmacSha512Klass); +} + +#endif /* XMLSEC_NO_SHA512 */ + + +#endif /* XMLSEC_NO_HMAC */ + diff --git a/src/openssl/kt_rsa.c b/src/openssl/kt_rsa.c new file mode 100644 index 00000000..1cf1aba1 --- /dev/null +++ b/src/openssl/kt_rsa.c @@ -0,0 +1,876 @@ +/** + * + * XMLSec library + * + * RSA Algorithms support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#ifndef XMLSEC_NO_RSA + +#include <stdlib.h> +#include <string.h> + +#include <openssl/rsa.h> +#include <openssl/evp.h> +#include <openssl/sha.h> +#include <openssl/objects.h> + +#include <libxml/tree.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/buffer.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/strings.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> +#include <xmlsec/openssl/bn.h> + +/************************************************************************** + * + * Internal OpenSSL RSA PKCS1 CTX + * + *************************************************************************/ +typedef struct _xmlSecOpenSSLRsaPkcs1Ctx xmlSecOpenSSLRsaPkcs1Ctx, + *xmlSecOpenSSLRsaPkcs1CtxPtr; +struct _xmlSecOpenSSLRsaPkcs1Ctx { + EVP_PKEY* pKey; +}; + +/********************************************************************* + * + * RSA PKCS1 key transport transform + * + * xmlSecOpenSSLRsaPkcs1Ctx is located after xmlSecTransform + * + ********************************************************************/ +#define xmlSecOpenSSLRsaPkcs1Size \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLRsaPkcs1Ctx)) +#define xmlSecOpenSSLRsaPkcs1GetCtx(transform) \ + ((xmlSecOpenSSLRsaPkcs1CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecOpenSSLRsaPkcs1Initialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLRsaPkcs1Finalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLRsaPkcs1SetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLRsaPkcs1SetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLRsaPkcs1Execute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLRsaPkcs1Process (xmlSecTransformPtr transform, + xmlSecTransformCtxPtr transformCtx); + +static xmlSecTransformKlass xmlSecOpenSSLRsaPkcs1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLRsaPkcs1Size, /* xmlSecSize objSize */ + + xmlSecNameRsaPkcs1, /* const xmlChar* name; */ + xmlSecHrefRsaPkcs1, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLRsaPkcs1Initialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLRsaPkcs1Finalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLRsaPkcs1SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLRsaPkcs1SetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLRsaPkcs1Execute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaPkcs1GetKlass: + * + * The RSA-PKCS1 key transport transform klass. + * + * Returns: RSA-PKCS1 key transport transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaPkcs1GetKlass(void) { + return(&xmlSecOpenSSLRsaPkcs1Klass); +} + +static int +xmlSecOpenSSLRsaPkcs1Initialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLRsaPkcs1CtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1); + + ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLRsaPkcs1Ctx)); + return(0); +} + +static void +xmlSecOpenSSLRsaPkcs1Finalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLRsaPkcs1CtxPtr ctx; + + xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size)); + + ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->pKey != NULL) { + EVP_PKEY_free(ctx->pKey); + } + memset(ctx, 0, sizeof(xmlSecOpenSSLRsaPkcs1Ctx)); +} + +static int +xmlSecOpenSSLRsaPkcs1SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecOpenSSLRsaPkcs1CtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecOpenSSLKeyDataRsaId; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyType = xmlSecKeyDataTypePublic; + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyType = xmlSecKeyDataTypePrivate; + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + return(0); +} + +static int +xmlSecOpenSSLRsaPkcs1SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLRsaPkcs1CtxPtr ctx; + EVP_PKEY* pKey; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataRsaId), -1); + + ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->pKey == NULL, -1); + + pKey = xmlSecOpenSSLKeyDataRsaGetEvp(xmlSecKeyGetValue(key)); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLKeyDataRsaGetEvp", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + xmlSecAssert2(pKey->type == EVP_PKEY_RSA, -1); + xmlSecAssert2(pKey->pkey.rsa != NULL, -1); + + ctx->pKey = xmlSecOpenSSLEvpKeyDup(pKey); + if(ctx->pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpKeyDup", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLRsaPkcs1Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLRsaPkcs1CtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->pKey != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) { + /* just do nothing */ + } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + ret = xmlSecOpenSSLRsaPkcs1Process(transform, transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLRsaPkcs1Process", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + transform->status = xmlSecTransformStatusFinished; + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + return(0); +} + +static int +xmlSecOpenSSLRsaPkcs1Process(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLRsaPkcs1CtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize, outSize; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->pKey != NULL, -1); + xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1); + xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1); + + keySize = RSA_size(ctx->pKey->pkey.rsa); + xmlSecAssert2(keySize > 0, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + xmlSecAssert2(outSize == 0, -1); + + /* the encoded size is equal to the keys size so we could not + * process more than that */ + if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "%d when expected less than %d", inSize, keySize); + return(-1); + } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "%d when expected %d", inSize, keySize); + return(-1); + } + + outSize = keySize; + ret = xmlSecBufferSetMaxSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), + xmlSecBufferGetData(out), + ctx->pKey->pkey.rsa, RSA_PKCS1_PADDING); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_public_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", inSize); + return(-1); + } + outSize = ret; + } else { + ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), + xmlSecBufferGetData(out), + ctx->pKey->pkey.rsa, RSA_PKCS1_PADDING); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_private_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", inSize); + return(-1); + } + outSize = ret; + } + + ret = xmlSecBufferSetSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + return(0); +} + +/************************************************************************** + * + * Internal OpenSSL RSA OAEP CTX + * + *************************************************************************/ +typedef struct _xmlSecOpenSSLRsaOaepCtx xmlSecOpenSSLRsaOaepCtx, + *xmlSecOpenSSLRsaOaepCtxPtr; +struct _xmlSecOpenSSLRsaOaepCtx { + EVP_PKEY* pKey; + xmlSecBuffer oaepParams; +}; + +/********************************************************************* + * + * RSA OAEP key transport transform + * + * xmlSecOpenSSLRsaOaepCtx is located after xmlSecTransform + * + ********************************************************************/ +#define xmlSecOpenSSLRsaOaepSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLRsaOaepCtx)) +#define xmlSecOpenSSLRsaOaepGetCtx(transform) \ + ((xmlSecOpenSSLRsaOaepCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecOpenSSLRsaOaepInitialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLRsaOaepFinalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLRsaOaepNodeRead (xmlSecTransformPtr transform, + xmlNodePtr node, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLRsaOaepSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLRsaOaepSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLRsaOaepExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLRsaOaepProcess (xmlSecTransformPtr transform, + xmlSecTransformCtxPtr transformCtx); + +static xmlSecTransformKlass xmlSecOpenSSLRsaOaepKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLRsaOaepSize, /* xmlSecSize objSize */ + + xmlSecNameRsaOaep, /* const xmlChar* name; */ + xmlSecHrefRsaOaep, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLRsaOaepInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLRsaOaepFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecOpenSSLRsaOaepNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLRsaOaepSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLRsaOaepSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLRsaOaepExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaOaepGetKlass: + * + * The RSA-OAEP key transport transform klass. + * + * Returns: RSA-OAEP key transport transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaOaepGetKlass(void) { + return(&xmlSecOpenSSLRsaOaepKlass); +} + +static int +xmlSecOpenSSLRsaOaepInitialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLRsaOaepCtx)); + + ret = xmlSecBufferInitialize(&(ctx->oaepParams), 0); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + +static void +xmlSecOpenSSLRsaOaepFinalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + + xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize)); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->pKey != NULL) { + EVP_PKEY_free(ctx->pKey); + } + xmlSecBufferFinalize(&(ctx->oaepParams)); + memset(ctx, 0, sizeof(xmlSecOpenSSLRsaOaepCtx)); +} + +static int +xmlSecOpenSSLRsaOaepNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + xmlNodePtr cur; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(xmlSecBufferGetSize(&(ctx->oaepParams)) == 0, -1); + + cur = xmlSecGetNextElementNode(node->children); + while(cur != NULL) { + if(xmlSecCheckNodeName(cur, xmlSecNodeRsaOAEPparams, xmlSecEncNs)) { + ret = xmlSecBufferBase64NodeContentRead(&(ctx->oaepParams), cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferBase64NodeContentRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } else if(xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs)) { + xmlChar* algorithm; + + /* Algorithm attribute is required */ + algorithm = xmlGetProp(cur, xmlSecAttrAlgorithm); + if(algorithm == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(xmlSecAttrAlgorithm), + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); + return(-1); + } + + /* for now we support only sha1 */ + if(xmlStrcmp(algorithm, xmlSecHrefSha1) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(algorithm), + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + "digest algorithm is not supported for rsa/oaep"); + xmlFree(algorithm); + return(-1); + } + xmlFree(algorithm); + } else { + /* not found */ + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* next node */ + cur = xmlSecGetNextElementNode(cur->next); + } + + return(0); +} + +static int +xmlSecOpenSSLRsaOaepSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecOpenSSLKeyDataRsaId; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyType = xmlSecKeyDataTypePublic; + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyType = xmlSecKeyDataTypePrivate; + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + + return(0); +} + +static int +xmlSecOpenSSLRsaOaepSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + EVP_PKEY* pKey; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataRsaId), -1); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->pKey == NULL, -1); + + pKey = xmlSecOpenSSLKeyDataRsaGetEvp(xmlSecKeyGetValue(key)); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLKeyDataRsaGetEvp", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + xmlSecAssert2(pKey->type == EVP_PKEY_RSA, -1); + xmlSecAssert2(pKey->pkey.rsa != NULL, -1); + + ctx->pKey = xmlSecOpenSSLEvpKeyDup(pKey); + if(ctx->pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpKeyDup", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLRsaOaepExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->pKey != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) { + /* just do nothing */ + } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + ret = xmlSecOpenSSLRsaOaepProcess(transform, transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLRsaOaepProcess", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + transform->status = xmlSecTransformStatusFinished; + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + return(0); +} + +static int +xmlSecOpenSSLRsaOaepProcess(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLRsaOaepCtxPtr ctx; + xmlSecSize paramsSize; + xmlSecBufferPtr in, out; + xmlSecSize inSize, outSize; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->pKey != NULL, -1); + xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1); + xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1); + + keySize = RSA_size(ctx->pKey->pkey.rsa); + xmlSecAssert2(keySize > 0, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + xmlSecAssert2(outSize == 0, -1); + + /* the encoded size is equal to the keys size so we could not + * process more than that */ + if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "%d when expected less than %d", inSize, keySize); + return(-1); + } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "%d when expected %d", inSize, keySize); + return(-1); + } + + outSize = keySize; + ret = xmlSecBufferSetMaxSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + paramsSize = xmlSecBufferGetSize(&(ctx->oaepParams)); + if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize == 0)) { + /* encode w/o OAEPParams --> simple */ + ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), + xmlSecBufferGetData(out), + ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_public_encrypt(RSA_PKCS1_OAEP_PADDING)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } else if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize > 0)) { + xmlSecAssert2(xmlSecBufferGetData(&(ctx->oaepParams)) != NULL, -1); + + /* add space for padding */ + ret = xmlSecBufferSetMaxSize(in, keySize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", keySize); + return(-1); + } + + /* add padding */ + ret = RSA_padding_add_PKCS1_OAEP(xmlSecBufferGetData(in), keySize, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(&(ctx->oaepParams)), + paramsSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_padding_add_PKCS1_OAEP", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + inSize = keySize; + + /* encode with OAEPParams */ + ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), + xmlSecBufferGetData(out), + ctx->pKey->pkey.rsa, RSA_NO_PADDING); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_public_encrypt(RSA_NO_PADDING)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize == 0)) { + ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), + xmlSecBufferGetData(out), + ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_private_decrypt(RSA_PKCS1_OAEP_PADDING)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize != 0)) { + BIGNUM bn; + + ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), + xmlSecBufferGetData(out), + ctx->pKey->pkey.rsa, RSA_NO_PADDING); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_private_decrypt(RSA_NO_PADDING)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + + /* + * the private decrypt w/o padding adds '0's at the begginning. + * it's not clear for me can I simply skip all '0's from the + * beggining so I have to do decode it back to BIGNUM and dump + * buffer again + */ + BN_init(&bn); + if(BN_bin2bn(xmlSecBufferGetData(out), outSize, &bn) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "BN_bin2bn", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", outSize); + BN_clear_free(&bn); + return(-1); + } + + ret = BN_bn2bin(&bn, xmlSecBufferGetData(out)); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "BN_bn2bin", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BN_clear_free(&bn); + return(-1); + } + BN_clear_free(&bn); + outSize = ret; + + ret = RSA_padding_check_PKCS1_OAEP(xmlSecBufferGetData(out), outSize, + xmlSecBufferGetData(out), outSize, + keySize, + xmlSecBufferGetData(&(ctx->oaepParams)), + paramsSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "RSA_padding_check_PKCS1_OAEP", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } else { + xmlSecAssert2("we could not be here" == NULL, -1); + return(-1); + } + + ret = xmlSecBufferSetSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + return(0); +} + +#endif /* XMLSEC_NO_RSA */ + diff --git a/src/openssl/kw_aes.c b/src/openssl/kw_aes.c new file mode 100644 index 00000000..573fb985 --- /dev/null +++ b/src/openssl/kw_aes.c @@ -0,0 +1,513 @@ +/** + * + * XMLSec library + * + * AES Algorithm support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef XMLSEC_NO_AES +#ifndef XMLSEC_OPENSSL_096 +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <openssl/aes.h> +#include <openssl/rand.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> + +#include "../kw_aes_des.h" + + +/********************************************************************* + * + * AES KW implementation + * + *********************************************************************/ +static int xmlSecOpenSSLKWAesBlockEncrypt (const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize, + void * context); +static int xmlSecOpenSSLKWAesBlockDecrypt (const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize, + void * context); +static xmlSecKWAesKlass xmlSecOpenSSLKWAesKlass = { + /* callbacks */ + xmlSecOpenSSLKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */ + xmlSecOpenSSLKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */ + + /* for the future */ + NULL, /* void* reserved0; */ + NULL /* void* reserved1; */ +}; + + +/********************************************************************* + * + * AES KW transforms + * + ********************************************************************/ +typedef struct _xmlSecOpenSSLKWAesCtx xmlSecOpenSSLKWAesCtx, + *xmlSecOpenSSLKWAesCtxPtr; +struct _xmlSecOpenSSLKWAesCtx { + xmlSecBuffer keyBuffer; + xmlSecSize keyExpectedSize; +}; +#define xmlSecOpenSSLKWAesSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLKWAesCtx)) +#define xmlSecOpenSSLKWAesGetCtx(transform) \ + ((xmlSecOpenSSLKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) +#define xmlSecOpenSSLKWAesCheckId(transform) \ + (xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes128Id) || \ + xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes192Id) || \ + xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes256Id)) + +static int xmlSecOpenSSLKWAesInitialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLKWAesFinalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLKWAesSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLKWAesSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLKWAesExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); + +static int +xmlSecOpenSSLKWAesInitialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLKWAesCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1); + + ctx = xmlSecOpenSSLKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes128Id)) { + ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE; + } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes192Id)) { + ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE; + } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes256Id)) { + ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE; + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLKWAesGetKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static void +xmlSecOpenSSLKWAesFinalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLKWAesCtxPtr ctx; + + xmlSecAssert(xmlSecOpenSSLKWAesCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize)); + + ctx = xmlSecOpenSSLKWAesGetCtx(transform); + xmlSecAssert(ctx != NULL); + + xmlSecBufferFinalize(&(ctx->keyBuffer)); +} + +static int +xmlSecOpenSSLKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecOpenSSLKWAesCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecOpenSSLKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecOpenSSLKeyDataAesId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + keyReq->keyBitsSize = 8 * ctx->keyExpectedSize; + + return(0); +} + +static int +xmlSecOpenSSLKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLKWAesCtxPtr ctx; + xmlSecBufferPtr buffer; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataAesId), -1); + + ctx = xmlSecOpenSSLKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer != NULL, -1); + + keySize = xmlSecBufferGetSize(buffer); + if(keySize < ctx->keyExpectedSize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "key=%d;expected=%d", + keySize, ctx->keyExpectedSize); + return(-1); + } + + ret = xmlSecBufferSetData(&(ctx->keyBuffer), + xmlSecBufferGetData(buffer), + ctx->keyExpectedSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "expected-size=%d", + ctx->keyExpectedSize); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLKWAesCtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize, outSize, keySize; + AES_KEY aesKey; + int ret; + + xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keySize = xmlSecBufferGetSize(&(ctx->keyBuffer)); + xmlSecAssert2(keySize == ctx->keyExpectedSize, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + xmlSecAssert2(outSize == 0, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) { + /* just do nothing */ + } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + if((inSize % 8) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "size=%d(not 8 bytes aligned)", inSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + /* the encoded key might be 8 bytes longer plus 8 bytes just in case */ + outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE + + XMLSEC_KW_AES_BLOCK_SIZE; + } else { + outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE; + } + + ret = xmlSecBufferSetMaxSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "outSize=%d", outSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + /* prepare key */ + ret = AES_set_encrypt_key(xmlSecBufferGetData(&(ctx->keyBuffer)), + 8 * keySize, + &aesKey); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "AES_set_decrypt_key", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecKWAesEncode(&xmlSecOpenSSLKWAesKlass, &aesKey, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWAesEncode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } else { + /* prepare key */ + ret = AES_set_decrypt_key(xmlSecBufferGetData(&(ctx->keyBuffer)), + 8 * keySize, + &aesKey); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "AES_set_decrypt_key", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecKWAesDecode(&xmlSecOpenSSLKWAesKlass, &aesKey, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWAesEncode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } + + ret = xmlSecBufferSetSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "outSize=%d", outSize); + return(-1); + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "inSize%d", inSize); + return(-1); + } + + transform->status = xmlSecTransformStatusFinished; + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + return(0); +} + +static xmlSecTransformKlass xmlSecOpenSSLKWAes128Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLKWAesSize, /* xmlSecSize objSize */ + + xmlSecNameKWAes128, /* const xmlChar* name; */ + xmlSecHrefKWAes128, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLKWAesExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformKWAes128GetKlass: + * + * The AES-128 kew wrapper transform klass. + * + * Returns: AES-128 kew wrapper transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformKWAes128GetKlass(void) { + return(&xmlSecOpenSSLKWAes128Klass); +} + +static xmlSecTransformKlass xmlSecOpenSSLKWAes192Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLKWAesSize, /* xmlSecSize objSize */ + + xmlSecNameKWAes192, /* const xmlChar* name; */ + xmlSecHrefKWAes192, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLKWAesExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + + +/** + * xmlSecOpenSSLTransformKWAes192GetKlass: + * + * The AES-192 kew wrapper transform klass. + * + * Returns: AES-192 kew wrapper transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformKWAes192GetKlass(void) { + return(&xmlSecOpenSSLKWAes192Klass); +} + +static xmlSecTransformKlass xmlSecOpenSSLKWAes256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLKWAesSize, /* xmlSecSize objSize */ + + xmlSecNameKWAes256, /* const xmlChar* name; */ + xmlSecHrefKWAes256, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLKWAesExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformKWAes256GetKlass: + * + * The AES-256 kew wrapper transform klass. + * + * Returns: AES-256 kew wrapper transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformKWAes256GetKlass(void) { + return(&xmlSecOpenSSLKWAes256Klass); +} + +/********************************************************************* + * + * AES KW implementation + * + *********************************************************************/ +static int +xmlSecOpenSSLKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize, + void * context) { + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize >= AES_BLOCK_SIZE, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= AES_BLOCK_SIZE, -1); + xmlSecAssert2(context != NULL, -1); + + AES_encrypt(in, out, (AES_KEY*)context); + return(AES_BLOCK_SIZE); +} + +static int +xmlSecOpenSSLKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize, + void * context) { + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize >= AES_BLOCK_SIZE, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= AES_BLOCK_SIZE, -1); + xmlSecAssert2(context != NULL, -1); + + AES_decrypt(in, out, (AES_KEY*)context); + return(AES_BLOCK_SIZE); +} + + +#endif /* XMLSEC_OPENSSL_096 */ +#endif /* XMLSEC_NO_AES */ diff --git a/src/openssl/kw_des.c b/src/openssl/kw_des.c new file mode 100644 index 00000000..9d55e107 --- /dev/null +++ b/src/openssl/kw_des.c @@ -0,0 +1,563 @@ +/** + * + * XMLSec library + * + * DES Algorithm support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef XMLSEC_NO_DES +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <openssl/des.h> +#include <openssl/rand.h> +#include <openssl/sha.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> + +#include "../kw_aes_des.h" + +/********************************************************************* + * + * DES KW implementation + * + *********************************************************************/ +static int xmlSecOpenSSLKWDes3GenerateRandom (void * context, + xmlSecByte * out, + xmlSecSize outSize); +static int xmlSecOpenSSLKWDes3Sha1 (void * context, + const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize); +static int xmlSecOpenSSLKWDes3BlockEncrypt (void * context, + const xmlSecByte * iv, + xmlSecSize ivSize, + const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize); +static int xmlSecOpenSSLKWDes3BlockDecrypt (void * context, + const xmlSecByte * iv, + xmlSecSize ivSize, + const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize); + +static xmlSecKWDes3Klass xmlSecOpenSSLKWDes3ImplKlass = { + /* callbacks */ + xmlSecOpenSSLKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */ + xmlSecOpenSSLKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */ + xmlSecOpenSSLKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */ + xmlSecOpenSSLKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */ + + /* for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +static int xmlSecOpenSSLKWDes3Encrypt (const xmlSecByte *key, + xmlSecSize keySize, + const xmlSecByte *iv, + xmlSecSize ivSize, + const xmlSecByte *in, + xmlSecSize inSize, + xmlSecByte *out, + xmlSecSize outSize, + int enc); + + +/********************************************************************* + * + * Triple DES Key Wrap transform + * + * key (xmlSecBuffer) is located after xmlSecTransform structure + * + ********************************************************************/ +typedef struct _xmlSecOpenSSLKWDes3Ctx xmlSecOpenSSLKWDes3Ctx, + *xmlSecOpenSSLKWDes3CtxPtr; +struct _xmlSecOpenSSLKWDes3Ctx { + xmlSecBuffer keyBuffer; +}; +#define xmlSecOpenSSLKWDes3Size \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLKWDes3Ctx)) +#define xmlSecOpenSSLKWDes3GetCtx(transform) \ + ((xmlSecOpenSSLKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecOpenSSLKWDes3Initialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLKWDes3Finalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLKWDes3SetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLKWDes3SetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLKWDes3Execute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static xmlSecTransformKlass xmlSecOpenSSLKWDes3Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLKWDes3Size, /* xmlSecSize objSize */ + + xmlSecNameKWDes3, /* const xmlChar* name; */ + xmlSecHrefKWDes3, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecOpenSSLKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecOpenSSLKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformKWDes3GetKlass: + * + * The Triple DES key wrapper transform klass. + * + * Returns: Triple DES key wrapper transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformKWDes3GetKlass(void) { + return(&xmlSecOpenSSLKWDes3Klass); +} + +static int +xmlSecOpenSSLKWDes3Initialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLKWDes3CtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1); + + ctx = xmlSecOpenSSLKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static void +xmlSecOpenSSLKWDes3Finalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLKWDes3CtxPtr ctx; + + xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size)); + + ctx = xmlSecOpenSSLKWDes3GetCtx(transform); + xmlSecAssert(ctx != NULL); + + xmlSecBufferFinalize(&(ctx->keyBuffer)); +} + +static int +xmlSecOpenSSLKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecOpenSSLKWDes3CtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecOpenSSLKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecOpenSSLKeyDataDesId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage= xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage= xmlSecKeyUsageDecrypt; + } + keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH; + return(0); +} + +static int +xmlSecOpenSSLKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLKWDes3CtxPtr ctx; + xmlSecBufferPtr buffer; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataDesId), -1); + + ctx = xmlSecOpenSSLKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer != NULL, -1); + + keySize = xmlSecBufferGetSize(buffer); + if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "key length %d is not enough (%d expected)", + keySize, XMLSEC_KW_DES3_KEY_LENGTH); + return(-1); + } + + ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", XMLSEC_KW_DES3_KEY_LENGTH); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLKWDes3CtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize, outSize, keySize; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keySize = xmlSecBufferGetSize(&(ctx->keyBuffer)); + xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + xmlSecAssert2(outSize == 0, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) { + /* just do nothing */ + } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "%d bytes - not %d bytes aligned", + inSize, XMLSEC_KW_DES3_BLOCK_LENGTH); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + /* the encoded key might be 16 bytes longer plus one block just in case */ + outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH + + XMLSEC_KW_DES3_BLOCK_LENGTH + + XMLSEC_KW_DES3_BLOCK_LENGTH; + } else { + /* just in case, add a block */ + outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH; + } + + ret = xmlSecBufferSetMaxSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + ret = xmlSecKWDes3Encode(&xmlSecOpenSSLKWDes3ImplKlass, ctx, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWDes3Encode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "key=%d,in=%d,out=%d", + keySize, inSize, outSize); + return(-1); + } + outSize = ret; + } else { + ret = xmlSecKWDes3Decode(&xmlSecOpenSSLKWDes3ImplKlass, ctx, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWDes3Decode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "key=%d,in=%d,out=%d", + keySize, inSize, outSize); + return(-1); + } + outSize = ret; + } + + ret = xmlSecBufferSetSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + transform->status = xmlSecTransformStatusFinished; + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + +/********************************************************************* + * + * DES KW implementation + * + *********************************************************************/ +static int +xmlSecOpenSSLKWDes3Sha1(void * context, + const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= SHA_DIGEST_LENGTH, -1); + + if(SHA1(in, inSize, out) == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SHA1", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(SHA_DIGEST_LENGTH); +} + +static int +xmlSecOpenSSLKWDes3GenerateRandom(void * context, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize > 0, -1); + + ret = RAND_bytes(out, outSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "RAND_bytes", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + + return((int)outSize); +} + +static int +xmlSecOpenSSLKWDes3BlockEncrypt(void * context, + const xmlSecByte * iv, xmlSecSize ivSize, + const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1); + xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1); + xmlSecAssert2(iv != NULL, -1); + xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= inSize, -1); + + ret = xmlSecOpenSSLKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH, + iv, XMLSEC_KW_DES3_IV_LENGTH, + in, inSize, + out, outSize, + 1); /* encrypt */ + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKWDes3Encrypt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(ret); +} + +static int +xmlSecOpenSSLKWDes3BlockDecrypt(void * context, + const xmlSecByte * iv, xmlSecSize ivSize, + const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1); + xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1); + xmlSecAssert2(iv != NULL, -1); + xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= inSize, -1); + + ret = xmlSecOpenSSLKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH, + iv, XMLSEC_KW_DES3_IV_LENGTH, + in, inSize, + out, outSize, + 0); /* decrypt */ + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLKWDes3Encrypt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(ret); +} + + + +static int +xmlSecOpenSSLKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize, + const xmlSecByte *iv, xmlSecSize ivSize, + const xmlSecByte *in, xmlSecSize inSize, + xmlSecByte *out, xmlSecSize outSize, + int enc) { + EVP_CIPHER_CTX cipherCtx; + int updateLen; + int finalLen; + int ret; + + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(keySize == (xmlSecSize)EVP_CIPHER_key_length(EVP_des_ede3_cbc()), -1); + xmlSecAssert2(iv != NULL, -1); + xmlSecAssert2(ivSize == (xmlSecSize)EVP_CIPHER_iv_length(EVP_des_ede3_cbc()), -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= inSize, -1); + + EVP_CIPHER_CTX_init(&cipherCtx); + ret = EVP_CipherInit(&cipherCtx, EVP_des_ede3_cbc(), key, iv, enc); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "EVP_CipherInit", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifndef XMLSEC_OPENSSL_096 + EVP_CIPHER_CTX_set_padding(&cipherCtx, 0); +#endif /* XMLSEC_OPENSSL_096 */ + + ret = EVP_CipherUpdate(&cipherCtx, out, &updateLen, in, inSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "EVP_CipherUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = EVP_CipherFinal(&cipherCtx, out + updateLen, &finalLen); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "EVP_CipherFinal", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + EVP_CIPHER_CTX_cleanup(&cipherCtx); + + return(updateLen + finalLen); +} + + +#endif /* XMLSEC_NO_DES */ + diff --git a/src/openssl/signatures.c b/src/openssl/signatures.c new file mode 100644 index 00000000..38f42b34 --- /dev/null +++ b/src/openssl/signatures.c @@ -0,0 +1,1065 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <openssl/evp.h> +#include <openssl/rand.h> +#include <openssl/sha.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> + +#ifndef XMLSEC_NO_DSA +#define XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE 40 +static const EVP_MD *xmlSecOpenSSLDsaSha1Evp (void); +#endif /* XMLSEC_NO_DSA */ + + +/************************************************************************** + * + * Internal OpenSSL evp signatures ctx + * + *****************************************************************************/ +typedef struct _xmlSecOpenSSLEvpSignatureCtx xmlSecOpenSSLEvpSignatureCtx, + *xmlSecOpenSSLEvpSignatureCtxPtr; +struct _xmlSecOpenSSLEvpSignatureCtx { + const EVP_MD* digest; + EVP_MD_CTX digestCtx; + xmlSecKeyDataId keyId; + EVP_PKEY* pKey; +}; + +/****************************************************************************** + * + * EVP Signature transforms + * + * xmlSecOpenSSLEvpSignatureCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecOpenSSLEvpSignatureSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLEvpSignatureCtx)) +#define xmlSecOpenSSLEvpSignatureGetCtx(transform) \ + ((xmlSecOpenSSLEvpSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecOpenSSLEvpSignatureCheckId (xmlSecTransformPtr transform); +static int xmlSecOpenSSLEvpSignatureInitialize (xmlSecTransformPtr transform); +static void xmlSecOpenSSLEvpSignatureFinalize (xmlSecTransformPtr transform); +static int xmlSecOpenSSLEvpSignatureSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecOpenSSLEvpSignatureSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecOpenSSLEvpSignatureVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecOpenSSLEvpSignatureExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); + +static int +xmlSecOpenSSLEvpSignatureCheckId(xmlSecTransformPtr transform) { +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDsaSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaMd5Id)) { + return(1); + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaRipemd160Id)) { + return(1); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha224Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha256Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha384Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + { + return(0); + } + + return(0); +} + +static int +xmlSecOpenSSLEvpSignatureInitialize(xmlSecTransformPtr transform) { + xmlSecOpenSSLEvpSignatureCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLEvpSignatureCtx)); + +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDsaSha1Id)) { + ctx->digest = xmlSecOpenSSLDsaSha1Evp(); + ctx->keyId = xmlSecOpenSSLKeyDataDsaId; + } else +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaMd5Id)) { + ctx->digest = EVP_md5(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaRipemd160Id)) { + ctx->digest = EVP_ripemd160(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha1Id)) { + ctx->digest = EVP_sha1(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha224Id)) { + ctx->digest = EVP_sha224(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha256Id)) { + ctx->digest = EVP_sha256(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha384Id)) { + ctx->digest = EVP_sha384(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha512Id)) { + ctx->digest = EVP_sha512(); + ctx->keyId = xmlSecOpenSSLKeyDataRsaId; + } else +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + if(1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifndef XMLSEC_OPENSSL_096 + EVP_MD_CTX_init(&(ctx->digestCtx)); +#endif /* XMLSEC_OPENSSL_096 */ + return(0); +} + +static void +xmlSecOpenSSLEvpSignatureFinalize(xmlSecTransformPtr transform) { + xmlSecOpenSSLEvpSignatureCtxPtr ctx; + + xmlSecAssert(xmlSecOpenSSLEvpSignatureCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize)); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->pKey != NULL) { + EVP_PKEY_free(ctx->pKey); + } + +#ifndef XMLSEC_OPENSSL_096 + EVP_MD_CTX_cleanup(&(ctx->digestCtx)); +#endif /* XMLSEC_OPENSSL_096 */ + memset(ctx, 0, sizeof(xmlSecOpenSSLEvpSignatureCtx)); +} + +static int +xmlSecOpenSSLEvpSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecOpenSSLEvpSignatureCtxPtr ctx; + xmlSecKeyDataPtr value; + EVP_PKEY* pKey; + + xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1); + xmlSecAssert2(key != NULL, -1); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digest != NULL, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); + + value = xmlSecKeyGetValue(key); + xmlSecAssert2(value != NULL, -1); + + pKey = xmlSecOpenSSLEvpKeyDataGetEvp(value); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpKeyDataGetEvp", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if(ctx->pKey != NULL) { + EVP_PKEY_free(ctx->pKey); + } + + ctx->pKey = xmlSecOpenSSLEvpKeyDup(pKey); + if(ctx->pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecOpenSSLEvpKeyDup", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int +xmlSecOpenSSLEvpSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecOpenSSLEvpSignatureCtxPtr ctx; + + xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + + keyReq->keyId = ctx->keyId; + if(transform->operation == xmlSecTransformOperationSign) { + keyReq->keyType = xmlSecKeyDataTypePrivate; + keyReq->keyUsage = xmlSecKeyUsageSign; + } else { + keyReq->keyType = xmlSecKeyDataTypePublic; + keyReq->keyUsage = xmlSecKeyUsageVerify; + } + return(0); +} + + +static int +xmlSecOpenSSLEvpSignatureVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLEvpSignatureCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + ret = EVP_VerifyFinal(&(ctx->digestCtx), (xmlSecByte*)data, dataSize, ctx->pKey); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_VerifyFinal", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } else if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_VerifyFinal", + XMLSEC_ERRORS_R_DATA_NOT_MATCH, + "signature do not match"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + transform->status = xmlSecTransformStatusOk; + return(0); +} + +static int +xmlSecOpenSSLEvpSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecOpenSSLEvpSignatureCtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize; + xmlSecSize outSize; + int ret; + + xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digest != NULL, -1); + xmlSecAssert2(ctx->pKey != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { + xmlSecAssert2(outSize == 0, -1); + + if(transform->operation == xmlSecTransformOperationSign) { +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_SignInit(&(ctx->digestCtx), ctx->digest); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_SignInit", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_SignInit(&(ctx->digestCtx), ctx->digest); +#endif /* XMLSEC_OPENSSL_096 */ + } else { +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_VerifyInit(&(ctx->digestCtx), ctx->digest); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_VerifyInit", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_VerifyInit(&(ctx->digestCtx), ctx->digest); +#endif /* XMLSEC_OPENSSL_096 */ + } + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (inSize > 0)) { + xmlSecAssert2(outSize == 0, -1); + + if(transform->operation == xmlSecTransformOperationSign) { +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_SignUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_SignUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_SignUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize); +#endif /* XMLSEC_OPENSSL_096 */ + } else { +#ifndef XMLSEC_OPENSSL_096 + ret = EVP_VerifyUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_VerifyUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#else /* XMLSEC_OPENSSL_096 */ + EVP_VerifyUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize); +#endif /* XMLSEC_OPENSSL_096 */ + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + xmlSecAssert2(outSize == 0, -1); + if(transform->operation == xmlSecTransformOperationSign) { + unsigned int signSize; + + /* this is a hack: for rsa signatures + * we get size from EVP_PKEY_size(), + * for dsa signature we use a fixed constant */ + signSize = EVP_PKEY_size(ctx->pKey); +#ifndef XMLSEC_NO_DSA + if(signSize < XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE) { + signSize = XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE; + } +#endif /* XMLSEC_NO_DSA */ + + ret = xmlSecBufferSetMaxSize(out, signSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%u", signSize); + return(-1); + } + + ret = EVP_SignFinal(&(ctx->digestCtx), xmlSecBufferGetData(out), &signSize, ctx->pKey); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "EVP_SignFinal", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecBufferSetSize(out, signSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%u", signSize); + return(-1); + } + } + transform->status = xmlSecTransformStatusFinished; + } + + if((transform->status == xmlSecTransformStatusWorking) || (transform->status == xmlSecTransformStatusFinished)) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 +/**************************************************************************** + * + * DSA-SHA1 signature transform + * + ***************************************************************************/ + +static xmlSecTransformKlass xmlSecOpenSSLDsaSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameDsaSha1, /* const xmlChar* name; */ + xmlSecHrefDsaSha1, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformDsaSha1GetKlass: + * + * The DSA-SHA1 signature transform klass. + * + * Returns: DSA-SHA1 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformDsaSha1GetKlass(void) { + return(&xmlSecOpenSSLDsaSha1Klass); +} + +/**************************************************************************** + * + * DSA-SHA1 EVP + * + * XMLDSig specifies dsa signature packing not supported by OpenSSL so + * we created our own EVP_MD. + * + * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg: + * + * The output of the DSA algorithm consists of a pair of integers + * usually referred by the pair (r, s). The signature value consists of + * the base64 encoding of the concatenation of two octet-streams that + * respectively result from the octet-encoding of the values r and s in + * that order. Integer to octet-stream conversion must be done according + * to the I2OSP operation defined in the RFC 2437 [PKCS1] specification + * with a l parameter equal to 20. For example, the SignatureValue element + * for a DSA signature (r, s) with values specified in hexadecimal: + * + * r = 8BAC1AB6 6410435C B7181F95 B16AB97C 92B341C0 + * s = 41E2345F 1F56DF24 58F426D1 55B4BA2D B6DCD8C8 + * + * from the example in Appendix 5 of the DSS standard would be + * + * <SignatureValue>i6watmQQQ1y3GB+VsWq5fJKzQcBB4jRfH1bfJFj0JtFVtLotttzYyA==</SignatureValue> + * + ***************************************************************************/ +#ifndef XMLSEC_OPENSSL_096 +static int +xmlSecOpenSSLDsaSha1EvpInit(EVP_MD_CTX *ctx) +{ + return SHA1_Init(ctx->md_data); +} + +static int +xmlSecOpenSSLDsaSha1EvpUpdate(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return SHA1_Update(ctx->md_data,data,count); +} + +static int +xmlSecOpenSSLDsaSha1EvpFinal(EVP_MD_CTX *ctx, unsigned char *md) +{ + return SHA1_Final(md,ctx->md_data); +} +#endif /* XMLSEC_OPENSSL_096 */ + +static int +xmlSecOpenSSLDsaSha1EvpSign(int type ATTRIBUTE_UNUSED, + const unsigned char *dgst, unsigned int dlen, + unsigned char *sig, unsigned int *siglen, void *dsa) { + DSA_SIG *s; + int rSize, sSize; + + s = DSA_do_sign(dgst, dlen, dsa); + if(s == NULL) { + *siglen=0; + return(0); + } + + rSize = BN_num_bytes(s->r); + sSize = BN_num_bytes(s->s); + if((rSize > (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2)) || + (sSize > (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2))) { + + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "size(r)=%d or size(s)=%d > %d", + rSize, sSize, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2); + DSA_SIG_free(s); + return(0); + } + + memset(sig, 0, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE); + BN_bn2bin(s->r, sig + (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2) - rSize); + BN_bn2bin(s->s, sig + XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE - sSize); + *siglen = XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE; + + DSA_SIG_free(s); + return(1); +} + +static int +xmlSecOpenSSLDsaSha1EvpVerify(int type ATTRIBUTE_UNUSED, + const unsigned char *dgst, unsigned int dgst_len, + const unsigned char *sigbuf, unsigned int siglen, + void *dsa) { + DSA_SIG *s; + int ret = -1; + + s = DSA_SIG_new(); + if (s == NULL) { + return(ret); + } + + if(siglen != XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "invalid length %d (%d expected)", + siglen, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE); + goto err; + } + + s->r = BN_bin2bn(sigbuf, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2, NULL); + s->s = BN_bin2bn(sigbuf + (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2), + XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2, NULL); + if((s->r == NULL) || (s->s == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_bin2bn", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto err; + } + + ret = DSA_do_verify(dgst, dgst_len, s, dsa); + +err: + DSA_SIG_free(s); + return(ret); +} + +static const EVP_MD xmlSecOpenSSLDsaMdEvp = { + NID_dsaWithSHA, + NID_dsaWithSHA, + SHA_DIGEST_LENGTH, +#ifndef XMLSEC_OPENSSL_096 + 0, + xmlSecOpenSSLDsaSha1EvpInit, + xmlSecOpenSSLDsaSha1EvpUpdate, + xmlSecOpenSSLDsaSha1EvpFinal, + NULL, + NULL, +#else /* XMLSEC_OPENSSL_096 */ + SHA1_Init, + SHA1_Update, + SHA1_Final, +#endif /* XMLSEC_OPENSSL_096 */ + xmlSecOpenSSLDsaSha1EvpSign, + xmlSecOpenSSLDsaSha1EvpVerify, + {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3,EVP_PKEY_DSA4,0}, + SHA_CBLOCK, + sizeof(EVP_MD *)+sizeof(SHA_CTX), +}; + +static const EVP_MD *xmlSecOpenSSLDsaSha1Evp(void) +{ + return(&xmlSecOpenSSLDsaMdEvp); +} +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 +/**************************************************************************** + * + * RSA-MD5 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaMd5Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaMd5, /* const xmlChar* name; */ + xmlSecHrefRsaMd5, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaMd5GetKlass: + * + * The RSA-MD5 signature transform klass. + * + * Returns: RSA-MD5 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaMd5GetKlass(void) { + return(&xmlSecOpenSSLRsaMd5Klass); +} + +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 +/**************************************************************************** + * + * RSA-RIPEMD160 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaRipemd160Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaRipemd160, /* const xmlChar* name; */ + xmlSecHrefRsaRipemd160, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaRipemd160GetKlass: + * + * The RSA-RIPEMD160 signature transform klass. + * + * Returns: RSA-RIPEMD160 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaRipemd160GetKlass(void) { + return(&xmlSecOpenSSLRsaRipemd160Klass); +} + +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 +/**************************************************************************** + * + * RSA-SHA1 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha1, /* const xmlChar* name; */ + xmlSecHrefRsaSha1, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaSha1GetKlass: + * + * The RSA-SHA1 signature transform klass. + * + * Returns: RSA-SHA1 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaSha1GetKlass(void) { + return(&xmlSecOpenSSLRsaSha1Klass); +} + +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA224 +/**************************************************************************** + * + * RSA-SHA224 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaSha224Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha224, /* const xmlChar* name; */ + xmlSecHrefRsaSha224, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaSha224GetKlass: + * + * The RSA-SHA224 signature transform klass. + * + * Returns: RSA-SHA224 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaSha224GetKlass(void) { + return(&xmlSecOpenSSLRsaSha224Klass); +} + +#endif /* XMLSEC_NO_SHA224 */ + +#ifndef XMLSEC_NO_SHA256 +/**************************************************************************** + * + * RSA-SHA256 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha256, /* const xmlChar* name; */ + xmlSecHrefRsaSha256, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaSha256GetKlass: + * + * The RSA-SHA256 signature transform klass. + * + * Returns: RSA-SHA256 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaSha256GetKlass(void) { + return(&xmlSecOpenSSLRsaSha256Klass); +} + +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 +/**************************************************************************** + * + * RSA-SHA384 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaSha384Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha384, /* const xmlChar* name; */ + xmlSecHrefRsaSha384, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaSha384GetKlass: + * + * The RSA-SHA384 signature transform klass. + * + * Returns: RSA-SHA384 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaSha384GetKlass(void) { + return(&xmlSecOpenSSLRsaSha384Klass); +} + +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 +/**************************************************************************** + * + * RSA-SHA512 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecOpenSSLRsaSha512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha512, /* const xmlChar* name; */ + xmlSecHrefRsaSha512, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLTransformRsaSha512GetKlass: + * + * The RSA-SHA512 signature transform klass. + * + * Returns: RSA-SHA512 signature transform klass. + */ +xmlSecTransformId +xmlSecOpenSSLTransformRsaSha512GetKlass(void) { + return(&xmlSecOpenSSLRsaSha512Klass); +} + +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + + diff --git a/src/openssl/symkeys.c b/src/openssl/symkeys.c new file mode 100644 index 00000000..6195ed6d --- /dev/null +++ b/src/openssl/symkeys.c @@ -0,0 +1,447 @@ +/** + * + * XMLSec library + * + * DES Algorithm support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <openssl/rand.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> + +/***************************************************************************** + * + * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary + * + ****************************************************************************/ +static int xmlSecOpenSSLSymKeyDataInitialize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLSymKeyDataDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecOpenSSLSymKeyDataFinalize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLSymKeyDataXmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLSymKeyDataXmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLSymKeyDataBinRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + const xmlSecByte* buf, + xmlSecSize bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLSymKeyDataBinWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlSecByte** buf, + xmlSecSize* bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLSymKeyDataGenerate (xmlSecKeyDataPtr data, + xmlSecSize sizeBits, + xmlSecKeyDataType type); + +static xmlSecKeyDataType xmlSecOpenSSLSymKeyDataGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecOpenSSLSymKeyDataGetSize (xmlSecKeyDataPtr data); +static void xmlSecOpenSSLSymKeyDataDebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecOpenSSLSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); +static int xmlSecOpenSSLSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass); + +#define xmlSecOpenSSLSymKeyDataCheckId(data) \ + (xmlSecKeyDataIsValid((data)) && \ + xmlSecOpenSSLSymKeyDataKlassCheck((data)->id)) + +static int +xmlSecOpenSSLSymKeyDataInitialize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), -1); + + return(xmlSecKeyDataBinaryValueInitialize(data)); +} + +static int +xmlSecOpenSSLSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(dst), -1); + xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(src), -1); + xmlSecAssert2(dst->id == src->id, -1); + + return(xmlSecKeyDataBinaryValueDuplicate(dst, src)); +} + +static void +xmlSecOpenSSLSymKeyDataFinalize(xmlSecKeyDataPtr data) { + xmlSecAssert(xmlSecOpenSSLSymKeyDataCheckId(data)); + + xmlSecKeyDataBinaryValueFinalize(data); +} + +static int +xmlSecOpenSSLSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx)); +} + +static int +xmlSecOpenSSLSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx)); +} + +static int +xmlSecOpenSSLSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + const xmlSecByte* buf, xmlSecSize bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx)); +} + +static int +xmlSecOpenSSLSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlSecByte** buf, xmlSecSize* bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx)); +} + +static int +xmlSecOpenSSLSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), -1); + xmlSecAssert2(sizeBits > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecOpenSSLGenerateRandom(buffer, (sizeBits + 7) / 8)); +} + +static xmlSecKeyDataType +xmlSecOpenSSLSymKeyDataGetType(xmlSecKeyDataPtr data) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown); + + return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown); +} + +static xmlSecSize +xmlSecOpenSSLSymKeyDataGetSize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), 0); + + return(xmlSecKeyDataBinaryValueGetSize(data)); +} + +static void +xmlSecOpenSSLSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecOpenSSLSymKeyDataCheckId(data)); + + xmlSecKeyDataBinaryValueDebugDump(data, output); +} + +static void +xmlSecOpenSSLSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecOpenSSLSymKeyDataCheckId(data)); + + xmlSecKeyDataBinaryValueDebugXmlDump(data, output); +} + +static int +xmlSecOpenSSLSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) { +#ifndef XMLSEC_NO_DES + if(klass == xmlSecOpenSSLKeyDataDesId) { + return(1); + } +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES +#ifndef XMLSEC_OPENSSL_096 + if(klass == xmlSecOpenSSLKeyDataAesId) { + return(1); + } +#endif /* XMLSEC_OPENSSL_096 */ +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_HMAC + if(klass == xmlSecOpenSSLKeyDataHmacId) { + return(1); + } +#endif /* XMLSEC_NO_HMAC */ + + return(0); +} + +#ifndef XMLSEC_NO_AES +#ifndef XMLSEC_OPENSSL_096 +/************************************************************************** + * + * <xmlsec:AESKeyValue> processing + * + *************************************************************************/ +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataAesKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecKeyDataBinarySize, + + /* data */ + xmlSecNameAESKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefAESKeyValue, /* const xmlChar* href; */ + xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecOpenSSLSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecOpenSSLSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecOpenSSLSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecOpenSSLSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecOpenSSLSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecOpenSSLSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecOpenSSLSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecOpenSSLSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecOpenSSLSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + xmlSecOpenSSLSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecOpenSSLSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecOpenSSLSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataAesGetKlass: + * + * The AES key data klass. + * + * Returns: AES key data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataAesGetKlass(void) { + return(&xmlSecOpenSSLKeyDataAesKlass); +} + +/** + * xmlSecOpenSSLKeyDataAesSet: + * @data: the pointer to AES key data. + * @buf: the pointer to key value. + * @bufSize: the key value size (in bytes). + * + * Sets the value of AES key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataAesId), -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecBufferSetData(buffer, buf, bufSize)); +} + +#endif /* XMLSEC_OPENSSL_096 */ +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES +/************************************************************************** + * + * <xmlsec:DESKeyValue> processing + * + *************************************************************************/ +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataDesKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecKeyDataBinarySize, + + /* data */ + xmlSecNameDESKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefDESKeyValue, /* const xmlChar* href; */ + xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecOpenSSLSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecOpenSSLSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecOpenSSLSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecOpenSSLSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecOpenSSLSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecOpenSSLSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecOpenSSLSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecOpenSSLSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecOpenSSLSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + xmlSecOpenSSLSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecOpenSSLSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecOpenSSLSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataDesGetKlass: + * + * The DES key data klass. + * + * Returns: DES key data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataDesGetKlass(void) { + return(&xmlSecOpenSSLKeyDataDesKlass); +} + +/** + * xmlSecOpenSSLKeyDataDesSet: + * @data: the pointer to DES key data. + * @buf: the pointer to key value. + * @bufSize: the key value size (in bytes). + * + * Sets the value of DES key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDesId), -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecBufferSetData(buffer, buf, bufSize)); +} + +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_HMAC +/************************************************************************** + * + * <xmlsec:HMACKeyValue> processing + * + *************************************************************************/ +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataHmacKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecKeyDataBinarySize, + + /* data */ + xmlSecNameHMACKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefHMACKeyValue, /* const xmlChar* href; */ + xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecOpenSSLSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecOpenSSLSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecOpenSSLSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecOpenSSLSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecOpenSSLSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecOpenSSLSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecOpenSSLSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecOpenSSLSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecOpenSSLSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + xmlSecOpenSSLSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecOpenSSLSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecOpenSSLSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataHmacGetKlass: + * + * The HMAC key data klass. + * + * Returns: HMAC key data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataHmacGetKlass(void) { + return(&xmlSecOpenSSLKeyDataHmacKlass); +} + +/** + * xmlSecOpenSSLKeyDataHmacSet: + * @data: the pointer to HMAC key data. + * @buf: the pointer to key value. + * @bufSize: the key value size (in bytes). + * + * Sets the value of HMAC key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataHmacId), -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecBufferSetData(buffer, buf, bufSize)); +} + +#endif /* XMLSEC_NO_HMAC */ + diff --git a/src/openssl/x509.c b/src/openssl/x509.c new file mode 100644 index 00000000..459a312d --- /dev/null +++ b/src/openssl/x509.c @@ -0,0 +1,2414 @@ +/** + * XMLSec library + * + * X509 support + * + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#ifndef XMLSEC_NO_X509 + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> + +#include <libxml/tree.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/x509_vfy.h> +#include <openssl/x509v3.h> +#include <openssl/asn1.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/x509.h> +#include <xmlsec/base64.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> +#include <xmlsec/openssl/x509.h> + +/************************************************************************* + * + * X509 utility functions + * + ************************************************************************/ +static int xmlSecOpenSSLX509DataNodeRead (xmlSecKeyDataPtr data, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509CertificateNodeRead (xmlSecKeyDataPtr data, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509CertificateNodeWrite (X509* cert, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509SubjectNameNodeRead (xmlSecKeyDataPtr data, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509SubjectNameNodeWrite (X509* cert, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509IssuerSerialNodeRead (xmlSecKeyDataPtr data, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509IssuerSerialNodeWrite (X509* cert, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509SKINodeRead (xmlSecKeyDataPtr data, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509SKINodeWrite (X509* cert, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509CRLNodeRead (xmlSecKeyDataPtr data, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLX509CRLNodeWrite (X509_CRL* crl, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, + xmlSecKeyPtr key, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static X509* xmlSecOpenSSLX509CertDerRead (const xmlSecByte* buf, + xmlSecSize size); +static X509* xmlSecOpenSSLX509CertBase64DerRead (xmlChar* buf); +static xmlChar* xmlSecOpenSSLX509CertBase64DerWrite (X509* cert, + int base64LineWrap); +static X509_CRL* xmlSecOpenSSLX509CrlDerRead (xmlSecByte* buf, + xmlSecSize size); +static X509_CRL* xmlSecOpenSSLX509CrlBase64DerRead (xmlChar* buf); +static xmlChar* xmlSecOpenSSLX509CrlBase64DerWrite (X509_CRL* crl, + int base64LineWrap); +static xmlChar* xmlSecOpenSSLX509NameWrite (X509_NAME* nm); +static xmlChar* xmlSecOpenSSLASN1IntegerWrite (ASN1_INTEGER *asni); +static xmlChar* xmlSecOpenSSLX509SKIWrite (X509* cert); +static void xmlSecOpenSSLX509CertDebugDump (X509* cert, + FILE* output); +static void xmlSecOpenSSLX509CertDebugXmlDump (X509* cert, + FILE* output); +static int xmlSecOpenSSLX509CertGetTime (ASN1_TIME* t, + time_t* res); + +/************************************************************************* + * + * Internal OpenSSL X509 data CTX + * + ************************************************************************/ +typedef struct _xmlSecOpenSSLX509DataCtx xmlSecOpenSSLX509DataCtx, + *xmlSecOpenSSLX509DataCtxPtr; +struct _xmlSecOpenSSLX509DataCtx { + X509* keyCert; + STACK_OF(X509)* certsList; + STACK_OF(X509_CRL)* crlsList; +}; + +/************************************************************************** + * + * <dsig:X509Data> processing + * + * + * The X509Data Element (http://www.w3.org/TR/xmldsig-core/#sec-X509Data) + * + * An X509Data element within KeyInfo contains one or more identifiers of keys + * or X509 certificates (or certificates' identifiers or a revocation list). + * The content of X509Data is: + * + * 1. At least one element, from the following set of element types; any of these may appear together or more than once iff (if and only if) each instance describes or is related to the same certificate: + * 2. + * * The X509IssuerSerial element, which contains an X.509 issuer + * distinguished name/serial number pair that SHOULD be compliant + * with RFC2253 [LDAP-DN], + * * The X509SubjectName element, which contains an X.509 subject + * distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN], + * * The X509SKI element, which contains the base64 encoded plain (i.e. + * non-DER-encoded) value of a X509 V.3 SubjectKeyIdentifier extension. + * * The X509Certificate element, which contains a base64-encoded [X509v3] + * certificate, and + * * Elements from an external namespace which accompanies/complements any + * of the elements above. + * * The X509CRL element, which contains a base64-encoded certificate + * revocation list (CRL) [X509v3]. + * + * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear + * MUST refer to the certificate or certificates containing the validation key. + * All such elements that refer to a particular individual certificate MUST be + * grouped inside a single X509Data element and if the certificate to which + * they refer appears, it MUST also be in that X509Data element. + * + * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that relate to + * the same key but different certificates MUST be grouped within a single + * KeyInfo but MAY occur in multiple X509Data elements. + * + * All certificates appearing in an X509Data element MUST relate to the + * validation key by either containing it or being part of a certification + * chain that terminates in a certificate containing the validation key. + * + * No ordering is implied by the above constraints. + * + * Note, there is no direct provision for a PKCS#7 encoded "bag" of + * certificates or CRLs. However, a set of certificates and CRLs can occur + * within an X509Data element and multiple X509Data elements can occur in a + * KeyInfo. Whenever multiple certificates occur in an X509Data element, at + * least one such certificate must contain the public key which verifies the + * signature. + * + * Schema Definition + * + * <element name="X509Data" type="ds:X509DataType"/> + * <complexType name="X509DataType"> + * <sequence maxOccurs="unbounded"> + * <choice> + * <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/> + * <element name="X509SKI" type="base64Binary"/> + * <element name="X509SubjectName" type="string"/> + * <element name="X509Certificate" type="base64Binary"/> + * <element name="X509CRL" type="base64Binary"/> + * <any namespace="##other" processContents="lax"/> + * </choice> + * </sequence> + * </complexType> + * <complexType name="X509IssuerSerialType"> + * <sequence> + * <element name="X509IssuerName" type="string"/> + * <element name="X509SerialNumber" type="integer"/> + * </sequence> + * </complexType> + * + * DTD + * + * <!ELEMENT X509Data ((X509IssuerSerial | X509SKI | X509SubjectName | + * X509Certificate | X509CRL)+ %X509.ANY;)> + * <!ELEMENT X509IssuerSerial (X509IssuerName, X509SerialNumber) > + * <!ELEMENT X509IssuerName (#PCDATA) > + * <!ELEMENT X509SubjectName (#PCDATA) > + * <!ELEMENT X509SerialNumber (#PCDATA) > + * <!ELEMENT X509SKI (#PCDATA) > + * <!ELEMENT X509Certificate (#PCDATA) > + * <!ELEMENT X509CRL (#PCDATA) > + * + * ----------------------------------------------------------------------- + * + * xmlSecOpenSSLX509DataCtx is located after xmlSecTransform + * + *************************************************************************/ +#define xmlSecOpenSSLX509DataSize \ + (sizeof(xmlSecKeyData) + sizeof(xmlSecOpenSSLX509DataCtx)) +#define xmlSecOpenSSLX509DataGetCtx(data) \ + ((xmlSecOpenSSLX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData))) + +static int xmlSecOpenSSLKeyDataX509Initialize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLKeyDataX509Duplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecOpenSSLKeyDataX509Finalize (xmlSecKeyDataPtr data); +static int xmlSecOpenSSLKeyDataX509XmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecOpenSSLKeyDataX509XmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static xmlSecKeyDataType xmlSecOpenSSLKeyDataX509GetType (xmlSecKeyDataPtr data); +static const xmlChar* xmlSecOpenSSLKeyDataX509GetIdentifier (xmlSecKeyDataPtr data); + +static void xmlSecOpenSSLKeyDataX509DebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecOpenSSLKeyDataX509DebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); + + + +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataX509Klass = { + sizeof(xmlSecKeyDataKlass), + xmlSecOpenSSLX509DataSize, + + /* data */ + xmlSecNameX509Data, + xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefX509Data, /* const xmlChar* href; */ + xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */ + xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecOpenSSLKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecOpenSSLKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecOpenSSLKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + NULL, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecOpenSSLKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */ + NULL, /* xmlSecKeyDataGetSizeMethod getSize; */ + xmlSecOpenSSLKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecOpenSSLKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecOpenSSLKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + NULL, /* xmlSecKeyDataBinReadMethod binRead; */ + NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecOpenSSLKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecOpenSSLKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataX509GetKlass: + * + * The OpenSSL X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data). + * + * Returns: the X509 data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataX509GetKlass(void) { + return(&xmlSecOpenSSLKeyDataX509Klass); +} + +/** + * xmlSecOpenSSLKeyDataX509GetKeyCert: + * @data: the pointer to X509 key data. + * + * Gets the certificate from which the key was extracted. + * + * Returns: the key's certificate or NULL if key data was not used for key + * extraction or an error occurs. + */ +X509* +xmlSecOpenSSLKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, NULL); + + return(ctx->keyCert); +} + +/** + * xmlSecOpenSSLKeyDataX509AdoptKeyCert: + * @data: the pointer to X509 key data. + * @cert: the pointer to OpenSSL X509 certificate. + * + * Sets the key's certificate in @data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, X509* cert) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(cert != NULL, -1); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + if(ctx->keyCert != NULL) { + X509_free(ctx->keyCert); + } + ctx->keyCert = cert; + return(0); +} + +/** + * xmlSecOpenSSLKeyDataX509AdoptCert: + * @data: the pointer to X509 key data. + * @cert: the pointer to OpenSSL X509 certificate. + * + * Adds certificate to the X509 key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLKeyDataX509AdoptCert(xmlSecKeyDataPtr data, X509* cert) { + xmlSecOpenSSLX509DataCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(cert != NULL, -1); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + if(ctx->certsList == NULL) { + ctx->certsList = sk_X509_new_null(); + if(ctx->certsList == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "sk_X509_new_null", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + ret = sk_X509_push(ctx->certsList, cert); + if(ret < 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "sk_X509_push", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLKeyDataX509GetCert: + * @data: the pointer to X509 key data. + * @pos: the desired certificate position. + * + * Gets a certificate from X509 key data. + * + * Returns: the pointer to certificate or NULL if @pos is larger than the + * number of certificates in @data or an error occurs. + */ +X509* +xmlSecOpenSSLKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, NULL); + xmlSecAssert2(ctx->certsList != NULL, NULL); + xmlSecAssert2((int)pos < sk_X509_num(ctx->certsList), NULL); + + return(sk_X509_value(ctx->certsList, pos)); +} + +/** + * xmlSecOpenSSLKeyDataX509GetCertsSize: + * @data: the pointer to X509 key data. + * + * Gets the number of certificates in @data. + * + * Returns: te number of certificates in @data. + */ +xmlSecSize +xmlSecOpenSSLKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), 0); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, 0); + + return((ctx->certsList != NULL) ? sk_X509_num(ctx->certsList) : 0); +} + +/** + * xmlSecOpenSSLKeyDataX509AdoptCrl: + * @data: the pointer to X509 key data. + * @crl: the pointer to OpenSSL X509 CRL. + * + * Adds CRL to the X509 key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, X509_CRL* crl) { + xmlSecOpenSSLX509DataCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(crl != NULL, -1); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + if(ctx->crlsList == NULL) { + ctx->crlsList = sk_X509_CRL_new_null(); + if(ctx->crlsList == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "sk_X509_CRL_new_null", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + ret = sk_X509_CRL_push(ctx->crlsList, crl); + if(ret < 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "sk_X509_CRL_push", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecOpenSSLKeyDataX509GetCrl: + * @data: the pointer to X509 key data. + * @pos: the desired CRL position. + * + * Gets a CRL from X509 key data. + * + * Returns: the pointer to CRL or NULL if @pos is larger than the + * number of CRLs in @data or an error occurs. + */ +X509_CRL* +xmlSecOpenSSLKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, NULL); + + xmlSecAssert2(ctx->crlsList != NULL, NULL); + xmlSecAssert2((int)pos < sk_X509_CRL_num(ctx->crlsList), NULL); + + return(sk_X509_CRL_value(ctx->crlsList, pos)); +} + +/** + * xmlSecOpenSSLKeyDataX509GetCrlsSize: + * @data: the pointer to X509 key data. + * + * Gets the number of CRLs in @data. + * + * Returns: te number of CRLs in @data. + */ +xmlSecSize +xmlSecOpenSSLKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), 0); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, 0); + + return((ctx->crlsList != NULL) ? sk_X509_CRL_num(ctx->crlsList) : 0); +} + +static int +xmlSecOpenSSLKeyDataX509Initialize(xmlSecKeyDataPtr data) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLX509DataCtx)); + return(0); +} + +static int +xmlSecOpenSSLKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + X509* certSrc; + X509* certDst; + X509_CRL* crlSrc; + X509_CRL* crlDst; + xmlSecSize size, pos; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecOpenSSLKeyDataX509Id), -1); + + /* copy certsList */ + size = xmlSecOpenSSLKeyDataX509GetCertsSize(src); + for(pos = 0; pos < size; ++pos) { + certSrc = xmlSecOpenSSLKeyDataX509GetCert(src, pos); + if(certSrc == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)), + "xmlSecOpenSSLKeyDataX509GetCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + + certDst = X509_dup(certSrc); + if(certDst == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(dst, certDst); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(certDst); + return(-1); + } + } + + /* copy crls */ + size = xmlSecOpenSSLKeyDataX509GetCrlsSize(src); + for(pos = 0; pos < size; ++pos) { + crlSrc = xmlSecOpenSSLKeyDataX509GetCrl(src, pos); + if(crlSrc == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)), + "xmlSecOpenSSLKeyDataX509GetCrl", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + + crlDst = X509_CRL_dup(crlSrc); + if(crlDst == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "X509_CRL_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCrl(dst, crlDst); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "xmlSecOpenSSLKeyDataX509AdoptCrl", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_CRL_free(crlDst); + return(-1); + } + } + + /* copy key cert if exist */ + certSrc = xmlSecOpenSSLKeyDataX509GetKeyCert(src); + if(certSrc != NULL) { + certDst = X509_dup(certSrc); + if(certDst == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(dst, certDst); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "xmlSecOpenSSLKeyDataX509AdoptKeyCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(certDst); + return(-1); + } + } + return(0); +} + +static void +xmlSecOpenSSLKeyDataX509Finalize(xmlSecKeyDataPtr data) { + xmlSecOpenSSLX509DataCtxPtr ctx; + + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id)); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert(ctx != NULL); + + if(ctx->certsList != NULL) { + sk_X509_pop_free(ctx->certsList, X509_free); + } + if(ctx->crlsList != NULL) { + sk_X509_CRL_pop_free(ctx->crlsList, X509_CRL_free); + } + if(ctx->keyCert != NULL) { + X509_free(ctx->keyCert); + } + memset(ctx, 0, sizeof(xmlSecOpenSSLX509DataCtx)); +} + +static int +xmlSecOpenSSLKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataPtr data; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataX509Id, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + data = xmlSecKeyEnsureData(key, id); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeyEnsureData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecOpenSSLX509DataNodeRead(data, node, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLX509DataNodeRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) { + ret = xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLKeyDataX509VerifyAndExtractKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + return(0); +} + +static int +xmlSecOpenSSLKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataPtr data; + X509* cert; + X509_CRL* crl; + xmlSecSize size, pos; + int content; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataX509Id, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + content = xmlSecX509DataGetNodeContent (node, 1, keyInfoCtx); + if (content < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecX509DataGetNodeContent", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "content=%d", content); + return(-1); + } else if(content == 0) { + /* by default we are writing certificates and crls */ + content = XMLSEC_X509DATA_DEFAULT; + } + + /* get x509 data */ + data = xmlSecKeyGetData(key, id); + if(data == NULL) { + /* no x509 data in the key */ + return(0); + } + + /* write certs */ + size = xmlSecOpenSSLKeyDataX509GetCertsSize(data); + for(pos = 0; pos < size; ++pos) { + cert = xmlSecOpenSSLKeyDataX509GetCert(data, pos); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLKeyDataX509GetCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + + if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) { + ret = xmlSecOpenSSLX509CertificateNodeWrite(cert, node, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLX509CertificateNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + } + + if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) { + ret = xmlSecOpenSSLX509SubjectNameNodeWrite(cert, node, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLX509SubjectNameNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + } + + if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) { + ret = xmlSecOpenSSLX509IssuerSerialNodeWrite(cert, node, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLX509IssuerSerialNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + } + + if((content & XMLSEC_X509DATA_SKI_NODE) != 0) { + ret = xmlSecOpenSSLX509SKINodeWrite(cert, node, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLX509SKINodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + } + } + + /* write crls if needed */ + if((content & XMLSEC_X509DATA_CRL_NODE) != 0) { + size = xmlSecOpenSSLKeyDataX509GetCrlsSize(data); + for(pos = 0; pos < size; ++pos) { + crl = xmlSecOpenSSLKeyDataX509GetCrl(data, pos); + if(crl == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLKeyDataX509GetCrl", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + + ret = xmlSecOpenSSLX509CRLNodeWrite(crl, node, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLX509CRLNodeWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return(-1); + } + } + } + + return(0); +} + + +static xmlSecKeyDataType +xmlSecOpenSSLKeyDataX509GetType(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), xmlSecKeyDataTypeUnknown); + + /* TODO: return verified/not verified status */ + return(xmlSecKeyDataTypeUnknown); +} + +static const xmlChar* +xmlSecOpenSSLKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL); + + /* TODO */ + return(NULL); +} + +static void +xmlSecOpenSSLKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) { + X509* cert; + xmlSecSize size, pos; + + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id)); + xmlSecAssert(output != NULL); + + fprintf(output, "=== X509 Data:\n"); + cert = xmlSecOpenSSLKeyDataX509GetKeyCert(data); + if(cert != NULL) { + fprintf(output, "==== Key Certificate:\n"); + xmlSecOpenSSLX509CertDebugDump(cert, output); + } + + size = xmlSecOpenSSLKeyDataX509GetCertsSize(data); + for(pos = 0; pos < size; ++pos) { + cert = xmlSecOpenSSLKeyDataX509GetCert(data, pos); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509GetCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return; + } + fprintf(output, "==== Certificate:\n"); + xmlSecOpenSSLX509CertDebugDump(cert, output); + } + + /* we don't print out crls */ +} + +static void +xmlSecOpenSSLKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + X509* cert; + xmlSecSize size, pos; + + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id)); + xmlSecAssert(output != NULL); + + fprintf(output, "<X509Data>\n"); + cert = xmlSecOpenSSLKeyDataX509GetKeyCert(data); + if(cert != NULL) { + fprintf(output, "<KeyCertificate>\n"); + xmlSecOpenSSLX509CertDebugXmlDump(cert, output); + fprintf(output, "</KeyCertificate>\n"); + } + + size = xmlSecOpenSSLKeyDataX509GetCertsSize(data); + for(pos = 0; pos < size; ++pos) { + cert = xmlSecOpenSSLKeyDataX509GetCert(data, pos); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509GetCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "pos=%d", pos); + return; + } + fprintf(output, "<Certificate>\n"); + xmlSecOpenSSLX509CertDebugXmlDump(cert, output); + fprintf(output, "</Certificate>\n"); + } + + /* we don't print out crls */ + fprintf(output, "</X509Data>\n"); +} + +static int +xmlSecOpenSSLX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlNodePtr cur; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + for(cur = xmlSecGetNextElementNode(node->children); + cur != NULL; + cur = xmlSecGetNextElementNode(cur->next)) { + + ret = 0; + if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) { + ret = xmlSecOpenSSLX509CertificateNodeRead(data, cur, keyInfoCtx); + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) { + ret = xmlSecOpenSSLX509SubjectNameNodeRead(data, cur, keyInfoCtx); + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) { + ret = xmlSecOpenSSLX509IssuerSerialNodeRead(data, cur, keyInfoCtx); + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) { + ret = xmlSecOpenSSLX509SKINodeRead(data, cur, keyInfoCtx); + } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) { + ret = xmlSecOpenSSLX509CRLNodeRead(data, cur, keyInfoCtx); + } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CHILD) != 0) { + /* laxi schema validation: ignore unknown nodes */ + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "read node failed"); + return(-1); + } + } + return(0); +} + +static int +xmlSecOpenSSLX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlChar *content; + X509* cert; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + content = xmlNodeGetContent(node); + if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) { + if(content != NULL) { + xmlFree(content); + } + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(node)), + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); + } + + cert = xmlSecOpenSSLX509CertBase64DerRead(content); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLX509CertBase64DerRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFree(content); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert); + xmlFree(content); + return(-1); + } + + xmlFree(content); + return(0); +} + +static int +xmlSecOpenSSLX509CertificateNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlChar* buf; + xmlNodePtr cur; + + xmlSecAssert2(cert != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + /* set base64 lines size from context */ + buf = xmlSecOpenSSLX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509CertBase64DerWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509Certificate)); + xmlFree(buf); + return(-1); + } + + /* todo: add \n around base64 data - from context */ + /* todo: add errors check */ + xmlNodeSetContent(cur, xmlSecStringCR); + xmlNodeSetContent(cur, buf); + xmlFree(buf); + return(0); +} + +static int +xmlSecOpenSSLX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataStorePtr x509Store; + xmlChar* subject; + X509* cert; + X509* cert2; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); + + x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + subject = xmlNodeGetContent(node); + if((subject == NULL) || (xmlSecIsEmptyString(subject) == 1)) { + if(subject != NULL) { + xmlFree(subject); + } + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(node)), + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); + } + + cert = xmlSecOpenSSLX509StoreFindCert(x509Store, subject, NULL, NULL, NULL, keyInfoCtx); + if(cert == NULL){ + + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + NULL, + XMLSEC_ERRORS_R_CERT_NOT_FOUND, + "subject=%s", + xmlSecErrorsSafeString(subject)); + xmlFree(subject); + return(-1); + } + + xmlFree(subject); + return(0); + } + + cert2 = X509_dup(cert); + if(cert2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + + xmlFree(subject); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert2); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert2); + xmlFree(subject); + return(-1); + } + + xmlFree(subject); + return(0); +} + +static int +xmlSecOpenSSLX509SubjectNameNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) { + xmlChar* buf = NULL; + xmlNodePtr cur = NULL; + + xmlSecAssert2(cert != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + buf = xmlSecOpenSSLX509NameWrite(X509_get_subject_name(cert)); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameWrite(X509_get_subject_name)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509SubjectName)); + xmlFree(buf); + return(-1); + } + xmlSecNodeEncodeAndSetContent(cur, buf); + xmlFree(buf); + return(0); +} + +static int +xmlSecOpenSSLX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataStorePtr x509Store; + xmlNodePtr cur; + xmlChar *issuerName; + xmlChar *issuerSerial; + X509* cert; + X509* cert2; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); + + x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecGetNextElementNode(node->children); + if(cur == NULL) { + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeX509IssuerName), + XMLSEC_ERRORS_R_NODE_NOT_FOUND, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); + return(-1); + } + return(0); + } + + /* the first is required node X509IssuerName */ + if(!xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeX509IssuerName), + XMLSEC_ERRORS_R_NODE_NOT_FOUND, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); + return(-1); + } + issuerName = xmlNodeGetContent(cur); + if(issuerName == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509IssuerName)); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is required node X509SerialNumber */ + if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_NODE_NOT_FOUND, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber)); + xmlFree(issuerName); + return(-1); + } + issuerSerial = xmlNodeGetContent(cur); + if(issuerSerial == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber), + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); + xmlFree(issuerName); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFree(issuerSerial); + xmlFree(issuerName); + return(-1); + } + + cert = xmlSecOpenSSLX509StoreFindCert(x509Store, NULL, issuerName, issuerSerial, NULL, keyInfoCtx); + if(cert == NULL){ + + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + NULL, + XMLSEC_ERRORS_R_CERT_NOT_FOUND, + "issuerName=%s;issuerSerial=%s", + xmlSecErrorsSafeString(issuerName), + xmlSecErrorsSafeString(issuerSerial)); + xmlFree(issuerSerial); + xmlFree(issuerName); + return(-1); + } + xmlFree(issuerSerial); + xmlFree(issuerName); + return(0); + } + + cert2 = X509_dup(cert); + if(cert2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFree(issuerSerial); + xmlFree(issuerName); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert2); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert2); + xmlFree(issuerSerial); + xmlFree(issuerName); + return(-1); + } + + xmlFree(issuerSerial); + xmlFree(issuerName); + return(0); +} + +static int +xmlSecOpenSSLX509IssuerSerialNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) { + xmlNodePtr cur; + xmlNodePtr issuerNameNode; + xmlNodePtr issuerNumberNode; + xmlChar* buf; + + xmlSecAssert2(cert != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + /* create xml nodes */ + cur = xmlSecAddChild(node, xmlSecNodeX509IssuerSerial, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial)); + return(-1); + } + + issuerNameNode = xmlSecAddChild(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs); + if(issuerNameNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509IssuerName)); + return(-1); + } + + issuerNumberNode = xmlSecAddChild(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs); + if(issuerNumberNode == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber)); + return(-1); + } + + /* write data */ + buf = xmlSecOpenSSLX509NameWrite(X509_get_issuer_name(cert)); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameWrite(X509_get_issuer_name)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + xmlSecNodeEncodeAndSetContent(issuerNameNode, buf); + xmlFree(buf); + + buf = xmlSecOpenSSLASN1IntegerWrite(X509_get_serialNumber(cert)); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLASN1IntegerWrite(X509_get_serialNumber)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + xmlSecNodeEncodeAndSetContent(issuerNumberNode, buf); + xmlFree(buf); + + return(0); +} + + +static int +xmlSecOpenSSLX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataStorePtr x509Store; + xmlChar* ski; + X509* cert; + X509* cert2; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); + + x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ski = xmlNodeGetContent(node); + if((ski == NULL) || (xmlSecIsEmptyString(ski) == 1)) { + if(ski != NULL) { + xmlFree(ski); + } + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(node)), + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509SKI)); + return(-1); + } + return(0); + } + + cert = xmlSecOpenSSLX509StoreFindCert(x509Store, NULL, NULL, NULL, ski, keyInfoCtx); + if(cert == NULL){ + xmlFree(ski); + + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + NULL, + XMLSEC_ERRORS_R_CERT_NOT_FOUND, + "ski=%s", + xmlSecErrorsSafeString(ski)); + return(-1); + } + return(0); + } + + cert2 = X509_dup(cert); + if(cert2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFree(ski); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert2); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert2); + xmlFree(ski); + return(-1); + } + + xmlFree(ski); + return(0); +} + +static int +xmlSecOpenSSLX509SKINodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) { + xmlChar *buf = NULL; + xmlNodePtr cur = NULL; + + xmlSecAssert2(cert != NULL, -1); + xmlSecAssert2(node != NULL, -1); + + buf = xmlSecOpenSSLX509SKIWrite(cert); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509SKIWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "new_node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509SKI)); + xmlFree(buf); + return(-1); + } + xmlSecNodeEncodeAndSetContent(cur, buf); + xmlFree(buf); + + return(0); +} + +static int +xmlSecOpenSSLX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlChar *content; + X509_CRL* crl; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + content = xmlNodeGetContent(node); + if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) { + if(content != NULL) { + xmlFree(content); + } + if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + xmlSecErrorsSafeString(xmlSecNodeGetName(node)), + XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); + } + + crl = xmlSecOpenSSLX509CrlBase64DerRead(content); + if(crl == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLX509CrlBase64DerRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlFree(content); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCrl(data, crl); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLKeyDataX509AdoptCrl", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_CRL_free(crl); + xmlFree(content); + return(-1); + } + + xmlFree(content); + return(0); +} + +static int +xmlSecOpenSSLX509CRLNodeWrite(X509_CRL* crl, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlChar* buf = NULL; + xmlNodePtr cur = NULL; + + xmlSecAssert2(crl != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + /* set base64 lines size from context */ + buf = xmlSecOpenSSLX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509CrlBase64DerWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + cur = xmlSecAddChild(node, xmlSecNodeX509CRL, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "new_node=%s", + xmlSecErrorsSafeString(xmlSecNodeX509CRL)); + xmlFree(buf); + return(-1); + } + /* todo: add \n around base64 data - from context */ + /* todo: add errors check */ + xmlNodeSetContent(cur, xmlSecStringCR); + xmlNodeSetContent(cur, buf); + xmlFree(buf); + + return(0); +} + +static int +xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key, + xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecOpenSSLX509DataCtxPtr ctx; + xmlSecKeyDataStorePtr x509Store; + int ret; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); + + ctx = xmlSecOpenSSLX509DataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if((ctx->keyCert == NULL) && (ctx->certsList != NULL) && (xmlSecKeyGetValue(key) == NULL)) { + X509* cert; + + cert = xmlSecOpenSSLX509StoreVerify(x509Store, ctx->certsList, ctx->crlsList, keyInfoCtx); + if(cert != NULL) { + xmlSecKeyDataPtr keyValue; + + ctx->keyCert = X509_dup(cert); + if(ctx->keyCert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + keyValue = xmlSecOpenSSLX509CertGetKey(ctx->keyCert); + if(keyValue == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLX509CertGetKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* verify that the key matches our expectations */ + if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), keyValue) != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeyReqMatchKeyValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(keyValue); + return(-1); + } + + ret = xmlSecKeySetValue(key, keyValue); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(keyValue); + return(-1); + } + + if((X509_get_notBefore(ctx->keyCert) != NULL) && (X509_get_notAfter(ctx->keyCert) != NULL)) { + ret = xmlSecOpenSSLX509CertGetTime(X509_get_notBefore(ctx->keyCert), &(key->notValidBefore)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLX509CertGetTime", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "notValidBefore"); + return(-1); + } + ret = xmlSecOpenSSLX509CertGetTime(X509_get_notAfter(ctx->keyCert), &(key->notValidAfter)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecOpenSSLX509CertGetTime", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "notValidAfter"); + return(-1); + } + } else { + key->notValidBefore = key->notValidAfter = 0; + } + } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_INVALID_CERT) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + NULL, + XMLSEC_ERRORS_R_CERT_NOT_FOUND, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + return(0); +} + +#ifdef HAVE_TIMEGM +extern time_t timegm (struct tm *tm); +#else /* HAVE_TIMEGM */ +#ifdef WIN32 +#define timegm(tm) (mktime(tm) - _timezone) +#else /* WIN32 */ +/* Absolutely not the best way but it's the only ANSI compatible way I know. + * If you system has a native struct tm --> GMT time_t conversion function + * (like timegm) use it instead. + */ +static time_t +my_timegm(struct tm *t) { + time_t tl, tb; + struct tm *tg; + + tl = mktime (t); + if(tl == -1) { + t->tm_hour--; + tl = mktime (t); + if (tl == -1) { + return -1; + } + tl += 3600; + } + tg = gmtime (&tl); + tg->tm_isdst = 0; + tb = mktime (tg); + if (tb == -1) { + tg->tm_hour--; + tb = mktime (tg); + if (tb == -1) { + return -1; + } + tb += 3600; + } + return (tl - (tb - tl)); +} + +#define timegm(tm) my_timegm(tm) +#endif /* WIN32 */ +#endif /* HAVE_TIMEGM */ + +static int +xmlSecOpenSSLX509CertGetTime(ASN1_TIME* t, time_t* res) { + struct tm tm; + int offset; + + xmlSecAssert2(t != NULL, -1); + xmlSecAssert2(res != NULL, -1); + + (*res) = 0; +#ifndef XMLSEC_OPENSSL_096 + if(!ASN1_TIME_check(t)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "ASN1_TIME_check", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } +#endif /* XMLSEC_OPENSSL_096 */ + + memset(&tm, 0, sizeof(tm)); + +#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0') + if(t->type == V_ASN1_UTCTIME) { + xmlSecAssert2(t->length > 12, -1); + + + /* this code is copied from OpenSSL asn1/a_utctm.c file */ + tm.tm_year = g2(t->data); + if(tm.tm_year < 50) { + tm.tm_year += 100; + } + tm.tm_mon = g2(t->data + 2) - 1; + tm.tm_mday = g2(t->data + 4); + tm.tm_hour = g2(t->data + 6); + tm.tm_min = g2(t->data + 8); + tm.tm_sec = g2(t->data + 10); + if(t->data[12] == 'Z') { + offset = 0; + } else { + xmlSecAssert2(t->length > 16, -1); + + offset = g2(t->data + 13) * 60 + g2(t->data + 15); + if(t->data[12] == '-') { + offset = -offset; + } + } + tm.tm_isdst = -1; + } else { + xmlSecAssert2(t->length > 14, -1); + + tm.tm_year = g2(t->data) * 100 + g2(t->data + 2); + tm.tm_mon = g2(t->data + 4) - 1; + tm.tm_mday = g2(t->data + 6); + tm.tm_hour = g2(t->data + 8); + tm.tm_min = g2(t->data + 10); + tm.tm_sec = g2(t->data + 12); + if(t->data[14] == 'Z') { + offset = 0; + } else { + xmlSecAssert2(t->length > 18, -1); + + offset = g2(t->data + 15) * 60 + g2(t->data + 17); + if(t->data[14] == '-') { + offset = -offset; + } + } + tm.tm_isdst = -1; + } +#undef g2 + (*res) = timegm(&tm) - offset * 60; + return(0); +} + +/** + * xmlSecOpenSSLX509CertGetKey: + * @cert: the certificate. + * + * Extracts public key from the @cert. + * + * Returns: public key value or NULL if an error occurs. + */ +xmlSecKeyDataPtr +xmlSecOpenSSLX509CertGetKey(X509* cert) { + xmlSecKeyDataPtr data; + EVP_PKEY *pKey = NULL; + + xmlSecAssert2(cert != NULL, NULL); + + pKey = X509_get_pubkey(cert); + if(pKey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_get_pubkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + data = xmlSecOpenSSLEvpKeyAdopt(pKey); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLEvpKeyAdopt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + EVP_PKEY_free(pKey); + return(NULL); + } + + return(data); +} + +static X509* +xmlSecOpenSSLX509CertBase64DerRead(xmlChar* buf) { + int ret; + + xmlSecAssert2(buf != NULL, NULL); + + /* usual trick with base64 decoding "in-place" */ + ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBase64Decode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + return(xmlSecOpenSSLX509CertDerRead((xmlSecByte*)buf, ret)); +} + +static X509* +xmlSecOpenSSLX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) { + X509 *cert = NULL; + BIO *mem = NULL; + int ret; + + xmlSecAssert2(buf != NULL, NULL); + xmlSecAssert2(size > 0, NULL); + + mem = BIO_new(BIO_s_mem()); + if(mem == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "BIO_s_mem"); + return(NULL); + } + + ret = BIO_write(mem, buf, size); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_write", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", size); + BIO_free_all(mem); + return(NULL); + } + + cert = d2i_X509_bio(mem, NULL); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "d2i_X509_bio", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + BIO_free_all(mem); + return(cert); +} + +static xmlChar* +xmlSecOpenSSLX509CertBase64DerWrite(X509* cert, int base64LineWrap) { + xmlChar *res = NULL; + BIO *mem = NULL; + xmlSecByte *p = NULL; + long size; + + xmlSecAssert2(cert != NULL, NULL); + + mem = BIO_new(BIO_s_mem()); + if(mem == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "BIO_s_mem"); + return(NULL); + } + + /* todo: add error checks */ + i2d_X509_bio(mem, cert); + BIO_flush(mem); + + size = BIO_get_mem_data(mem, &p); + if((size <= 0) || (p == NULL)){ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_get_mem_data", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + res = xmlSecBase64Encode(p, size, base64LineWrap); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBase64Encode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + BIO_free_all(mem); + return(res); +} + +static X509_CRL* +xmlSecOpenSSLX509CrlBase64DerRead(xmlChar* buf) { + int ret; + + xmlSecAssert2(buf != NULL, NULL); + + /* usual trick with base64 decoding "in-place" */ + ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf)); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBase64Decode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + return(xmlSecOpenSSLX509CrlDerRead((xmlSecByte*)buf, ret)); +} + +static X509_CRL* +xmlSecOpenSSLX509CrlDerRead(xmlSecByte* buf, xmlSecSize size) { + X509_CRL *crl = NULL; + BIO *mem = NULL; + int ret; + + xmlSecAssert2(buf != NULL, NULL); + xmlSecAssert2(size > 0, NULL); + + mem = BIO_new(BIO_s_mem()); + if(mem == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "BIO_s_mem"); + return(NULL); + } + + ret = BIO_write(mem, buf, size); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_write", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", size); + BIO_free_all(mem); + return(NULL); + } + + crl = d2i_X509_CRL_bio(mem, NULL); + if(crl == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "d2i_X509_CRL_bio", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + BIO_free_all(mem); + return(crl); +} + +static xmlChar* +xmlSecOpenSSLX509CrlBase64DerWrite(X509_CRL* crl, int base64LineWrap) { + xmlChar *res = NULL; + BIO *mem = NULL; + xmlSecByte *p = NULL; + long size; + + xmlSecAssert2(crl != NULL, NULL); + + mem = BIO_new(BIO_s_mem()); + if(mem == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "BIO_s_mem"); + return(NULL); + } + + /* todo: add error checks */ + i2d_X509_CRL_bio(mem, crl); + BIO_flush(mem); + + size = BIO_get_mem_data(mem, &p); + if((size <= 0) || (p == NULL)){ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_get_mem_data", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + res = xmlSecBase64Encode(p, size, base64LineWrap); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBase64Encode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + BIO_free_all(mem); + return(res); +} + +static xmlChar* +xmlSecOpenSSLX509NameWrite(X509_NAME* nm) { + xmlChar *res = NULL; + BIO *mem = NULL; + long size; + + xmlSecAssert2(nm != NULL, NULL); + + mem = BIO_new(BIO_s_mem()); + if(mem == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BIO_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "BIO_s_mem"); + return(NULL); + } + + if (X509_NAME_print_ex(mem, nm, 0, XN_FLAG_RFC2253) <=0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_NAME_print_ex", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + BIO_flush(mem); /* should call flush ? */ + + size = BIO_pending(mem); + res = xmlMalloc(size + 1); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlMalloc", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BIO_free_all(mem); + return(NULL); + } + + size = BIO_read(mem, res, size); + res[size] = '\0'; + + BIO_free_all(mem); + return(res); +} + +static xmlChar* +xmlSecOpenSSLASN1IntegerWrite(ASN1_INTEGER *asni) { + xmlChar *res = NULL; + BIGNUM *bn; + char *p; + + xmlSecAssert2(asni != NULL, NULL); + + bn = ASN1_INTEGER_to_BN(asni, NULL); + if(bn == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "ASN1_INTEGER_to_BN", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + p = BN_bn2dec(bn); + if (p == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_bn2dec", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BN_free(bn); + return(NULL); + } + BN_free(bn); + bn = NULL; + + /* OpenSSL and LibXML2 can have different memory callbacks, i.e. + when data is allocated in OpenSSL should be freed with OpenSSL + method, not with LibXML2 method. + */ + res = xmlCharStrdup(p); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlCharStrdup", + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + OPENSSL_free(p); + return(NULL); + } + OPENSSL_free(p); + p = NULL; + return(res); +} + +static xmlChar* +xmlSecOpenSSLX509SKIWrite(X509* cert) { + xmlChar *res = NULL; + int index; + X509_EXTENSION *ext; + ASN1_OCTET_STRING *keyId; + + xmlSecAssert2(cert != NULL, NULL); + + index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if (index < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Certificate without SubjectKeyIdentifier extension", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + ext = X509_get_ext(cert, index); + if (ext == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_get_ext", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + keyId = X509V3_EXT_d2i(ext); + if (keyId == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509V3_EXT_d2i", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + M_ASN1_OCTET_STRING_free(keyId); + return(NULL); + } + + res = xmlSecBase64Encode(M_ASN1_STRING_data(keyId), M_ASN1_STRING_length(keyId), 0); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBase64Encode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + M_ASN1_OCTET_STRING_free(keyId); + return(NULL); + } + M_ASN1_OCTET_STRING_free(keyId); + + return(res); +} + +static void +xmlSecOpenSSLX509CertDebugDump(X509* cert, FILE* output) { + char buf[1024]; + BIGNUM *bn = NULL; + + xmlSecAssert(cert != NULL); + xmlSecAssert(output != NULL); + + fprintf(output, "==== Subject Name: %s\n", + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf))); + fprintf(output, "==== Issuer Name: %s\n", + X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf))); + fprintf(output, "==== Issuer Serial: "); + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert),NULL); + if(bn != NULL) { + BN_print_fp(output, bn); + BN_free(bn); + fprintf(output, "\n"); + } else { + fprintf(output, "unknown\n"); + } +} + + +static void +xmlSecOpenSSLX509CertDebugXmlDump(X509* cert, FILE* output) { + char buf[1024]; + BIGNUM *bn = NULL; + + xmlSecAssert(cert != NULL); + xmlSecAssert(output != NULL); + + fprintf(output, "<SubjectName>"); + xmlSecPrintXmlString(output, + BAD_CAST X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)) + ); + fprintf(output, "</SubjectName>\n"); + + + fprintf(output, "<IssuerName>"); + xmlSecPrintXmlString(output, + BAD_CAST X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf))); + fprintf(output, "</IssuerName>\n"); + + fprintf(output, "<SerialNumber>"); + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert),NULL); + if(bn != NULL) { + BN_print_fp(output, bn); + BN_free(bn); + } + fprintf(output, "</SerialNumber>\n"); +} + + +/************************************************************************** + * + * Raw X509 Certificate processing + * + * + *************************************************************************/ +static int xmlSecOpenSSLKeyDataRawX509CertBinRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + const xmlSecByte* buf, + xmlSecSize bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx); + +static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataRawX509CertKlass = { + sizeof(xmlSecKeyDataKlass), + sizeof(xmlSecKeyData), + + /* data */ + xmlSecNameRawX509Cert, + xmlSecKeyDataUsageRetrievalMethodNodeBin, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefRawX509Cert, /* const xmlChar* href; */ + NULL, /* const xmlChar* dataNodeName; */ + xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + NULL, /* xmlSecKeyDataInitializeMethod initialize; */ + NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */ + NULL, /* xmlSecKeyDataFinalizeMethod finalize; */ + NULL, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + NULL, /* xmlSecKeyDataGetTypeMethod getType; */ + NULL, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecOpenSSLKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecOpenSSLKeyDataRawX509CertGetKlass: + * + * The raw X509 certificates key data klass. + * + * Returns: raw X509 certificates key data klass. + */ +xmlSecKeyDataId +xmlSecOpenSSLKeyDataRawX509CertGetKlass(void) { + return(&xmlSecOpenSSLKeyDataRawX509CertKlass); +} + +static int +xmlSecOpenSSLKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + const xmlSecByte* buf, xmlSecSize bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecKeyDataPtr data; + X509* cert; + int ret; + + xmlSecAssert2(id == xmlSecOpenSSLKeyDataRawX509CertId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + cert = xmlSecOpenSSLX509CertDerRead(buf, bufSize); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509CertDerRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + data = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeyEnsureData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_free(cert); + return(-1); + } + + ret = xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecOpenSSLKeyDataX509VerifyAndExtractKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + +#endif /* XMLSEC_NO_X509 */ diff --git a/src/openssl/x509vfy.c b/src/openssl/x509vfy.c new file mode 100644 index 00000000..fe51da4e --- /dev/null +++ b/src/openssl/x509vfy.c @@ -0,0 +1,1284 @@ +/** + * XMLSec library + * + * X509 support + * + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#ifndef XMLSEC_NO_X509 + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#include <libxml/tree.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/x509_vfy.h> +#include <openssl/x509v3.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/base64.h> +#include <xmlsec/errors.h> + +#include <xmlsec/openssl/crypto.h> +#include <xmlsec/openssl/evp.h> +#include <xmlsec/openssl/x509.h> + +/************************************************************************** + * + * Internal OpenSSL X509 store CTX + * + *************************************************************************/ +typedef struct _xmlSecOpenSSLX509StoreCtx xmlSecOpenSSLX509StoreCtx, + *xmlSecOpenSSLX509StoreCtxPtr; +struct _xmlSecOpenSSLX509StoreCtx { + X509_STORE* xst; + STACK_OF(X509)* untrusted; + STACK_OF(X509_CRL)* crls; + +#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) + X509_VERIFY_PARAM * vpm; +#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ +}; + +/**************************************************************************** + * + * xmlSecOpenSSLKeyDataStoreX509Id: + * + * xmlSecOpenSSLX509StoreCtx is located after xmlSecTransform + * + ***************************************************************************/ +#define xmlSecOpenSSLX509StoreGetCtx(store) \ + ((xmlSecOpenSSLX509StoreCtxPtr)(((xmlSecByte*)(store)) + \ + sizeof(xmlSecKeyDataStoreKlass))) +#define xmlSecOpenSSLX509StoreSize \ + (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecOpenSSLX509StoreCtx)) + +static int xmlSecOpenSSLX509StoreInitialize (xmlSecKeyDataStorePtr store); +static void xmlSecOpenSSLX509StoreFinalize (xmlSecKeyDataStorePtr store); + +static xmlSecKeyDataStoreKlass xmlSecOpenSSLX509StoreKlass = { + sizeof(xmlSecKeyDataStoreKlass), + xmlSecOpenSSLX509StoreSize, + + /* data */ + xmlSecNameX509Store, /* const xmlChar* name; */ + + /* constructors/destructor */ + xmlSecOpenSSLX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */ + xmlSecOpenSSLX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +static int xmlSecOpenSSLX509VerifyCRL (X509_STORE* xst, + X509_CRL *crl ); +static X509* xmlSecOpenSSLX509FindCert (STACK_OF(X509) *certs, + xmlChar *subjectName, + xmlChar *issuerName, + xmlChar *issuerSerial, + xmlChar *ski); +static X509* xmlSecOpenSSLX509FindNextChainCert (STACK_OF(X509) *chain, + X509 *cert); +static int xmlSecOpenSSLX509VerifyCertAgainstCrls (STACK_OF(X509_CRL) *crls, + X509* cert); +static X509_NAME* xmlSecOpenSSLX509NameRead (xmlSecByte *str, + int len); +static int xmlSecOpenSSLX509NameStringRead (xmlSecByte **str, + int *strLen, + xmlSecByte *res, + int resLen, + xmlSecByte delim, + int ingoreTrailingSpaces); +static int xmlSecOpenSSLX509NamesCompare (X509_NAME *a, + X509_NAME *b); +static int xmlSecOpenSSLX509_NAME_cmp (const X509_NAME * a, + const X509_NAME * b); +static int xmlSecOpenSSLX509_NAME_ENTRY_cmp (const X509_NAME_ENTRY * const *a, + const X509_NAME_ENTRY * const *b); + +/** + * xmlSecOpenSSLX509StoreGetKlass: + * + * The OpenSSL X509 certificates key data store klass. + * + * Returns: pointer to OpenSSL X509 certificates key data store klass. + */ +xmlSecKeyDataStoreId +xmlSecOpenSSLX509StoreGetKlass(void) { + return(&xmlSecOpenSSLX509StoreKlass); +} + +/** + * xmlSecOpenSSLX509StoreFindCert: + * @store: the pointer to X509 key data store klass. + * @subjectName: the desired certificate name. + * @issuerName: the desired certificate issuer name. + * @issuerSerial: the desired certificate issuer serial number. + * @ski: the desired certificate SKI. + * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. + * + * Searches @store for a certificate that matches given criteria. + * + * Returns: pointer to found certificate or NULL if certificate is not found + * or an error occurs. + */ +X509* +xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName, + xmlChar *issuerName, xmlChar *issuerSerial, + xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + X509* res = NULL; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL); + xmlSecAssert2(keyInfoCtx != NULL, NULL); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, NULL); + + if((res == NULL) && (ctx->untrusted != NULL)) { + res = xmlSecOpenSSLX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski); + } + return(res); +} + +/** + * xmlSecOpenSSLX509StoreVerify: + * @store: the pointer to X509 key data store klass. + * @certs: the untrusted certificates stack. + * @crls: the crls stack. + * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. + * + * Verifies @certs list. + * + * Returns: pointer to the first verified certificate from @certs. + */ +X509* +xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs, + XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + STACK_OF(X509)* certs2 = NULL; + STACK_OF(X509_CRL)* crls2 = NULL; + X509 * res = NULL; + X509 * cert; + X509 * err_cert = NULL; + char buf[256]; + int err = 0, depth; + int i; + int ret; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL); + xmlSecAssert2(certs != NULL, NULL); + xmlSecAssert2(keyInfoCtx != NULL, NULL); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, NULL); + xmlSecAssert2(ctx->xst != NULL, NULL); + + /* dup certs */ + certs2 = sk_X509_dup(certs); + if(certs2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* add untrusted certs from the store */ + if(ctx->untrusted != NULL) { + for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) { + ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i)); + if(ret < 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_push", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + } + + /* dup crls but remove all non-verified */ + if(crls != NULL) { + crls2 = sk_X509_CRL_dup(crls); + if(crls2 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_CRL_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + for(i = 0; i < sk_X509_CRL_num(crls2); ) { + ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i)); + if(ret == 1) { + ++i; + } else if(ret == 0) { + (void)sk_X509_CRL_delete(crls2, i); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecOpenSSLX509VerifyCRL", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + } + + /* remove all revoked certs */ + for(i = 0; i < sk_X509_num(certs2);) { + cert = sk_X509_value(certs2, i); + + if(crls2 != NULL) { + ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert); + if(ret == 0) { + (void)sk_X509_delete(certs2, i); + continue; + } else if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecOpenSSLX509VerifyCertAgainstCrls", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + + if(ctx->crls != NULL) { + ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert); + if(ret == 0) { + (void)sk_X509_delete(certs2, i); + continue; + } else if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "xmlSecOpenSSLX509VerifyCertAgainstCrls", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + ++i; + } + + /* get one cert after another and try to verify */ + for(i = 0; i < sk_X509_num(certs2); ++i) { + cert = sk_X509_value(certs2, i); + if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) { + X509_STORE_CTX xsc; + +#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) + X509_VERIFY_PARAM * vpm = NULL; + unsigned long vpm_flags = 0; + + vpm = X509_VERIFY_PARAM_new(); + if(vpm == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_VERIFY_PARAM_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + vpm_flags = vpm->flags; +/* + vpm_flags &= (~X509_V_FLAG_X509_STRICT); +*/ + vpm_flags &= (~X509_V_FLAG_CRL_CHECK); + + X509_VERIFY_PARAM_set_depth(vpm, 9); + X509_VERIFY_PARAM_set_flags(vpm, vpm_flags); +#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ + + + X509_STORE_CTX_init (&xsc, ctx->xst, cert, certs2); + + if(keyInfoCtx->certsVerificationTime > 0) { +#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) + vpm_flags |= X509_V_FLAG_USE_CHECK_TIME; + X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime); +#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ + X509_STORE_CTX_set_time(&xsc, 0, keyInfoCtx->certsVerificationTime); + } + +#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) + X509_STORE_CTX_set0_param(&xsc, vpm); +#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ + + + ret = X509_verify_cert(&xsc); + err_cert = X509_STORE_CTX_get_current_cert(&xsc); + err = X509_STORE_CTX_get_error(&xsc); + depth = X509_STORE_CTX_get_error_depth(&xsc); + + X509_STORE_CTX_cleanup (&xsc); + + if(ret == 1) { + res = cert; + goto done; + } else if(ret < 0) { + const char* err_msg; + + buf[0] = '\0'; + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); + err_msg = X509_verify_cert_error_string(err); + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_verify_cert", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "subj=%s;err=%d;msg=%s", + xmlSecErrorsSafeString(buf), + err, + xmlSecErrorsSafeString(err_msg)); + goto done; + } else if(ret == 0) { + const char* err_msg; + + buf[0] = '\0'; + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); + err_msg = X509_verify_cert_error_string(err); + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_verify_cert", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "subj=%s;err=%d;msg=%s", + xmlSecErrorsSafeString(buf), + err, + xmlSecErrorsSafeString(err_msg)); + } + } + } + + /* if we came here then we found nothing. do we have any error? */ + if((err != 0) && (err_cert != NULL)) { + const char* err_msg; + + err_msg = X509_verify_cert_error_string(err); + switch (err) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf); + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + NULL, + XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, + "err=%d;msg=%s;issuer=%s", + err, + xmlSecErrorsSafeString(err_msg), + xmlSecErrorsSafeString(buf)); + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + NULL, + XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, + "err=%d;msg=%s", err, + xmlSecErrorsSafeString(err_msg)); + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + NULL, + XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, + "err=%d;msg=%s", err, + xmlSecErrorsSafeString(err_msg)); + break; + default: + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + NULL, + XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, + "err=%d;msg=%s", err, + xmlSecErrorsSafeString(err_msg)); + } + } + +done: + if(certs2 != NULL) { + sk_X509_free(certs2); + } + if(crls2 != NULL) { + sk_X509_CRL_free(crls2); + } + return(res); +} + +/** + * xmlSecOpenSSLX509StoreAdoptCert: + * @store: the pointer to X509 key data store klass. + * @cert: the pointer to OpenSSL X509 certificate. + * @type: the certificate type (trusted/untrusted). + * + * Adds trusted (root) or untrusted certificate to the store. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store, X509* cert, xmlSecKeyDataType type) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1); + xmlSecAssert2(cert != NULL, -1); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + + if((type & xmlSecKeyDataTypeTrusted) != 0) { + xmlSecAssert2(ctx->xst != NULL, -1); + + ret = X509_STORE_add_cert(ctx->xst, cert); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_STORE_add_cert", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + /* add cert increments the reference */ + X509_free(cert); + } else { + xmlSecAssert2(ctx->untrusted != NULL, -1); + + ret = sk_X509_push(ctx->untrusted, cert); + if(ret < 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_push", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + return(0); +} + +/** + * xmlSecOpenSSLX509StoreAdoptCrl: + * @store: the pointer to X509 key data store klass. + * @crl: the pointer to OpenSSL X509_CRL. + * + * Adds X509 CRL to the store. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store, X509_CRL* crl) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1); + xmlSecAssert2(crl != NULL, -1); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->crls != NULL, -1); + + ret = sk_X509_CRL_push(ctx->crls, crl); + if(ret < 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_CRL_push", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return (0); +} + +/** + * xmlSecOpenSSLX509StoreAddCertsPath: + * @store: the pointer to OpenSSL x509 store. + * @path: the path to the certs dir. + * + * Adds all certs in the @path to the list of trusted certs + * in @store. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store, const char *path) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + X509_LOOKUP *lookup = NULL; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1); + xmlSecAssert2(path != NULL, -1); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->xst != NULL, -1); + + lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir()); + if(lookup == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_STORE_add_lookup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + if(!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_LOOKUP_add_dir", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "path='%s'", + xmlSecErrorsSafeString(path) + ); + return(-1); + } + return(0); +} + +/** + * xmlSecOpenSSLX509StoreAddCertsFile: + * @store: the pointer to OpenSSL x509 store. + * @file: the certs file. + * + * Adds all certs in @file to the list of trusted certs + * in @store. It is possible for @file to contain multiple certs. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store, const char *file) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + X509_LOOKUP *lookup = NULL; + + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1); + xmlSecAssert2(file != NULL, -1); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->xst != NULL, -1); + + lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_file()); + if(lookup == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_STORE_add_lookup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + if(!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_LOOKUP_load_file", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "file='%s'", + xmlSecErrorsSafeString(file) + ); + return(-1); + } + return(0); +} + +static int +xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store) { + const xmlChar* path; + X509_LOOKUP *lookup = NULL; + + xmlSecOpenSSLX509StoreCtxPtr ctx; + xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx)); + + ctx->xst = X509_STORE_new(); + if(ctx->xst == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_STORE_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if(!X509_STORE_set_default_paths(ctx->xst)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_STORE_set_default_paths", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + + lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir()); + if(lookup == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_STORE_add_lookup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + path = xmlSecOpenSSLGetDefaultTrustedCertsFolder(); + if(path != NULL) { + if(!X509_LOOKUP_add_dir(lookup, (char*)path, X509_FILETYPE_PEM)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_LOOKUP_add_dir", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "path='%s'", + xmlSecErrorsSafeString(path) + ); + return(-1); + } + } else { + if(!X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_LOOKUP_add_dir", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE + ); + return(-1); + } + } + + ctx->untrusted = sk_X509_new_null(); + if(ctx->untrusted == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_new_null", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ctx->crls = sk_X509_CRL_new_null(); + if(ctx->crls == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "sk_X509_CRL_new_null", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) + ctx->vpm = X509_VERIFY_PARAM_new(); + if(ctx->vpm == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), + "X509_VERIFY_PARAM_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + X509_VERIFY_PARAM_set_depth(ctx->vpm, 9); /* the default cert verification path in openssl */ + X509_STORE_set1_param(ctx->xst, ctx->vpm); + +#else /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ + ctx->xst->depth = 9; /* the default cert verification path in openssl */ +#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ + + return(0); +} + +static void +xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store) { + xmlSecOpenSSLX509StoreCtxPtr ctx; + xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId)); + + ctx = xmlSecOpenSSLX509StoreGetCtx(store); + xmlSecAssert(ctx != NULL); + + + if(ctx->xst != NULL) { + X509_STORE_free(ctx->xst); + } + if(ctx->untrusted != NULL) { + sk_X509_pop_free(ctx->untrusted, X509_free); + } + if(ctx->crls != NULL) { + sk_X509_CRL_pop_free(ctx->crls, X509_CRL_free); + } +#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) + if(ctx->vpm != NULL) { + X509_VERIFY_PARAM_free(ctx->vpm); + } +#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ + + memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx)); +} + + +/***************************************************************************** + * + * Low-level x509 functions + * + *****************************************************************************/ +static int +xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) { + X509_STORE_CTX xsc; + X509_OBJECT xobj; + EVP_PKEY *pkey; + int ret; + + xmlSecAssert2(xst != NULL, -1); + xmlSecAssert2(crl != NULL, -1); + + X509_STORE_CTX_init(&xsc, xst, NULL, NULL); + ret = X509_STORE_get_by_subject(&xsc, X509_LU_X509, + X509_CRL_get_issuer(crl), &xobj); + if(ret <= 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_STORE_get_by_subject", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + pkey = X509_get_pubkey(xobj.data.x509); + X509_OBJECT_free_contents(&xobj); + if(pkey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_get_pubkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + ret = X509_CRL_verify(crl, pkey); + EVP_PKEY_free(pkey); + if(ret != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_CRL_verify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + } + X509_STORE_CTX_cleanup (&xsc); + return((ret == 1) ? 1 : 0); +} + +static X509* +xmlSecOpenSSLX509FindCert(STACK_OF(X509) *certs, xmlChar *subjectName, + xmlChar *issuerName, xmlChar *issuerSerial, + xmlChar *ski) { + X509 *cert = NULL; + int i; + + xmlSecAssert2(certs != NULL, NULL); + + /* todo: may be this is not the fastest way to search certs */ + if(subjectName != NULL) { + X509_NAME *nm; + X509_NAME *subj; + + nm = xmlSecOpenSSLX509NameRead(subjectName, xmlStrlen(subjectName)); + if(nm == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "subject=%s", + xmlSecErrorsSafeString(subjectName)); + return(NULL); + } + + for(i = 0; i < sk_X509_num(certs); ++i) { + cert = sk_X509_value(certs, i); + subj = X509_get_subject_name(cert); + if(xmlSecOpenSSLX509NamesCompare(nm, subj) == 0) { + X509_NAME_free(nm); + return(cert); + } + } + X509_NAME_free(nm); + } else if((issuerName != NULL) && (issuerSerial != NULL)) { + X509_NAME *nm; + X509_NAME *issuer; + BIGNUM *bn; + ASN1_INTEGER *serial; + + nm = xmlSecOpenSSLX509NameRead(issuerName, xmlStrlen(issuerName)); + if(nm == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "issuer=%s", + xmlSecErrorsSafeString(issuerName)); + return(NULL); + } + + bn = BN_new(); + if(bn == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_NAME_free(nm); + return(NULL); + } + if(BN_dec2bn(&bn, (char*)issuerSerial) == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_dec2bn", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BN_free(bn); + X509_NAME_free(nm); + return(NULL); + } + + serial = BN_to_ASN1_INTEGER(bn, NULL); + if(serial == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "BN_to_ASN1_INTEGER", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + BN_free(bn); + X509_NAME_free(nm); + return(NULL); + } + BN_free(bn); + + + for(i = 0; i < sk_X509_num(certs); ++i) { + cert = sk_X509_value(certs, i); + if(ASN1_INTEGER_cmp(X509_get_serialNumber(cert), serial) != 0) { + continue; + } + issuer = X509_get_issuer_name(cert); + if(xmlSecOpenSSLX509NamesCompare(nm, issuer) == 0) { + ASN1_INTEGER_free(serial); + X509_NAME_free(nm); + return(cert); + } + } + + X509_NAME_free(nm); + ASN1_INTEGER_free(serial); + } else if(ski != NULL) { + int len; + int index; + X509_EXTENSION *ext; + ASN1_OCTET_STRING *keyId; + + /* our usual trick with base64 decode */ + len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski)); + if(len < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBase64Decode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ski=%s", + xmlSecErrorsSafeString(ski)); + return(NULL); + } + for(i = 0; i < sk_X509_num(certs); ++i) { + cert = sk_X509_value(certs, i); + index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if((index >= 0) && (ext = X509_get_ext(cert, index))) { + keyId = X509V3_EXT_d2i(ext); + if((keyId != NULL) && (keyId->length == len) && + (memcmp(keyId->data, ski, len) == 0)) { + M_ASN1_OCTET_STRING_free(keyId); + return(cert); + } + M_ASN1_OCTET_STRING_free(keyId); + } + } + } + + return(NULL); +} + +static X509* +xmlSecOpenSSLX509FindNextChainCert(STACK_OF(X509) *chain, X509 *cert) { + unsigned long certSubjHash; + int i; + + xmlSecAssert2(chain != NULL, NULL); + xmlSecAssert2(cert != NULL, NULL); + + certSubjHash = X509_subject_name_hash(cert); + for(i = 0; i < sk_X509_num(chain); ++i) { + if((sk_X509_value(chain, i) != cert) && + (X509_issuer_name_hash(sk_X509_value(chain, i)) == certSubjHash)) { + + return(sk_X509_value(chain, i)); + } + } + return(NULL); +} + +static int +xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF(X509_CRL) *crls, X509* cert) { + X509_NAME *issuer; + X509_CRL *crl = NULL; + X509_REVOKED *revoked; + int i, n; + int ret; + + xmlSecAssert2(crls != NULL, -1); + xmlSecAssert2(cert != NULL, -1); + + /* + * Try to retrieve a CRL corresponding to the issuer of + * the current certificate + */ + n = sk_X509_CRL_num(crls); + for(i = 0; i < n; i++) { + crl = sk_X509_CRL_value(crls, i); + if(crl == NULL) { + continue; + } + + issuer = X509_CRL_get_issuer(crl); + if(xmlSecOpenSSLX509NamesCompare(X509_CRL_get_issuer(crl), issuer) == 0) { + break; + } + } + if((i >= n) || (crl == NULL)){ + /* no crls for this issuer */ + return(1); + } + + /* + * Check date of CRL to make sure it's not expired + */ + ret = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl)); + if (ret == 0) { + /* crl expired */ + return(1); + } + + /* + * Check if the current certificate is revoked by this CRL + */ + n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); + for (i = 0; i < n; i++) { + revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); + if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(cert)) == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_CERT_REVOKED, + XMLSEC_ERRORS_NO_MESSAGE); + return(0); + } + } + return(1); +} + +static X509_NAME * +xmlSecOpenSSLX509NameRead(xmlSecByte *str, int len) { + xmlSecByte name[256]; + xmlSecByte value[256]; + int nameLen, valueLen; + X509_NAME *nm; + int type = MBSTRING_ASC; + + xmlSecAssert2(str != NULL, NULL); + + nm = X509_NAME_new(); + if(nm == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_NAME_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + while(len > 0) { + /* skip spaces after comma or semicolon */ + while((len > 0) && isspace(*str)) { + ++str; --len; + } + + nameLen = xmlSecOpenSSLX509NameStringRead(&str, &len, name, sizeof(name), '=', 0); + if(nameLen < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameStringRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_NAME_free(nm); + return(NULL); + } + name[nameLen] = '\0'; + if(len > 0) { + ++str; --len; + if((*str) == '\"') { + ++str; --len; + valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len, + value, sizeof(value), '"', 1); + if(valueLen < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameStringRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_NAME_free(nm); + return(NULL); + } + + /* skip quote */ + if((len <= 0) || ((*str) != '\"')) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "quote is expected:%s", + xmlSecErrorsSafeString(str)); + X509_NAME_free(nm); + return(NULL); + } + ++str; --len; + + /* skip spaces before comma or semicolon */ + while((len > 0) && isspace(*str)) { + ++str; --len; + } + if((len > 0) && ((*str) != ',')) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "comma is expected:%s", + xmlSecErrorsSafeString(str)); + X509_NAME_free(nm); + return(NULL); + } + if(len > 0) { + ++str; --len; + } + type = MBSTRING_ASC; + } else if((*str) == '#') { + /* TODO: read octect values */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "reading octect values is not implemented yet"); + X509_NAME_free(nm); + return(NULL); + } else { + valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len, + value, sizeof(value), ',', 1); + if(valueLen < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecOpenSSLX509NameStringRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + X509_NAME_free(nm); + return(NULL); + } + type = MBSTRING_ASC; + } + } else { + valueLen = 0; + } + value[valueLen] = '\0'; + if(len > 0) { + ++str; --len; + } + X509_NAME_add_entry_by_txt(nm, (char*)name, type, value, valueLen, -1, 0); + } + + return(nm); +} + +static int +xmlSecOpenSSLX509NameStringRead(xmlSecByte **str, int *strLen, + xmlSecByte *res, int resLen, + xmlSecByte delim, int ingoreTrailingSpaces) { + xmlSecByte *p, *q, *nonSpace; + + xmlSecAssert2(str != NULL, -1); + xmlSecAssert2(strLen != NULL, -1); + xmlSecAssert2(res != NULL, -1); + + p = (*str); + nonSpace = q = res; + while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) { + if((*p) != '\\') { + if(ingoreTrailingSpaces && !isspace(*p)) nonSpace = q; + *(q++) = *(p++); + } else { + ++p; + nonSpace = q; + if(xmlSecIsHex((*p))) { + if((p - (*str) + 1) >= (*strLen)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "two hex digits expected"); + return(-1); + } + *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]); + p += 2; + } else { + if(((++p) - (*str)) >= (*strLen)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "escaped symbol missed"); + return(-1); + } + *(q++) = *(p++); + } + } + } + if(((p - (*str)) < (*strLen)) && ((*p) != delim)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "buffer is too small"); + return(-1); + } + (*strLen) -= (p - (*str)); + (*str) = p; + return((ingoreTrailingSpaces) ? nonSpace - res + 1 : q - res); +} + +static +int xmlSecOpenSSLX509_NAME_cmp(const X509_NAME * a, const X509_NAME * b) { + int i,ret; + const X509_NAME_ENTRY *na,*nb; + + xmlSecAssert2(a != NULL, -1); + xmlSecAssert2(b != NULL, 1); + + if (sk_X509_NAME_ENTRY_num(a->entries) != sk_X509_NAME_ENTRY_num(b->entries)) { + return sk_X509_NAME_ENTRY_num(a->entries) - sk_X509_NAME_ENTRY_num(b->entries); + } + + for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { + na=sk_X509_NAME_ENTRY_value(a->entries,i); + nb=sk_X509_NAME_ENTRY_value(b->entries,i); + + ret = xmlSecOpenSSLX509_NAME_ENTRY_cmp(&na, &nb); + if(ret != 0) { + return(ret); + } + } + + return(0); +} + + +/** + * xmlSecOpenSSLX509NamesCompare: + * + * We have to sort X509_NAME entries to get correct results. + * This is ugly but OpenSSL does not support it + */ +static int +xmlSecOpenSSLX509NamesCompare(X509_NAME *a, X509_NAME *b) { + X509_NAME *a1 = NULL; + X509_NAME *b1 = NULL; + int ret; + + xmlSecAssert2(a != NULL, -1); + xmlSecAssert2(b != NULL, 1); + + a1 = X509_NAME_dup(a); + if(a1 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_NAME_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + b1 = X509_NAME_dup(b); + if(b1 == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "X509_NAME_dup", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(1); + } + + /* sort both */ + (void)sk_X509_NAME_ENTRY_set_cmp_func(a1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp); + sk_X509_NAME_ENTRY_sort(a1->entries); + (void)sk_X509_NAME_ENTRY_set_cmp_func(b1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp); + sk_X509_NAME_ENTRY_sort(b1->entries); + + /* actually compare */ + ret = xmlSecOpenSSLX509_NAME_cmp(a1, b1); + + /* cleanup */ + X509_NAME_free(a1); + X509_NAME_free(b1); + return(ret); +} + +static int +xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY * const *a, const X509_NAME_ENTRY * const *b) { + int ret; + + xmlSecAssert2(a != NULL, -1); + xmlSecAssert2(b != NULL, 1); + xmlSecAssert2((*a) != NULL, -1); + xmlSecAssert2((*b) != NULL, 1); + + /* first compare values */ + if(((*a)->value == NULL) && ((*b)->value != NULL)) { + return(-1); + } else if(((*a)->value != NULL) && ((*b)->value == NULL)) { + return(1); + } else if(((*a)->value == NULL) && ((*b)->value == NULL)) { + return(0); + } + + ret = (*a)->value->length - (*b)->value->length; + if(ret != 0) { + return(ret); + } + + ret = memcmp((*a)->value->data, (*b)->value->data, (*a)->value->length); + if(ret != 0) { + return(ret); + } + + /* next compare names */ + return(OBJ_cmp((*a)->object, (*b)->object)); +} + + +#endif /* XMLSEC_NO_X509 */ + + |