summaryrefslogtreecommitdiff
path: root/src/openssl
diff options
context:
space:
mode:
Diffstat (limited to 'src/openssl')
-rw-r--r--src/openssl/Makefile.am56
-rw-r--r--src/openssl/Makefile.in790
-rw-r--r--src/openssl/README17
-rw-r--r--src/openssl/app.c1628
-rw-r--r--src/openssl/bn.c163
-rw-r--r--src/openssl/ciphers.c856
-rw-r--r--src/openssl/crypto.c491
-rw-r--r--src/openssl/digests.c682
-rw-r--r--src/openssl/evp.c1559
-rw-r--r--src/openssl/globals.h24
-rw-r--r--src/openssl/hmac.c857
-rw-r--r--src/openssl/kt_rsa.c876
-rw-r--r--src/openssl/kw_aes.c513
-rw-r--r--src/openssl/kw_des.c563
-rw-r--r--src/openssl/signatures.c1065
-rw-r--r--src/openssl/symkeys.c447
-rw-r--r--src/openssl/x509.c2414
-rw-r--r--src/openssl/x509vfy.c1284
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 */
+
+