summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am69
-rw-r--r--src/Makefile.in863
-rw-r--r--src/app.c1498
-rw-r--r--src/base64.c1034
-rw-r--r--src/bn.c1060
-rw-r--r--src/buffer.c674
-rw-r--r--src/c14n.c801
-rw-r--r--src/dl.c978
-rw-r--r--src/enveloped.c152
-rw-r--r--src/errors.c242
-rw-r--r--src/globals.h25
-rw-r--r--src/gnutls/Makefile.am48
-rw-r--r--src/gnutls/Makefile.in706
-rw-r--r--src/gnutls/README9
-rw-r--r--src/gnutls/app.c499
-rw-r--r--src/gnutls/ciphers.c860
-rw-r--r--src/gnutls/crypto.c205
-rw-r--r--src/gnutls/digests.c318
-rw-r--r--src/gnutls/globals.h24
-rw-r--r--src/gnutls/hmac.c601
-rw-r--r--src/gnutls/symkeys.c440
-rw-r--r--src/io.c496
-rw-r--r--src/keyinfo.c1561
-rw-r--r--src/keys.c1415
-rw-r--r--src/keysdata.c1387
-rw-r--r--src/keysmngr.c745
-rw-r--r--src/list.c508
-rw-r--r--src/membuf.c209
-rw-r--r--src/mscrypto/Makefile.am58
-rw-r--r--src/mscrypto/Makefile.in760
-rw-r--r--src/mscrypto/README52
-rw-r--r--src/mscrypto/app.c1288
-rw-r--r--src/mscrypto/certkeys.c2633
-rw-r--r--src/mscrypto/ciphers.c1350
-rw-r--r--src/mscrypto/crypto.c387
-rw-r--r--src/mscrypto/csp_calg.h92
-rw-r--r--src/mscrypto/csp_oid.h114
-rw-r--r--src/mscrypto/digests.c413
-rw-r--r--src/mscrypto/globals.h24
-rw-r--r--src/mscrypto/keysstore.c678
-rw-r--r--src/mscrypto/kt_rsa.c410
-rw-r--r--src/mscrypto/mingw-crypt32.def32
-rw-r--r--src/mscrypto/signatures.c663
-rw-r--r--src/mscrypto/symkeys.c333
-rw-r--r--src/mscrypto/x509.c2270
-rw-r--r--src/mscrypto/x509vfy.c1062
-rw-r--r--src/mscrypto/xmlsec-mingw.h165
-rw-r--r--src/nodeset.c599
-rw-r--r--src/nss/Makefile.am57
-rw-r--r--src/nss/Makefile.in786
-rw-r--r--src/nss/README137
-rw-r--r--src/nss/app.c1598
-rw-r--r--src/nss/bignum.c163
-rw-r--r--src/nss/ciphers.c838
-rw-r--r--src/nss/crypto.c366
-rw-r--r--src/nss/digests.c331
-rw-r--r--src/nss/globals.h24
-rw-r--r--src/nss/hmac.c633
-rw-r--r--src/nss/keysstore.c485
-rw-r--r--src/nss/keytrans.c744
-rw-r--r--src/nss/kw_aes.c857
-rw-r--r--src/nss/kw_des.c758
-rw-r--r--src/nss/pkikeys.c1554
-rw-r--r--src/nss/signatures.c550
-rw-r--r--src/nss/symkeys.c440
-rw-r--r--src/nss/x509.c2205
-rw-r--r--src/nss/x509vfy.c704
-rw-r--r--src/openssl/Makefile.am56
-rw-r--r--src/openssl/Makefile.in778
-rw-r--r--src/openssl/README17
-rw-r--r--src/openssl/app.c1581
-rw-r--r--src/openssl/bn.c163
-rw-r--r--src/openssl/ciphers.c856
-rw-r--r--src/openssl/crypto.c474
-rw-r--r--src/openssl/digests.c679
-rw-r--r--src/openssl/evp.c1559
-rw-r--r--src/openssl/globals.h24
-rw-r--r--src/openssl/hmac.c841
-rw-r--r--src/openssl/kt_rsa.c877
-rw-r--r--src/openssl/kw_aes.c622
-rw-r--r--src/openssl/kw_des.c628
-rw-r--r--src/openssl/signatures.c1061
-rw-r--r--src/openssl/symkeys.c447
-rw-r--r--src/openssl/x509.c2414
-rw-r--r--src/openssl/x509vfy.c1286
-rw-r--r--src/parser.c571
-rw-r--r--src/skeleton/Makefile.am45
-rw-r--r--src/skeleton/README0
-rw-r--r--src/skeleton/app.c499
-rw-r--r--src/skeleton/crypto.c227
-rw-r--r--src/skeleton/globals.h24
-rw-r--r--src/soap.c1322
-rw-r--r--src/strings.c601
-rw-r--r--src/templates.c2091
-rw-r--r--src/transforms.c2892
-rw-r--r--src/x509.c97
-rw-r--r--src/xkms.c4981
-rw-r--r--src/xmldsig.c1795
-rw-r--r--src/xmlenc.c1339
-rw-r--r--src/xmlsec.c185
-rw-r--r--src/xmltree.c1908
-rw-r--r--src/xpath.c1148
-rw-r--r--src/xslt.c518
103 files changed, 78646 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 00000000..e28bb5ed
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,69 @@
+NULL =
+
+SUBDIRS = . $(XMLSEC_CRYPTO_LIST)
+
+INCLUDES = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(XMLSEC_DL_INCLUDES) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+EXTRA_DIST = \
+ globals.h \
+ skeleton \
+ mscrypto \
+ $(XMLSEC_CRYPTO_DISABLED_LIST) \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_la_SOURCES = \
+ $(LTDL_SOURCE_FILES) \
+ app.c \
+ base64.c \
+ bn.c \
+ buffer.c \
+ c14n.c \
+ dl.c \
+ enveloped.c \
+ errors.c \
+ io.c \
+ keyinfo.c \
+ keys.c \
+ keysdata.c \
+ keysmngr.c \
+ list.c \
+ membuf.c \
+ nodeset.c \
+ parser.c \
+ soap.c \
+ strings.c \
+ templates.c \
+ transforms.c \
+ x509.c \
+ xkms.c \
+ xmldsig.c \
+ xmlenc.c \
+ xmlsec.c \
+ xmltree.c \
+ xpath.c \
+ xslt.c \
+ $(NULL)
+
+libxmlsec1_la_LIBADD = \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(XMLSEC_DL_LIBS) \
+ $(NULL)
+
+libxmlsec1_la_LDFLAGS = \
+ @XMLSEC_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
+
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 00000000..56fb659d
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,863 @@
+# Makefile.in generated by automake 1.11 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@
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+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 =
+libxmlsec1_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__objects_1 =
+am_libxmlsec1_la_OBJECTS = app.lo base64.lo bn.lo buffer.lo c14n.lo \
+ dl.lo enveloped.lo errors.lo io.lo keyinfo.lo keys.lo \
+ keysdata.lo keysmngr.lo list.lo membuf.lo nodeset.lo parser.lo \
+ soap.lo strings.lo templates.lo transforms.lo x509.lo xkms.lo \
+ xmldsig.lo xmlenc.lo xmlsec.lo xmltree.lo xpath.lo xslt.lo \
+ $(am__objects_1)
+libxmlsec1_la_OBJECTS = $(am_libxmlsec1_la_OBJECTS)
+libxmlsec1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_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_la_SOURCES)
+DIST_SOURCES = $(libxmlsec1_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+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@
+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@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_ENABLED = @PKG_CONFIG_ENABLED@
+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_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_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 =
+SUBDIRS = . $(XMLSEC_CRYPTO_LIST)
+INCLUDES = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(XMLSEC_DL_INCLUDES) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+EXTRA_DIST = \
+ globals.h \
+ skeleton \
+ mscrypto \
+ $(XMLSEC_CRYPTO_DISABLED_LIST) \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_la_SOURCES = \
+ $(LTDL_SOURCE_FILES) \
+ app.c \
+ base64.c \
+ bn.c \
+ buffer.c \
+ c14n.c \
+ dl.c \
+ enveloped.c \
+ errors.c \
+ io.c \
+ keyinfo.c \
+ keys.c \
+ keysdata.c \
+ keysmngr.c \
+ list.c \
+ membuf.c \
+ nodeset.c \
+ parser.c \
+ soap.c \
+ strings.c \
+ templates.c \
+ transforms.c \
+ x509.c \
+ xkms.c \
+ xmldsig.c \
+ xmlenc.c \
+ xmlsec.c \
+ xmltree.c \
+ xpath.c \
+ xslt.c \
+ $(NULL)
+
+libxmlsec1_la_LIBADD = \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(XMLSEC_DL_LIBS) \
+ $(NULL)
+
+libxmlsec1_la_LDFLAGS = \
+ @XMLSEC_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
+
+all: all-recursive
+
+.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/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/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.la: $(libxmlsec1_la_OBJECTS) $(libxmlsec1_la_DEPENDENCIES)
+ $(libxmlsec1_la_LINK) -rpath $(libdir) $(libxmlsec1_la_OBJECTS) $(libxmlsec1_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c14n.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enveloped.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keysdata.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keysmngr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/membuf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nodeset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/soap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/templates.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transforms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xkms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmldsig.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlenc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmltree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xslt.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 $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+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: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ 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: ctags-recursive $(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
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+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-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \
+ 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 installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-recursive 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/app.c b/src/app.c
new file mode 100644
index 00000000..ca09f62c
--- /dev/null
+++ b/src/app.c
@@ -0,0 +1,1498 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ *
+ * 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_CRYPTO_DYNAMIC_LOADING
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/app.h>
+#include <xmlsec/list.h>
+#include <xmlsec/keysdata.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/private.h>
+#include <xmlsec/errors.h>
+
+
+/******************************************************************************
+ *
+ * Crypto Init/shutdown
+ *
+ *****************************************************************************/
+/**
+ * xmlSecCryptoInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecCryptoInit(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoInit == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoInit",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoInit());
+}
+
+/**
+ * xmlSecCryptoShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecCryptoShutdown(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoShutdown == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoShutdown",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoShutdown());
+}
+
+/**
+ * xmlSecCryptoKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds crypto specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecCryptoKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoKeysMngrInit == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoKeysMngrInit",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoKeysMngrInit(mngr));
+}
+
+/******************************************************************************
+ *
+ * Key data ids
+ *
+ *****************************************************************************/
+/**
+ * xmlSecKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the AES key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataAesGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataAesGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataAesId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataAesGetKlass());
+}
+
+/**
+ * xmlSecKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the DES key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataDesGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataDesGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataDesId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataDesGetKlass());
+}
+
+/**
+ * xmlSecKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: DSA key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the DSA key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataDsaGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataDsaGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataDsaId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataDsaGetKlass());
+}
+
+/**
+ * xmlSecKeyDataGost2001GetKlass:
+ *
+ * The GOST2001 key data klass.
+ *
+ * Returns: GOST2001 key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the GOST2001 key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataGost2001GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataGost2001GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataGost2001Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataGost2001GetKlass());
+}
+
+/**
+ * xmlSecKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the HMAC key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataHmacGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataHmacGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataHmacId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataHmacGetKlass());
+}
+
+/**
+ * xmlSecKeyDataRsaGetKlass:
+ *
+ * The RSA key data klass.
+ *
+ * Returns: RSA key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the RSA key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataRsaGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataRsaGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataRsaId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataRsaGetKlass());
+}
+
+/**
+ * xmlSecKeyDataX509GetKlass:
+ *
+ * The X509 key data klass.
+ *
+ * Returns: X509 key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the X509 key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataX509GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataX509GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataX509Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataX509GetKlass());
+}
+
+/**
+ * xmlSecKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 cert key data klass.
+ *
+ * Returns: raw x509 cert key data klass or NULL if an error occurs
+ * (xmlsec-crypto library is not loaded or the raw X509 cert key data
+ * klass is not implemented).
+ */
+xmlSecKeyDataId
+xmlSecKeyDataRawX509CertGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->keyDataRawX509CertGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "keyDataRawX509CertId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyDataIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->keyDataRawX509CertGetKlass());
+}
+
+/******************************************************************************
+ *
+ * Key data store ids
+ *
+ *****************************************************************************/
+/**
+ * xmlSecX509StoreGetKlass:
+ *
+ * The X509 certificates key data store klass.
+ *
+ * Returns: pointer to X509 certificates key data store klass or NULL if
+ * an error occurs (xmlsec-crypto library is not loaded or the raw X509
+ * cert key data klass is not implemented).
+ */
+xmlSecKeyDataStoreId
+xmlSecX509StoreGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->x509StoreGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "x509StoreId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecKeyStoreIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->x509StoreGetKlass());
+}
+
+/******************************************************************************
+ *
+ * Crypto transforms ids
+ *
+ *****************************************************************************/
+/**
+ * xmlSecTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformAes128CbcGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformAes128CbcGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformAes128CbcId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformAes128CbcGetKlass());
+}
+
+/**
+ * xmlSecTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformAes192CbcGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformAes192CbcGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformAes192CbcId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformAes192CbcGetKlass());
+}
+
+/**
+ * xmlSecTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformAes256CbcGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformAes256CbcGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformAes256CbcId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformAes256CbcGetKlass());
+}
+
+/**
+ * xmlSecTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformKWAes128GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformKWAes128GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformKWAes128Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformKWAes128GetKlass());
+}
+
+/**
+ * xmlSecTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformKWAes192GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformKWAes192GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformKWAes192Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformKWAes192GetKlass());
+}
+
+/**
+ * xmlSecTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformKWAes256GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformKWAes256GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformKWAes256Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformKWAes256GetKlass());
+}
+
+/**
+ * xmlSecTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformDes3CbcGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformDes3CbcGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformDes3CbcId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformDes3CbcGetKlass());
+}
+
+/**
+ * xmlSecTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformKWDes3GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformKWDes3GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformKWDes3Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformKWDes3GetKlass());
+}
+
+/**
+ * xmlSecTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformDsaSha1GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformDsaSha1GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformDsaSha1Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformDsaSha1GetKlass());
+}
+
+/**
+ * xmlSecTransformGost2001GostR3411_94GetKlass:
+ *
+ * The GOST2001-GOSTR3411_94 signature transform klass.
+ *
+ * Returns: GOST2001-GOSTR3411_94 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformGost2001GostR3411_94GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformGost2001GostR3411_94GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformGost2001GostR3411_94Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformGost2001GostR3411_94GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacMd5GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacMd5GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacMd5Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacMd5GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacRipemd160GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacRipemd160GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacRipemd160Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacRipemd160GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacSha1GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacSha1GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacSha1Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacSha1GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacSha224GetKlass:
+ *
+ * The HMAC-SHA224 transform klass.
+ *
+ * Returns: the HMAC-SHA224 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacSha224GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacSha224GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacSha224Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacSha224GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacSha256GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacSha256GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacSha256Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacSha256GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacSha384GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacSha384GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacSha384Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacSha384GetKlass());
+}
+
+/**
+ * xmlSecTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformHmacSha512GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformHmacSha512GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformHmacSha512Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformHmacSha512GetKlass());
+}
+
+/**
+ * xmlSecTransformMd5GetKlass:
+ *
+ * MD5 digest transform klass.
+ *
+ * Returns: pointer to MD5 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformMd5GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformMd5GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformMd5Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformMd5GetKlass());
+}
+
+/**
+ * xmlSecTransformRipemd160GetKlass:
+ *
+ * RIPEMD-160 digest transform klass.
+ *
+ * Returns: pointer to RIPEMD-160 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRipemd160GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRipemd160GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRipemd160Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRipemd160GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaMd5GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaMd5GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaMd5Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaMd5GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaRipemd160GetKlass:
+ *
+ * The RSA-RIPEMD160 signature transform klass.
+ *
+ * Returns: RSA-RIPEMD160 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaRipemd160GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaRipemd160GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaRipemd160Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaRipemd160GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaSha1GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaSha1GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaSha1Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaSha1GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaSha224GetKlass:
+ *
+ * The RSA-SHA224 signature transform klass.
+ *
+ * Returns: RSA-SHA224 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaSha224GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaSha224GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaSha224Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaSha224GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaSha256GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaSha256GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaSha256Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaSha256GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaSha384GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaSha384GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaSha384Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaSha384GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaSha512GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaSha512GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaSha512Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaSha512GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaPkcs1GetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaPkcs1GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaPkcs1GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaPkcs1Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaPkcs1GetKlass());
+}
+
+/**
+ * xmlSecTransformRsaOaepGetKlass:
+ *
+ * The RSA-OAEP key transport transform klass.
+ *
+ * Returns: RSA-OAEP key transport transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformRsaOaepGetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformRsaOaepGetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformRsaOaepId",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformRsaOaepGetKlass());
+}
+
+/**
+ * xmlSecTransformGostR3411_94GetKlass:
+ *
+ * GOSTR3411_94 digest transform klass.
+ *
+ * Returns: pointer to GOSTR3411_94 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformGostR3411_94GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformGostR3411_94GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformGostR3411_94Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformGostR3411_94GetKlass());
+}
+
+
+/**
+ * xmlSecTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformSha1GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformSha1GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformSha1Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformSha1GetKlass());
+}
+
+/**
+ * xmlSecTransformSha224GetKlass:
+ *
+ * SHA224 digest transform klass.
+ *
+ * Returns: pointer to SHA224 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformSha224GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformSha224GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformSha224Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformSha224GetKlass());
+}
+
+/**
+ * xmlSecTransformSha256GetKlass:
+ *
+ * SHA256 digest transform klass.
+ *
+ * Returns: pointer to SHA256 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformSha256GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformSha256GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformSha256Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformSha256GetKlass());
+}
+
+/**
+ * xmlSecTransformSha384GetKlass:
+ *
+ * SHA384 digest transform klass.
+ *
+ * Returns: pointer to SHA384 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformSha384GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformSha384GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformSha384Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformSha384GetKlass());
+}
+
+/**
+ * xmlSecTransformSha512GetKlass:
+ *
+ * SHA512 digest transform klass.
+ *
+ * Returns: pointer to SHA512 digest transform klass or NULL if an error
+ * occurs (the xmlsec-crypto library is not loaded or this transform is not
+ * implemented).
+ */
+xmlSecTransformId
+xmlSecTransformSha512GetKlass(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->transformSha512GetKlass == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "transformSha512Id",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecTransformIdUnknown);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->transformSha512GetKlass());
+}
+
+/******************************************************************************
+ *
+ * High level routines form xmlsec command line utility
+ *
+ *****************************************************************************/
+/**
+ * xmlSecCryptoAppInit:
+ * @config: the path to crypto library configuration.
+ *
+ * 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
+xmlSecCryptoAppInit(const char* config) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppInit == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppInit",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppInit(config));
+}
+
+
+/**
+ * xmlSecCryptoAppShutdown:
+ *
+ * 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
+xmlSecCryptoAppShutdown(void) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppShutdown == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppShutdown",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppShutdown());
+}
+
+/**
+ * xmlSecCryptoAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId
+ * and a default crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecCryptoAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrInit == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppDefaultKeysMngrInit",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrInit(mngr));
+}
+
+/**
+ * xmlSecCryptoAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecCryptoAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecCryptoAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrAdoptKey == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppDefaultKeysMngrAdoptKey",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrAdoptKey(mngr, key));
+}
+
+/**
+ * xmlSecCryptoAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecCryptoAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecCryptoAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrLoad == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppDefaultKeysMngrLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrLoad(mngr, uri));
+}
+
+/**
+ * xmlSecCryptoAppDefaultKeysMngrSave:
+ * @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
+xmlSecCryptoAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename,
+ xmlSecKeyDataType type) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrSave == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppDefaultKeysMngrSave",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppDefaultKeysMngrSave(mngr, filename, type));
+}
+
+/**
+ * xmlSecCryptoAppKeysMngrCertLoad:
+ * @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
+xmlSecCryptoAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format, xmlSecKeyDataType type) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppKeysMngrCertLoad == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppKeysMngrCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppKeysMngrCertLoad(mngr, filename, format, type));
+}
+
+/**
+ * xmlSecCryptoAppKeysMngrCertLoadMemory:
+ * @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
+xmlSecCryptoAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppKeysMngrCertLoadMemory == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppKeysMngrCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppKeysMngrCertLoadMemory(mngr, data, dataSize, format, type));
+}
+
+/**
+ * xmlSecCryptoAppKeyLoad:
+ * @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
+xmlSecCryptoAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppKeyLoad == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppKeyLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppKeyLoad(filename, format, pwd, pwdCallback, pwdCallbackCtx));
+}
+
+/**
+ * xmlSecCryptoAppKeyLoadMemory:
+ * @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
+xmlSecCryptoAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppKeyLoadMemory == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppKeyLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppKeyLoadMemory(data, dataSize, format, pwd, pwdCallback, pwdCallbackCtx));
+}
+
+/**
+ * xmlSecCryptoAppPkcs12Load:
+ * @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 xmlSecCryptoAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecCryptoAppPkcs12Load(const char* filename, const char* pwd, void* pwdCallback,
+ void* pwdCallbackCtx) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppPkcs12Load == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppPkcs12Load",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppPkcs12Load(filename, pwd, pwdCallback, pwdCallbackCtx));
+}
+
+/**
+ * xmlSecCryptoAppPkcs12LoadMemory:
+ * @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 xmlSecCryptoAppKeyLoadMemory instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecCryptoAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ const char *pwd, void* pwdCallback,
+ void* pwdCallbackCtx) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppPkcs12LoadMemory == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppPkcs12LoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppPkcs12LoadMemory(data, dataSize, pwd, pwdCallback, pwdCallbackCtx));
+}
+
+/**
+ * xmlSecCryptoAppKeyCertLoad:
+ * @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
+xmlSecCryptoAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppKeyCertLoad == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppKeyCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppKeyCertLoad(key, filename, format));
+}
+
+/**
+ * xmlSecCryptoAppKeyCertLoadMemory:
+ * @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
+xmlSecCryptoAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ if((xmlSecCryptoDLGetFunctions() == NULL) || (xmlSecCryptoDLGetFunctions()->cryptoAppKeyCertLoadMemory == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cryptoAppKeyCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppKeyCertLoadMemory(key, data, dataSize, format));
+}
+
+/**
+ * xmlSecCryptoAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecCryptoAppGetDefaultPwdCallback(void) {
+ if(xmlSecCryptoDLGetFunctions() == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecCryptoDLGetFunctions()->cryptoAppDefaultPwdCallback);
+}
+
+#endif /* XMLSEC_NO_CRYPTO_DYNAMIC_LOADING */
+
diff --git a/src/base64.c b/src/base64.c
new file mode 100644
index 00000000..73b9e504
--- /dev/null
+++ b/src/base64.c
@@ -0,0 +1,1034 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Base64 encode/decode transform and utility functions.
+ *
+ * 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 <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+/*
+ * the table to map numbers to base64
+ */
+static const xmlSecByte base64[] =
+{
+/* 0 1 2 3 4 5 6 7 */
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 0 */
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 1 */
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 2 */
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 3 */
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 4 */
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 5 */
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 6 */
+ '4', '5', '6', '7', '8', '9', '+', '/' /* 7 */
+};
+
+
+/* few macros to simplify the code */
+#define xmlSecBase64Encode1(a) (((a) >> 2) & 0x3F)
+#define xmlSecBase64Encode2(a, b) ((((a) << 4) & 0x30) + (((b) >> 4) & 0x0F))
+#define xmlSecBase64Encode3(b, c) ((((b) << 2) & 0x3c) + (((c) >> 6) & 0x03))
+#define xmlSecBase64Encode4(c) ((c) & 0x3F)
+
+#define xmlSecBase64Decode1(a, b) (((a) << 2) | (((b) & 0x3F) >> 4))
+#define xmlSecBase64Decode2(b, c) (((b) << 4) | (((c) & 0x3F) >> 2))
+#define xmlSecBase64Decode3(c, d) (((c) << 6) | ((d) & 0x3F))
+
+#define xmlSecIsBase64Char(ch) ((((ch) >= 'A') && ((ch) <= 'Z')) || \
+ (((ch) >= 'a') && ((ch) <= 'z')) || \
+ (((ch) >= '0') && ((ch) <= '9')) || \
+ ((ch) == '+') || ((ch) == '/'))
+#define xmlSecIsBase64Space(ch) (((ch) == ' ') || ((ch) == '\t') || \
+ ((ch) == '\x0d') || ((ch) == '\x0a'))
+
+
+
+/***********************************************************************
+ *
+ * Base64 Context
+ *
+ ***********************************************************************/
+typedef enum {
+ xmlSecBase64StatusConsumeAndNext = 0,
+ xmlSecBase64StatusConsumeAndRepeat,
+ xmlSecBase64StatusNext,
+ xmlSecBase64StatusDone,
+ xmlSecBase64StatusFailed
+} xmlSecBase64Status;
+
+struct _xmlSecBase64Ctx {
+ int encode;
+ int inByte;
+ int inPos;
+ xmlSecSize linePos;
+ xmlSecSize columns;
+ int finished;
+};
+
+static xmlSecBase64Status xmlSecBase64CtxEncodeByte (xmlSecBase64CtxPtr ctx,
+ xmlSecByte inByte,
+ xmlSecByte* outByte);
+static xmlSecBase64Status xmlSecBase64CtxEncodeByteFinal (xmlSecBase64CtxPtr ctx,
+ xmlSecByte* outByte);
+static xmlSecBase64Status xmlSecBase64CtxDecodeByte (xmlSecBase64CtxPtr ctx,
+ xmlSecByte inByte,
+ xmlSecByte* outByte);
+static int xmlSecBase64CtxEncode (xmlSecBase64CtxPtr ctx,
+ const xmlSecByte* inBuf,
+ xmlSecSize inBufSize,
+ xmlSecSize* inBufResSize,
+ xmlSecByte* outBuf,
+ xmlSecSize outBufSize,
+ xmlSecSize* outBufResSize);
+static int xmlSecBase64CtxEncodeFinal (xmlSecBase64CtxPtr ctx,
+ xmlSecByte* outBuf,
+ xmlSecSize outBufSize,
+ xmlSecSize* outBufResSize);
+static int xmlSecBase64CtxDecode (xmlSecBase64CtxPtr ctx,
+ const xmlSecByte* inBuf,
+ xmlSecSize inBufSize,
+ xmlSecSize* inBufResSize,
+ xmlSecByte* outBuf,
+ xmlSecSize outBufSize,
+ xmlSecSize* outBufResSize);
+static int xmlSecBase64CtxDecodeIsFinished (xmlSecBase64CtxPtr ctx);
+
+
+static int g_xmlsec_base64_default_line_size = XMLSEC_BASE64_LINESIZE;
+
+/**
+ * xmlSecBase64GetDefaultLineSize:
+ *
+ * Gets the current default line size.
+ *
+ * Returns: the current default line size.
+ */
+int
+xmlSecBase64GetDefaultLineSize(void)
+{
+ return g_xmlsec_base64_default_line_size;
+}
+
+/**
+ * xmlSecBase64SetDefaultLineSize:
+ * @columns: number of columns
+ *
+ * Sets the current default line size.
+ */
+void
+xmlSecBase64SetDefaultLineSize(int columns)
+{
+ g_xmlsec_base64_default_line_size = columns;
+}
+
+/**
+ * xmlSecBase64CtxCreate:
+ * @encode: the encode/decode flag (1 - encode, 0 - decode)
+ * @columns: the max line length.
+ *
+ * Allocates and initializes new base64 context.
+ *
+ * Returns: a pointer to newly created #xmlSecBase64Ctx structure
+ * or NULL if an error occurs.
+ */
+xmlSecBase64CtxPtr
+xmlSecBase64CtxCreate(int encode, int columns) {
+ xmlSecBase64CtxPtr ctx;
+ int ret;
+
+ /*
+ * Allocate a new xmlSecBase64CtxPtr and fill the fields.
+ */
+ ctx = (xmlSecBase64CtxPtr) xmlMalloc(sizeof(xmlSecBase64Ctx));
+ if (ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecBase64Ctx)=%d",
+ sizeof(xmlSecBase64Ctx));
+ return(NULL);
+ }
+
+ ret = xmlSecBase64CtxInitialize(ctx, encode, columns);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBase64CtxDestroy(ctx);
+ return(NULL);
+ }
+ return(ctx);
+}
+
+/**
+ * xmlSecBase64CtxDestroy:
+ * @ctx: the pointer to #xmlSecBase64Ctx structure.
+ *
+ * Destroys base64 context.
+ */
+void
+xmlSecBase64CtxDestroy(xmlSecBase64CtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBase64CtxFinalize(ctx);
+ xmlFree(ctx);
+}
+
+/**
+ * xmlSecBase64CtxInitialize:
+ * @ctx: the pointer to #xmlSecBase64Ctx structure,
+ * @encode: the encode/decode flag (1 - encode, 0 - decode)
+ * @columns: the max line length.
+ *
+ * Initializes new base64 context.
+ *
+ * Returns: 0 on success and a negative value otherwise.
+ */
+int
+xmlSecBase64CtxInitialize(xmlSecBase64CtxPtr ctx, int encode, int columns) {
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecBase64Ctx));
+
+ ctx->encode = encode;
+ ctx->columns = columns;
+ return(0);
+}
+
+/**
+ * xmlSecBase64CtxFinalize:
+ * @ctx: the pointer to #xmlSecBase64Ctx structure,
+ *
+ * Frees all the resources allocated by @ctx.
+ */
+void
+xmlSecBase64CtxFinalize(xmlSecBase64CtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ memset(ctx, 0, sizeof(xmlSecBase64Ctx));
+}
+
+/**
+ * xmlSecBase64CtxUpdate:
+ * @ctx: the pointer to #xmlSecBase64Ctx structure
+ * @in: the input buffer
+ * @inSize: the input buffer size
+ * @out: the output buffer
+ * @outSize: the output buffer size
+ *
+ * Encodes or decodes the next piece of data from input buffer.
+ *
+ * Returns: the number of bytes written to output buffer or
+ * -1 if an error occurs.
+ */
+int
+xmlSecBase64CtxUpdate(xmlSecBase64CtxPtr ctx,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecSize inResSize = 0, outResSize = 0;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ if(ctx->encode != 0) {
+ ret = xmlSecBase64CtxEncode(ctx, in, inSize, &inResSize,
+ out, outSize, &outResSize);
+ if((ret < 0) || (inResSize != inSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ ret = xmlSecBase64CtxDecode(ctx, in, inSize, &inResSize,
+ out, outSize, &outResSize);
+ if((ret < 0) || (inResSize != inSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxDecode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(outResSize);
+}
+
+/**
+ * xmlSecBase64CtxFinal:
+ * @ctx: the pointer to #xmlSecBase64Ctx structure
+ * @out: the output buffer
+ * @outSize: the output buffer size
+ *
+ * Encodes or decodes the last piece of data stored in the context
+ * and finalizes the result.
+ *
+ * Returns: the number of bytes written to output buffer or
+ * -1 if an error occurs.
+ */
+int
+xmlSecBase64CtxFinal(xmlSecBase64CtxPtr ctx,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecSize outResSize = 0;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ if(ctx->encode != 0) {
+ ret = xmlSecBase64CtxEncodeFinal(ctx, out, outSize, &outResSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxEncodeFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+ } else {
+ if(!xmlSecBase64CtxDecodeIsFinished(ctx)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxIsFinished",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* add \0 */
+ if((outResSize + 1) < outSize) {
+ out[outResSize] = '\0';
+ }
+ return(outResSize);
+}
+
+static xmlSecBase64Status
+xmlSecBase64CtxEncodeByte(xmlSecBase64CtxPtr ctx, xmlSecByte inByte, xmlSecByte* outByte) {
+ xmlSecAssert2(ctx != NULL, xmlSecBase64StatusFailed);
+ xmlSecAssert2(outByte != NULL, xmlSecBase64StatusFailed);
+
+ if((ctx->columns > 0) && (ctx->linePos >= ctx->columns)) {
+ (*outByte) = '\n';
+ ctx->linePos = 0;
+ return(xmlSecBase64StatusConsumeAndRepeat);
+ } else if(ctx->inPos == 0) {
+ /* we just started new block */
+ (*outByte) = base64[xmlSecBase64Encode1(inByte)];
+ ctx->inByte = inByte;
+ ++ctx->linePos;
+ ++ctx->inPos;
+ return(xmlSecBase64StatusConsumeAndNext);
+ } else if(ctx->inPos == 1) {
+ (*outByte) = base64[xmlSecBase64Encode2(ctx->inByte, inByte)];
+ ctx->inByte = inByte;
+ ++ctx->linePos;
+ ++ctx->inPos;
+ return(xmlSecBase64StatusConsumeAndNext);
+ } else if(ctx->inPos == 2) {
+ (*outByte) = base64[xmlSecBase64Encode3(ctx->inByte, inByte)];
+ ctx->inByte = inByte;
+ ++ctx->linePos;
+ ++ctx->inPos;
+ return(xmlSecBase64StatusConsumeAndRepeat);
+ } else if(ctx->inPos == 3) {
+ (*outByte) = base64[xmlSecBase64Encode4(ctx->inByte)];
+ ++ctx->linePos;
+ ctx->inByte = 0;
+ ctx->inPos = 0;
+ return(xmlSecBase64StatusConsumeAndNext);
+ }
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "ctx->inPos=%d", ctx->inPos);
+ return(xmlSecBase64StatusFailed);
+}
+
+static xmlSecBase64Status
+xmlSecBase64CtxEncodeByteFinal(xmlSecBase64CtxPtr ctx, xmlSecByte* outByte) {
+ xmlSecAssert2(ctx != NULL, xmlSecBase64StatusFailed);
+ xmlSecAssert2(outByte != NULL, xmlSecBase64StatusFailed);
+
+ if(ctx->inPos == 0) {
+ return(xmlSecBase64StatusDone);
+ } else if((ctx->columns > 0) && (ctx->linePos >= ctx->columns)) {
+ (*outByte) = '\n';
+ ctx->linePos = 0;
+ return(xmlSecBase64StatusConsumeAndRepeat);
+ } else if(ctx->finished == 0) {
+ ctx->finished = 1;
+ return(xmlSecBase64CtxEncodeByte(ctx, 0, outByte));
+ } else if(ctx->inPos < 3) {
+ (*outByte) = '=';
+ ++ctx->inPos;
+ ++ctx->linePos;
+ return(xmlSecBase64StatusConsumeAndRepeat);
+ } else if(ctx->inPos == 3) {
+ (*outByte) = '=';
+ ++ctx->linePos;
+ ctx->inPos = 0;
+ return(xmlSecBase64StatusConsumeAndRepeat);
+ }
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "ctx->inPos=%d", ctx->inPos);
+ return(xmlSecBase64StatusFailed);
+}
+
+static xmlSecBase64Status
+xmlSecBase64CtxDecodeByte(xmlSecBase64CtxPtr ctx, xmlSecByte inByte, xmlSecByte* outByte) {
+ xmlSecAssert2(ctx != NULL, xmlSecBase64StatusFailed);
+ xmlSecAssert2(outByte != NULL, xmlSecBase64StatusFailed);
+
+ if((ctx->finished != 0) && (ctx->inPos == 0)) {
+ return(xmlSecBase64StatusDone);
+ } if(inByte == '=') {
+ ctx->finished = 1;
+ if(ctx->inPos < 2) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "ctx->inPos=%d", ctx->inPos);
+ return(xmlSecBase64StatusFailed);
+ } else if(ctx->inPos == 2) {
+ ++ctx->inPos;
+ return(xmlSecBase64StatusNext);
+ } else if(ctx->inPos == 3) {
+ ctx->inPos = 0;
+ return(xmlSecBase64StatusNext);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "ctx->inPos=%d", ctx->inPos);
+ return(xmlSecBase64StatusFailed);
+ }
+ } else if(xmlSecIsBase64Space(inByte)) {
+ return(xmlSecBase64StatusNext);
+ } else if(!xmlSecIsBase64Char(inByte) || (ctx->finished != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "inByte=0x%02x", inByte);
+ return(xmlSecBase64StatusFailed);
+ }
+
+ /* convert from character to position in base64 array */
+ if((inByte >= 'A') && (inByte <= 'Z')) {
+ inByte = (inByte - 'A');
+ } else if((inByte >= 'a') && (inByte <= 'z')) {
+ inByte = 26 + (inByte - 'a');
+ } else if((inByte >= '0') && (inByte <= '9')) {
+ inByte = 52 + (inByte - '0');
+ } else if(inByte == '+') {
+ inByte = 62;
+ } else if(inByte == '/') {
+ inByte = 63;
+ }
+
+ if(ctx->inPos == 0) {
+ ctx->inByte = inByte;
+ ++ctx->inPos;
+ return(xmlSecBase64StatusNext);
+ } else if(ctx->inPos == 1) {
+ (*outByte) = xmlSecBase64Decode1(ctx->inByte, inByte);
+ ctx->inByte = inByte;
+ ++ctx->inPos;
+ return(xmlSecBase64StatusConsumeAndNext);
+ } else if(ctx->inPos == 2) {
+ (*outByte) = xmlSecBase64Decode2(ctx->inByte, inByte);
+ ctx->inByte = inByte;
+ ++ctx->inPos;
+ return(xmlSecBase64StatusConsumeAndNext);
+ } else if(ctx->inPos == 3) {
+ (*outByte) = xmlSecBase64Decode3(ctx->inByte, inByte);
+ ctx->inByte = 0;
+ ctx->inPos = 0;
+ return(xmlSecBase64StatusConsumeAndNext);
+ }
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "ctx->inPos=%d", ctx->inPos);
+ return(xmlSecBase64StatusFailed);
+}
+
+
+static int
+xmlSecBase64CtxEncode(xmlSecBase64CtxPtr ctx,
+ const xmlSecByte* inBuf, xmlSecSize inBufSize, xmlSecSize* inBufResSize,
+ xmlSecByte* outBuf, xmlSecSize outBufSize, xmlSecSize* outBufResSize) {
+ xmlSecBase64Status status = xmlSecBase64StatusNext;
+ xmlSecSize inPos, outPos;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(inBuf != NULL, -1);
+ xmlSecAssert2(inBufResSize != NULL, -1);
+ xmlSecAssert2(outBuf != NULL, -1);
+ xmlSecAssert2(outBufResSize != NULL, -1);
+
+ /* encode */
+ for(inPos = outPos = 0; (inPos < inBufSize) && (outPos < outBufSize); ) {
+ status = xmlSecBase64CtxEncodeByte(ctx, inBuf[inPos], &(outBuf[outPos]));
+ switch(status) {
+ case xmlSecBase64StatusConsumeAndNext:
+ ++inPos;
+ ++outPos;
+ break;
+ case xmlSecBase64StatusConsumeAndRepeat:
+ ++outPos;
+ break;
+ case xmlSecBase64StatusNext:
+ case xmlSecBase64StatusDone:
+ case xmlSecBase64StatusFailed:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxEncodeByte",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "status=%d", status);
+ return(-1);
+ }
+ }
+
+ (*inBufResSize) = inPos;
+ (*outBufResSize) = outPos;
+
+ return(0);
+}
+
+static int
+xmlSecBase64CtxEncodeFinal(xmlSecBase64CtxPtr ctx,
+ xmlSecByte* outBuf, xmlSecSize outBufSize, xmlSecSize* outBufResSize) {
+ xmlSecBase64Status status = xmlSecBase64StatusNext;
+ xmlSecSize outPos;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(outBuf != NULL, -1);
+ xmlSecAssert2(outBufResSize != NULL, -1);
+
+ /* encode final bytes */
+ for(outPos = 0; (outPos < outBufSize) && (status != xmlSecBase64StatusDone); ) {
+ status = xmlSecBase64CtxEncodeByteFinal(ctx, &(outBuf[outPos]));
+ switch(status) {
+ case xmlSecBase64StatusConsumeAndNext:
+ case xmlSecBase64StatusConsumeAndRepeat:
+ ++outPos;
+ break;
+ case xmlSecBase64StatusDone:
+ break;
+ case xmlSecBase64StatusNext:
+ case xmlSecBase64StatusFailed:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxEncodeByteFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "status=%d", status);
+ return(-1);
+ }
+ }
+
+ if(status != xmlSecBase64StatusDone) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "outBufSize=%d", outBufSize);
+ return(-1);
+ }
+ if(outPos < outBufSize) {
+ outBuf[outPos] = '\0'; /* just in case */
+ }
+
+ (*outBufResSize) = outPos;
+ return(0);
+}
+
+
+static int
+xmlSecBase64CtxDecode(xmlSecBase64CtxPtr ctx,
+ const xmlSecByte* inBuf, xmlSecSize inBufSize, xmlSecSize* inBufResSize,
+ xmlSecByte* outBuf, xmlSecSize outBufSize, xmlSecSize* outBufResSize) {
+ xmlSecBase64Status status = xmlSecBase64StatusNext;
+ xmlSecSize inPos, outPos;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(inBuf != NULL, -1);
+ xmlSecAssert2(inBufResSize != NULL, -1);
+ xmlSecAssert2(outBuf != NULL, -1);
+ xmlSecAssert2(outBufResSize != NULL, -1);
+
+ /* decode */
+ for(inPos = outPos = 0; (inPos < inBufSize) && (outPos < outBufSize) && (status != xmlSecBase64StatusDone); ) {
+ status = xmlSecBase64CtxDecodeByte(ctx, inBuf[inPos], &(outBuf[outPos]));
+ switch(status) {
+ case xmlSecBase64StatusConsumeAndNext:
+ ++inPos;
+ ++outPos;
+ break;
+ case xmlSecBase64StatusConsumeAndRepeat:
+ ++outPos;
+ break;
+ case xmlSecBase64StatusNext:
+ ++inPos;
+ break;
+ case xmlSecBase64StatusDone:
+ break;
+ case xmlSecBase64StatusFailed:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxDecodeByte",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "status=%d", status);
+ return(-1);
+ }
+ }
+
+ /* skip spaces at the end */
+ while((inPos < inBufSize) && xmlSecIsBase64Space(inBuf[inPos])) {
+ ++inPos;
+ }
+
+ (*inBufResSize) = inPos;
+ (*outBufResSize) = outPos;
+
+ return(0);
+}
+
+static int
+xmlSecBase64CtxDecodeIsFinished(xmlSecBase64CtxPtr ctx) {
+ xmlSecAssert2(ctx != NULL, -1);
+
+ return((ctx->inPos == 0) ? 1 : 0);
+}
+
+/**
+ * xmlSecBase64Encode:
+ * @buf: the input buffer.
+ * @len: the input buffer size.
+ * @columns: the output max line length (if 0 then no line breaks
+ * would be inserted)
+ *
+ * Encodes the data from input buffer and allocates the string for the result.
+ * The caller is responsible for freeing returned buffer using
+ * xmlFree() function.
+ *
+ * Returns: newly allocated string with base64 encoded data
+ * or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecBase64Encode(const xmlSecByte *buf, xmlSecSize len, int columns) {
+ xmlSecBase64Ctx ctx;
+ xmlChar *ptr;
+ xmlSecSize size;
+ int size_update, size_final;
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+
+ ret = xmlSecBase64CtxInitialize(&ctx, 1, columns);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* create result buffer */
+ size = (4 * len) / 3 + 4;
+ if(columns > 0) {
+ size += (size / columns) + 4;
+ }
+ ptr = (xmlChar*) xmlMalloc(size);
+ if(ptr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", size);
+ xmlSecBase64CtxFinalize(&ctx);
+ return(NULL);
+ }
+
+ ret = xmlSecBase64CtxUpdate(&ctx, buf, len, (xmlSecByte*)ptr, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "len=%d", len);
+ xmlFree(ptr);
+ xmlSecBase64CtxFinalize(&ctx);
+ return(NULL);
+ }
+ size_update = ret;
+
+ ret = xmlSecBase64CtxFinal(&ctx, ((xmlSecByte*)ptr) + size_update, size - size_update);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(ptr);
+ xmlSecBase64CtxFinalize(&ctx);
+ return(NULL);
+ }
+ size_final = ret;
+ ptr[size_update + size_final] = '\0';
+
+ xmlSecBase64CtxFinalize(&ctx);
+ return(ptr);
+}
+
+/**
+ * xmlSecBase64Decode:
+ * @str: the input buffer with base64 encoded string
+ * @buf: the output buffer
+ * @len: the output buffer size
+ *
+ * Decodes input base64 encoded string and puts result into
+ * the output buffer.
+ *
+ * Returns: the number of bytes written to the output buffer or
+ * a negative value if an error occurs
+ */
+int
+xmlSecBase64Decode(const xmlChar* str, xmlSecByte *buf, xmlSecSize len) {
+ xmlSecBase64Ctx ctx;
+ int size_update;
+ int size_final;
+ int ret;
+
+ xmlSecAssert2(str != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+
+ ret = xmlSecBase64CtxInitialize(&ctx, 0, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBase64CtxUpdate(&ctx, (const xmlSecByte*)str, xmlStrlen(str), buf, len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBase64CtxFinalize(&ctx);
+ return(-1);
+ }
+
+ size_update = ret;
+ ret = xmlSecBase64CtxFinal(&ctx, buf + size_update, len - size_update);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64CtxFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBase64CtxFinalize(&ctx);
+ return(-1);
+ }
+ size_final = ret;
+
+ xmlSecBase64CtxFinalize(&ctx);
+ return(size_update + size_final);
+}
+
+/**************************************************************
+ *
+ * Base64 Transform
+ *
+ * xmlSecBase64Ctx is located after xmlSecTransform
+ *
+ **************************************************************/
+#define xmlSecBase64Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBase64Ctx))
+#define xmlSecBase64GetCtx(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecBase64Size)) ? \
+ (xmlSecBase64CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlSecBase64CtxPtr)NULL)
+
+static int xmlSecBase64Initialize (xmlSecTransformPtr transform);
+static void xmlSecBase64Finalize (xmlSecTransformPtr transform);
+static int xmlSecBase64Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecBase64Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecBase64Size, /* xmlSecSize objSize */
+
+ xmlSecNameBase64, /* const xmlChar* name; */
+ xmlSecHrefBase64, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecBase64Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecBase64Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecBase64Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformBase64GetKlass:
+ *
+ * The Base64 transform klass (http://www.w3.org/TR/xmldsig-core/#sec-Base-64).
+ * The normative specification for base64 decoding transforms is RFC 2045
+ * (http://www.ietf.org/rfc/rfc2045.txt). The base64 Transform element has
+ * no content. The input is decoded by the algorithms. This transform is
+ * useful if an application needs to sign the raw data associated with
+ * the encoded content of an element.
+ *
+ * Returns: base64 transform id.
+ */
+xmlSecTransformId
+xmlSecTransformBase64GetKlass(void) {
+ return(&xmlSecBase64Klass);
+}
+
+/**
+ * xmlSecTransformBase64SetLineSize:
+ * @transform: the pointer to BASE64 encode transform.
+ * @lineSize: the new max line size.
+ *
+ * Sets the max line size to @lineSize.
+ */
+void
+xmlSecTransformBase64SetLineSize(xmlSecTransformPtr transform, xmlSecSize lineSize) {
+ xmlSecBase64CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id));
+
+ ctx = xmlSecBase64GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ ctx->columns = lineSize;
+}
+
+static int
+xmlSecBase64Initialize(xmlSecTransformPtr transform) {
+ xmlSecBase64CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id), -1);
+
+ ctx = xmlSecBase64GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ transform->operation = xmlSecTransformOperationDecode;
+ ret = xmlSecBase64CtxInitialize(ctx, 0, xmlSecBase64GetDefaultLineSize());
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBase64CtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecBase64Finalize(xmlSecTransformPtr transform) {
+ xmlSecBase64CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id));
+
+ ctx = xmlSecBase64GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBase64CtxFinalize(ctx);
+}
+
+static int
+xmlSecBase64Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBase64CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, outLen;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformBase64Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncode) || (transform->operation == xmlSecTransformOperationDecode), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecBase64GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ ctx->encode = (transform->operation == xmlSecTransformOperationEncode) ? 1 : 0;
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ switch(transform->status) {
+ case xmlSecTransformStatusWorking:
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ if(inSize > 0) {
+ if(ctx->encode != 0) {
+ outLen = 4 * inSize / 3 + 8;
+ if(ctx->columns > 0) {
+ outLen += inSize / ctx->columns + 4;
+ }
+ } else {
+ outLen = 3 * inSize / 4 + 8;
+ }
+ ret = xmlSecBufferSetMaxSize(out, outSize + outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen);
+ return(-1);
+ }
+
+ /* encode/decode the next chunk */
+ ret = xmlSecBase64CtxUpdate(ctx, xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out) + outSize,
+ outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBase64CtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outLen = ret;
+
+ /* set correct size */
+ ret = xmlSecBufferSetSize(out, outSize + outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen);
+ return(-1);
+ }
+
+ /* remove chunk from input */
+ 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) {
+ outSize = xmlSecBufferGetSize(out);
+
+ ret = xmlSecBufferSetMaxSize(out, outSize + 16);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + 16);
+ return(-1);
+ }
+
+ /* add from ctx buffer */
+ ret = xmlSecBase64CtxFinal(ctx, xmlSecBufferGetData(out) + outSize, 16);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBase64CtxFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outLen = ret;
+
+ /* set correct size */
+ ret = xmlSecBufferSetSize(out, outSize + outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ break;
+ case xmlSecTransformStatusFinished:
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+
diff --git a/src/bn.c b/src/bn.c
new file mode 100644
index 00000000..5a26de28
--- /dev/null
+++ b/src/bn.c
@@ -0,0 +1,1060 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Big Numbers.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/bn.h>
+#include <xmlsec/errors.h>
+
+/* table for converting hex digits back to bytes */
+static const int xmlSecBnLookupTable[] =
+{
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static const char xmlSecBnRevLookupTable[] =
+{
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+/*****************************************************************************
+ *
+ * xmlSecBn
+ *
+ ****************************************************************************/
+/**
+ * xmlSecBnCreate:
+ * @size: the initial allocated BN size.
+ *
+ * Creates a new BN object. Caller is responsible for destroying it
+ * by calling @xmlSecBnDestroy function.
+ *
+ * Returns: the newly BN or a NULL if an error occurs.
+ */
+xmlSecBnPtr
+xmlSecBnCreate(xmlSecSize size) {
+ return(xmlSecBufferCreate(size));
+}
+
+/**
+ * xmlSecBnDestroy:
+ * @bn: the pointer to BN.
+ *
+ * Destroys @bn object created with @xmlSecBnCreate function.
+ */
+void
+xmlSecBnDestroy(xmlSecBnPtr bn) {
+ xmlSecBufferDestroy(bn);
+}
+
+/**
+ * xmlSecBnInitialize:
+ * @bn: the pointer to BN.
+ * @size: the initial allocated BN size.
+ *
+ * Initializes a BN object. Caller is responsible for destroying it
+ * by calling @xmlSecBnFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnInitialize(xmlSecBnPtr bn, xmlSecSize size) {
+ return(xmlSecBufferInitialize(bn, size));
+}
+
+/**
+ * xmlSecBnFinalize:
+ * @bn: the pointer to BN.
+ *
+ * Destroys @bn object created with @xmlSecBnInitialize function.
+ */
+void
+xmlSecBnFinalize(xmlSecBnPtr bn) {
+ xmlSecBufferFinalize(bn);
+}
+
+/**
+ * xmlSecBnGetData:
+ * @bn: the pointer to BN.
+ *
+ * Gets pointer to the binary @bn representation.
+ *
+ * Returns: pointer to binary BN data or NULL if an error occurs.
+ */
+xmlSecByte*
+xmlSecBnGetData(xmlSecBnPtr bn) {
+ return(xmlSecBufferGetData(bn));
+}
+
+/**
+ * xmlSecBnSetData:
+ * @bn: the pointer to BN.
+ * @data: the pointer to new BN binary data.
+ * @size: the size of new BN data.
+ *
+ * Sets the value of @bn to @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnSetData(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize size) {
+ return(xmlSecBufferSetData(bn, data, size));
+}
+
+/**
+ * xmlSecBnGetSize:
+ * @bn: the pointer to BN.
+ *
+ * Gets the size of binary data in @bn.
+ *
+ * Returns: the size of binary data.
+ */
+xmlSecSize
+xmlSecBnGetSize(xmlSecBnPtr bn) {
+ return(xmlSecBufferGetSize(bn));
+}
+
+/**
+ * xmlSecBnZero:
+ * @bn: the pointer to BN.
+ *
+ * Sets the value of @bn to zero.
+ */
+void
+xmlSecBnZero(xmlSecBnPtr bn) {
+ xmlSecBufferEmpty(bn);
+}
+
+/**
+ * xmlSecBnFromString:
+ * @bn: the pointer to BN.
+ * @str: the string with BN.
+ * @base: the base for @str.
+ *
+ * Reads @bn from string @str assuming it has base @base.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnFromString(xmlSecBnPtr bn, const xmlChar* str, xmlSecSize base) {
+ xmlSecSize i, len, size;
+ xmlSecByte ch;
+ xmlSecByte* data;
+ int positive;
+ int nn;
+ int ret;
+
+ xmlSecAssert2(bn != NULL, -1);
+ xmlSecAssert2(str != NULL, -1);
+ xmlSecAssert2(base > 1, -1);
+ xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), -1);
+
+ /* trivial case */
+ len = xmlStrlen(str);
+ if(len == 0) {
+ return(0);
+ }
+
+ /* The result size could not exceed the input string length
+ * because each char fits inside a byte in all cases :)
+ * In truth, it would be likely less than 1/2 input string length
+ * because each byte is represented by 2 chars. If needed,
+ * buffer size would be increased by Mul/Add functions.
+ * Finally, we can add one byte for 00 or 10 prefix.
+ */
+ ret = xmlSecBufferSetMaxSize(bn, xmlSecBufferGetSize(bn) + len / 2 + 1 + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnRevLookupTable",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", len / 2 + 1);
+ return (-1);
+ }
+
+ /* figure out if it is positive or negative number */
+ positive = 1;
+ i = 0;
+ while(i < len) {
+ ch = str[i++];
+
+ /* skip spaces */
+ if(isspace(ch)) {
+ continue;
+ }
+
+ /* check if it is + or - */
+ if(ch == '+') {
+ positive = 1;
+ break;
+ } else if(ch == '-') {
+ positive = 0;
+ break;
+ }
+
+ /* otherwise, it must be start of the number */
+ nn = xmlSecBnLookupTable[ch];
+ if((nn >= 0) && ((xmlSecSize)nn < base)) {
+ xmlSecAssert2(i > 0, -1);
+
+ /* no sign, positive by default */
+ positive = 1;
+ --i; /* make sure that we will look at this character in next loop */
+ break;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "char=%c;base=%d",
+ ch, base);
+ return (-1);
+ }
+ }
+
+ /* now parse the number itself */
+ while(i < len) {
+ ch = str[i++];
+ if(isspace(ch)) {
+ continue;
+ }
+
+ xmlSecAssert2(ch <= sizeof(xmlSecBnLookupTable), -1);
+ nn = xmlSecBnLookupTable[ch];
+ if((nn < 0) || ((xmlSecSize)nn > base)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "char=%c;base=%d",
+ ch, base);
+ return (-1);
+ }
+
+ ret = xmlSecBnMul(bn, base);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnMul",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "base=%d", base);
+ return (-1);
+ }
+
+ ret = xmlSecBnAdd(bn, nn);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "base=%d", base);
+ return (-1);
+}
+ }
+
+ /* check if we need to add 00 prefix, do this for empty bn too */
+ data = xmlSecBufferGetData(bn);
+ size = xmlSecBufferGetSize(bn);
+ if(((size > 0) && (data[0] > 127)) || (size == 0)) {
+ ch = 0;
+ ret = xmlSecBufferPrepend(bn, &ch, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "base=%d", base);
+ return (-1);
+ }
+ }
+
+ /* do 2's compliment and add 1 to represent negative value */
+ if(positive == 0) {
+ data = xmlSecBufferGetData(bn);
+ size = xmlSecBufferGetSize(bn);
+ for(i = 0; i < size; ++i) {
+ data[i] ^= 0xFF;
+ }
+
+ ret = xmlSecBnAdd(bn, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "base=%d", base);
+ return (-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBnToString:
+ * @bn: the pointer to BN.
+ * @base: the base for returned string.
+ *
+ * Writes @bn to string with base @base. Caller is responsible for
+ * freeing returned string with @xmlFree.
+ *
+ * Returns: the string represenataion if BN or a NULL if an error occurs.
+ */
+xmlChar*
+xmlSecBnToString(xmlSecBnPtr bn, xmlSecSize base) {
+ xmlSecBn bn2;
+ int positive = 1;
+ xmlChar* res;
+ xmlSecSize i, len, size;
+ xmlSecByte* data;
+ int ret;
+ int nn;
+ xmlChar ch;
+
+ xmlSecAssert2(bn != NULL, NULL);
+ xmlSecAssert2(base > 1, NULL);
+ xmlSecAssert2(base <= sizeof(xmlSecBnRevLookupTable), NULL);
+
+
+ /* copy bn */
+ data = xmlSecBufferGetData(bn);
+ size = xmlSecBufferGetSize(bn);
+ ret = xmlSecBnInitialize(&bn2, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return (NULL);
+ }
+
+ ret = xmlSecBnSetData(&bn2, data, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ xmlSecBnFinalize(&bn2);
+ return (NULL);
+ }
+
+ /* check if it is a negative number or not */
+ data = xmlSecBufferGetData(&bn2);
+ size = xmlSecBufferGetSize(&bn2);
+ if((size > 0) && (data[0] > 127)) {
+ /* subtract 1 and do 2's compliment */
+ ret = xmlSecBnAdd(&bn2, -1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ xmlSecBnFinalize(&bn2);
+ return (NULL);
+ }
+ for(i = 0; i < size; ++i) {
+ data[i] ^= 0xFF;
+ }
+
+ positive = 0;
+ } else {
+ positive = 1;
+ }
+
+ /* Result string len is
+ * len = log base (256) * <bn size>
+ * Since the smallest base == 2 then we can get away with
+ * len = 8 * <bn size>
+ */
+ len = 8 * size + 1 + 1;
+ res = (xmlChar*)xmlMalloc(len + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "len=%d", len);
+ xmlSecBnFinalize(&bn2);
+ return (NULL);
+ }
+ memset(res, 0, len + 1);
+
+ for(i = 0; (xmlSecBufferGetSize(&bn2) > 0) && (i < len); i++) {
+ if(xmlSecBnDiv(&bn2, base, &nn) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnDiv",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "base=%d", base);
+ xmlFree(res);
+ xmlSecBnFinalize(&bn2);
+ return (NULL);
+ }
+ xmlSecAssert2((size_t)nn < sizeof(xmlSecBnRevLookupTable), NULL);
+ res[i] = xmlSecBnRevLookupTable[nn];
+ }
+ xmlSecAssert2(i < len, NULL);
+
+ /* we might have '0' at the beggining, remove it but keep one zero */
+ for(len = i; (len > 1) && (res[len - 1] == '0'); len--);
+ res[len] = '\0';
+
+ /* add "-" for negative numbers */
+ if(positive == 0) {
+ res[len] = '-';
+ res[++len] = '\0';
+ }
+
+ /* swap the string because we wrote it in reverse order */
+ for(i = 0; i < len / 2; i++) {
+ ch = res[i];
+ res[i] = res[len - i - 1];
+ res[len - i - 1] = ch;
+ }
+
+ xmlSecBnFinalize(&bn2);
+ return(res);
+}
+
+/**
+ * xmlSecBnFromHexString:
+ * @bn: the pointer to BN.
+ * @str: the string with BN.
+ *
+ * Reads @bn from hex string @str.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnFromHexString(xmlSecBnPtr bn, const xmlChar* str) {
+ return(xmlSecBnFromString(bn, str, 16));
+}
+
+/**
+ * xmlSecBnToHexString:
+ * @bn: the pointer to BN.
+ *
+ * Writes @bn to hex string. Caller is responsible for
+ * freeing returned string with @xmlFree.
+ *
+ * Returns: the string represenataion if BN or a NULL if an error occurs.
+ */
+xmlChar*
+xmlSecBnToHexString(xmlSecBnPtr bn) {
+ return(xmlSecBnToString(bn, 16));
+}
+
+/**
+ * xmlSecBnFromDecString:
+ * @bn: the pointer to BN.
+ * @str: the string with BN.
+ *
+ * Reads @bn from decimal string @str.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnFromDecString(xmlSecBnPtr bn, const xmlChar* str) {
+ return(xmlSecBnFromString(bn, str, 10));
+}
+
+/**
+ * xmlSecBnToDecString:
+ * @bn: the pointer to BN.
+ *
+ * Writes @bn to decimal string. Caller is responsible for
+ * freeing returned string with @xmlFree.
+ *
+ * Returns: the string represenataion if BN or a NULL if an error occurs.
+ */
+xmlChar*
+xmlSecBnToDecString(xmlSecBnPtr bn) {
+ return(xmlSecBnToString(bn, 10));
+}
+
+/**
+ * xmlSecBnMul:
+ * @bn: the pointer to BN.
+ * @multiplier: the multiplier.
+ *
+ * Multiplies @bn with @multiplier.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnMul(xmlSecBnPtr bn, int multiplier) {
+ xmlSecByte* data;
+ int over;
+ xmlSecSize i;
+ xmlSecByte ch;
+ int ret;
+
+ xmlSecAssert2(bn != NULL, -1);
+ xmlSecAssert2(multiplier > 0, -1);
+
+ if(multiplier == 1) {
+ return(0);
+ }
+
+ data = xmlSecBufferGetData(bn);
+ i = xmlSecBufferGetSize(bn);
+ over = 0;
+ while(i > 0) {
+ xmlSecAssert2(data != NULL, -1);
+
+ over = over + multiplier * data[--i];
+ data[i] = over % 256;
+ over = over / 256;
+ }
+
+ while(over > 0) {
+ ch = over % 256;
+ over = over / 256;
+
+ ret = xmlSecBufferPrepend(bn, &ch, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=1");
+ return (-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBnDiv:
+ * @bn: the pointer to BN.
+ * @divider: the divider
+ * @mod: the pointer for modulus result.
+ *
+ * Divides @bn by @divider and places modulus into @mod.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnDiv(xmlSecBnPtr bn, int divider, int* mod) {
+ int over;
+ xmlSecSize i, size;
+ xmlSecByte* data;
+ int ret;
+
+ xmlSecAssert2(bn != NULL, -1);
+ xmlSecAssert2(divider > 0, -1);
+ xmlSecAssert2(mod != NULL, -1);
+
+ if(divider == 1) {
+ return(0);
+ }
+
+ data = xmlSecBufferGetData(bn);
+ size = xmlSecBufferGetSize(bn);
+ for(over = 0, i = 0; i < size; i++) {
+ xmlSecAssert2(data != NULL, -1);
+
+ over = over * 256 + data[i];
+ data[i] = over / divider;
+ over = over % divider;
+ }
+ (*mod) = over;
+
+ /* remove leading zeros */
+ for(i = 0; i < size; i++) {
+ xmlSecAssert2(data != NULL, -1);
+
+ if(data[i] != 0) {
+ break;
+ }
+ }
+ if(i > 0) {
+ ret = xmlSecBufferRemoveHead(bn, i);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", i);
+ return (-1);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecBnAdd:
+ * @bn: the pointer to BN.
+ * @delta: the delta.
+ *
+ * Adds @delta to @bn.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnAdd(xmlSecBnPtr bn, int delta) {
+ int over, tmp;
+ xmlSecByte* data;
+ xmlSecSize i;
+ xmlSecByte ch;
+ int ret;
+
+ xmlSecAssert2(bn != NULL, -1);
+
+ if(delta == 0) {
+ return(0);
+ }
+
+ data = xmlSecBufferGetData(bn);
+ if(delta > 0) {
+ for(over = delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0) ;) {
+ xmlSecAssert2(data != NULL, -1);
+
+ tmp = data[--i];
+ over += tmp;
+ data[i] = over % 256;
+ over = over / 256;
+ }
+
+ while(over > 0) {
+ ch = over % 256;
+ over = over / 256;
+
+ ret = xmlSecBufferPrepend(bn, &ch, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=1");
+ return (-1);
+ }
+ }
+ } else {
+ for(over = -delta, i = xmlSecBufferGetSize(bn); (i > 0) && (over > 0);) {
+ xmlSecAssert2(data != NULL, -1);
+
+ tmp = data[--i];
+ if(tmp < over) {
+ data[i] = 0;
+ over = (over - tmp) / 256;
+ } else {
+ data[i] = tmp - over;
+ over = 0;
+ }
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecBnReverse:
+ * @bn: the pointer to BN.
+ *
+ * Reverses bytes order in @bn.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBnReverse(xmlSecBnPtr bn) {
+ xmlSecByte* data;
+ xmlSecSize i, j, size;
+ xmlSecByte ch;
+
+ xmlSecAssert2(bn != NULL, -1);
+
+ data = xmlSecBufferGetData(bn);
+ size = xmlSecBufferGetSize(bn);
+ for(i = 0, j = size - 1; i < size / 2; ++i, --j) {
+ xmlSecAssert2(data != NULL, -1);
+
+ ch = data[i];
+ data[i] = data[j];
+ data[j] = ch;
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBnCompare:
+ * @bn: the pointer to BN.
+ * @data: the data to compare BN to.
+ * @dataSize: the @data size.
+ *
+ * Compares the @bn with @data.
+ *
+ * Returns: 0 if data is equal, negative value if @bn is less or positive value if @bn
+ * is greater than @data.
+ */
+int
+xmlSecBnCompare(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
+ xmlSecByte* bnData;
+ xmlSecSize bnSize;
+
+ xmlSecAssert2(bn != NULL, -1);
+
+ bnData = xmlSecBnGetData(bn);
+ bnSize = xmlSecBnGetSize(bn);
+
+ /* skip zeros in the beggining */
+ while((dataSize > 0) && (data != 0) && (data[0] == 0)) {
+ ++data;
+ --dataSize;
+ }
+ while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
+ ++bnData;
+ --bnSize;
+ }
+
+ if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
+ return(0);
+ } else if((bnData == NULL) || (bnSize == 0)) {
+ return(-1);
+ } else if((data == NULL) || (dataSize == 0)) {
+ return(1);
+ } else if(bnSize < dataSize) {
+ return(-1);
+ } else if(bnSize > dataSize) {
+ return(-1);
+ }
+
+ xmlSecAssert2(bnData != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(bnSize == dataSize, -1);
+
+ return(memcmp(bnData, data, dataSize));
+}
+
+/**
+ * xmlSecBnCompareReverse:
+ * @bn: the pointer to BN.
+ * @data: the data to compare BN to.
+ * @dataSize: the @data size.
+ *
+ * Compares the @bn with reverse @data.
+ *
+ * Returns: 0 if data is equal, negative value if @bn is less or positive value if @bn
+ * is greater than @data.
+ */
+int
+xmlSecBnCompareReverse(xmlSecBnPtr bn, const xmlSecByte* data, xmlSecSize dataSize) {
+ xmlSecByte* bnData;
+ xmlSecSize bnSize;
+ xmlSecSize i, j;
+
+ xmlSecAssert2(bn != NULL, -1);
+
+ bnData = xmlSecBnGetData(bn);
+ bnSize = xmlSecBnGetSize(bn);
+
+ /* skip zeros in the beggining */
+ while((dataSize > 0) && (data != 0) && (data[dataSize - 1] == 0)) {
+ --dataSize;
+ }
+ while((bnSize > 0) && (bnData != 0) && (bnData[0] == 0)) {
+ ++bnData;
+ --bnSize;
+ }
+
+ if(((bnData == NULL) || (bnSize == 0)) && ((data == NULL) || (dataSize == 0))) {
+ return(0);
+ } else if((bnData == NULL) || (bnSize == 0)) {
+ return(-1);
+ } else if((data == NULL) || (dataSize == 0)) {
+ return(1);
+ } else if(bnSize < dataSize) {
+ return(-1);
+ } else if(bnSize > dataSize) {
+ return(-1);
+ }
+
+ xmlSecAssert2(bnData != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(bnSize == dataSize, -1);
+ for(i = 0, j = dataSize - 1; i < dataSize; ++i, --j) {
+ if(bnData[i] < data[j]) {
+ return(-1);
+ } else if(data[j] < bnData[i]) {
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBnGetNodeValue:
+ * @bn: the pointer to BN.
+ * @cur: the poitner to an XML node.
+ * @format: the BN format.
+ * @reverse: if set then reverse read buffer after reading.
+ *
+ * Converts the node content from @format to @bn.
+ *
+ * Returns: 0 on success and a negative values if an error occurs.
+ */
+int
+xmlSecBnGetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse) {
+ xmlChar* content;
+ int ret;
+
+ xmlSecAssert2(bn != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ switch(format) {
+ case xmlSecBnBase64:
+ ret = xmlSecBufferBase64NodeContentRead(bn, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferBase64NodeContentRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ break;
+ case xmlSecBnHex:
+ content = xmlNodeGetContent(cur);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNodeGetContent",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ret = xmlSecBnFromHexString(bn, content);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnFromHexString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+ xmlFree(content);
+ break;
+ case xmlSecBnDec:
+ content = xmlNodeGetContent(cur);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNodeGetContent",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ret = xmlSecBnFromDecString(bn, content);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnFromDecString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+ xmlFree(content);
+ break;
+ }
+
+ if(reverse != 0) {
+ ret = xmlSecBnReverse(bn);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecBnSetNodeValue:
+ * @bn: the pointer to BN.
+ * @cur: the poitner to an XML node.
+ * @format: the BN format.
+ * @reverse: the flag that indicates whether to reverse the buffer before writing.
+ * @addLineBreaks: the flag; it is equal to 1 then linebreaks will be added before and after new buffer content.
+ *
+ * Converts the @bn and sets it to node content.
+ *
+ * Returns: 0 on success and a negative values if an error occurs.
+ */
+int
+xmlSecBnSetNodeValue(xmlSecBnPtr bn, xmlNodePtr cur, xmlSecBnFormat format, int reverse, int addLineBreaks) {
+ xmlChar* content;
+ int ret;
+
+ xmlSecAssert2(bn != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ if(reverse != 0) {
+ ret = xmlSecBnReverse(bn);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(addLineBreaks) {
+ xmlNodeAddContent(cur, xmlSecStringCR);
+ }
+
+ switch(format) {
+ case xmlSecBnBase64:
+ ret = xmlSecBufferBase64NodeContentWrite(bn, cur, xmlSecBase64GetDefaultLineSize());
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferBase64NodeContentWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ break;
+ case xmlSecBnHex:
+ content = xmlSecBnToHexString(bn);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnToHexString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+ xmlNodeSetContent(cur, content);
+ xmlFree(content);
+ break;
+ case xmlSecBnDec:
+ content = xmlSecBnToDecString(bn);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnToDecString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+ xmlNodeSetContent(cur, content);
+ xmlFree(content);
+ break;
+ }
+
+ if(addLineBreaks) {
+ xmlNodeAddContent(cur, xmlSecStringCR);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBnBlobSetNodeValue:
+ * @data: the pointer to BN blob.
+ * @dataSize: the size of BN blob.
+ * @cur: the poitner to an XML node.
+ * @format: the BN format.
+ * @reverse: the flag that indicates whether to reverse the buffer before writing.
+ * @addLineBreaks: if the flag is equal to 1 then
+ * linebreaks will be added before and after
+ * new buffer content.
+ *
+ * Converts the @blob and sets it to node content.
+ *
+ * Returns: 0 on success and a negative values if an error occurs.
+ */
+int
+xmlSecBnBlobSetNodeValue(const xmlSecByte* data, xmlSecSize dataSize,
+ xmlNodePtr cur, xmlSecBnFormat format, int reverse,
+ int addLineBreaks) {
+ xmlSecBn bn;
+ int ret;
+
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ ret = xmlSecBnInitialize(&bn, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBnSetData(&bn, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBnFinalize(&bn);
+ return(-1);
+ }
+
+ ret = xmlSecBnSetNodeValue(&bn, cur, format, reverse, addLineBreaks);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBnFinalize(&bn);
+ return(-1);
+ }
+
+ xmlSecBnFinalize(&bn);
+ return(0);
+}
+
+
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 00000000..c13fe44f
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,674 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Memory buffer.
+ *
+ * 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 <ctype.h>
+#include <errno.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/errors.h>
+
+/*****************************************************************************
+ *
+ * xmlSecBuffer
+ *
+ ****************************************************************************/
+static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble;
+static xmlSecSize gInitialSize = 1024;
+
+/**
+ * xmlSecBufferSetDefaultAllocMode:
+ * @defAllocMode: the new default buffer allocation mode.
+ * @defInitialSize: the new default buffer minimal intial size.
+ *
+ * Sets new global default allocation mode and minimal intial size.
+ */
+void
+xmlSecBufferSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) {
+ xmlSecAssert(defInitialSize > 0);
+
+ gAllocMode = defAllocMode;
+ gInitialSize = defInitialSize;
+}
+
+/**
+ * xmlSecBufferCreate:
+ * @size: the intial size.
+ *
+ * Allocates and initalizes new memory buffer with given size.
+ * Caller is responsible for calling #xmlSecBufferDestroy function
+ * to free the buffer.
+ *
+ * Returns: pointer to newly allocated buffer or NULL if an error occurs.
+ */
+xmlSecBufferPtr
+xmlSecBufferCreate(xmlSecSize size) {
+ xmlSecBufferPtr buf;
+ int ret;
+
+ buf = (xmlSecBufferPtr)xmlMalloc(sizeof(xmlSecBuffer));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecBuffer)=%d", sizeof(xmlSecBuffer));
+ return(NULL);
+ }
+
+ ret = xmlSecBufferInitialize(buf, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ xmlSecBufferDestroy(buf);
+ return(NULL);
+ }
+ return(buf);
+}
+
+/**
+ * xmlSecBufferDestroy:
+ * @buf: the pointer to buffer object.
+ *
+ * Desrtoys buffer object created with #xmlSecBufferCreate function.
+ */
+void
+xmlSecBufferDestroy(xmlSecBufferPtr buf) {
+ xmlSecAssert(buf != NULL);
+
+ xmlSecBufferFinalize(buf);
+ xmlFree(buf);
+}
+
+/**
+ * xmlSecBufferInitialize:
+ * @buf: the pointer to buffer object.
+ * @size: the initial buffer size.
+ *
+ * Initializes buffer object @buf. Caller is responsible for calling
+ * #xmlSecBufferFinalize function to free allocated resources.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferInitialize(xmlSecBufferPtr buf, xmlSecSize size) {
+ xmlSecAssert2(buf != NULL, -1);
+
+ buf->data = NULL;
+ buf->size = buf->maxSize = 0;
+ buf->allocMode = gAllocMode;
+
+ return(xmlSecBufferSetMaxSize(buf, size));
+}
+
+/**
+ * xmlSecBufferFinalize:
+ * @buf: the pointer to buffer object.
+ *
+ * Frees allocated resource for a buffer intialized with #xmlSecBufferInitialize
+ * function.
+ */
+void
+xmlSecBufferFinalize(xmlSecBufferPtr buf) {
+ xmlSecAssert(buf != NULL);
+
+ xmlSecBufferEmpty(buf);
+ if(buf->data != 0) {
+ xmlFree(buf->data);
+ }
+ buf->data = NULL;
+ buf->size = buf->maxSize = 0;
+}
+
+/**
+ * xmlSecBufferEmpty:
+ * @buf: the pointer to buffer object.
+ *
+ * Empties the buffer.
+ */
+void
+xmlSecBufferEmpty(xmlSecBufferPtr buf) {
+ xmlSecAssert(buf != NULL);
+
+ if(buf->data != 0) {
+ xmlSecAssert(buf->maxSize > 0);
+
+ memset(buf->data, 0, buf->maxSize);
+ }
+ buf->size = 0;
+}
+
+/**
+ * xmlSecBufferGetData:
+ * @buf: the pointer to buffer object.
+ *
+ * Gets pointer to buffer's data.
+ *
+ * Returns: pointer to buffer's data.
+ */
+xmlSecByte*
+xmlSecBufferGetData(xmlSecBufferPtr buf) {
+ xmlSecAssert2(buf != NULL, NULL);
+
+ return(buf->data);
+}
+
+/**
+ * xmlSecBufferSetData:
+ * @buf: the pointer to buffer object.
+ * @data: the data.
+ * @size: the data size.
+ *
+ * Sets the value of the buffer to @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferSetData(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ xmlSecBufferEmpty(buf);
+ if(size > 0) {
+ xmlSecAssert2(data != NULL, -1);
+
+ ret = xmlSecBufferSetMaxSize(buf, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+
+ memcpy(buf->data, data, size);
+ }
+
+ buf->size = size;
+ return(0);
+}
+
+/**
+ * xmlSecBufferGetSize:
+ * @buf: the pointer to buffer object.
+ *
+ * Gets the current buffer data size.
+ *
+ * Returns: the current data size.
+ */
+xmlSecSize
+xmlSecBufferGetSize(xmlSecBufferPtr buf) {
+ xmlSecAssert2(buf != NULL, 0);
+
+ return(buf->size);
+}
+
+/**
+ * xmlSecBufferSetSize:
+ * @buf: the pointer to buffer object.
+ * @size: the new data size.
+ *
+ * Sets new buffer data size. If necessary, buffer grows to
+ * have at least @size bytes.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferSetSize(xmlSecBufferPtr buf, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ ret = xmlSecBufferSetMaxSize(buf, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+
+
+ buf->size = size;
+ return(0);
+}
+
+/**
+ * xmlSecBufferGetMaxSize:
+ * @buf: the pointer to buffer object.
+ *
+ * Gets the maximum (allocated) buffer size.
+ *
+ * Returns: the maximum (allocated) buffer size.
+ */
+xmlSecSize
+xmlSecBufferGetMaxSize(xmlSecBufferPtr buf) {
+ xmlSecAssert2(buf != NULL, 0);
+
+ return(buf->maxSize);
+}
+
+/**
+ * xmlSecBufferSetMaxSize:
+ * @buf: the pointer to buffer object.
+ * @size: the new maximum size.
+ *
+ * Sets new buffer maximum size. If necessary, buffer grows to
+ * have at least @size bytes.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferSetMaxSize(xmlSecBufferPtr buf, xmlSecSize size) {
+ xmlSecByte* newData;
+ xmlSecSize newSize = 0;
+
+ xmlSecAssert2(buf != NULL, -1);
+ if(size <= buf->maxSize) {
+ return(0);
+ }
+
+ switch(buf->allocMode) {
+ case xmlSecAllocModeExact:
+ newSize = size + 8;
+ break;
+ case xmlSecAllocModeDouble:
+ newSize = 2 * size + 32;
+ break;
+ }
+
+ if(newSize < gInitialSize) {
+ newSize = gInitialSize;
+ }
+
+
+ if(buf->data != NULL) {
+ newData = (xmlSecByte*)xmlRealloc(buf->data, newSize);
+ } else {
+ newData = (xmlSecByte*)xmlMalloc(newSize);
+ }
+ if(newData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", newSize);
+ return(-1);
+ }
+
+ buf->data = newData;
+ buf->maxSize = newSize;
+
+ if(buf->size < buf->maxSize) {
+ xmlSecAssert2(buf->data != NULL, -1);
+ memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBufferAppend:
+ * @buf: the pointer to buffer object.
+ * @data: the data.
+ * @size: the data size.
+ *
+ * Appends the @data after the current data stored in the buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferAppend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ if(size > 0) {
+ xmlSecAssert2(data != NULL, -1);
+
+ ret = xmlSecBufferSetMaxSize(buf, buf->size + size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", buf->size + size);
+ return(-1);
+ }
+
+ memcpy(buf->data + buf->size, data, size);
+ buf->size += size;
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBufferPrepend:
+ * @buf: the pointer to buffer object.
+ * @data: the data.
+ * @size: the data size.
+ *
+ * Prepends the @data before the current data stored in the buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferPrepend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ if(size > 0) {
+ xmlSecAssert2(data != NULL, -1);
+
+ ret = xmlSecBufferSetMaxSize(buf, buf->size + size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", buf->size + size);
+ return(-1);
+ }
+
+ memmove(buf->data + size, buf->data, buf->size);
+ memcpy(buf->data, data, size);
+ buf->size += size;
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecBufferRemoveHead:
+ * @buf: the pointer to buffer object.
+ * @size: the number of bytes to be removed.
+ *
+ * Removes @size bytes from the beginning of the current buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferRemoveHead(xmlSecBufferPtr buf, xmlSecSize size) {
+ xmlSecAssert2(buf != NULL, -1);
+
+ if(size < buf->size) {
+ xmlSecAssert2(buf->data != NULL, -1);
+
+ buf->size -= size;
+ memmove(buf->data, buf->data + size, buf->size);
+ } else {
+ buf->size = 0;
+ }
+ if(buf->size < buf->maxSize) {
+ xmlSecAssert2(buf->data != NULL, -1);
+ memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecBufferRemoveTail:
+ * @buf: the pointer to buffer object.
+ * @size: the number of bytes to be removed.
+ *
+ * Removes @size bytes from the end of current buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferRemoveTail(xmlSecBufferPtr buf, xmlSecSize size) {
+ xmlSecAssert2(buf != NULL, -1);
+
+ if(size < buf->size) {
+ buf->size -= size;
+ } else {
+ buf->size = 0;
+ }
+ if(buf->size < buf->maxSize) {
+ xmlSecAssert2(buf->data != NULL, -1);
+ memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecBufferReadFile:
+ * @buf: the pointer to buffer object.
+ * @filename: the filename.
+ *
+ * Reads the content of the file @filename in the buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferReadFile(xmlSecBufferPtr buf, const char* filename) {
+ xmlSecByte buffer[1024];
+ FILE* f;
+ int ret, len;
+
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+
+ f = fopen(filename, "rb");
+ if(f == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "fopen",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ return(-1);
+ }
+
+ while(1) {
+ len = fread(buffer, 1, sizeof(buffer), f);
+ if(len == 0) {
+ break;
+ }else if(len < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "fread",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ fclose(f);
+ return(-1);
+ }
+
+ ret = xmlSecBufferAppend(buf, buffer, len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ len);
+ fclose(f);
+ return(-1);
+ }
+ }
+
+ fclose(f);
+ return(0);
+}
+
+/**
+ * xmlSecBufferBase64NodeContentRead:
+ * @buf: the pointer to buffer object.
+ * @node: the pointer to node.
+ *
+ * Reads the content of the @node, base64 decodes it and stores the
+ * result in the buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferBase64NodeContentRead(xmlSecBufferPtr buf, xmlNodePtr node) {
+ xmlChar* content;
+ xmlSecSize size;
+ int ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ content = xmlNodeGetContent(node);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* base64 decode size is less than input size */
+ ret = xmlSecBufferSetMaxSize(buf, xmlStrlen(content));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecBase64Decode(content, xmlSecBufferGetData(buf), xmlSecBufferGetMaxSize(buf));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ 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);
+ xmlFree(content);
+ return(-1);
+ }
+ xmlFree(content);
+
+ return(0);
+}
+
+/**
+ * xmlSecBufferBase64NodeContentWrite:
+ * @buf: the pointer to buffer object.
+ * @node: the pointer to a node.
+ * @columns: the max line size fro base64 encoded data.
+ *
+ * Sets the content of the @node to the base64 encoded buffer data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecBufferBase64NodeContentWrite(xmlSecBufferPtr buf, xmlNodePtr node, int columns) {
+ xmlChar* content;
+
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ content = xmlSecBase64Encode(xmlSecBufferGetData(buf), xmlSecBufferGetSize(buf), columns);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlNodeAddContent(node, content);
+ xmlFree(content);
+
+ return(0);
+}
+
+/************************************************************************
+ *
+ * IO buffer
+ *
+ ************************************************************************/
+static int xmlSecBufferIOWrite (xmlSecBufferPtr buf,
+ const xmlSecByte *data,
+ xmlSecSize size);
+static int xmlSecBufferIOClose (xmlSecBufferPtr buf);
+
+/**
+ * xmlSecBufferCreateOutputBuffer:
+ * @buf: the pointer to buffer.
+ *
+ * Creates new LibXML output buffer to store data in the @buf. Caller is
+ * responsible for destroying @buf when processing is done.
+ *
+ * Returns: pointer to newly allocated output buffer or NULL if an error
+ * occurs.
+ */
+xmlOutputBufferPtr
+xmlSecBufferCreateOutputBuffer(xmlSecBufferPtr buf) {
+ return(xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecBufferIOWrite,
+ (xmlOutputCloseCallback)xmlSecBufferIOClose,
+ buf,
+ NULL));
+}
+
+static int
+xmlSecBufferIOWrite(xmlSecBufferPtr buf, const xmlSecByte *data, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+
+ ret = xmlSecBufferAppend(buf, data, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+
+ return(size);
+}
+
+static int
+xmlSecBufferIOClose(xmlSecBufferPtr buf) {
+ xmlSecAssert2(buf != NULL, -1);
+
+ /* just do nothing */
+ return(0);
+}
diff --git a/src/c14n.c b/src/c14n.c
new file mode 100644
index 00000000..384e2d86
--- /dev/null
+++ b/src/c14n.c
@@ -0,0 +1,801 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Canonicalization transforms.
+ *
+ * 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 <libxml/tree.h>
+#include <libxml/c14n.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/list.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/errors.h>
+
+/******************************************************************************
+ *
+ * C14N transforms
+ *
+ * Inclusive namespaces list for ExclC14N (xmlSecStringList) is located
+ * after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecTransformC14NSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecPtrList))
+#define xmlSecTransformC14NGetNsList(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecTransformC14NSize)) ? \
+ (xmlSecPtrListPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlSecPtrListPtr)NULL)
+
+#define xmlSecTransformC14NCheckId(transform) \
+ (xmlSecTransformInclC14NCheckId((transform)) || \
+ xmlSecTransformInclC14N11CheckId((transform)) || \
+ xmlSecTransformExclC14NCheckId((transform)) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformRemoveXmlTagsC14NId))
+#define xmlSecTransformInclC14NCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformInclC14NId) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformInclC14NWithCommentsId))
+#define xmlSecTransformInclC14N11CheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformInclC14N11Id) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformInclC14N11WithCommentsId))
+#define xmlSecTransformExclC14NCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformExclC14NId) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformExclC14NWithCommentsId) )
+
+
+static int xmlSecTransformC14NInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformC14NFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformC14NNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecTransformC14NPushXml (xmlSecTransformPtr transform,
+ xmlSecNodeSetPtr nodes,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecTransformC14NPopBin (xmlSecTransformPtr transform,
+ xmlSecByte* data,
+ xmlSecSize maxDataSize,
+ xmlSecSize* dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecTransformC14NExecute (xmlSecTransformId id,
+ xmlSecNodeSetPtr nodes,
+ xmlChar** nsList,
+ xmlOutputBufferPtr buf);
+static int
+xmlSecTransformC14NInitialize(xmlSecTransformPtr transform) {
+ xmlSecPtrListPtr nsList;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformC14NCheckId(transform), -1);
+
+ nsList = xmlSecTransformC14NGetNsList(transform);
+ xmlSecAssert2(nsList != NULL, -1);
+
+ ret = xmlSecPtrListInitialize(nsList, xmlSecStringListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecTransformC14NFinalize(xmlSecTransformPtr transform) {
+ xmlSecPtrListPtr nsList;
+
+ xmlSecAssert(xmlSecTransformC14NCheckId(transform));
+
+ nsList = xmlSecTransformC14NGetNsList(transform);
+ xmlSecAssert(xmlSecPtrListCheckId(nsList, xmlSecStringListId));
+
+ xmlSecPtrListFinalize(nsList);
+}
+
+static int
+xmlSecTransformC14NNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr nsList;
+ xmlNodePtr cur;
+ xmlChar *list;
+ xmlChar *p, *n, *tmp;
+ int ret;
+
+ /* we have something to read only for exclusive c14n transforms */
+ xmlSecAssert2(xmlSecTransformExclC14NCheckId(transform), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ nsList = xmlSecTransformC14NGetNsList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(nsList, xmlSecStringListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(nsList) == 0, -1);
+
+ /* there is only one optional node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if(cur != NULL) {
+ if(!xmlSecCheckNodeName(cur, xmlSecNodeInclusiveNamespaces, xmlSecNsExcC14N)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ list = xmlGetProp(cur, xmlSecAttrPrefixList);
+ if(list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrPrefixList),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ /* the list of namespaces is space separated */
+ for(p = n = list; ((p != NULL) && ((*p) != '\0')); p = n) {
+ n = (xmlChar*)xmlStrchr(p, ' ');
+ if(n != NULL) {
+ *(n++) = '\0';
+ }
+
+ tmp = xmlStrdup(p);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "len=%d", xmlStrlen(p));
+ xmlFree(list);
+ return(-1);
+ }
+
+ ret = xmlSecPtrListAdd(nsList, tmp);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(tmp);
+ xmlFree(list);
+ return(-1);
+ }
+ }
+ xmlFree(list);
+
+ /* add NULL at the end */
+ ret = xmlSecPtrListAdd(nsList, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that we have nothing else */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecTransformC14NPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlOutputBufferPtr buf;
+ xmlSecPtrListPtr nsList;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformC14NCheckId(transform), -1);
+ xmlSecAssert2(nodes != NULL, -1);
+ xmlSecAssert2(nodes->doc != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ /* check/update current transform status */
+ switch(transform->status) {
+ case xmlSecTransformStatusNone:
+ transform->status = xmlSecTransformStatusWorking;
+ break;
+ case xmlSecTransformStatusWorking:
+ case xmlSecTransformStatusFinished:
+ return(0);
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
+
+ /* prepare output buffer: next transform or ourselves */
+ if(transform->next != NULL) {
+ buf = xmlSecTransformCreateOutputBuffer(transform->next, transformCtx);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ buf = xmlSecBufferCreateOutputBuffer(&(transform->outBuf));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* we are using a semi-hack here: we know that xmlSecPtrList keeps
+ * all pointers in the big array */
+ nsList = xmlSecTransformC14NGetNsList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(nsList, xmlSecStringListId), -1);
+
+ ret = xmlSecTransformC14NExecute(transform->id, nodes, (xmlChar**)(nsList->data), buf);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformC14NExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlOutputBufferClose(buf);
+ return(-1);
+ }
+
+ ret = xmlOutputBufferClose(buf);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlOutputBufferClose",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ return(0);
+}
+
+static int
+xmlSecTransformC14NPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
+ xmlSecSize maxDataSize, xmlSecSize* dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr nsList;
+ xmlSecBufferPtr out;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformC14NCheckId(transform), -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ out = &(transform->outBuf);
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlOutputBufferPtr buf;
+
+ xmlSecAssert2(transform->inNodes == NULL, -1);
+
+ /* todo: isn't it an error? */
+ if(transform->prev == NULL) {
+ (*dataSize) = 0;
+ transform->status = xmlSecTransformStatusFinished;
+ return(0);
+ }
+
+ /* get xml data from previous transform */
+ ret = xmlSecTransformPopXml(transform->prev, &(transform->inNodes), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformPopXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* dump everything to internal buffer */
+ buf = xmlSecBufferCreateOutputBuffer(out);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* we are using a semi-hack here: we know that xmlSecPtrList keeps
+ * all pointers in the big array */
+ nsList = xmlSecTransformC14NGetNsList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(nsList, xmlSecStringListId), -1);
+
+ ret = xmlSecTransformC14NExecute(transform->id, transform->inNodes, (xmlChar**)(nsList->data), buf);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformC14NExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlOutputBufferClose(buf);
+ return(-1);
+ }
+ ret = xmlOutputBufferClose(buf);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlOutputBufferClose",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize outSize;
+
+ /* return chunk after chunk */
+ outSize = xmlSecBufferGetSize(out);
+ if(outSize > maxDataSize) {
+ outSize = maxDataSize;
+ }
+ if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
+ outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
+ }
+ if(outSize > 0) {
+ xmlSecAssert2(xmlSecBufferGetData(&(transform->outBuf)), -1);
+
+ memcpy(data, xmlSecBufferGetData(&(transform->outBuf)), outSize);
+ ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+ } else if(xmlSecBufferGetSize(out) == 0) {
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ (*dataSize) = outSize;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no output */
+ xmlSecAssert2(xmlSecBufferGetSize(out) == 0, -1);
+ (*dataSize) = 0;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecTransformC14NExecute(xmlSecTransformId id, xmlSecNodeSetPtr nodes, xmlChar** nsList,
+ xmlOutputBufferPtr buf) {
+ int ret;
+
+ xmlSecAssert2(id != xmlSecTransformIdUnknown, -1);
+ xmlSecAssert2(nodes != NULL, -1);
+ xmlSecAssert2(nodes->doc != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+
+ /* execute c14n transform */
+ if(id == xmlSecTransformInclC14NId) {
+ ret = xmlC14NExecute(nodes->doc,
+ (xmlC14NIsVisibleCallback)xmlSecNodeSetContains,
+ nodes, XML_C14N_1_0, NULL, 0, buf);
+ } else if(id == xmlSecTransformInclC14NWithCommentsId) {
+ ret = xmlC14NExecute(nodes->doc,
+ (xmlC14NIsVisibleCallback)xmlSecNodeSetContains,
+ nodes, XML_C14N_1_0, NULL, 1, buf);
+ } else if(id == xmlSecTransformInclC14N11Id) {
+ ret = xmlC14NExecute(nodes->doc,
+ (xmlC14NIsVisibleCallback)xmlSecNodeSetContains,
+ nodes, XML_C14N_1_1, NULL, 0, buf);
+ } else if(id == xmlSecTransformInclC14N11WithCommentsId) {
+ ret = xmlC14NExecute(nodes->doc,
+ (xmlC14NIsVisibleCallback)xmlSecNodeSetContains,
+ nodes, XML_C14N_1_1, NULL, 1, buf);
+ } else if(id == xmlSecTransformExclC14NId) {
+ ret = xmlC14NExecute(nodes->doc,
+ (xmlC14NIsVisibleCallback)xmlSecNodeSetContains,
+ nodes, XML_C14N_EXCLUSIVE_1_0, nsList, 0, buf);
+ } else if(id == xmlSecTransformExclC14NWithCommentsId) {
+ ret = xmlC14NExecute(nodes->doc,
+ (xmlC14NIsVisibleCallback)xmlSecNodeSetContains,
+ nodes, XML_C14N_EXCLUSIVE_1_0, nsList, 1, buf);
+ } else if(id == xmlSecTransformRemoveXmlTagsC14NId) {
+ ret = xmlSecNodeSetDumpTextNodes(nodes, buf);
+ } else {
+ /* shoudn't be possible to come here, actually */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)),
+ "xmlC14NExecute",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/***************************************************************************
+ *
+ * C14N
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformInclC14NKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ xmlSecNameC14N, /* const xmlChar* name; */
+ xmlSecHrefC14N, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformInclC14NGetKlass:
+ *
+ * Inclusive (regular) canonicalization that omits comments transform klass
+ * (http://www.w3.org/TR/xmldsig-core/#sec-c14nAlg and
+ * http://www.w3.org/TR/2001/REC-xml-c14n-20010315).
+ *
+ * Returns: c14n transform id.
+ */
+xmlSecTransformId
+xmlSecTransformInclC14NGetKlass(void) {
+ return(&xmlSecTransformInclC14NKlass);
+}
+
+/***************************************************************************
+ *
+ * C14N With Comments
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformInclC14NWithCommentsKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ /* same as xmlSecTransformId */
+ xmlSecNameC14NWithComments, /* const xmlChar* name; */
+ xmlSecHrefC14NWithComments, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod read; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformInclC14NWithCommentsGetKlass:
+ *
+ * Inclusive (regular) canonicalization that includes comments transform klass
+ * (http://www.w3.org/TR/xmldsig-core/#sec-c14nAlg and
+ * http://www.w3.org/TR/2001/REC-xml-c14n-20010315).
+ *
+ * Returns: c14n with comments transform id.
+ */
+xmlSecTransformId
+xmlSecTransformInclC14NWithCommentsGetKlass(void) {
+ return(&xmlSecTransformInclC14NWithCommentsKlass);
+}
+
+/***************************************************************************
+ *
+ * C14N v1.1
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformInclC14N11Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ xmlSecNameC14N11, /* const xmlChar* name; */
+ xmlSecHrefC14N11, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformInclC14N11GetKlass:
+ *
+ * C14N version 1.1 (http://www.w3.org/TR/xml-c14n11)
+ *
+ * Returns: c14n v1.1 transform id.
+ */
+xmlSecTransformId
+xmlSecTransformInclC14N11GetKlass(void) {
+ return(&xmlSecTransformInclC14N11Klass);
+}
+
+/***************************************************************************
+ *
+ * C14N v1.1 With Comments
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformInclC14N11WithCommentsKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ /* same as xmlSecTransformId */
+ xmlSecNameC14N11WithComments, /* const xmlChar* name; */
+ xmlSecHrefC14N11WithComments, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod read; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformInclC14N11WithCommentsGetKlass:
+ *
+ * C14N version 1.1 (http://www.w3.org/TR/xml-c14n11) with comments
+ *
+ * Returns: c14n v1.1 with comments transform id.
+ */
+xmlSecTransformId
+xmlSecTransformInclC14N11WithCommentsGetKlass(void) {
+ return(&xmlSecTransformInclC14N11WithCommentsKlass);
+}
+
+
+/***************************************************************************
+ *
+ * Excl C14N
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformExclC14NKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ xmlSecNameExcC14N, /* const xmlChar* name; */
+ xmlSecHrefExcC14N, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformC14NNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformExclC14NGetKlass:
+ *
+ * Exclusive canoncicalization that ommits comments transform klass
+ * (http://www.w3.org/TR/xml-exc-c14n/).
+ *
+ * Returns: exclusive c14n transform id.
+ */
+xmlSecTransformId
+xmlSecTransformExclC14NGetKlass(void) {
+ return(&xmlSecTransformExclC14NKlass);
+}
+
+/***************************************************************************
+ *
+ * Excl C14N With Comments
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformExclC14NWithCommentsKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ xmlSecNameExcC14NWithComments, /* const xmlChar* name; */
+ xmlSecHrefExcC14NWithComments, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformC14NNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformExclC14NWithCommentsGetKlass:
+ *
+ * Exclusive canoncicalization that includes comments transform klass
+ * (http://www.w3.org/TR/xml-exc-c14n/).
+ *
+ * Returns: exclusive c14n with comments transform id.
+ */
+xmlSecTransformId
+xmlSecTransformExclC14NWithCommentsGetKlass(void) {
+ return(&xmlSecTransformExclC14NWithCommentsKlass);
+}
+
+/***************************************************************************
+ *
+ * Remove XML tags C14N
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecTransformRemoveXmlTagsC14NKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformC14NSize, /* xmlSecSize objSize */
+
+ BAD_CAST "remove-xml-tags-transform", /* const xmlChar* name; */
+ NULL, /* const xmlChar* href; */
+ xmlSecTransformUsageC14NMethod | xmlSecTransformUsageDSigTransform,
+ /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformC14NInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformC14NFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformC14NPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformC14NPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformRemoveXmlTagsC14NGetKlass:
+ *
+ * The "remove xml tags" transform klass (http://www.w3.org/TR/xmldsig-core/#sec-Base-64):
+ * Base64 transform requires an octet stream for input. If an XPath node-set
+ * (or sufficiently functional alternative) is given as input, then it is
+ * converted to an octet stream by performing operations logically equivalent
+ * to 1) applying an XPath transform with expression self::text(), then 2)
+ * taking the string-value of the node-set. Thus, if an XML element is
+ * identified by a barename XPointer in the Reference URI, and its content
+ * consists solely of base64 encoded character data, then this transform
+ * automatically strips away the start and end tags of the identified element
+ * and any of its descendant elements as well as any descendant comments and
+ * processing instructions. The output of this transform is an octet stream.
+ *
+ * Returns: "remove xml tags" transform id.
+ */
+xmlSecTransformId
+xmlSecTransformRemoveXmlTagsC14NGetKlass(void) {
+ return(&xmlSecTransformRemoveXmlTagsC14NKlass);
+}
+
diff --git a/src/dl.c b/src/dl.c
new file mode 100644
index 00000000..6c0aa180
--- /dev/null
+++ b/src/dl.c
@@ -0,0 +1,978 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ *
+ * 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 <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/app.h>
+#include <xmlsec/list.h>
+#include <xmlsec/keysdata.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/private.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/dl.h>
+
+#ifndef XMLSEC_NO_CRYPTO_DYNAMIC_LOADING
+
+
+#ifdef XMLSEC_DL_LIBLTDL
+#include <ltdl.h>
+#endif /* XMLSEC_DL_LIBLTDL */
+
+#ifdef XMLSEC_DL_WIN32
+#include <windows.h>
+#endif /* XMLSEC_DL_WIN32 */
+
+/***********************************************************************
+ *
+ * loaded libraries list
+ *
+ **********************************************************************/
+typedef struct _xmlSecCryptoDLLibrary xmlSecCryptoDLLibrary,
+ *xmlSecCryptoDLLibraryPtr;
+struct _xmlSecCryptoDLLibrary {
+ xmlChar* name;
+ xmlChar* filename;
+ xmlChar* getFunctionsName;
+ xmlSecCryptoDLFunctionsPtr functions;
+
+#ifdef XMLSEC_DL_LIBLTDL
+ lt_dlhandle handle;
+#endif /* XMLSEC_DL_LIBLTDL */
+
+#ifdef XMLSEC_DL_WIN32
+ HINSTANCE handle;
+#endif /* XMLSEC_DL_WIN32 */
+};
+
+static xmlSecCryptoDLLibraryPtr xmlSecCryptoDLLibraryCreate (const xmlChar* name);
+static void xmlSecCryptoDLLibraryDestroy (xmlSecCryptoDLLibraryPtr lib);
+static xmlSecCryptoDLLibraryPtr xmlSecCryptoDLLibraryDuplicate (xmlSecCryptoDLLibraryPtr lib);
+static xmlChar* xmlSecCryptoDLLibraryConstructFilename (const xmlChar* name);
+static xmlChar* xmlSecCryptoDLLibraryConstructGetFunctionsName(const xmlChar* name);
+
+
+static xmlSecPtrListKlass xmlSecCryptoDLLibrariesListKlass = {
+ BAD_CAST "dl-libraries-list",
+ (xmlSecPtrDuplicateItemMethod)xmlSecCryptoDLLibraryDuplicate,/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecCryptoDLLibraryDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+static xmlSecPtrListId xmlSecCryptoDLLibrariesListGetKlass (void);
+static int xmlSecCryptoDLLibrariesListFindByName (xmlSecPtrListPtr list,
+ const xmlChar* name);
+
+typedef xmlSecCryptoDLFunctionsPtr (*xmlSecCryptoGetFunctionsCallback)(void);
+
+static xmlSecCryptoDLLibraryPtr
+xmlSecCryptoDLLibraryCreate(const xmlChar* name) {
+ xmlSecCryptoDLLibraryPtr lib;
+ xmlSecCryptoGetFunctionsCallback getFunctions;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ /* fprintf (stderr, "loading \"library %s\"...\n", name); */
+
+ /* Allocate a new xmlSecCryptoDLLibrary and fill the fields. */
+ lib = (xmlSecCryptoDLLibraryPtr)xmlMalloc(sizeof(xmlSecCryptoDLLibrary));
+ if(lib == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(lib));
+ return(NULL);
+ }
+ memset(lib, 0, sizeof(xmlSecCryptoDLLibrary));
+
+ lib->name = xmlStrdup(name);
+ if(lib->name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlStrdup",
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ lib->filename = xmlSecCryptoDLLibraryConstructFilename(name);
+ if(lib->filename == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecCryptoDLLibraryConstructFilename",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ lib->getFunctionsName = xmlSecCryptoDLLibraryConstructGetFunctionsName(name);
+ if(lib->getFunctionsName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecCryptoDLLibraryConstructGetFunctionsName",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+#ifdef XMLSEC_DL_LIBLTDL
+ lib->handle = lt_dlopenext((char*)lib->filename);
+ if(lib->handle == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "lt_dlopenext",
+ NULL,
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(lib->filename));
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ getFunctions = (xmlSecCryptoGetFunctionsCallback)lt_dlsym(lib->handle, (char*)lib->getFunctionsName);
+ if(getFunctions == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "lt_dlsym",
+ NULL,
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "function=%s",
+ xmlSecErrorsSafeString(lib->getFunctionsName));
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+#endif /* XMLSEC_DL_LIBLTDL */
+
+#ifdef XMLSEC_DL_WIN32
+ lib->handle = LoadLibraryA((char*)lib->filename);
+ if(lib->handle == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "LoadLibraryA",
+ NULL,
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(lib->filename));
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ getFunctions = (xmlSecCryptoGetFunctionsCallback)GetProcAddress(lib->handle, (char*)lib->getFunctionsName);
+ if(getFunctions == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "GetProcAddressA",
+ NULL,
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "function=%s",
+ xmlSecErrorsSafeString(lib->getFunctionsName));
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+#endif /* XMLSEC_DL_WIN32 */
+
+ if(getFunctions == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "invalid configuration: no way to load library");
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ lib->functions = getFunctions();
+ if(lib->functions == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "getFunctions",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ /* fprintf (stderr, "library %s loaded\n", name); */
+ return(lib);
+}
+
+static void
+xmlSecCryptoDLLibraryDestroy(xmlSecCryptoDLLibraryPtr lib) {
+ xmlSecAssert(lib != NULL);
+
+ /* fprintf (stderr, "unloading \"library %s\"...\n", lib->name); */
+ if(lib->name != NULL) {
+ xmlFree(lib->name);
+ }
+
+ if(lib->filename != NULL) {
+ xmlFree(lib->filename);
+ }
+
+ if(lib->getFunctionsName != NULL) {
+ xmlFree(lib->getFunctionsName);
+ }
+
+#ifdef XMLSEC_DL_LIBLTDL
+ if(lib->handle != NULL) {
+ int ret;
+
+ ret = lt_dlclose(lib->handle);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "lt_dlclose",
+ NULL,
+ XMLSEC_ERRORS_R_IO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+ }
+#endif /* XMLSEC_DL_LIBLTDL */
+
+#ifdef XMLSEC_DL_WIN32
+ if(lib->handle != NULL) {
+ BOOL res;
+
+ res = FreeLibrary(lib->handle);
+ if(!res) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "FreeLibrary",
+ NULL,
+ XMLSEC_ERRORS_R_IO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+ }
+#endif /* XMLSEC_DL_WIN32*/
+
+ memset(lib, 0, sizeof(xmlSecCryptoDLLibrary));
+ xmlFree(lib);
+}
+
+static xmlSecCryptoDLLibraryPtr
+xmlSecCryptoDLLibraryDuplicate(xmlSecCryptoDLLibraryPtr lib) {
+ xmlSecAssert2(lib != NULL, NULL);
+ xmlSecAssert2(lib->name != NULL, NULL);
+
+ return(xmlSecCryptoDLLibraryCreate(lib->name));
+}
+
+static xmlChar*
+xmlSecCryptoDLLibraryConstructFilename(const xmlChar* name) {
+ static xmlChar tmpl[] = "lib%s-%s";
+ xmlChar* res;
+ int len;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ /* TODO */
+ len = xmlStrlen(BAD_CAST PACKAGE) + xmlStrlen(name) + xmlStrlen(tmpl) + 1;
+ res = (xmlChar*)xmlMalloc(len + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", len + 1);
+ return(NULL);
+ }
+ xmlSecStrPrintf(res, len, tmpl, PACKAGE, name);
+
+ return(res);
+}
+
+static xmlChar*
+xmlSecCryptoDLLibraryConstructGetFunctionsName(const xmlChar* name) {
+ static xmlChar tmpl[] = "xmlSecCryptoGetFunctions_%s";
+ xmlChar* res;
+ int len;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ len = xmlStrlen(name) + xmlStrlen(tmpl) + 1;
+ res = (xmlChar*)xmlMalloc(len + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", len + 1);
+ return(NULL);
+ }
+ xmlSecStrPrintf(res, len, tmpl, name);
+
+ return(res);
+}
+
+static xmlSecPtrListId
+xmlSecCryptoDLLibrariesListGetKlass(void) {
+ return(&xmlSecCryptoDLLibrariesListKlass);
+}
+
+static int
+xmlSecCryptoDLLibrariesListFindByName(xmlSecPtrListPtr list, const xmlChar* name) {
+ xmlSecSize i, size;
+ xmlSecCryptoDLLibraryPtr lib;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecCryptoDLLibrariesListGetKlass()), -1);
+ xmlSecAssert2(name != NULL, -1);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ lib = (xmlSecCryptoDLLibraryPtr)xmlSecPtrListGetItem(list, i);
+ if((lib != NULL) && (lib->name != NULL) && (xmlStrcmp(lib->name, name) == 0)) {
+ return(i);
+ }
+ }
+ return(-1);
+}
+
+/******************************************************************************
+ *
+ * Dynamic load functions
+ *
+ *****************************************************************************/
+static xmlSecCryptoDLFunctionsPtr gXmlSecCryptoDLFunctions = NULL;
+static xmlSecPtrList gXmlSecCryptoDLLibraries;
+
+/**
+ * xmlSecCryptoDLInit:
+ *
+ * Initializes dynamic loading engine. This is an internal function
+ * and should not be called by application directly.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecCryptoDLInit(void) {
+ int ret;
+
+ ret = xmlSecPtrListInitialize(&gXmlSecCryptoDLLibraries, xmlSecCryptoDLLibrariesListGetKlass());
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListPtrInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecCryptoDLLibrariesListGetKlass");
+ return(-1);
+ }
+
+#ifdef XMLSEC_DL_LIBLTDL
+ ret = lt_dlinit ();
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "lt_dlinit",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#endif /* XMLSEC_DL_LIBLTDL */
+
+ return(0);
+}
+
+
+/**
+ * xmlSecCryptoDLShutdown:
+ *
+ * Shutdowns dynamic loading engine. This is an internal function
+ * and should not be called by application directly.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecCryptoDLShutdown(void) {
+ int ret;
+
+ xmlSecPtrListFinalize(&gXmlSecCryptoDLLibraries);
+
+#ifdef XMLSEC_DL_LIBLTDL
+ ret = lt_dlexit ();
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "lt_dlexit",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+#endif /* XMLSEC_DL_LIBLTDL */
+
+ return(0);
+}
+
+/**
+ * xmlSecCryptoDLLoadLibrary:
+ * @crypto: the desired crypto library name ("openssl", "nss", ...).
+ *
+ * Loads the xmlsec-<crypto> library. This function is NOT thread safe,
+ * application MUST NOT call #xmlSecCryptoDLLoadLibrary, #xmlSecCryptoDLGetLibraryFunctions,
+ * and #xmlSecCryptoDLUnloadLibrary functions from multiple threads.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecCryptoDLLoadLibrary(const xmlChar* crypto) {
+ xmlSecCryptoDLFunctionsPtr functions;
+ int ret;
+
+ xmlSecAssert2(crypto != NULL, -1);
+
+ functions = xmlSecCryptoDLGetLibraryFunctions(crypto);
+ if(functions == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLGetLibraryFunctions",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecCryptoDLSetFunctions(functions);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLSetFunctions",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecCryptoDLGetLibraryFunctions:
+ * @crypto: the desired crypto library name ("openssl", "nss", ...).
+ *
+ * Loads the xmlsec-<crypto> library and gets global crypto functions/transforms/keys data/keys store
+ * table. This function is NOT thread safe, application MUST NOT call #xmlSecCryptoDLLoadLibrary,
+ * #xmlSecCryptoDLGetLibraryFunctions, and #xmlSecCryptoDLUnloadLibrary functions from multiple threads.
+ *
+ * Returns: the table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoDLGetLibraryFunctions(const xmlChar* crypto) {
+ xmlSecCryptoDLLibraryPtr lib;
+ int pos;
+ int ret;
+
+ xmlSecAssert2(crypto != NULL, NULL);
+
+ pos = xmlSecCryptoDLLibrariesListFindByName(&gXmlSecCryptoDLLibraries, crypto);
+ if(pos >= 0) {
+ lib = (xmlSecCryptoDLLibraryPtr)xmlSecPtrListGetItem(&gXmlSecCryptoDLLibraries, pos);
+ xmlSecAssert2(lib != NULL, NULL);
+ xmlSecAssert2(lib->functions != NULL, NULL);
+
+ return(lib->functions);
+ }
+
+ lib = xmlSecCryptoDLLibraryCreate(crypto);
+ if(lib == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLLibraryCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "crypto=%s",
+ xmlSecErrorsSafeString(crypto));
+ return(NULL);
+ }
+
+ ret = xmlSecPtrListAdd(&gXmlSecCryptoDLLibraries, lib);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "crypto=%s",
+ xmlSecErrorsSafeString(crypto));
+ xmlSecCryptoDLLibraryDestroy(lib);
+ return(NULL);
+ }
+
+ return(lib->functions);
+}
+
+/**
+ * xmlSecCryptoDLUnloadLibrary:
+ * @crypto: the desired crypto library name ("openssl", "nss", ...).
+ *
+ * Unloads the xmlsec-<crypto> library. All pointers to this library
+ * functions tables became invalid. This function is NOT thread safe,
+ * application MUST NOT call #xmlSecCryptoDLLoadLibrary, #xmlSecCryptoDLGetLibraryFunctions,
+ * and #xmlSecCryptoDLUnloadLibrary functions from multiple threads.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecCryptoDLUnloadLibrary(const xmlChar* crypto) {
+ xmlSecCryptoDLLibraryPtr lib;
+ int pos;
+ int ret;
+
+ xmlSecAssert2(crypto != NULL, -1);
+
+ pos = xmlSecCryptoDLLibrariesListFindByName(&gXmlSecCryptoDLLibraries, crypto);
+ if(pos < 0) {
+ /* todo: is it an error? */
+ return(0);
+ }
+
+ lib = (xmlSecCryptoDLLibraryPtr)xmlSecPtrListGetItem(&gXmlSecCryptoDLLibraries, pos);
+ if((lib != NULL) && (lib->functions == gXmlSecCryptoDLFunctions)) {
+ gXmlSecCryptoDLFunctions = NULL;
+ }
+
+ ret = xmlSecPtrListRemove(&gXmlSecCryptoDLLibraries, pos);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListRemove",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecCryptoDLSetFunctions:
+ * @functions: the new table
+ *
+ * Sets global crypto functions/transforms/keys data/keys store table.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecCryptoDLSetFunctions(xmlSecCryptoDLFunctionsPtr functions) {
+ xmlSecAssert2(functions != NULL, -1);
+
+ gXmlSecCryptoDLFunctions = functions;
+
+ return(0);
+}
+
+/**
+ * xmlSecCryptoDLGetFunctions:
+ *
+ * Gets global crypto functions/transforms/keys data/keys store table.
+ *
+ * Returns: the table.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoDLGetFunctions(void) {
+ return(gXmlSecCryptoDLFunctions);
+}
+
+#endif /* XMLSEC_NO_CRYPTO_DYNAMIC_LOADING */
+
+/**
+ * xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms:
+ * @functions: the functions table.
+ *
+ * Registers the key data and transforms klasses from @functions table in xmlsec.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(struct _xmlSecCryptoDLFunctions* functions) {
+ xmlSecAssert2(functions != NULL, -1);
+
+ /**
+ * Register keys
+ */
+ if((functions->keyDataAesGetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataAesGetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataAesGetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataDesGetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataDesGetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataDesGetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataDsaGetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataDsaGetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataDsaGetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataGost2001GetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataGost2001GetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataGost2001GetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataHmacGetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataHmacGetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataHmacGetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataRsaGetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataRsaGetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataRsaGetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataX509GetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataX509GetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataX509GetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if((functions->keyDataRawX509CertGetKlass != NULL) && (xmlSecKeyDataIdsRegister(functions->keyDataRawX509CertGetKlass()) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(functions->keyDataRawX509CertGetKlass())),
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+
+ /**
+ * Register transforms
+ */
+ if((functions->transformAes128CbcGetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformAes128CbcGetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformAes128CbcGetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformAes192CbcGetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformAes192CbcGetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformAes192CbcGetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformAes256CbcGetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformAes256CbcGetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformAes256CbcGetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformKWAes128GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformKWAes128GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformKWAes128GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformKWAes192GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformKWAes192GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformKWAes192GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformKWAes256GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformKWAes256GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformKWAes256GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformDes3CbcGetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformDes3CbcGetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformDes3CbcGetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformKWDes3GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformKWDes3GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformKWDes3GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformGost2001GostR3411_94GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformGost2001GostR3411_94GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformGost2001GostR3411_94GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformDsaSha1GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformDsaSha1GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformDsaSha1GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacMd5GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacMd5GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacMd5GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacRipemd160GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacRipemd160GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacRipemd160GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacSha1GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacSha1GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacSha1GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacSha224GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacSha224GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacSha224GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacSha256GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacSha256GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacSha256GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacSha384GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacSha384GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacSha384GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformHmacSha512GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformHmacSha512GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformHmacSha512GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformMd5GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformMd5GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformMd5GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRipemd160GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRipemd160GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRipemd160GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaMd5GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaMd5GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaMd5GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaRipemd160GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaRipemd160GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaRipemd160GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaSha1GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaSha1GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaSha1GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaSha224GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaSha224GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaSha224GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaSha256GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaSha256GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaSha256GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaSha384GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaSha384GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaSha384GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaSha512GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaSha512GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaSha512GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaPkcs1GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaPkcs1GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaPkcs1GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformRsaOaepGetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformRsaOaepGetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformRsaOaepGetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformGostR3411_94GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformGostR3411_94GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformGostR3411_94GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformSha1GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformSha1GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformSha1GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformSha224GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformSha224GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformSha224GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformSha256GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformSha256GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformSha256GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformSha384GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformSha384GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformSha384GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((functions->transformSha512GetKlass != NULL) && xmlSecTransformIdsRegister(functions->transformSha512GetKlass()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(functions->transformSha512GetKlass())),
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
diff --git a/src/enveloped.c b/src/enveloped.c
new file mode 100644
index 00000000..bea30a15
--- /dev/null
+++ b/src/enveloped.c
@@ -0,0 +1,152 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Enveloped transform.
+ *
+ * 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 <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+/**************************************************************************
+ *
+ * Enveloped transform
+ *
+ *************************************************************************/
+static int xmlSecTransformEnvelopedExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+
+static xmlSecTransformKlass xmlSecTransformEnvelopedKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ sizeof(xmlSecTransform), /* xmlSecSize objSize */
+
+ xmlSecNameEnveloped, /* const xmlChar* name; */
+ xmlSecHrefEnveloped, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ NULL, /* xmlSecTransformInitializeMethod initialize; */
+ NULL, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformEnvelopedExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformEnvelopedGetKlass:
+ *
+ * The enveloped transform klass (http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature):
+ *
+ * An enveloped signature transform T removes the whole Signature element
+ * containing T from the digest calculation of the Reference element
+ * containing T. The entire string of characters used by an XML processor
+ * to match the Signature with the XML production element is removed.
+ * The output of the transform is equivalent to the output that would
+ * result from replacing T with an XPath transform containing the following
+ * XPath parameter element:
+ *
+ * <XPath xmlns:dsig="&dsig;">
+ * count(ancestor-or-self::dsig:Signature |
+ * here()/ancestor::dsig:Signature[1]) >
+ * count(ancestor-or-self::dsig:Signature)</XPath>
+ *
+ * The input and output requirements of this transform are identical to
+ * those of the XPath transform, but may only be applied to a node-set from
+ * its parent XML document. Note that it is not necessary to use an XPath
+ * expression evaluator to create this transform. However, this transform
+ * MUST produce output in exactly the same manner as the XPath transform
+ * parameterized by the XPath expression above.
+ *
+ * Returns: enveloped transform id.
+ */
+xmlSecTransformId
+xmlSecTransformEnvelopedGetKlass(void) {
+ return(&xmlSecTransformEnvelopedKlass);
+}
+
+static int
+xmlSecTransformEnvelopedExecute(xmlSecTransformPtr transform, int last,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlNodePtr node;
+ xmlSecNodeSetPtr children;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformEnvelopedId), -1);
+ xmlSecAssert2(transform->hereNode != NULL, -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(last != 0, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ if((transform->inNodes != NULL) && (transform->inNodes->doc != transform->hereNode->doc)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* find signature node and get all its children in the nodes set */
+ node = xmlSecFindParent(transform->hereNode, xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeSignature),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ children = xmlSecNodeSetGetChildren(node->doc, node, 1, 1);
+ if(children == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNodeSetGetChildren",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+
+ /* intersect <dsig:Signature/> node children with input nodes (if exist) */
+ transform->outNodes = xmlSecNodeSetAdd(transform->inNodes, children, xmlSecNodeSetIntersection);
+ if(transform->outNodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNodeSetAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecNodeSetDestroy(children);
+ return(-1);
+ }
+
+ return(0);
+}
+
diff --git a/src/errors.c b/src/errors.c
new file mode 100644
index 00000000..54e34e6c
--- /dev/null
+++ b/src/errors.c
@@ -0,0 +1,242 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Error codes and error reporting functions.
+ *
+ * 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 <stdarg.h>
+#include <time.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/private.h>
+#include <xmlsec/errors.h>
+
+#define XMLSEC_ERRORS_BUFFER_SIZE 1024
+
+typedef struct _xmlSecErrorDescription xmlSecErrorDescription, *xmlSecErrorDescriptionPtr;
+struct _xmlSecErrorDescription {
+ int errorCode;
+ const char* errorMsg;
+};
+
+static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = {
+ { XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlsec library function failed" },
+ { XMLSEC_ERRORS_R_MALLOC_FAILED, "malloc function failed" },
+ { XMLSEC_ERRORS_R_STRDUP_FAILED, "strdup function failed" },
+ { XMLSEC_ERRORS_R_CRYPTO_FAILED, "crypto library function failed" },
+ { XMLSEC_ERRORS_R_XML_FAILED, "libxml2 library function failed" },
+ { XMLSEC_ERRORS_R_XSLT_FAILED, "libxslt library function failed" },
+ { XMLSEC_ERRORS_R_IO_FAILED, "io function failed" },
+ { XMLSEC_ERRORS_R_DISABLED, "feature is disabled" },
+ { XMLSEC_ERRORS_R_NOT_IMPLEMENTED, "feature is not implemented" },
+ { XMLSEC_ERRORS_R_INVALID_SIZE, "invalid size" },
+ { XMLSEC_ERRORS_R_INVALID_DATA, "invalid data" },
+ { XMLSEC_ERRORS_R_INVALID_RESULT, "invalid result" },
+ { XMLSEC_ERRORS_R_INVALID_TYPE, "invalid type" },
+ { XMLSEC_ERRORS_R_INVALID_OPERATION, "invalid operation" },
+ { XMLSEC_ERRORS_R_INVALID_STATUS, "invalid status" },
+ { XMLSEC_ERRORS_R_INVALID_FORMAT, "invalid format" },
+ { XMLSEC_ERRORS_R_DATA_NOT_MATCH, "data do not match" },
+ { XMLSEC_ERRORS_R_INVALID_NODE, "invalid node" },
+ { XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "invalid node content" },
+ { XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, "invalid node attribute" },
+ { XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE, "missing node attribute" },
+ { XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, "node already present" },
+ { XMLSEC_ERRORS_R_UNEXPECTED_NODE, "unexpected node" },
+ { XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node node found" },
+ { XMLSEC_ERRORS_R_INVALID_TRANSFORM, "invalid transform" },
+ { XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY, "invalid transform key" },
+ { XMLSEC_ERRORS_R_INVALID_URI_TYPE, "invalid URI type" },
+ { XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED, "same document is required for transform" },
+ { XMLSEC_ERRORS_R_TRANSFORM_DISABLED, "transform is disabled" },
+ { XMLSEC_ERRORS_R_INVALID_KEY_DATA, "invalid key data" },
+ { XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND, "key data is not found" },
+ { XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST, "key data already exist" },
+ { XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, "invalid key data size" },
+ { XMLSEC_ERRORS_R_KEY_NOT_FOUND, "key is not found" },
+ { XMLSEC_ERRORS_R_KEYDATA_DISABLED, "key data is disabled" },
+ { XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL, "maximum key retrieval level" },
+ { XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" },
+ { XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL, "maximum encrypted key level" },
+ { XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "certificate verification failed" },
+ { XMLSEC_ERRORS_R_CERT_NOT_FOUND, "certificate is not found" },
+ { XMLSEC_ERRORS_R_CERT_REVOKED, "certificate is revoked" },
+ { XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "certificate issuer check failed" },
+ { XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "certificate is not yet valid" },
+ { XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "certificate has expirred" },
+ { XMLSEC_ERRORS_R_DSIG_NO_REFERENCES, "Reference nodes are not found" },
+ { XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE, "Reference verification failed" },
+ { XMLSEC_ERRORS_R_ASSERTION, "assertion" },
+ { 0, NULL}
+};
+
+static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback;
+static int xmlSecPrintErrorMessages = 1; /* whether the error messages will be printed immidiatelly */
+
+/**
+ * xmlSecErrorsInit:
+ *
+ * Initializes the errors reporting. It is called from #xmlSecInit function.
+ * and applications must not call this function directly.
+ */
+void
+xmlSecErrorsInit(void) {
+}
+
+/**
+ * xmlSecErrorsShutdown:
+ *
+ * Cleanups the errors reporting. It is called from #xmlSecShutdown function.
+ * and applications must not call this function directly.
+ */
+void
+xmlSecErrorsShutdown(void) {
+}
+
+/**
+ * xmlSecErrorsSetCallback:
+ * @callback: the new errors callback function.
+ *
+ * Sets the errors callback function to @callback that will be called
+ * every time an error occurs.
+ */
+void
+xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) {
+ xmlSecErrorsClbk = callback;
+}
+
+/**
+ * xmlSecErrorsDefaultCallback:
+ * @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 error reporting callback that utilizes LibXML
+ * error reporting #xmlGenericError function.
+ */
+void
+xmlSecErrorsDefaultCallback(const char* file, int line, const char* func,
+ const char* errorObject, const char* errorSubject,
+ int reason, const char* msg) {
+ if(xmlSecPrintErrorMessages) {
+ const char* error_msg = NULL;
+ xmlSecSize i;
+
+ for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
+ if(xmlSecErrorsGetCode(i) == reason) {
+ error_msg = xmlSecErrorsGetMsg(i);
+ break;
+ }
+ }
+ xmlGenericError(xmlGenericErrorContext,
+ "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n",
+ (func != NULL) ? func : "unknown",
+ (file != NULL) ? file : "unknown",
+ line,
+ (errorObject != NULL) ? errorObject : "unknown",
+ (errorSubject != NULL) ? errorSubject : "unknown",
+ reason,
+ (error_msg != NULL) ? error_msg : "",
+ (msg != NULL) ? msg : "");
+ }
+}
+
+/**
+ * xmlSecErrorsDefaultCallbackEnableOutput:
+ * @enabled: the flag.
+ *
+ * Enables or disables calling LibXML2 callback from the default
+ * errors callback.
+ */
+void
+xmlSecErrorsDefaultCallbackEnableOutput(int enabled) {
+ xmlSecPrintErrorMessages = enabled;
+}
+
+/**
+ * xmlSecErrorsGetCode:
+ * @pos: the error position.
+ *
+ * Gets the known error code at position @pos.
+ *
+ * Returns: the known error code or 0 if @pos is greater than
+ * total number of known error codes.
+ */
+int
+xmlSecErrorsGetCode(xmlSecSize pos) {
+ /* could not use asserts here! */
+ if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
+ return(xmlSecErrorsTable[pos].errorCode);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecErrorsGetMsg:
+ * @pos: the error position.
+ *
+ * Gets the known error message at position @pos.
+ *
+ * Returns: the known error message or NULL if @pos is greater than
+ * total number of known error codes.
+ */
+const char*
+xmlSecErrorsGetMsg(xmlSecSize pos) {
+ /* could not use asserts here! */
+ if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
+ return(xmlSecErrorsTable[pos].errorMsg);
+ }
+ return(NULL);
+}
+
+/**
+ * xmlSecError:
+ * @file: the error location filename (__FILE__).
+ * @line: the error location line number (__LINE__).
+ * @func: the error location function (__FUNCTIION__).
+ * @errorObject: the error specific error object
+ * @errorSubject: the error specific error subject.
+ * @reason: the error code.
+ * @msg: the error message in printf format.
+ * @...: the parameters for the @msg.
+ *
+ * Reports an error to the default (#xmlSecErrorsDefaultCallback) or
+ * application specific callback installed using #xmlSecErrorsSetCallback
+ * function.
+ */
+void
+xmlSecError(const char* file, int line, const char* func,
+ const char* errorObject, const char* errorSubject,
+ int reason, const char* msg, ...) {
+
+ if(xmlSecErrorsClbk != NULL) {
+ xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE];
+
+ if(msg != NULL) {
+ va_list va;
+
+ va_start(va, msg);
+ xmlSecStrVPrintf(error_msg, sizeof(error_msg), BAD_CAST msg, va);
+ error_msg[sizeof(error_msg) - 1] = '\0';
+ va_end(va);
+ } else {
+ error_msg[0] = '\0';
+ }
+ xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg);
+ }
+}
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 00000000..35a238cc
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,25 @@
+/*
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * 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
+#define XMLSEC_PRIVATE
+
+#endif /* __XMLSEC_GLOBALS_H__ */
diff --git a/src/gnutls/Makefile.am b/src/gnutls/Makefile.am
new file mode 100644
index 00000000..7d639a34
--- /dev/null
+++ b/src/gnutls/Makefile.am
@@ -0,0 +1,48 @@
+NULL =
+
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-gnutls.la \
+ $(NULL)
+
+libxmlsec1_gnutls_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(GNUTLS_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_gnutls_la_SOURCES =\
+ app.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ hmac.c \
+ symkeys.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_gnutls_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_gnutls_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(GNUTLS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_gnutls_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_gnutls_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/gnutls/Makefile.in b/src/gnutls/Makefile.in
new file mode 100644
index 00000000..f07a4b49
--- /dev/null
+++ b/src/gnutls/Makefile.in
@@ -0,0 +1,706 @@
+# Makefile.in generated by automake 1.11 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/gnutls
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+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_gnutls_la_SOURCES_DIST = app.c ciphers.c crypto.c \
+ digests.c hmac.c symkeys.c globals.h ../strings.c
+am__objects_1 =
+@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_gnutls_la-strings.lo
+am_libxmlsec1_gnutls_la_OBJECTS = libxmlsec1_gnutls_la-app.lo \
+ libxmlsec1_gnutls_la-ciphers.lo libxmlsec1_gnutls_la-crypto.lo \
+ libxmlsec1_gnutls_la-digests.lo libxmlsec1_gnutls_la-hmac.lo \
+ libxmlsec1_gnutls_la-symkeys.lo $(am__objects_1) \
+ $(am__objects_2)
+libxmlsec1_gnutls_la_OBJECTS = $(am_libxmlsec1_gnutls_la_OBJECTS)
+libxmlsec1_gnutls_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_gnutls_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_gnutls_la_SOURCES)
+DIST_SOURCES = $(am__libxmlsec1_gnutls_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@
+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@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_ENABLED = @PKG_CONFIG_ENABLED@
+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_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_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-gnutls.la \
+ $(NULL)
+
+libxmlsec1_gnutls_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(GNUTLS_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_gnutls_la_SOURCES = app.c ciphers.c crypto.c digests.c \
+ hmac.c symkeys.c globals.h $(NULL) $(am__append_1)
+libxmlsec1_gnutls_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(GNUTLS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_gnutls_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_gnutls_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/gnutls/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/gnutls/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-gnutls.la: $(libxmlsec1_gnutls_la_OBJECTS) $(libxmlsec1_gnutls_la_DEPENDENCIES)
+ $(libxmlsec1_gnutls_la_LINK) -rpath $(libdir) $(libxmlsec1_gnutls_la_OBJECTS) $(libxmlsec1_gnutls_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-ciphers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-digests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-symkeys.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_gnutls_la-app.lo: app.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-app.Tpo -c -o libxmlsec1_gnutls_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-app.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-app.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+
+libxmlsec1_gnutls_la-ciphers.lo: ciphers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-ciphers.Tpo -c -o libxmlsec1_gnutls_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-ciphers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+
+libxmlsec1_gnutls_la-crypto.lo: crypto.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-crypto.Tpo -c -o libxmlsec1_gnutls_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-crypto.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+
+libxmlsec1_gnutls_la-digests.lo: digests.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-digests.Tpo -c -o libxmlsec1_gnutls_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-digests.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-digests.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+
+libxmlsec1_gnutls_la-hmac.lo: hmac.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-hmac.Tpo -c -o libxmlsec1_gnutls_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-hmac.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+
+libxmlsec1_gnutls_la-symkeys.lo: symkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-symkeys.Tpo -c -o libxmlsec1_gnutls_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-symkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+
+libxmlsec1_gnutls_la-strings.lo: ../strings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gnutls_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-strings.Tpo -c -o libxmlsec1_gnutls_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-strings.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-strings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_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/gnutls/README b/src/gnutls/README
new file mode 100644
index 00000000..02c5fbbf
--- /dev/null
+++ b/src/gnutls/README
@@ -0,0 +1,9 @@
+The xmlsec-gnutls implementation is really limited and is not ready
+for production use. The only supported crypto transforms are:
+
+ - HMAC
+ - Tripple DES
+ - AES [128|192|256]
+ - SHA1
+
+ \ No newline at end of file
diff --git a/src/gnutls/app.c b/src/gnutls/app.c
new file mode 100644
index 00000000..54da1999
--- /dev/null
+++ b/src/gnutls/app.c
@@ -0,0 +1,499 @@
+/**
+ * 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 <gnutls/gnutls.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/app.h>
+#include <xmlsec/gnutls/crypto.h>
+
+/**
+ * xmlSecGnuTLSAppInit:
+ * @config: the path to GnuTLS configuration (unused).
+ *
+ * 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
+xmlSecGnuTLSAppInit(const char* config ATTRIBUTE_UNUSED) {
+ int ret;
+
+ ret = gnutls_global_init();
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_global_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSAppShutdown:
+ *
+ * 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
+xmlSecGnuTLSAppShutdown(void) {
+ gnutls_global_deinit();
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSAppKeyLoad:
+ * @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 (not implemented yet).
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGnuTLSAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd,
+ void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+
+ if (format == xmlSecKeyDataFormatPkcs12) {
+ return (xmlSecGnuTLSAppPkcs12Load(filename, pwd, pwdCallback,
+ pwdCallbackCtx));
+ }
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeyLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecGnuTLSAppKeyLoadMemory:
+ * @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 (not implemented yet).
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGnuTLSAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format, const char *pwd,
+ void* pwdCallback, void* pwdCallbackCtx) {
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ if (format == xmlSecKeyDataFormatPkcs12) {
+ return (xmlSecGnuTLSAppPkcs12LoadMemory(data, dataSize, pwd,
+ pwdCallback, pwdCallbackCtx));
+ }
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeyLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+#ifndef XMLSEC_NO_X509
+/**
+ * xmlSecGnuTLSAppKeyCertLoad:
+ * @key: the pointer to key.
+ * @filename: the certificate filename.
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from $@filename and adds it to key
+ * (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeyCertLoad(xmlSecKeyPtr key, const char* filename,
+ xmlSecKeyDataFormat format) {
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeyCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecGnuTLSAppKeyCertLoadMemory:
+ * @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 (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeyCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecGnuTLSAppPkcs12Load:
+ * @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
+ * (not implemented yet).
+ * For uniformity, call xmlSecGnuTLSAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGnuTLSAppPkcs12Load(const char *filename,
+ const char *pwd ATTRIBUTE_UNUSED,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(filename != NULL, NULL);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppPkcs12Load",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecGnuTLSAppPkcs12LoadMemory:
+ * @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 xmlSecGnuTLSAppKeyLoadMemory instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12 (not implemented yet).
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGnuTLSAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ const char *pwd, void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecAssert2(data != NULL, NULL);
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppPkcs12LoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecGnuTLSAppKeysMngrCertLoad:
+ * @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 (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeysMngrCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecGnuTLSAppKeysMngrCertLoadMemory:
+ * @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 (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeysMngrCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecGnuTLSAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId
+ * and a default GnuTLS crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppDefaultKeysMngrInit(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 = xmlSecGnuTLSKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* TODO */
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecGnuTLSAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppDefaultKeysMngrAdoptKey(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);
+}
+
+/**
+ * xmlSecGnuTLSAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecGnuTLSAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppDefaultKeysMngrLoad(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);
+}
+
+/**
+ * xmlSecGnuTLSAppDefaultKeysMngrSave:
+ * @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
+xmlSecGnuTLSAppDefaultKeysMngrSave(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);
+}
+
+/**
+ * xmlSecGnuTLSAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecGnuTLSAppGetDefaultPwdCallback(void) {
+ return(NULL);
+}
+
diff --git a/src/gnutls/ciphers.c b/src/gnutls/ciphers.c
new file mode 100644
index 00000000..b9421597
--- /dev/null
+++ b/src/gnutls/ciphers.c
@@ -0,0 +1,860 @@
+/**
+ * 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 <gnutls/gnutls.h>
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+/**************************************************************************
+ *
+ * Internal GnuTLS Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGnuTLSBlockCipherCtx xmlSecGnuTLSBlockCipherCtx,
+ *xmlSecGnuTLSBlockCipherCtxPtr;
+struct _xmlSecGnuTLSBlockCipherCtx {
+ int cipher;
+ int mode;
+ GcryCipherHd cipherCtx;
+ xmlSecKeyDataId keyId;
+ int keyInitialized;
+ int ctxInitialized;
+};
+
+static int xmlSecGnuTLSBlockCipherCtxInit (xmlSecGnuTLSBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSBlockCipherCtxUpdate (xmlSecGnuTLSBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSBlockCipherCtxFinal (xmlSecGnuTLSBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int
+xmlSecGnuTLSBlockCipherCtxInit(xmlSecGnuTLSBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ int blockLen;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized != 0, -1);
+ xmlSecAssert2(ctx->ctxInitialized == 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ /* iv len == block len */
+ blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ if(encrypt) {
+ xmlSecByte* iv;
+ xmlSecSize outSize;
+
+ /* allocate space for IV */
+ outSize = xmlSecBufferGetSize(out);
+ ret = xmlSecBufferSetSize(out, outSize + blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + blockLen);
+ return(-1);
+ }
+ iv = xmlSecBufferGetData(out) + outSize;
+
+ /* generate and use random iv */
+ gcry_randomize(iv, blockLen, GCRY_STRONG_RANDOM);
+ ret = gcry_cipher_setiv(ctx->cipherCtx, iv, blockLen);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ } else {
+ /* if we don't have enough data, exit and hope that
+ * we'll have iv next time */
+ if(xmlSecBufferGetSize(in) < (xmlSecSize)blockLen) {
+ return(0);
+ }
+ xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
+
+ /* set iv */
+ ret = gcry_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* and remove from input */
+ ret = xmlSecBufferRemoveHead(in, blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blockLen);
+ return(-1);
+ }
+ }
+
+ ctx->ctxInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecGnuTLSBlockCipherCtxUpdate(xmlSecGnuTLSBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, inBlocks, outSize;
+ int blockLen;
+ xmlSecByte* outBuf;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(inSize < (xmlSecSize)blockLen) {
+ return(0);
+ }
+
+ if(encrypt) {
+ inBlocks = inSize / ((xmlSecSize)blockLen);
+ } else {
+ /* we want to have the last block in the input buffer
+ * for padding check */
+ inBlocks = (inSize - 1) / ((xmlSecSize)blockLen);
+ }
+ inSize = inBlocks * ((xmlSecSize)blockLen);
+
+ /* we write out the input size plus may be one block */
+ 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;
+
+ if(encrypt) {
+ ret = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ } else {
+ ret = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ }
+
+ /* set correct output buffer size */
+ ret = xmlSecBufferSetSize(out, outSize + inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + inSize);
+ 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
+xmlSecGnuTLSBlockCipherCtxFinal(xmlSecGnuTLSBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, outSize;
+ int blockLen, outLen = 0;
+ xmlSecByte* inBuf;
+ xmlSecByte* outBuf;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = gcry_cipher_get_algo_blklen(ctx->cipher);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(encrypt != 0) {
+ xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1);
+
+ /* create padding */
+ ret = xmlSecBufferSetMaxSize(in, blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blockLen);
+ return(-1);
+ }
+ inBuf = xmlSecBufferGetData(in);
+
+ /* create random padding */
+ if((xmlSecSize)blockLen > (inSize + 1)) {
+ gcry_randomize(inBuf + inSize, blockLen - inSize - 1,
+ GCRY_STRONG_RANDOM); /* as usual, we are paranoid */
+ }
+ inBuf[blockLen - 1] = blockLen - inSize;
+ inSize = blockLen;
+ } else {
+ if(inSize != (xmlSecSize)blockLen) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data=%d;block=%d", inSize, blockLen);
+ return(-1);
+ }
+ }
+
+ /* process last block */
+ 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;
+
+ if(encrypt) {
+ ret = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ } else {
+ ret = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ }
+
+ if(encrypt == 0) {
+ /* check padding */
+ if(inSize < outBuf[blockLen - 1]) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "padding=%d;buffer=%d",
+ outBuf[blockLen - 1], inSize);
+ return(-1);
+ }
+ outLen = inSize - outBuf[blockLen - 1];
+ } else {
+ outLen = inSize;
+ }
+
+ /* 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);
+ }
+
+
+ /* 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);
+}
+
+
+/******************************************************************************
+ *
+ * Block Cipher transforms
+ *
+ * xmlSecGnuTLSBlockCipherCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecGnuTLSBlockCipherSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGnuTLSBlockCipherCtx))
+#define xmlSecGnuTLSBlockCipherGetCtx(transform) \
+ ((xmlSecGnuTLSBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGnuTLSBlockCipherInitialize (xmlSecTransformPtr transform);
+static void xmlSecGnuTLSBlockCipherFinalize (xmlSecTransformPtr transform);
+static int xmlSecGnuTLSBlockCipherSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGnuTLSBlockCipherSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGnuTLSBlockCipherExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSBlockCipherCheckId (xmlSecTransformPtr transform);
+
+
+
+static int
+xmlSecGnuTLSBlockCipherCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DES
+ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformDes3CbcId)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformAes128CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformAes192CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformAes256CbcId)) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
+
+static int
+xmlSecGnuTLSBlockCipherInitialize(xmlSecTransformPtr transform) {
+ xmlSecGnuTLSBlockCipherCtxPtr ctx;
+#ifndef XMLSEC_GNUTLS_OLD
+ gpg_err_code_t ret;
+#endif /* XMLSEC_GNUTLS_OLD */
+
+ xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
+
+ ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGnuTLSBlockCipherCtx));
+
+#ifndef XMLSEC_NO_DES
+ if(transform->id == xmlSecGnuTLSTransformDes3CbcId) {
+ ctx->cipher = GCRY_CIPHER_3DES;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGnuTLSKeyDataDesId;
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(transform->id == xmlSecGnuTLSTransformAes128CbcId) {
+ ctx->cipher = GCRY_CIPHER_AES128;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGnuTLSKeyDataAesId;
+ } else if(transform->id == xmlSecGnuTLSTransformAes192CbcId) {
+ ctx->cipher = GCRY_CIPHER_AES192;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGnuTLSKeyDataAesId;
+ } else if(transform->id == xmlSecGnuTLSTransformAes256CbcId) {
+ ctx->cipher = GCRY_CIPHER_AES256;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGnuTLSKeyDataAesId;
+ } 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);
+ }
+
+#ifndef XMLSEC_GNUTLS_OLD
+ ret = gcry_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */
+ if(ret != GPG_ERR_NO_ERROR) {
+#else /* XMLSEC_GNUTLS_OLD */
+ ctx->cipherCtx = gcry_cipher_open(ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */
+ if(ctx->cipherCtx == NULL) {
+#endif /* XMLSEC_GNUTLS_OLD */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_cipher_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecGnuTLSBlockCipherFinalize(xmlSecTransformPtr transform) {
+ xmlSecGnuTLSBlockCipherCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGnuTLSBlockCipherCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize));
+
+ ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->cipherCtx != NULL) {
+ gcry_cipher_close(ctx->cipherCtx);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecGnuTLSBlockCipherCtx));
+}
+
+static int
+xmlSecGnuTLSBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGnuTLSBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+
+ keyReq->keyId = ctx->keyId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+
+ keyReq->keyBitsSize = 8 * gcry_cipher_get_algo_keylen(ctx->cipher);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGnuTLSBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->keyInitialized == 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ keySize = gcry_cipher_get_algo_keylen(ctx->cipher);
+ xmlSecAssert2(keySize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) < keySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "keySize=%d;expected=%d",
+ xmlSecBufferGetSize(buffer), keySize);
+ return(-1);
+ }
+
+ xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
+ ret = gcry_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_cipher_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ ctx->keyInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecGnuTLSBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGnuTLSBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecGnuTLSBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSBlockCipherSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecGnuTLSBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ if(ctx->ctxInitialized == 0) {
+ ret = xmlSecGnuTLSBlockCipherCtxInit(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGnuTLSBlockCipherCtxInit",
+ 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 = xmlSecGnuTLSBlockCipherCtxUpdate(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGnuTLSBlockCipherCtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(last) {
+ ret = xmlSecGnuTLSBlockCipherCtxFinal(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGnuTLSBlockCipherCtxFinal",
+ 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 xmlSecGnuTLSAes128CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes128Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes128Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGnuTLSBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGnuTLSBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformAes128CbcGetKlass(void) {
+ return(&xmlSecGnuTLSAes128CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecGnuTLSAes192CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes192Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes192Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGnuTLSBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGnuTLSBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformAes192CbcGetKlass(void) {
+ return(&xmlSecGnuTLSAes192CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecGnuTLSAes256CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes256Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes256Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGnuTLSBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGnuTLSBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformAes256CbcGetKlass(void) {
+ return(&xmlSecGnuTLSAes256CbcKlass);
+}
+
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+static xmlSecTransformKlass xmlSecGnuTLSDes3CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameDes3Cbc, /* const xmlChar* name; */
+ xmlSecHrefDes3Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGnuTLSBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGnuTLSBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformDes3CbcGetKlass(void) {
+ return(&xmlSecGnuTLSDes3CbcKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/gnutls/crypto.c b/src/gnutls/crypto.c
new file mode 100644
index 00000000..dbf69f21
--- /dev/null
+++ b/src/gnutls/crypto.c
@@ -0,0 +1,205 @@
+/**
+ * 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 <gnutls/gnutls.h>
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/private.h>
+
+#include <xmlsec/gnutls/app.h>
+#include <xmlsec/gnutls/crypto.h>
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecGnuTLSFunctions = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_gnutls:
+ *
+ * Gets the pointer to xmlsec-gnutls functions table.
+ *
+ * Returns: the xmlsec-gnutls functions table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_gnutls(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecGnuTLSFunctions != NULL) {
+ return(gXmlSecGnuTLSFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecGnuTLSFunctions = &functions;
+
+ /**
+ * Crypto Init/shutdown
+ */
+ gXmlSecGnuTLSFunctions->cryptoInit = xmlSecGnuTLSInit;
+ gXmlSecGnuTLSFunctions->cryptoShutdown = xmlSecGnuTLSShutdown;
+ gXmlSecGnuTLSFunctions->cryptoKeysMngrInit = xmlSecGnuTLSKeysMngrInit;
+
+ /**
+ * Key data ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecGnuTLSFunctions->keyDataAesGetKlass = xmlSecGnuTLSKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecGnuTLSFunctions->keyDataDesGetKlass = xmlSecGnuTLSKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecGnuTLSFunctions->keyDataHmacGetKlass = xmlSecGnuTLSKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+ /**
+ * Key data store ids
+ */
+
+ /**
+ * Crypto transforms ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecGnuTLSFunctions->transformAes128CbcGetKlass = xmlSecGnuTLSTransformAes128CbcGetKlass;
+ gXmlSecGnuTLSFunctions->transformAes192CbcGetKlass = xmlSecGnuTLSTransformAes192CbcGetKlass;
+ gXmlSecGnuTLSFunctions->transformAes256CbcGetKlass = xmlSecGnuTLSTransformAes256CbcGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecGnuTLSFunctions->transformDes3CbcGetKlass = xmlSecGnuTLSTransformDes3CbcGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecGnuTLSFunctions->transformHmacSha1GetKlass = xmlSecGnuTLSTransformHmacSha1GetKlass;
+ gXmlSecGnuTLSFunctions->transformHmacRipemd160GetKlass = xmlSecGnuTLSTransformHmacRipemd160GetKlass;
+ gXmlSecGnuTLSFunctions->transformHmacMd5GetKlass = xmlSecGnuTLSTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGnuTLSFunctions->transformSha1GetKlass = xmlSecGnuTLSTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+ /**
+ * High level routines form xmlsec command line utility
+ */
+ gXmlSecGnuTLSFunctions->cryptoAppInit = xmlSecGnuTLSAppInit;
+ gXmlSecGnuTLSFunctions->cryptoAppShutdown = xmlSecGnuTLSAppShutdown;
+ gXmlSecGnuTLSFunctions->cryptoAppDefaultKeysMngrInit = xmlSecGnuTLSAppDefaultKeysMngrInit;
+ gXmlSecGnuTLSFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecGnuTLSAppDefaultKeysMngrAdoptKey;
+ gXmlSecGnuTLSFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecGnuTLSAppDefaultKeysMngrLoad;
+ gXmlSecGnuTLSFunctions->cryptoAppDefaultKeysMngrSave = xmlSecGnuTLSAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecGnuTLSFunctions->cryptoAppKeysMngrCertLoad = xmlSecGnuTLSAppKeysMngrCertLoad;
+ gXmlSecGnuTLSFunctions->cryptoAppPkcs12Load = xmlSecGnuTLSAppPkcs12Load;
+ gXmlSecGnuTLSFunctions->cryptoAppKeyCertLoad = xmlSecGnuTLSAppKeyCertLoad;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecGnuTLSFunctions->cryptoAppKeyLoad = xmlSecGnuTLSAppKeyLoad;
+ gXmlSecGnuTLSFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecGnuTLSAppGetDefaultPwdCallback();
+
+ return(gXmlSecGnuTLSFunctions);
+}
+
+
+/**
+ * xmlSecGnuTLSInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSInit (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);
+ }
+
+ /* register our klasses */
+ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_gnutls()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSShutdown(void) {
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds GnuTLS specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* TODO: add key data stores */
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSGenerateRandom:
+ * @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
+xmlSecGnuTLSGenerateRandom(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 */
+ gcry_randomize(xmlSecBufferGetData(buffer), size, GCRY_STRONG_RANDOM);
+ return(0);
+}
diff --git a/src/gnutls/digests.c b/src/gnutls/digests.c
new file mode 100644
index 00000000..fb8109de
--- /dev/null
+++ b/src/gnutls/digests.c
@@ -0,0 +1,318 @@
+/**
+ * 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 <gnutls/gnutls.h>
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/app.h>
+#include <xmlsec/gnutls/crypto.h>
+
+#define XMLSEC_GNUTLS_MAX_DIGEST_SIZE 32
+
+/**************************************************************************
+ *
+ * Internal GNUTLS Digest CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGnuTLSDigestCtx xmlSecGnuTLSDigestCtx, *xmlSecGnuTLSDigestCtxPtr;
+struct _xmlSecGnuTLSDigestCtx {
+ int digest;
+ GcryMDHd digestCtx;
+ xmlSecByte dgst[XMLSEC_GNUTLS_MAX_DIGEST_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+/******************************************************************************
+ *
+ * Digest transforms
+ *
+ * xmlSecGnuTLSDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGnuTLSDigestSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGnuTLSDigestCtx))
+#define xmlSecGnuTLSDigestGetCtx(transform) \
+ ((xmlSecGnuTLSDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGnuTLSDigestInitialize (xmlSecTransformPtr transform);
+static void xmlSecGnuTLSDigestFinalize (xmlSecTransformPtr transform);
+static int xmlSecGnuTLSDigestVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSDigestExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSDigestCheckId (xmlSecTransformPtr transform);
+
+static int
+xmlSecGnuTLSDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+ return(0);
+}
+
+static int
+xmlSecGnuTLSDigestInitialize(xmlSecTransformPtr transform) {
+ xmlSecGnuTLSDigestCtxPtr ctx;
+#ifndef XMLSEC_GNUTLS_OLD
+ gpg_err_code_t ret;
+#endif /* XMLSEC_GNUTLS_OLD */
+
+ xmlSecAssert2(xmlSecGnuTLSDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize), -1);
+
+ ctx = xmlSecGnuTLSDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecGnuTLSDigestCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_GNUTLS_OLD
+ ret = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(ret != GPG_ERR_NO_ERROR) {
+#else /* XMLSEC_GNUTLS_OLD */
+ ctx->digestCtx = gcry_md_open(ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(ctx->digestCtx == NULL) {
+#endif /* XMLSEC_GNUTLS_OLD */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecGnuTLSDigestFinalize(xmlSecTransformPtr transform) {
+ xmlSecGnuTLSDigestCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGnuTLSDigestCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize));
+
+ ctx = xmlSecGnuTLSDigestGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ gcry_md_close(ctx->digestCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecGnuTLSDigestCtx));
+}
+
+static int
+xmlSecGnuTLSDigestVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGnuTLSDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGnuTLSDigestCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGnuTLSDigestGetCtx(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_DATA,
+ "data and digest sizes are different (data=%d, dgst=%d)",
+ dataSize, ctx->dgstSize);
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ if(memcmp(ctx->dgst, data, dataSize) != 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
+xmlSecGnuTLSDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGnuTLSDigestCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecGnuTLSDigestCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize), -1);
+
+ ctx = xmlSecGnuTLSDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digest != GCRY_MD_NONE, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ gcry_md_write(ctx->digestCtx, 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) {
+ xmlSecByte* buf;
+
+ /* get the final digest */
+ gcry_md_final(ctx->digestCtx);
+ buf = gcry_md_read(ctx->digestCtx, ctx->digest);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_read",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* copy it to our internal buffer */
+ ctx->dgstSize = gcry_md_get_algo_dlen(ctx->digest);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+ xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1);
+ memcpy(ctx->dgst, buf, ctx->dgstSize);
+
+ /* and to the output if needed */
+ 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(&(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_SHA1
+/******************************************************************************
+ *
+ * SHA1 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecGnuTLSSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha1, /* const xmlChar* name; */
+ xmlSecHrefSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGnuTLSDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGnuTLSDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformSha1GetKlass(void) {
+ return(&xmlSecGnuTLSSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+
diff --git a/src/gnutls/globals.h b/src/gnutls/globals.h
new file mode 100644
index 00000000..272a27b8
--- /dev/null
+++ b/src/gnutls/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/gnutls/hmac.c b/src/gnutls/hmac.c
new file mode 100644
index 00000000..bc106471
--- /dev/null
+++ b/src/gnutls/hmac.c
@@ -0,0 +1,601 @@
+/**
+ * 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>
+ */
+#ifndef XMLSEC_NO_HMAC
+#include "globals.h"
+
+#include <string.h>
+
+#include <gnutls/gnutls.h>
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/app.h>
+#include <xmlsec/gnutls/crypto.h>
+
+/* sizes in bits */
+#define XMLSEC_GNUTLS_MIN_HMAC_SIZE 80
+#define XMLSEC_GNUTLS_MAX_HMAC_SIZE (128 * 8)
+
+/**************************************************************************
+ *
+ * Configuration
+ *
+ *****************************************************************************/
+static int g_xmlsec_gnutls_hmac_min_length = XMLSEC_GNUTLS_MIN_HMAC_SIZE;
+
+/**
+ * xmlSecGnuTLSHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecGnuTLSHmacGetMinOutputLength(void)
+{
+ return g_xmlsec_gnutls_hmac_min_length;
+}
+
+/**
+ * xmlSecGnuTLSHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecGnuTLSHmacSetMinOutputLength(int min_length)
+{
+ g_xmlsec_gnutls_hmac_min_length = min_length;
+}
+
+/**************************************************************************
+ *
+ * Internal GNUTLS HMAC CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGnuTLSHmacCtx xmlSecGnuTLSHmacCtx, *xmlSecGnuTLSHmacCtxPtr;
+struct _xmlSecGnuTLSHmacCtx {
+ int digest;
+ GcryMDHd digestCtx;
+ xmlSecByte dgst[XMLSEC_GNUTLS_MAX_HMAC_SIZE / 8];
+ xmlSecSize dgstSize; /* dgst size in bits */
+};
+
+/******************************************************************************
+ *
+ * HMAC transforms
+ *
+ * xmlSecGnuTLSHmacCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGnuTLSHmacGetCtx(transform) \
+ ((xmlSecGnuTLSHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecGnuTLSHmacSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGnuTLSHmacCtx))
+#define xmlSecGnuTLSHmacCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecGnuTLSTransformHmacSha1Id) || \
+ xmlSecTransformCheckId((transform), xmlSecGnuTLSTransformHmacMd5Id) || \
+ xmlSecTransformCheckId((transform), xmlSecGnuTLSTransformHmacRipemd160Id))
+
+static int xmlSecGnuTLSHmacInitialize (xmlSecTransformPtr transform);
+static void xmlSecGnuTLSHmacFinalize (xmlSecTransformPtr transform);
+static int xmlSecGnuTLSHmacNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSHmacSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGnuTLSHmacSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGnuTLSHmacVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGnuTLSHmacExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecGnuTLSHmacInitialize(xmlSecTransformPtr transform) {
+ xmlSecGnuTLSHmacCtxPtr ctx;
+#ifndef XMLSEC_GNUTLS_OLD
+ gpg_err_code_t ret;
+#endif /* XMLSEC_GNUTLS_OLD */
+
+ xmlSecAssert2(xmlSecGnuTLSHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize), -1);
+
+ ctx = xmlSecGnuTLSHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGnuTLSHmacCtx));
+ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformHmacSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformHmacMd5Id)) {
+ ctx->digest = GCRY_MD_MD5;
+ } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformHmacRipemd160Id)) {
+ ctx->digest = GCRY_MD_RMD160;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_GNUTLS_OLD
+ ret = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(ret != GPG_ERR_NO_ERROR) {
+#else /* XMLSEC_GNUTLS_OLD */
+ ctx->digestCtx = gcry_md_open(ctx->digest, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(ctx->digestCtx == NULL) {
+#endif /* XMLSEC_GNUTLS_OLD */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecGnuTLSHmacFinalize(xmlSecTransformPtr transform) {
+ xmlSecGnuTLSHmacCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGnuTLSHmacCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize));
+
+ ctx = xmlSecGnuTLSHmacGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ gcry_md_close(ctx->digestCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecGnuTLSHmacCtx));
+}
+
+/**
+ * xmlSecGnuTLSHmacNodeRead:
+ *
+ * HMAC (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>
+ *
+ * Schema Definition:
+ *
+ * <simpleType name="HMACOutputLengthType">
+ * <restriction base="integer"/>
+ * </simpleType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT HMACOutputLength (#PCDATA)>
+ */
+static int
+xmlSecGnuTLSHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGnuTLSHmacCtxPtr ctx;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecGnuTLSHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGnuTLSHmacGetCtx(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 lenght to 0 or very
+ small value
+ */
+ if((int)ctx->dgstSize < xmlSecGnuTLSHmacGetMinOutputLength()) {
+ 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_INVALID_NODE,
+ "no nodes expected");
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecGnuTLSHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGnuTLSHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGnuTLSHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize), -1);
+
+ ctx = xmlSecGnuTLSHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecGnuTLSKeyDataHmacId;
+ keyReq->keyType= xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGnuTLSHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGnuTLSHmacCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+ int ret;
+
+ xmlSecAssert2(xmlSecGnuTLSHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecGnuTLSHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecGnuTLSKeyDataHmacId), -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,
+ "key is empty");
+ return(-1);
+ }
+
+ ret = gcry_md_setkey(ctx->digestCtx, xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer));
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecGnuTLSHmacVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ static xmlSecByte last_byte_masks[] =
+ { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+
+ xmlSecGnuTLSHmacCtxPtr ctx;
+ xmlSecByte mask;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGnuTLSHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ /* compare the digest size in bytes */
+ if(dataSize != ((ctx->dgstSize + 7) / 8)){
+ 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
+xmlSecGnuTLSHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGnuTLSHmacCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecByte* dgst;
+ xmlSecSize dgstSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGnuTLSHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSHmacSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGnuTLSHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ gcry_md_write(ctx->digestCtx, 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) {
+ /* get the final digest */
+ gcry_md_final(ctx->digestCtx);
+ dgst = gcry_md_read(ctx->digestCtx, ctx->digest);
+ if(dgst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_read",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* copy it to our internal buffer */
+ dgstSize = gcry_md_get_algo_dlen(ctx->digest);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(dgstSize <= sizeof(ctx->dgst), -1);
+ memcpy(ctx->dgst, dgst, dgstSize);
+
+ /* check/set the result digest size */
+ if(ctx->dgstSize == 0) {
+ ctx->dgstSize = dgstSize * 8; /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= 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);
+ }
+
+ 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(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "size=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * HMAC SHA1
+ */
+static xmlSecTransformKlass xmlSecGnuTLSHmacSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha1, /* const xmlChar* name; */
+ xmlSecHrefHmacSha1, /* const xmlChar *href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGnuTLSHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGnuTLSHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGnuTLSHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGnuTLSHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacSha1GetKlass(void) {
+ return(&xmlSecGnuTLSHmacSha1Klass);
+}
+
+/**
+ * HMAC Ripemd160
+ */
+static xmlSecTransformKlass xmlSecGnuTLSHmacRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacRipemd160, /* const xmlChar* name; */
+ xmlSecHrefHmacRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGnuTLSHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGnuTLSHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGnuTLSHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGnuTLSHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacRipemd160GetKlass(void) {
+ return(&xmlSecGnuTLSHmacRipemd160Klass);
+}
+
+/**
+ * HMAC Md5
+ */
+static xmlSecTransformKlass xmlSecGnuTLSHmacMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGnuTLSHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacMd5, /* const xmlChar* name; */
+ xmlSecHrefHmacMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGnuTLSHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGnuTLSHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGnuTLSHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGnuTLSHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGnuTLSHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGnuTLSHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGnuTLSHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacMd5GetKlass(void) {
+ return(&xmlSecGnuTLSHmacMd5Klass);
+}
+
+
+#endif /* XMLSEC_NO_HMAC */
diff --git a/src/gnutls/symkeys.c b/src/gnutls/symkeys.c
new file mode 100644
index 00000000..4a11d13a
--- /dev/null
+++ b/src/gnutls/symkeys.c
@@ -0,0 +1,440 @@
+/**
+ *
+ * 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 <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/gnutls/crypto.h>
+
+/*****************************************************************************
+ *
+ * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary
+ *
+ ****************************************************************************/
+static int xmlSecGnuTLSSymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecGnuTLSSymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecGnuTLSSymKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecGnuTLSSymKeyDataXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSSymKeyDataXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSSymKeyDataBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlSecByte** buf,
+ xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecGnuTLSSymKeyDataGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecGnuTLSSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecGnuTLSSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecGnuTLSSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecGnuTLSSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+#define xmlSecGnuTLSSymKeyDataCheckId(data) \
+ (xmlSecKeyDataIsValid((data)) && \
+ xmlSecGnuTLSSymKeyDataKlassCheck((data)->id))
+
+static int
+xmlSecGnuTLSSymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataCheckId(data), -1);
+
+ return(xmlSecKeyDataBinaryValueInitialize(data));
+}
+
+static int
+xmlSecGnuTLSSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataCheckId(dst), -1);
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataCheckId(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ return(xmlSecKeyDataBinaryValueDuplicate(dst, src));
+}
+
+static void
+xmlSecGnuTLSSymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecGnuTLSSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueFinalize(data);
+}
+
+static int
+xmlSecGnuTLSSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecGnuTLSSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecGnuTLSSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecGnuTLSSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecGnuTLSSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataCheckId(data), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecGnuTLSGenerateRandom(buffer, (sizeBits + 7) / 8));
+}
+
+static xmlSecKeyDataType
+xmlSecGnuTLSSymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown);
+
+ return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecGnuTLSSymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecGnuTLSSymKeyDataCheckId(data), 0);
+
+ return(xmlSecKeyDataBinaryValueGetSize(data));
+}
+
+static void
+xmlSecGnuTLSSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecGnuTLSSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugDump(data, output);
+}
+
+static void
+xmlSecGnuTLSSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecGnuTLSSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugXmlDump(data, output);
+}
+
+static int
+xmlSecGnuTLSSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) {
+#ifndef XMLSEC_NO_DES
+ if(klass == xmlSecGnuTLSKeyDataDesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(klass == xmlSecGnuTLSKeyDataAesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_HMAC
+ if(klass == xmlSecGnuTLSKeyDataHmacId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_HMAC */
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_AES
+/**************************************************************************
+ *
+ * <xmlsec:AESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecGnuTLSKeyDataAesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameAESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefAESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGnuTLSSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGnuTLSSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGnuTLSSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGnuTLSSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGnuTLSSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGnuTLSSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGnuTLSSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGnuTLSSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecGnuTLSSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecGnuTLSSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGnuTLSSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGnuTLSSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataAesGetKlass(void) {
+ return(&xmlSecGnuTLSKeyDataAesKlass);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataAesSet:
+ * @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
+xmlSecGnuTLSKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataAesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**************************************************************************
+ *
+ * <xmlsec:DESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecGnuTLSKeyDataDesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameDESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGnuTLSSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGnuTLSSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGnuTLSSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGnuTLSSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGnuTLSSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGnuTLSSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGnuTLSSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGnuTLSSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecGnuTLSSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecGnuTLSSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGnuTLSSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGnuTLSSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataDesGetKlass(void) {
+ return(&xmlSecGnuTLSKeyDataDesKlass);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataDesSet:
+ * @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
+xmlSecGnuTLSKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataDesId), -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 xmlSecGnuTLSKeyDataHmacKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameHMACKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefHMACKeyValue, /* const xmlChar* href; */
+ xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGnuTLSSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGnuTLSSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGnuTLSSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGnuTLSSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGnuTLSSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGnuTLSSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGnuTLSSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGnuTLSSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecGnuTLSSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecGnuTLSSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGnuTLSSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGnuTLSSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataHmacGetKlass(void) {
+ return(&xmlSecGnuTLSKeyDataHmacKlass);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataHmacSet:
+ * @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
+xmlSecGnuTLSKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataHmacId), -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/io.c b/src/io.c
new file mode 100644
index 00000000..a691f68b
--- /dev/null
+++ b/src/io.c
@@ -0,0 +1,496 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Input uri transform and utility functions.
+ *
+ * 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 <errno.h>
+
+#include <libxml/uri.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+
+#ifdef LIBXML_HTTP_ENABLED
+#include <libxml/nanohttp.h>
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+#include <libxml/nanoftp.h>
+#endif /* LIBXML_FTP_ENABLED */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/io.h>
+#include <xmlsec/errors.h>
+
+/*******************************************************************
+ *
+ * Input I/O callback sets
+ *
+ ******************************************************************/
+typedef struct _xmlSecIOCallback {
+ xmlInputMatchCallback matchcallback;
+ xmlInputOpenCallback opencallback;
+ xmlInputReadCallback readcallback;
+ xmlInputCloseCallback closecallback;
+} xmlSecIOCallback, *xmlSecIOCallbackPtr;
+
+static xmlSecIOCallbackPtr xmlSecIOCallbackCreate (xmlInputMatchCallback matchFunc,
+ xmlInputOpenCallback openFunc,
+ xmlInputReadCallback readFunc,
+ xmlInputCloseCallback closeFunc);
+static void xmlSecIOCallbackDestroy (xmlSecIOCallbackPtr callbacks);
+
+static xmlSecIOCallbackPtr
+xmlSecIOCallbackCreate(xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc,
+ xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc) {
+ xmlSecIOCallbackPtr callbacks;
+
+ xmlSecAssert2(matchFunc != NULL, NULL);
+
+ /* Allocate a new xmlSecIOCallback and fill the fields. */
+ callbacks = (xmlSecIOCallbackPtr)xmlMalloc(sizeof(xmlSecIOCallback));
+ if(callbacks == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecIOCallback)=%d",
+ sizeof(xmlSecIOCallback));
+ return(NULL);
+ }
+ memset(callbacks, 0, sizeof(xmlSecIOCallback));
+
+ callbacks->matchcallback = matchFunc;
+ callbacks->opencallback = openFunc;
+ callbacks->readcallback = readFunc;
+ callbacks->closecallback = closeFunc;
+
+ return(callbacks);
+}
+
+static void
+xmlSecIOCallbackDestroy(xmlSecIOCallbackPtr callbacks) {
+ xmlSecAssert(callbacks != NULL);
+
+ memset(callbacks, 0, sizeof(xmlSecIOCallback));
+ xmlFree(callbacks);
+}
+
+/*******************************************************************
+ *
+ * Input I/O callback list
+ *
+ ******************************************************************/
+static xmlSecPtrListKlass xmlSecIOCallbackPtrListKlass = {
+ BAD_CAST "io-callbacks-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecIOCallbackDestroy,/* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+#define xmlSecIOCallbackPtrListId xmlSecIOCallbackPtrListGetKlass ()
+static xmlSecPtrListId xmlSecIOCallbackPtrListGetKlass (void);
+static xmlSecIOCallbackPtr xmlSecIOCallbackPtrListFind (xmlSecPtrListPtr list,
+ const char* uri);
+
+/**
+ * xmlSecIOCallbackPtrListGetKlass:
+ *
+ * The keys list klass.
+ *
+ * Returns: keys list id.
+ */
+static xmlSecPtrListId
+xmlSecIOCallbackPtrListGetKlass(void) {
+ return(&xmlSecIOCallbackPtrListKlass);
+}
+
+static xmlSecIOCallbackPtr
+xmlSecIOCallbackPtrListFind(xmlSecPtrListPtr list, const char* uri) {
+ xmlSecIOCallbackPtr callbacks;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecIOCallbackPtrListId), NULL);
+ xmlSecAssert2(uri != NULL, NULL);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ callbacks = (xmlSecIOCallbackPtr)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(callbacks != NULL, NULL);
+ xmlSecAssert2(callbacks->matchcallback != NULL, NULL);
+
+ if((callbacks->matchcallback(uri)) != 0) {
+ return(callbacks);
+ }
+ }
+ return(NULL);
+}
+
+static xmlSecPtrList xmlSecAllIOCallbacks;
+
+/**
+ * xmlSecIOInit:
+ *
+ * The IO initialization (called from #xmlSecInit function).
+ * Applications should not call this function directly.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecIOInit(void) {
+ int ret;
+
+ ret = xmlSecPtrListInitialize(&xmlSecAllIOCallbacks, xmlSecIOCallbackPtrListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListPtrInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifdef LIBXML_HTTP_ENABLED
+ xmlNanoHTTPInit();
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+ xmlNanoFTPInit();
+#endif /* LIBXML_FTP_ENABLED */
+
+ return(xmlSecIORegisterDefaultCallbacks());
+}
+
+/**
+ * xmlSecIOShutdown:
+ *
+ * The IO clenaup (called from #xmlSecShutdown function).
+ * Applications should not call this function directly.
+ */
+void
+xmlSecIOShutdown(void) {
+
+#ifdef LIBXML_HTTP_ENABLED
+ xmlNanoHTTPCleanup();
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+ xmlNanoFTPCleanup();
+#endif /* LIBXML_FTP_ENABLED */
+
+ xmlSecPtrListFinalize(&xmlSecAllIOCallbacks);
+}
+
+/**
+ * xmlSecIOCleanupCallbacks:
+ *
+ * Clears the entire input callback table. this includes the
+ * compiled-in I/O.
+ */
+void
+xmlSecIOCleanupCallbacks(void) {
+ xmlSecPtrListEmpty(&xmlSecAllIOCallbacks);
+}
+
+/**
+ * xmlSecIORegisterCallbacks:
+ * @matchFunc: the protocol match callback.
+ * @openFunc: the open stream callback.
+ * @readFunc: the read from stream callback.
+ * @closeFunc: the close stream callback.
+ *
+ * Register a new set of I/O callback for handling parser input.
+ *
+ * Returns: the 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecIORegisterCallbacks(xmlInputMatchCallback matchFunc,
+ xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
+ xmlInputCloseCallback closeFunc) {
+ xmlSecIOCallbackPtr callbacks;
+ int ret;
+
+ xmlSecAssert2(matchFunc != NULL, -1);
+
+ callbacks = xmlSecIOCallbackCreate(matchFunc, openFunc, readFunc, closeFunc);
+ if(callbacks == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecIOCallbackCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecPtrListAdd(&xmlSecAllIOCallbacks, callbacks);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecIOCallbackDestroy(callbacks);
+ return(-1);
+ }
+ return(0);
+}
+
+
+/**
+ * xmlSecIORegisterDefaultCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecIORegisterDefaultCallbacks(void) {
+ int ret;
+
+#ifdef LIBXML_HTTP_ENABLED
+ ret = xmlSecIORegisterCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
+ xmlIOHTTPRead, xmlIOHTTPClose);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecIORegisterCallbacks",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "http");
+ return(-1);
+ }
+#endif /* LIBXML_HTTP_ENABLED */
+
+#ifdef LIBXML_FTP_ENABLED
+ ret = xmlSecIORegisterCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
+ xmlIOFTPRead, xmlIOFTPClose);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecIORegisterCallbacks",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ftp");
+ return(-1);
+ }
+#endif /* LIBXML_FTP_ENABLED */
+
+ ret = xmlSecIORegisterCallbacks(xmlFileMatch, xmlFileOpen,
+ xmlFileRead, xmlFileClose);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecIORegisterCallbacks",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "file");
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+
+
+/**************************************************************
+ *
+ * Input URI Transform
+ *
+ * xmlSecInputURICtx is located after xmlSecTransform
+ *
+ **************************************************************/
+typedef struct _xmlSecInputURICtx xmlSecInputURICtx,
+ *xmlSecInputURICtxPtr;
+struct _xmlSecInputURICtx {
+ xmlSecIOCallbackPtr clbks;
+ void* clbksCtx;
+};
+#define xmlSecTransformInputUriSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecInputURICtx))
+#define xmlSecTransformInputUriGetCtx(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecTransformInputUriSize)) ? \
+ (xmlSecInputURICtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlSecInputURICtxPtr)NULL)
+
+static int xmlSecTransformInputURIInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformInputURIFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformInputURIPopBin (xmlSecTransformPtr transform,
+ xmlSecByte* data,
+ xmlSecSize maxDataSize,
+ xmlSecSize* dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecTransformInputURIKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformInputUriSize, /* xmlSecSize objSize */
+
+ BAD_CAST "input-uri", /* const xmlChar* name; */
+ NULL, /* const xmlChar* href; */
+ 0, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformInputURIInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformInputURIFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformInputURIPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformInputURIGetKlass:
+ *
+ * The input uri transform klass. Reads binary data from an uri.
+ *
+ * Returns: input URI transform id.
+ */
+xmlSecTransformId
+xmlSecTransformInputURIGetKlass(void) {
+ return(&xmlSecTransformInputURIKlass);
+}
+
+/**
+ * xmlSecTransformInputURIOpen:
+ * @transform: the pointer to IO transform.
+ * @uri: the URL to open.
+ *
+ * Opens the given @uri for reading.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformInputURIOpen(xmlSecTransformPtr transform, const xmlChar *uri) {
+ xmlSecInputURICtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ ctx = xmlSecTransformInputUriGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->clbks == NULL, -1);
+ xmlSecAssert2(ctx->clbksCtx == NULL, -1);
+
+ /*
+ * Try to find one of the input accept method accepting that scheme
+ * Go in reverse to give precedence to user defined handlers.
+ * try with an unescaped version of the uri
+ */
+ if(ctx->clbks == NULL) {
+ char *unescaped;
+
+ unescaped = xmlURIUnescapeString((char*)uri, 0, NULL);
+ if (unescaped != NULL) {
+ ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, unescaped);
+ if(ctx->clbks != NULL) {
+ ctx->clbksCtx = ctx->clbks->opencallback(unescaped);
+ }
+ xmlFree(unescaped);
+ }
+ }
+
+ /*
+ * If this failed try with a non-escaped uri this may be a strange
+ * filename
+ */
+ if (ctx->clbks == NULL) {
+ ctx->clbks = xmlSecIOCallbackPtrListFind(&xmlSecAllIOCallbacks, (char*)uri);
+ if(ctx->clbks != NULL) {
+ ctx->clbksCtx = ctx->clbks->opencallback((char*)uri);
+ }
+ }
+
+ if((ctx->clbks == NULL) || (ctx->clbksCtx == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "opencallback",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "uri=%s;errno=%d",
+ xmlSecErrorsSafeString(uri),
+ errno);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecTransformInputURIInitialize(xmlSecTransformPtr transform) {
+ xmlSecInputURICtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
+
+ ctx = xmlSecTransformInputUriGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecInputURICtx));
+ return(0);
+}
+
+static void
+xmlSecTransformInputURIFinalize(xmlSecTransformPtr transform) {
+ xmlSecInputURICtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId));
+
+ ctx = xmlSecTransformInputUriGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->closecallback != NULL)) {
+ (ctx->clbks->closecallback)(ctx->clbksCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecInputURICtx));
+}
+
+static int
+xmlSecTransformInputURIPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
+ xmlSecSize maxDataSize, xmlSecSize* dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecInputURICtxPtr ctx;
+
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformInputURIId), -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecTransformInputUriGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if((ctx->clbksCtx != NULL) && (ctx->clbks != NULL) && (ctx->clbks->readcallback != NULL)) {
+ ret = (ctx->clbks->readcallback)(ctx->clbksCtx, (char*)data, (int)maxDataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "readcallback",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "errno=%d", errno);
+ return(-1);
+ }
+ (*dataSize) = ret;
+ } else {
+ (*dataSize) = 0;
+ }
+ return(0);
+}
+
diff --git a/src/keyinfo.c b/src/keyinfo.c
new file mode 100644
index 00000000..6e327b2b
--- /dev/null
+++ b/src/keyinfo.c
@@ -0,0 +1,1561 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * <dsig:KeyInfo/> element processing
+ * (http://www.w3.org/TR/xmlSec-core/#sec-KeyInfo:
+ *
+ * The KeyInfo Element
+ *
+ * KeyInfo is an optional element that enables the recipient(s) to obtain
+ * the key needed to validate the signature. KeyInfo may contain keys,
+ * names, certificates and other public key management information, such as
+ * in-band key distribution or key agreement data.
+ *
+ * Schema Definition:
+ *
+ * <element name="KeyInfo" type="ds:KeyInfoType"/>
+ * <complexType name="KeyInfoType" mixed="true">
+ * <choice maxOccurs="unbounded">
+ * <element ref="ds:KeyName"/>
+ * <element ref="ds:KeyValue"/>
+ * <element ref="ds:RetrievalMethod"/>
+ * <element ref="ds:X509Data"/>
+ * <element ref="ds:PGPData"/>
+ * <element ref="ds:SPKIData"/>
+ * <element ref="ds:MgmtData"/>
+ * <any processContents="lax" namespace="##other"/>
+ * <!-- (1,1) elements from (0,unbounded) namespaces -->
+ * </choice>
+ * <attribute name="Id" type="ID" use="optional"/>
+ * </complexType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT KeyInfo (#PCDATA|KeyName|KeyValue|RetrievalMethod|
+ * X509Data|PGPData|SPKIData|MgmtData %KeyInfo.ANY;)* >
+ * <!ATTLIST KeyInfo Id ID #IMPLIED >
+ *
+ *
+ * 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/xmltree.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/errors.h>
+
+
+/**************************************************************************
+ *
+ * Hi level functions
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyInfoNodeRead:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ * @key: the pointer to result key object.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Parses the <dsig:KeyInfo/> element @keyInfoNode, extracts the key data
+ * and stores into @key.
+ *
+ * Returns: 0 on success or -1 if an error occurs.
+ */
+int
+xmlSecKeyInfoNodeRead(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const xmlChar* nodeName;
+ const xmlChar* nodeNs;
+ xmlSecKeyDataId dataId;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(keyInfoNode != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
+
+ for(cur = xmlSecGetNextElementNode(keyInfoNode->children);
+ (cur != NULL) &&
+ (((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND) != 0) ||
+ (xmlSecKeyIsValid(key) == 0) ||
+ (xmlSecKeyMatch(key, NULL, &(keyInfoCtx->keyReq)) == 0));
+ cur = xmlSecGetNextElementNode(cur->next)) {
+
+ /* find data id */
+ nodeName = cur->name;
+ nodeNs = xmlSecGetNodeNsHref(cur);
+
+ /* use global list only if we don't have a local one */
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
+ nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
+ } else {
+ dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
+ nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
+ }
+ if(dataId != xmlSecKeyDataIdUnknown) {
+ /* read data node */
+ ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyDataXmlRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
+ /* there is a laxi schema validation but application may
+ * desire to disable unknown nodes*/
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyInfoNodeWrite:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ * @key: the pointer to key object.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Writes the @key into the <dsig:KeyInfo/> element template @keyInfoNode.
+ *
+ * Returns: 0 on success or -1 if an error occurs.
+ */
+int
+xmlSecKeyInfoNodeWrite(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const xmlChar* nodeName;
+ const xmlChar* nodeNs;
+ xmlSecKeyDataId dataId;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(keyInfoNode != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
+
+ for(cur = xmlSecGetNextElementNode(keyInfoNode->children);
+ cur != NULL;
+ cur = xmlSecGetNextElementNode(cur->next)) {
+
+ /* find data id */
+ nodeName = cur->name;
+ nodeNs = xmlSecGetNodeNsHref(cur);
+
+ /* use global list only if we don't have a local one */
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
+ nodeName, nodeNs,
+ xmlSecKeyDataUsageKeyInfoNodeWrite);
+ } else {
+ dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
+ nodeName, nodeNs,
+ xmlSecKeyDataUsageKeyInfoNodeWrite);
+ }
+ if(dataId != xmlSecKeyDataIdUnknown) {
+ ret = xmlSecKeyDataXmlWrite(dataId, key, cur, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyDataXmlWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
+ /* laxi schema validation but application can disable it*/
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * KeyInfo context
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyInfoCtxCreate:
+ * @keysMngr: the pointer to keys manager (may be NULL).
+ *
+ * Allocates and initializes <dsig:KeyInfo/> element processing context.
+ * Caller is responsible for freeing it by calling #xmlSecKeyInfoCtxDestroy
+ * function.
+ *
+ * Returns: pointer to newly allocated object or NULL if an error occurs.
+ */
+xmlSecKeyInfoCtxPtr
+xmlSecKeyInfoCtxCreate(xmlSecKeysMngrPtr keysMngr) {
+ xmlSecKeyInfoCtxPtr keyInfoCtx;
+ int ret;
+
+ /* Allocate a new xmlSecKeyInfoCtx and fill the fields. */
+ keyInfoCtx = (xmlSecKeyInfoCtxPtr)xmlMalloc(sizeof(xmlSecKeyInfoCtx));
+ if(keyInfoCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(xmlSecKeyInfoCtx));
+ return(NULL);
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(keyInfoCtx, keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxDestroy(keyInfoCtx);
+ return(NULL);
+ }
+
+ return(keyInfoCtx);
+}
+
+/**
+ * xmlSecKeyInfoCtxDestroy:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Destroys @keyInfoCtx object created with #xmlSecKeyInfoCtxCreate function.
+ */
+void
+xmlSecKeyInfoCtxDestroy(xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert(keyInfoCtx != NULL);
+
+ xmlSecKeyInfoCtxFinalize(keyInfoCtx);
+ xmlFree(keyInfoCtx);
+}
+
+/**
+ * xmlSecKeyInfoCtxInitialize:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ * @keysMngr: the pointer to keys manager (may be NULL).
+ *
+ * Initializes <dsig:KeyInfo/> element processing context. Caller is
+ * responsible for cleaning it up by #xmlSecKeyInfoCtxFinalize function.
+ *
+ * Returns: 0 on success and a negative value if an error occurs.
+ */
+int
+xmlSecKeyInfoCtxInitialize(xmlSecKeyInfoCtxPtr keyInfoCtx, xmlSecKeysMngrPtr keysMngr) {
+ int ret;
+
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
+ keyInfoCtx->keysMngr = keysMngr;
+ keyInfoCtx->base64LineSize = xmlSecBase64GetDefaultLineSize();
+ ret = xmlSecPtrListInitialize(&(keyInfoCtx->enabledKeyData), xmlSecKeyDataIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ keyInfoCtx->maxRetrievalMethodLevel = 1;
+ ret = xmlSecTransformCtxInitialize(&(keyInfoCtx->retrievalMethodCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_NO_XMLENC
+ keyInfoCtx->maxEncryptedKeyLevel = 1;
+#endif /* XMLSEC_NO_XMLENC */
+
+#ifndef XMLSEC_NO_X509
+ keyInfoCtx->certsVerificationDepth= 9;
+#endif /* XMLSEC_NO_X509 */
+
+ ret = xmlSecKeyReqInitialize(&(keyInfoCtx->keyReq));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyReqInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyInfoCtxFinalize:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Cleans up the @keyInfoCtx initialized with #xmlSecKeyInfoCtxInitialize
+ * function.
+ */
+void
+xmlSecKeyInfoCtxFinalize(xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert(keyInfoCtx != NULL);
+
+ xmlSecPtrListFinalize(&(keyInfoCtx->enabledKeyData));
+ xmlSecTransformCtxFinalize(&(keyInfoCtx->retrievalMethodCtx));
+ xmlSecKeyReqFinalize(&(keyInfoCtx->keyReq));
+
+#ifndef XMLSEC_NO_XMLENC
+ if(keyInfoCtx->encCtx != NULL) {
+ xmlSecEncCtxDestroy(keyInfoCtx->encCtx);
+ }
+#endif /* XMLSEC_NO_XMLENC */
+
+ memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
+}
+
+/**
+ * xmlSecKeyInfoCtxReset:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Resets the @keyInfoCtx state. User settings are not changed.
+ */
+void
+xmlSecKeyInfoCtxReset(xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert(keyInfoCtx != NULL);
+
+ xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
+ keyInfoCtx->curRetrievalMethodLevel = 0;
+
+#ifndef XMLSEC_NO_XMLENC
+ if(keyInfoCtx->encCtx != NULL) {
+ xmlSecEncCtxReset(keyInfoCtx->encCtx);
+ }
+ keyInfoCtx->curEncryptedKeyLevel = 0;
+#endif /* XMLSEC_NO_XMLENC */
+
+ xmlSecKeyReqReset(&(keyInfoCtx->keyReq));
+}
+
+/**
+ * xmlSecKeyInfoCtxCreateEncCtx:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Creates encryption context form processing <enc:EncryptedKey/> child
+ * of <dsig:KeyInfo/> element.
+ *
+ * Returns: 0 on success and a negative value if an error occurs.
+ */
+int
+xmlSecKeyInfoCtxCreateEncCtx(xmlSecKeyInfoCtxPtr keyInfoCtx) {
+#ifndef XMLSEC_NO_XMLENC
+ xmlSecEncCtxPtr tmp;
+ int ret;
+
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->encCtx == NULL, -1);
+
+ /* we have to use tmp variable to avoid a recursive loop */
+ tmp = xmlSecEncCtxCreate(keyInfoCtx->keysMngr);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ tmp->mode = xmlEncCtxModeEncryptedKey;
+
+ /* copy user preferences from our current ctx */
+ switch(keyInfoCtx->mode) {
+ case xmlSecKeyInfoModeRead:
+ ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoReadCtx), keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecEncCtxDestroy(tmp);
+ return(-1);
+ }
+ break;
+ case xmlSecKeyInfoModeWrite:
+ ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoWriteCtx), keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecEncCtxDestroy(tmp);
+ return(-1);
+ }
+ break;
+ }
+ keyInfoCtx->encCtx = tmp;
+
+ return(0);
+#else /* XMLSEC_NO_XMLENC */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xml encryption",
+ XMLSEC_ERRORS_R_DISABLED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+#endif /* XMLSEC_NO_XMLENC */
+}
+
+/**
+ * xmlSecKeyInfoCtxCopyUserPref:
+ * @dst: the pointer to destination context object.
+ * @src: the pointer to source context object.
+ *
+ * Copies user preferences from @src context to @dst context.
+ *
+ * Returns: 0 on success and a negative value if an error occurs.
+ */
+int
+xmlSecKeyInfoCtxCopyUserPref(xmlSecKeyInfoCtxPtr dst, xmlSecKeyInfoCtxPtr src) {
+ int ret;
+
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(src != NULL, -1);
+
+ dst->userData = src->userData;
+ dst->flags = src->flags;
+ dst->flags2 = src->flags2;
+ dst->keysMngr = src->keysMngr;
+ dst->mode = src->mode;
+ dst->base64LineSize = src->base64LineSize;
+
+ ret = xmlSecPtrListCopy(&(dst->enabledKeyData), &(src->enabledKeyData));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "enabledKeyData");
+ return(-1);
+ }
+
+ /* <dsig:RetrievalMethod/> */
+ dst->maxRetrievalMethodLevel= src->maxRetrievalMethodLevel;
+ ret = xmlSecTransformCtxCopyUserPref(&(dst->retrievalMethodCtx),
+ &(src->retrievalMethodCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "enabledKeyData");
+ return(-1);
+ }
+
+ /* <enc:EncryptedContext /> */
+#ifndef XMLSEC_NO_XMLENC
+ xmlSecAssert2(dst->encCtx == NULL, -1);
+ if(src->encCtx != NULL) {
+ dst->encCtx = xmlSecEncCtxCreate(dst->keysMngr);
+ if(dst->encCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ dst->encCtx->mode = xmlEncCtxModeEncryptedKey;
+ ret = xmlSecEncCtxCopyUserPref(dst->encCtx, src->encCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ dst->maxEncryptedKeyLevel = src->maxEncryptedKeyLevel;
+#endif /* XMLSEC_NO_XMLENC */
+
+ /* <dsig:X509Data /> */
+#ifndef XMLSEC_NO_X509
+ dst->certsVerificationTime = src->certsVerificationTime;
+ dst->certsVerificationDepth = src->certsVerificationDepth;
+#endif /* XMLSEC_NO_X509 */
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyInfoCtxDebugDump:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ * @output: the output file pointer.
+ *
+ * Prints user settings and current context state to @output.
+ */
+void
+xmlSecKeyInfoCtxDebugDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
+ xmlSecAssert(keyInfoCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ switch(keyInfoCtx->mode) {
+ case xmlSecKeyInfoModeRead:
+ fprintf(output, "= KEY INFO READ CONTEXT\n");
+ break;
+ case xmlSecKeyInfoModeWrite:
+ fprintf(output, "= KEY INFO WRITE CONTEXT\n");
+ break;
+ }
+
+ fprintf(output, "== flags: 0x%08x\n", keyInfoCtx->flags);
+ fprintf(output, "== flags2: 0x%08x\n", keyInfoCtx->flags2);
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ fprintf(output, "== enabled key data: ");
+ xmlSecKeyDataIdListDebugDump(&(keyInfoCtx->enabledKeyData), output);
+ } else {
+ fprintf(output, "== enabled key data: all\n");
+ }
+ fprintf(output, "== RetrievalMethod level (cur/max): %d/%d\n",
+ keyInfoCtx->curRetrievalMethodLevel,
+ keyInfoCtx->maxRetrievalMethodLevel);
+ xmlSecTransformCtxDebugDump(&(keyInfoCtx->retrievalMethodCtx), output);
+
+#ifndef XMLSEC_NO_XMLENC
+ fprintf(output, "== EncryptedKey level (cur/max): %d/%d\n",
+ keyInfoCtx->curEncryptedKeyLevel,
+ keyInfoCtx->maxEncryptedKeyLevel);
+ if(keyInfoCtx->encCtx != NULL) {
+ xmlSecEncCtxDebugDump(keyInfoCtx->encCtx, output);
+ }
+#endif /* XMLSEC_NO_XMLENC */
+
+ xmlSecKeyReqDebugDump(&(keyInfoCtx->keyReq), output);
+}
+
+/**
+ * xmlSecKeyInfoCtxDebugXmlDump:
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ * @output: the output file pointer.
+ *
+ * Prints user settings and current context state in XML format to @output.
+ */
+void
+xmlSecKeyInfoCtxDebugXmlDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
+ xmlSecAssert(keyInfoCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ switch(keyInfoCtx->mode) {
+ case xmlSecKeyInfoModeRead:
+ fprintf(output, "<KeyInfoReadContext>\n");
+ break;
+ case xmlSecKeyInfoModeWrite:
+ fprintf(output, "<KeyInfoWriteContext>\n");
+ break;
+ }
+
+ fprintf(output, "<Flags>%08x</Flags>\n", keyInfoCtx->flags);
+ fprintf(output, "<Flags2>%08x</Flags2>\n", keyInfoCtx->flags2);
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ fprintf(output, "<EnabledKeyData>\n");
+ xmlSecKeyDataIdListDebugXmlDump(&(keyInfoCtx->enabledKeyData), output);
+ fprintf(output, "</EnabledKeyData>\n");
+ } else {
+ fprintf(output, "<EnabledKeyData>all</EnabledKeyData>\n");
+ }
+
+ fprintf(output, "<RetrievalMethodLevel cur=\"%d\" max=\"%d\" />\n",
+ keyInfoCtx->curRetrievalMethodLevel,
+ keyInfoCtx->maxRetrievalMethodLevel);
+ xmlSecTransformCtxDebugXmlDump(&(keyInfoCtx->retrievalMethodCtx), output);
+
+#ifndef XMLSEC_NO_XMLENC
+ fprintf(output, "<EncryptedKeyLevel cur=\"%d\" max=\"%d\" />\n",
+ keyInfoCtx->curEncryptedKeyLevel,
+ keyInfoCtx->maxEncryptedKeyLevel);
+ if(keyInfoCtx->encCtx != NULL) {
+ xmlSecEncCtxDebugXmlDump(keyInfoCtx->encCtx, output);
+ }
+#endif /* XMLSEC_NO_XMLENC */
+
+ xmlSecKeyReqDebugXmlDump(&(keyInfoCtx->keyReq), output);
+ switch(keyInfoCtx->mode) {
+ case xmlSecKeyInfoModeRead:
+ fprintf(output, "</KeyInfoReadContext>\n");
+ break;
+ case xmlSecKeyInfoModeWrite:
+ fprintf(output, "</KeyInfoWriteContext>\n");
+ break;
+ }
+}
+
+/**************************************************************************
+ *
+ * <dsig:KeyName/> processing
+ *
+ *************************************************************************/
+static int xmlSecKeyDataNameXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecKeyDataNameXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecKeyDataNameKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ sizeof(xmlSecKeyData),
+
+ /* data */
+ xmlSecNameKeyName,
+ xmlSecKeyDataUsageKeyInfoNode, /* xmlSecKeyDataUsage usage; */
+ NULL, /* const xmlChar* href; */
+ xmlSecNodeKeyName, /* 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 */
+ xmlSecKeyDataNameXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecKeyDataNameXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecKeyDataNameGetKlass:
+ *
+ * The <dsig:KeyName/> element key data klass
+ * (http://www.w3.org/TR/xmldsig-core/#sec-KeyName):
+ *
+ * The KeyName element contains a string value (in which white space is
+ * significant) which may be used by the signer to communicate a key
+ * identifier to the recipient. Typically, KeyName contains an identifier
+ * related to the key pair used to sign the message, but it may contain
+ * other protocol-related information that indirectly identifies a key pair.
+ * (Common uses of KeyName include simple string names for keys, a key index,
+ * a distinguished name (DN), an email address, etc.)
+ *
+ * Returns: the <dsig:KeyName/> element processing key data klass.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataNameGetKlass(void) {
+ return(&xmlSecKeyDataNameKlass);
+}
+
+static int
+xmlSecKeyDataNameXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const xmlChar* oldName;
+ xmlChar* newName;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
+
+ oldName = xmlSecKeyGetName(key);
+ newName = xmlNodeGetContent(node);
+ if(newName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ /* TODO: do we need to decode the name? */
+
+ /* compare name values */
+ if((oldName != NULL) && !xmlStrEqual(oldName, newName)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "key name is already specified",
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(newName);
+ return(-1);
+ }
+
+ /* try to find key in the manager */
+ if((xmlSecKeyGetValue(key) == NULL) && (keyInfoCtx->keysMngr != NULL)) {
+ xmlSecKeyPtr tmpKey;
+
+ tmpKey = xmlSecKeysMngrFindKey(keyInfoCtx->keysMngr, newName, keyInfoCtx);
+ if(tmpKey != NULL) {
+ /* erase any current information in the key */
+ xmlSecKeyEmpty(key);
+
+ /* TODO: since we will destroy tmpKey anyway, we can easily
+ * just re-assign key data values. It'll save use some memory
+ * malloc/free
+ */
+
+ /* and copy what we've found */
+ ret = xmlSecKeyCopy(key, tmpKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(tmpKey);
+ xmlFree(newName);
+ return(-1);
+ }
+ xmlSecKeyDestroy(tmpKey);
+ }
+ }
+
+ /* finally set key name if it is not there */
+ if(xmlSecKeyGetName(key) == NULL) {
+ xmlSecKeySetName(key, newName);
+ }
+ xmlFree(newName);
+ return(0);
+}
+
+static int
+xmlSecKeyDataNameXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const xmlChar* name;
+
+ xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
+
+ name = xmlSecKeyGetName(key);
+ if(name != NULL) {
+ xmlSecNodeEncodeAndSetContent(node, name);
+ }
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * <dsig:KeyValue/> processing
+ *
+ *************************************************************************/
+static int xmlSecKeyDataValueXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecKeyDataValueXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecKeyDataValueKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ sizeof(xmlSecKeyData),
+
+ /* data */
+ xmlSecNameKeyValue,
+ xmlSecKeyDataUsageKeyInfoNode, /* xmlSecKeyDataUsage usage; */
+ NULL, /* const xmlChar* href; */
+ xmlSecNodeKeyValue, /* 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 */
+ xmlSecKeyDataValueXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecKeyDataValueXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecKeyDataValueGetKlass:
+ *
+ * The <dsig:KeyValue/> element key data klass
+ * (http://www.w3.org/TR/xmldsig-core/#sec-KeyValue):
+ *
+ * The KeyValue element contains a single public key that may be useful in
+ * validating the signature.
+ *
+ * Returns: the <dsig:KeyValue/> element processing key data klass.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataValueGetKlass(void) {
+ return(&xmlSecKeyDataValueKlass);
+}
+
+static int
+xmlSecKeyDataValueXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const xmlChar* nodeName;
+ const xmlChar* nodeNs;
+ xmlSecKeyDataId dataId;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if(cur == NULL) {
+ /* just an empty node */
+ return(0);
+ }
+
+ /* find data id */
+ nodeName = cur->name;
+ nodeNs = xmlSecGetNodeNsHref(cur);
+
+ /* use global list only if we don't have a local one */
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
+ nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
+ } else {
+ dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
+ nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
+ }
+ if(dataId != xmlSecKeyDataIdUnknown) {
+ /* read data node */
+ ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataXmlRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
+ /* laxi schema validation but application can disable it */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* <dsig:KeyValue/> might have only one node */
+ 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);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecKeyDataValueXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const xmlChar* nodeName;
+ const xmlChar* nodeNs;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
+
+ if(!xmlSecKeyDataIsValid(key->value) ||
+ !xmlSecKeyDataCheckUsage(key->value, xmlSecKeyDataUsageKeyValueNodeWrite)){
+ /* nothing to write */
+ return(0);
+ }
+ if((xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) &&
+ (xmlSecKeyDataIdListFind(&(keyInfoCtx->enabledKeyData), id) != 1)) {
+
+ /* we are not enabled to write out key data with this id */
+ return(0);
+ }
+ if(xmlSecKeyReqMatchKey(&(keyInfoCtx->keyReq), key) != 1) {
+ /* we are not allowed to write out this key */
+ return(0);
+ }
+
+ nodeName = key->value->id->dataNodeName;
+ nodeNs = key->value->id->dataNodeNs;
+ xmlSecAssert2(nodeName != NULL, -1);
+
+ /* remove all existing key value */
+ xmlNodeSetContent(node, NULL);
+
+ /* create key node */
+ cur = xmlSecAddChild(node, nodeName, nodeNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+
+ ret = xmlSecKeyDataXmlWrite(key->value->id, key, cur, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataXmlWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * <dsig:RetrievalMethod/> processing
+ *
+ *************************************************************************/
+static int xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+
+
+static xmlSecKeyDataKlass xmlSecKeyDataRetrievalMethodKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ sizeof(xmlSecKeyData),
+
+ /* data */
+ xmlSecNameRetrievalMethod,
+ xmlSecKeyDataUsageKeyInfoNode, /* xmlSecKeyDataUsage usage; */
+ NULL, /* const xmlChar* href; */
+ xmlSecNodeRetrievalMethod, /* 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 */
+ xmlSecKeyDataRetrievalMethodXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecKeyDataRetrievalMethodXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static int xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId,
+ xmlSecKeyPtr key,
+ const xmlChar* buffer,
+ xmlSecSize bufferSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+/**
+ * xmlSecKeyDataRetrievalMethodGetKlass:
+ *
+ * The <dsig:RetrievalMethod/> element key data klass
+ * (http://www.w3.org/TR/xmldsig-core/#sec-RetrievalMethod):
+ * A RetrievalMethod element within KeyInfo is used to convey a reference to
+ * KeyInfo information that is stored at another location. For example,
+ * several signatures in a document might use a key verified by an X.509v3
+ * certificate chain appearing once in the document or remotely outside the
+ * document; each signature's KeyInfo can reference this chain using a single
+ * RetrievalMethod element instead of including the entire chain with a
+ * sequence of X509Certificate elements.
+ *
+ * RetrievalMethod uses the same syntax and dereferencing behavior as
+ * Reference's URI and The Reference Processing Model.
+ *
+ * Returns: the <dsig:RetrievalMethod/> element processing key data klass.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataRetrievalMethodGetKlass(void) {
+ return(&xmlSecKeyDataRetrievalMethodKlass);
+}
+
+static int
+xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataId dataId = xmlSecKeyDataIdUnknown;
+ xmlChar *retrType = NULL;
+ xmlChar *uri = NULL;
+ xmlNodePtr cur;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
+
+ /* check retrieval level */
+ if(keyInfoCtx->curRetrievalMethodLevel >= keyInfoCtx->maxRetrievalMethodLevel) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,
+ "cur=%d;max=%d",
+ keyInfoCtx->curRetrievalMethodLevel,
+ keyInfoCtx->maxRetrievalMethodLevel);
+ goto done;
+ }
+ ++keyInfoCtx->curRetrievalMethodLevel;
+
+ retrType = xmlGetProp(node, xmlSecAttrType);
+ if(retrType != NULL) {
+ /* use global list only if we don't have a local one */
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ dataId = xmlSecKeyDataIdListFindByHref(&(keyInfoCtx->enabledKeyData),
+ retrType, xmlSecKeyDataUsageRetrievalMethodNode);
+ } else {
+ dataId = xmlSecKeyDataIdListFindByHref(xmlSecKeyDataIdsGet(),
+ retrType, xmlSecKeyDataUsageRetrievalMethodNode);
+ }
+ }
+
+ /* laxi schema validation but aplication can disable it */
+ if(dataId == xmlSecKeyDataIdUnknown) {
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_UNKNOWN_HREF) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecAttrType),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "value=%s", xmlSecErrorsSafeString(retrType));
+ } else {
+ res = 0;
+ }
+ goto done;
+ }
+
+ /* destroy prev retrieval method context */
+ xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
+
+ /* set start URI and check that it is enabled */
+ uri = xmlGetProp(node, xmlSecAttrURI);
+ ret = xmlSecTransformCtxSetUri(&(keyInfoCtx->retrievalMethodCtx), uri, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecTransformCtxSetUri",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ goto done;
+ }
+
+ /* the only one node is optional Transforms node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
+ ret = xmlSecTransformCtxNodesListRead(&(keyInfoCtx->retrievalMethodCtx),
+ cur, xmlSecTransformUsageDSigTransform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecTransformCtxNodesListRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ goto done;
+ }
+ 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);
+ goto done;
+ }
+
+ /* finally get transforms results */
+ ret = xmlSecTransformCtxExecute(&(keyInfoCtx->retrievalMethodCtx), node->doc);
+ if((ret < 0) ||
+ (keyInfoCtx->retrievalMethodCtx.result == NULL) ||
+ (xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result) == NULL)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecTransformCtxExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+
+ /* assume that the data is in XML if we could not find id */
+ if((dataId == xmlSecKeyDataIdUnknown) ||
+ ((dataId->usage & xmlSecKeyDataUsageRetrievalMethodNodeXml) != 0)) {
+
+ ret = xmlSecKeyDataRetrievalMethodReadXmlResult(dataId, key,
+ xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
+ xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
+ keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataRetrievalMethodReadXmlResult",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ } else {
+ ret = xmlSecKeyDataBinRead(dataId, key,
+ xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
+ xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
+ keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataBinRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ --keyInfoCtx->curRetrievalMethodLevel;
+
+ res = 0;
+done:
+ if(uri != NULL) {
+ xmlFree(uri);
+ }
+ if(retrType != NULL) {
+ xmlFree(retrType);
+ }
+ return(res);
+}
+
+static int
+xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
+
+ /* just do nothing */
+ return(0);
+}
+
+static int
+xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId, xmlSecKeyPtr key,
+ const xmlChar* buffer, xmlSecSize bufferSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ const xmlChar* nodeName;
+ const xmlChar* nodeNs;
+ xmlSecKeyDataId dataId;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2(bufferSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
+
+ doc = xmlRecoverMemory((const char*)buffer, bufferSize);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
+ "xmlRecoverMemory",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
+ "xmlDocGetRootElement",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ nodeName = cur->name;
+ nodeNs = xmlSecGetNodeNsHref(cur);
+
+ /* use global list only if we don't have a local one */
+ if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
+ dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
+ nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
+ } else {
+ dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
+ nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
+ }
+ if(dataId == xmlSecKeyDataIdUnknown) {
+ xmlFreeDoc(doc);
+
+ /* laxi schema validation but application can disable it */
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ } else if((typeId != xmlSecKeyDataIdUnknown) && (typeId != dataId) &&
+ ((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_MISMATCH_HREF) != 0)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ /* read data node */
+ ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
+ "xmlSecKeyDataXmlRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ xmlFreeDoc(doc);
+ return(0);
+}
+
+
+#ifndef XMLSEC_NO_XMLENC
+/**************************************************************************
+ *
+ * <enc:EncryptedKey/> processing
+ *
+ *************************************************************************/
+static int xmlSecKeyDataEncryptedKeyXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecKeyDataEncryptedKeyXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+
+
+static xmlSecKeyDataKlass xmlSecKeyDataEncryptedKeyKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ sizeof(xmlSecKeyData),
+
+ /* data */
+ xmlSecNameEncryptedKey,
+ xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefEncryptedKey, /* const xmlChar* href; */
+ xmlSecNodeEncryptedKey, /* const xmlChar* dataNodeName; */
+ xmlSecEncNs, /* 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 */
+ xmlSecKeyDataEncryptedKeyXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecKeyDataEncryptedKeyXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecKeyDataEncryptedKeyGetKlass:
+ *
+ * The <enc:EncryptedKey/> element key data klass
+ * (http://www.w3.org/TR/xmlenc-core/#sec-EncryptedKey):
+ *
+ * The EncryptedKey element is used to transport encryption keys from
+ * the originator to a known recipient(s). It may be used as a stand-alone
+ * XML document, be placed within an application document, or appear inside
+ * an EncryptedData element as a child of a ds:KeyInfo element. The key value
+ * is always encrypted to the recipient(s). When EncryptedKey is decrypted the
+ * resulting octets are made available to the EncryptionMethod algorithm
+ * without any additional processing.
+ *
+ * Returns: the <enc:EncryptedKey/> element processing key data klass.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataEncryptedKeyGetKlass(void) {
+ return(&xmlSecKeyDataEncryptedKeyKlass);
+}
+
+static int
+xmlSecKeyDataEncryptedKeyXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecBufferPtr result;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
+
+ /* check the enc level */
+ if(keyInfoCtx->curEncryptedKeyLevel >= keyInfoCtx->maxEncryptedKeyLevel) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,
+ "cur=%d;max=%d",
+ keyInfoCtx->curEncryptedKeyLevel,
+ keyInfoCtx->maxEncryptedKeyLevel);
+ return(-1);
+ }
+ ++keyInfoCtx->curEncryptedKeyLevel;
+
+ /* init Enc context */
+ if(keyInfoCtx->encCtx != NULL) {
+ xmlSecEncCtxReset(keyInfoCtx->encCtx);
+ } else {
+ ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyInfoCtxCreateEncCtx",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
+
+ result = xmlSecEncCtxDecryptToBuffer(keyInfoCtx->encCtx, node);
+ if((result == NULL) || (xmlSecBufferGetData(result) == NULL)) {
+ /* We might have multiple EncryptedKey elements, encrypted
+ * for different receipints but application can enforce
+ * correct enc key.
+ */
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ENCKEY_DONT_STOP_ON_FAILED_DECRYPTION) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecEncCtxDecryptToBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ ret = xmlSecKeyDataBinRead(keyInfoCtx->keyReq.keyId, key,
+ xmlSecBufferGetData(result),
+ xmlSecBufferGetSize(result),
+ keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataBinRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ --keyInfoCtx->curEncryptedKeyLevel;
+
+ return(0);
+}
+
+static int
+xmlSecKeyDataEncryptedKeyXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyInfoCtx keyInfoCtx2;
+ xmlSecByte *keyBuf = NULL;
+ xmlSecSize keySize = 0;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyIsValid(key), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
+
+ /* dump key to a binary buffer */
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx2, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecKeyInfoCtxCopyUserPref(&keyInfoCtx2, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
+ goto done;
+ }
+
+ keyInfoCtx2.keyReq.keyType = xmlSecKeyDataTypeAny;
+ ret = xmlSecKeyDataBinWrite(key->value->id, key, &keyBuf, &keySize, &keyInfoCtx2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataBinWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
+ goto done;
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
+
+ /* init Enc context */
+ if(keyInfoCtx->encCtx != NULL) {
+ xmlSecEncCtxReset(keyInfoCtx->encCtx);
+ } else {
+ ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyInfoCtxCreateEncCtx",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
+
+ ret = xmlSecEncCtxBinaryEncrypt(keyInfoCtx->encCtx, node, keyBuf, keySize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecEncCtxBinaryEncrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ res = 0;
+done:
+ if(keyBuf != NULL) {
+ memset(keyBuf, 0, keySize);
+ xmlFree(keyBuf); keyBuf = NULL;
+ }
+ return(res);
+}
+
+#endif /* XMLSEC_NO_XMLENC */
+
diff --git a/src/keys.c b/src/keys.c
new file mode 100644
index 00000000..44522aa1
--- /dev/null
+++ b/src/keys.c
@@ -0,0 +1,1415 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Keys.
+ *
+ * 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/xmltree.h>
+#include <xmlsec/list.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/errors.h>
+
+/**************************************************************************
+ *
+ * xmlSecKeyUseWith
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyUseWithInitialize:
+ * @keyUseWith: the pointer to information about key application/user.
+ *
+ * Initializes @keyUseWith object.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyUseWithInitialize(xmlSecKeyUseWithPtr keyUseWith) {
+ xmlSecAssert2(keyUseWith != NULL, -1);
+
+ memset(keyUseWith, 0, sizeof(xmlSecKeyUseWith));
+ return(0);
+}
+
+/**
+ * xmlSecKeyUseWithFinalize:
+ * @keyUseWith: the pointer to information about key application/user.
+ *
+ * Finalizes @keyUseWith object.
+ */
+void
+xmlSecKeyUseWithFinalize(xmlSecKeyUseWithPtr keyUseWith) {
+ xmlSecAssert(keyUseWith != NULL);
+
+ xmlSecKeyUseWithReset(keyUseWith);
+ memset(keyUseWith, 0, sizeof(xmlSecKeyUseWith));
+}
+
+/**
+ * xmlSecKeyUseWithReset:
+ * @keyUseWith: the pointer to information about key application/user.
+ *
+ * Resets the @keyUseWith to its state after initialization.
+ */
+void
+xmlSecKeyUseWithReset(xmlSecKeyUseWithPtr keyUseWith) {
+ xmlSecAssert(keyUseWith != NULL);
+
+ xmlSecKeyUseWithSet(keyUseWith, NULL, NULL);
+}
+
+/**
+ * xmlSecKeyUseWithCopy:
+ * @dst: the pointer to destination object.
+ * @src: the pointer to source object.
+ *
+ * Copies information from @dst to @src.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyUseWithCopy(xmlSecKeyUseWithPtr dst, xmlSecKeyUseWithPtr src) {
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(src != NULL, -1);
+
+ return(xmlSecKeyUseWithSet(dst, src->application, src->identifier));
+}
+
+/**
+ * xmlSecKeyUseWithCreate:
+ * @application: the application value.
+ * @identifier: the identifier value.
+ *
+ * Creates new xmlSecKeyUseWith object. The caller is responsible for destroying
+ * returned object with @xmlSecKeyUseWithDestroy function.
+ *
+ * Returns: pointer to newly created object or NULL if an error occurs.
+ */
+xmlSecKeyUseWithPtr
+xmlSecKeyUseWithCreate(const xmlChar* application, const xmlChar* identifier) {
+ xmlSecKeyUseWithPtr keyUseWith;
+ int ret;
+
+ /* Allocate a new xmlSecKeyUseWith and fill the fields. */
+ keyUseWith = (xmlSecKeyUseWithPtr)xmlMalloc(sizeof(xmlSecKeyUseWith));
+ if(keyUseWith == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecKeyUseWith)=%d",
+ sizeof(xmlSecKeyUseWith));
+ return(NULL);
+ }
+ memset(keyUseWith, 0, sizeof(xmlSecKeyUseWith));
+
+ ret = xmlSecKeyUseWithInitialize(keyUseWith);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyUseWithInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyUseWithDestroy(keyUseWith);
+ return(NULL);
+ }
+
+ ret = xmlSecKeyUseWithSet(keyUseWith, application, identifier);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyUseWithSet",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyUseWithDestroy(keyUseWith);
+ return(NULL);
+ }
+
+ return(keyUseWith);
+}
+
+/**
+ * xmlSecKeyUseWithDuplicate:
+ * @keyUseWith: the pointer to information about key application/user.
+ *
+ * Duplicates @keyUseWith object. The caller is responsible for destroying
+ * returned object with @xmlSecKeyUseWithDestroy function.
+ *
+ * Returns: pointer to newly created object or NULL if an error occurs.
+ */
+xmlSecKeyUseWithPtr
+xmlSecKeyUseWithDuplicate(xmlSecKeyUseWithPtr keyUseWith) {
+ int ret;
+
+ xmlSecKeyUseWithPtr newKeyUseWith;
+
+ xmlSecAssert2(keyUseWith != NULL, NULL);
+
+ newKeyUseWith = xmlSecKeyUseWithCreate(NULL, NULL);
+ if(newKeyUseWith == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyUseWithCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecKeyUseWithCopy(newKeyUseWith, keyUseWith);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyUseWithCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyUseWithDestroy(keyUseWith);
+ return(NULL);
+ }
+
+ return(newKeyUseWith);
+}
+
+/**
+ * xmlSecKeyUseWithDestroy:
+ * @keyUseWith: the pointer to information about key application/user.
+ *
+ * Destroys @keyUseWith created with @xmlSecKeyUseWithCreate or @xmlSecKeyUseWithDuplicate
+ * functions.
+ */
+void
+xmlSecKeyUseWithDestroy(xmlSecKeyUseWithPtr keyUseWith) {
+ xmlSecAssert(keyUseWith != NULL);
+
+ xmlSecKeyUseWithFinalize(keyUseWith);
+ xmlFree(keyUseWith);
+}
+
+/**
+ * xmlSecKeyUseWithSet:
+ * @keyUseWith: the pointer to information about key application/user.
+ * @application: the new application value.
+ * @identifier: the new identifier value.
+ *
+ * Sets @application and @identifier in the @keyUseWith.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyUseWithSet(xmlSecKeyUseWithPtr keyUseWith, const xmlChar* application, const xmlChar* identifier) {
+ xmlSecAssert2(keyUseWith != NULL, -1);
+
+ if(keyUseWith->application != NULL) {
+ xmlFree(keyUseWith->application);
+ keyUseWith->application = NULL;
+ }
+ if(keyUseWith->identifier != NULL) {
+ xmlFree(keyUseWith->identifier);
+ keyUseWith->identifier = NULL;
+ }
+
+ if(application != NULL) {
+ keyUseWith->application = xmlStrdup(application);
+ if(keyUseWith->application == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "xmlStrlen(application)=%d",
+ xmlStrlen(application));
+ return(-1);
+ }
+ }
+ if(identifier != NULL) {
+ keyUseWith->identifier = xmlStrdup(identifier);
+ if(keyUseWith->identifier == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "xmlStrlen(identifier)=%d",
+ xmlStrlen(identifier));
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyUseWithDebugDump:
+ * @keyUseWith: the pointer to information about key application/user.
+ * @output: the pointer to output FILE.
+ *
+ * Prints xmlSecKeyUseWith debug information to a file @output.
+ */
+void
+xmlSecKeyUseWithDebugDump(xmlSecKeyUseWithPtr keyUseWith, FILE* output) {
+ xmlSecAssert(keyUseWith != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== KeyUseWith: application=\"%s\",identifier=\"%s\"\n",
+ (keyUseWith->application) ? keyUseWith->application : BAD_CAST "",
+ (keyUseWith->identifier) ? keyUseWith->identifier : BAD_CAST "");
+}
+
+/**
+ * xmlSecKeyUseWithDebugXmlDump:
+ * @keyUseWith: the pointer to information about key application/user.
+ * @output: the pointer to output FILE.
+ *
+ * Prints xmlSecKeyUseWith debug information to a file @output in XML format.
+ */
+void
+xmlSecKeyUseWithDebugXmlDump(xmlSecKeyUseWithPtr keyUseWith, FILE* output) {
+ xmlSecAssert(keyUseWith != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<KeyUseWith>\n");
+
+ fprintf(output, "<Application>");
+ xmlSecPrintXmlString(output, keyUseWith->application);
+ fprintf(output, "</Application>");
+
+ fprintf(output, "<Identifier>");
+ xmlSecPrintXmlString(output, keyUseWith->identifier);
+ fprintf(output, "</Identifier>");
+
+ fprintf(output, "</KeyUseWith>\n");
+}
+
+/***********************************************************************
+ *
+ * KeyUseWith list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyUseWithPtrListKlass = {
+ BAD_CAST "key-use-with-list",
+ (xmlSecPtrDuplicateItemMethod)xmlSecKeyUseWithDuplicate, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecKeyUseWithDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecKeyUseWithDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecKeyUseWithDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyUseWithPtrListGetKlass:
+ *
+ * The key data list klass.
+ *
+ * Returns: pointer to the key data list klass.
+ */
+xmlSecPtrListId
+xmlSecKeyUseWithPtrListGetKlass(void) {
+ return(&xmlSecKeyUseWithPtrListKlass);
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyReq - what key are we looking for?
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyReqInitialize:
+ * @keyReq: the pointer to key requirements object.
+ *
+ * Initialize key requirements object. Caller is responsible for
+ * cleaning it with #xmlSecKeyReqFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyReqInitialize(xmlSecKeyReqPtr keyReq) {
+ int ret;
+
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ memset(keyReq, 0, sizeof(xmlSecKeyReq));
+
+ keyReq->keyUsage = xmlSecKeyUsageAny; /* by default you can do whatever you want with the key */
+ ret = xmlSecPtrListInitialize(&keyReq->keyUseWithList, xmlSecKeyUseWithPtrListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyReqFinalize:
+ * @keyReq: the pointer to key requirements object.
+ *
+ * Cleans the key requirements object initialized with #xmlSecKeyReqInitialize
+ * function.
+ */
+void
+xmlSecKeyReqFinalize(xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert(keyReq != NULL);
+
+ xmlSecPtrListFinalize(&keyReq->keyUseWithList);
+ memset(keyReq, 0, sizeof(xmlSecKeyReq));
+}
+
+/**
+ * xmlSecKeyReqReset:
+ * @keyReq: the pointer to key requirements object.
+ *
+ * Resets key requirements object for new key search.
+ */
+void
+xmlSecKeyReqReset(xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert(keyReq != NULL);
+
+ xmlSecPtrListEmpty(&keyReq->keyUseWithList);
+ keyReq->keyId = NULL;
+ keyReq->keyType = 0;
+ keyReq->keyUsage = xmlSecKeyUsageAny;
+ keyReq->keyBitsSize = 0;
+}
+
+/**
+ * xmlSecKeyReqCopy:
+ * @dst: the pointer to destination object.
+ * @src: the pointer to source object.
+ *
+ * Copies key requirements from @src object to @dst object.
+ *
+ * Returns: 0 on success and a negative value if an error occurs.
+ */
+int
+xmlSecKeyReqCopy(xmlSecKeyReqPtr dst, xmlSecKeyReqPtr src) {
+ int ret;
+
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(src != NULL, -1);
+
+ dst->keyId = src->keyId;
+ dst->keyType = src->keyType;
+ dst->keyUsage = src->keyUsage;
+ dst->keyBitsSize = src->keyBitsSize;
+
+ ret = xmlSecPtrListCopy(&dst->keyUseWithList, &src->keyUseWithList);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyReqMatchKey:
+ * @keyReq: the pointer to key requirements object.
+ * @key: the pointer to key.
+ *
+ * Checks whether @key matches key requirements @keyReq.
+ *
+ * Returns: 1 if key matches requirements, 0 if not and a negative value
+ * if an error occurs.
+ */
+int
+xmlSecKeyReqMatchKey(xmlSecKeyReqPtr keyReq, xmlSecKeyPtr key) {
+ xmlSecAssert2(keyReq != NULL, -1);
+ xmlSecAssert2(xmlSecKeyIsValid(key), -1);
+
+ if((keyReq->keyType != xmlSecKeyDataTypeUnknown) && ((xmlSecKeyGetType(key) & keyReq->keyType) == 0)) {
+ return(0);
+ }
+ if((keyReq->keyUsage != xmlSecKeyDataUsageUnknown) && ((keyReq->keyUsage & key->usage) == 0)) {
+ return(0);
+ }
+
+ return(xmlSecKeyReqMatchKeyValue(keyReq, xmlSecKeyGetValue(key)));
+}
+
+/**
+ * xmlSecKeyReqMatchKeyValue:
+ * @keyReq: the pointer to key requirements.
+ * @value: the pointer to key value.
+ *
+ * Checks whether @keyValue matches key requirements @keyReq.
+ *
+ * Returns: 1 if key value matches requirements, 0 if not and a negative value
+ * if an error occurs.
+ */
+int
+xmlSecKeyReqMatchKeyValue(xmlSecKeyReqPtr keyReq, xmlSecKeyDataPtr value) {
+ xmlSecAssert2(keyReq != NULL, -1);
+ xmlSecAssert2(value != NULL, -1);
+
+ if((keyReq->keyId != xmlSecKeyDataIdUnknown) &&
+ (!xmlSecKeyDataCheckId(value, keyReq->keyId))) {
+
+ return(0);
+ }
+ if((keyReq->keyBitsSize > 0) &&
+ (xmlSecKeyDataGetSize(value) > 0) &&
+ (xmlSecKeyDataGetSize(value) < keyReq->keyBitsSize)) {
+
+ return(0);
+ }
+ return(1);
+}
+
+/**
+ * xmlSecKeyReqDebugDump:
+ * @keyReq: the pointer to key requirements object.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @keyReq into @output.
+ */
+void
+xmlSecKeyReqDebugDump(xmlSecKeyReqPtr keyReq, FILE* output) {
+ xmlSecAssert(keyReq != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== KeyReq:\n");
+ fprintf(output, "==== keyId: %s\n",
+ (xmlSecKeyDataKlassGetName(keyReq->keyId)) ?
+ xmlSecKeyDataKlassGetName(keyReq->keyId) :
+ BAD_CAST "NULL");
+ fprintf(output, "==== keyType: 0x%08x\n", keyReq->keyType);
+ fprintf(output, "==== keyUsage: 0x%08x\n", keyReq->keyUsage);
+ fprintf(output, "==== keyBitsSize: %d\n", keyReq->keyBitsSize);
+ xmlSecPtrListDebugDump(&(keyReq->keyUseWithList), output);
+}
+
+/**
+ * xmlSecKeyReqDebugXmlDump:
+ * @keyReq: the pointer to key requirements object.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @keyReq into @output in XML format.
+ */
+void
+xmlSecKeyReqDebugXmlDump(xmlSecKeyReqPtr keyReq, FILE* output) {
+ xmlSecAssert(keyReq != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<KeyReq>\n");
+
+ fprintf(output, "<KeyId>");
+ xmlSecPrintXmlString(output, xmlSecKeyDataKlassGetName(keyReq->keyId));
+ fprintf(output, "</KeyId>\n");
+
+ fprintf(output, "<KeyType>0x%08x</KeyType>\n", keyReq->keyType);
+ fprintf(output, "<KeyUsage>0x%08x</KeyUsage>\n", keyReq->keyUsage);
+ fprintf(output, "<KeyBitsSize>%d</KeyBitsSize>\n", keyReq->keyBitsSize);
+ xmlSecPtrListDebugXmlDump(&(keyReq->keyUseWithList), output);
+ fprintf(output, "</KeyReq>\n");
+}
+
+
+/**************************************************************************
+ *
+ * xmlSecKey
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyCreate:
+ *
+ * Allocates and initializes new key. Caller is responsible for
+ * freeing returned object with #xmlSecKeyDestroy function.
+ *
+ * Returns: the pointer to newly allocated @xmlSecKey structure
+ * or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyCreate(void) {
+ xmlSecKeyPtr key;
+
+ /* Allocate a new xmlSecKey and fill the fields. */
+ key = (xmlSecKeyPtr)xmlMalloc(sizeof(xmlSecKey));
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecKey)=%d",
+ sizeof(xmlSecKey));
+ return(NULL);
+ }
+ memset(key, 0, sizeof(xmlSecKey));
+ key->usage = xmlSecKeyUsageAny;
+ return(key);
+}
+
+/**
+ * xmlSecKeyEmpty:
+ * @key: the pointer to key.
+ *
+ * Clears the @key data.
+ */
+void
+xmlSecKeyEmpty(xmlSecKeyPtr key) {
+ xmlSecAssert(key != NULL);
+
+ if(key->value != NULL) {
+ xmlSecKeyDataDestroy(key->value);
+ }
+ if(key->name != NULL) {
+ xmlFree(key->name);
+ }
+ if(key->dataList != NULL) {
+ xmlSecPtrListDestroy(key->dataList);
+ }
+
+ memset(key, 0, sizeof(xmlSecKey));
+}
+
+/**
+ * xmlSecKeyDestroy:
+ * @key: the pointer to key.
+ *
+ * Destroys the key created using #xmlSecKeyCreate function.
+ */
+void
+xmlSecKeyDestroy(xmlSecKeyPtr key) {
+ xmlSecAssert(key != NULL);
+
+ xmlSecKeyEmpty(key);
+ xmlFree(key);
+}
+
+/**
+ * xmlSecKeyCopy:
+ * @keyDst: the destination key.
+ * @keySrc: the source key.
+ *
+ * Copies key data from @keySrc to @keyDst.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyCopy(xmlSecKeyPtr keyDst, xmlSecKeyPtr keySrc) {
+ xmlSecAssert2(keyDst != NULL, -1);
+ xmlSecAssert2(keySrc != NULL, -1);
+
+ /* empty destination */
+ xmlSecKeyEmpty(keyDst);
+
+ /* copy everything */
+ if(keySrc->name != NULL) {
+ keyDst->name = xmlStrdup(keySrc->name);
+ if(keyDst->name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "len=%d", xmlStrlen(keySrc->name));
+ return(-1);
+ }
+ }
+
+ if(keySrc->value != NULL) {
+ keyDst->value = xmlSecKeyDataDuplicate(keySrc->value);
+ if(keyDst->value == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataDuplicate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(keySrc->dataList != NULL) {
+ keyDst->dataList = xmlSecPtrListDuplicate(keySrc->dataList);
+ if(keyDst->dataList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListDuplicate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ keyDst->usage = keySrc->usage;
+ keyDst->notValidBefore = keySrc->notValidBefore;
+ keyDst->notValidAfter = keySrc->notValidAfter;
+ return(0);
+}
+
+/**
+ * xmlSecKeyDuplicate:
+ * @key: the pointer to the #xmlSecKey structure.
+ *
+ * Creates a duplicate of the given @key.
+ *
+ * Returns: the pointer to newly allocated #xmlSecKey structure
+ * or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyDuplicate(xmlSecKeyPtr key) {
+ xmlSecKeyPtr newKey;
+ int ret;
+
+ xmlSecAssert2(key != NULL, NULL);
+
+ newKey = xmlSecKeyCreate();
+ if(newKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecKeyCopy(newKey, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(newKey);
+ return(NULL);
+ }
+
+ return(newKey);
+}
+
+/**
+ * xmlSecKeyMatch:
+ * @key: the pointer to key.
+ * @name: the pointer to key name (may be NULL).
+ * @keyReq: the pointer to key requirements.
+ *
+ * Checks whether the @key matches the given criteria.
+ *
+ * Returns: 1 if the key satisfies the given criteria or 0 otherwise.
+ */
+int
+xmlSecKeyMatch(xmlSecKeyPtr key, const xmlChar *name, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecKeyIsValid(key), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ if((name != NULL) && (!xmlStrEqual(xmlSecKeyGetName(key), name))) {
+ return(0);
+ }
+ return(xmlSecKeyReqMatchKey(keyReq, key));
+}
+
+/**
+ * xmlSecKeyGetType:
+ * @key: the pointer to key.
+ *
+ * Gets @key type.
+ *
+ * Returns: key type.
+ */
+xmlSecKeyDataType
+xmlSecKeyGetType(xmlSecKeyPtr key) {
+ xmlSecKeyDataPtr data;
+
+ xmlSecAssert2(key != NULL, xmlSecKeyDataTypeUnknown);
+
+ data = xmlSecKeyGetValue(key);
+ if(data == NULL) {
+ return(xmlSecKeyDataTypeUnknown);
+ }
+ return(xmlSecKeyDataGetType(data));
+}
+
+/**
+ * xmlSecKeyGetName:
+ * @key: the pointer to key.
+ *
+ * Gets key name (see also #xmlSecKeySetName function).
+ *
+ * Returns: key name.
+ */
+const xmlChar*
+xmlSecKeyGetName(xmlSecKeyPtr key) {
+ xmlSecAssert2(key != NULL, NULL);
+
+ return(key->name);
+}
+
+/**
+ * xmlSecKeySetName:
+ * @key: the pointer to key.
+ * @name: the new key name.
+ *
+ * Sets key name (see also #xmlSecKeyGetName function).
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeySetName(xmlSecKeyPtr key, const xmlChar* name) {
+ xmlSecAssert2(key != NULL, -1);
+
+ if(key->name != NULL) {
+ xmlFree(key->name);
+ key->name = NULL;
+ }
+
+ if(name != NULL) {
+ key->name = xmlStrdup(name);
+ if(key->name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "len=%d", xmlStrlen(name));
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyGetValue:
+ * @key: the pointer to key.
+ *
+ * Gets key value (see also #xmlSecKeySetValue function).
+ *
+ * Returns: key value (crypto material).
+ */
+xmlSecKeyDataPtr
+xmlSecKeyGetValue(xmlSecKeyPtr key) {
+ xmlSecAssert2(key != NULL, NULL);
+
+ return(key->value);
+}
+
+/**
+ * xmlSecKeySetValue:
+ * @key: the pointer to key.
+ * @value: the new value.
+ *
+ * Sets key value (see also #xmlSecKeyGetValue function).
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeySetValue(xmlSecKeyPtr key, xmlSecKeyDataPtr value) {
+ xmlSecAssert2(key != NULL, -1);
+
+ if(key->value != NULL) {
+ xmlSecKeyDataDestroy(key->value);
+ key->value = NULL;
+ }
+ key->value = value;
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyGetData:
+ * @key: the pointer to key.
+ * @dataId: the requested data klass.
+ *
+ * Gets key's data.
+ *
+ * Returns: additional data associated with the @key (see also
+ * #xmlSecKeyAdoptData function).
+ */
+xmlSecKeyDataPtr
+xmlSecKeyGetData(xmlSecKeyPtr key, xmlSecKeyDataId dataId) {
+
+ xmlSecAssert2(key != NULL, NULL);
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, NULL);
+
+ /* special cases */
+ if(dataId == xmlSecKeyDataValueId) {
+ return(key->value);
+ } else if(key->dataList != NULL) {
+ xmlSecKeyDataPtr tmp;
+ xmlSecSize pos, size;
+
+ size = xmlSecPtrListGetSize(key->dataList);
+ for(pos = 0; pos < size; ++pos) {
+ tmp = (xmlSecKeyDataPtr)xmlSecPtrListGetItem(key->dataList, pos);
+ if((tmp != NULL) && (tmp->id == dataId)) {
+ return(tmp);
+ }
+ }
+ }
+ return(NULL);
+}
+
+/**
+ * xmlSecKeyEnsureData:
+ * @key: the pointer to key.
+ * @dataId: the requested data klass.
+ *
+ * If necessary, creates key data of @dataId klass and adds to @key.
+ *
+ * Returns: pointer to key data or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecKeyEnsureData(xmlSecKeyPtr key, xmlSecKeyDataId dataId) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(key != NULL, NULL);
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, NULL);
+
+ data = xmlSecKeyGetData(key, dataId);
+ if(data != NULL) {
+ return(data);
+ }
+
+ data = xmlSecKeyDataCreate(dataId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "dataId=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)));
+ return(NULL);
+ }
+
+ ret = xmlSecKeyAdoptData(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyAdoptData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "dataId=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)));
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+
+ return(data);
+}
+
+/**
+ * xmlSecKeyAdoptData:
+ * @key: the pointer to key.
+ * @data: the pointer to key data.
+ *
+ * Adds @data to the @key. The @data object will be destroyed
+ * by @key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyAdoptData(xmlSecKeyPtr key, xmlSecKeyDataPtr data) {
+ xmlSecKeyDataPtr tmp;
+ xmlSecSize pos, size;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+
+ /* special cases */
+ if(data->id == xmlSecKeyDataValueId) {
+ if(key->value != NULL) {
+ xmlSecKeyDataDestroy(key->value);
+ }
+ key->value = data;
+ return(0);
+ }
+
+ if(key->dataList == NULL) {
+ key->dataList = xmlSecPtrListCreate(xmlSecKeyDataListId);
+ if(key->dataList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+
+ size = xmlSecPtrListGetSize(key->dataList);
+ for(pos = 0; pos < size; ++pos) {
+ tmp = (xmlSecKeyDataPtr)xmlSecPtrListGetItem(key->dataList, pos);
+ if((tmp != NULL) && (tmp->id == data->id)) {
+ return(xmlSecPtrListSet(key->dataList, data, pos));
+ }
+ }
+
+ return(xmlSecPtrListAdd(key->dataList, data));
+}
+
+/**
+ * xmlSecKeyDebugDump:
+ * @key: the pointer to key.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the information about the @key to the @output.
+ */
+void
+xmlSecKeyDebugDump(xmlSecKeyPtr key, FILE *output) {
+ xmlSecAssert(xmlSecKeyIsValid(key));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "== KEY\n");
+ fprintf(output, "=== method: %s\n",
+ (key->value->id->dataNodeName != NULL) ?
+ (char*)(key->value->id->dataNodeName) : "NULL");
+
+ fprintf(output, "=== key type: ");
+ if((xmlSecKeyGetType(key) & xmlSecKeyDataTypeSymmetric) != 0) {
+ fprintf(output, "Symmetric\n");
+ } else if((xmlSecKeyGetType(key) & xmlSecKeyDataTypePrivate) != 0) {
+ fprintf(output, "Private\n");
+ } else if((xmlSecKeyGetType(key) & xmlSecKeyDataTypePublic) != 0) {
+ fprintf(output, "Public\n");
+ } else {
+ fprintf(output, "Unknown\n");
+ }
+
+ if(key->name != NULL) {
+ fprintf(output, "=== key name: %s\n", key->name);
+ }
+ fprintf(output, "=== key usage: %d\n", key->usage);
+ if(key->notValidBefore < key->notValidAfter) {
+ fprintf(output, "=== key not valid before: %ld\n", (unsigned long)key->notValidBefore);
+ fprintf(output, "=== key not valid after: %ld\n", (unsigned long)key->notValidAfter);
+ }
+ if(key->value != NULL) {
+ xmlSecKeyDataDebugDump(key->value, output);
+ }
+ if(key->dataList != NULL) {
+ xmlSecPtrListDebugDump(key->dataList, output);
+ }
+}
+
+/**
+ * xmlSecKeyDebugXmlDump:
+ * @key: the pointer to key.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the information about the @key to the @output in XML format.
+ */
+void
+xmlSecKeyDebugXmlDump(xmlSecKeyPtr key, FILE *output) {
+ xmlSecAssert(xmlSecKeyIsValid(key));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<KeyInfo>\n");
+
+ fprintf(output, "<KeyMethod>");
+ xmlSecPrintXmlString(output, key->value->id->dataNodeName);
+ fprintf(output, "</KeyMethod>\n");
+
+ fprintf(output, "<KeyType>");
+ if((xmlSecKeyGetType(key) & xmlSecKeyDataTypeSymmetric) != 0) {
+ fprintf(output, "Symmetric\n");
+ } else if((xmlSecKeyGetType(key) & xmlSecKeyDataTypePrivate) != 0) {
+ fprintf(output, "Private\n");
+ } else if((xmlSecKeyGetType(key) & xmlSecKeyDataTypePublic) != 0) {
+ fprintf(output, "Public\n");
+ } else {
+ fprintf(output, "Unknown\n");
+ }
+ fprintf(output, "</KeyType>\n");
+
+ fprintf(output, "<KeyName>");
+ xmlSecPrintXmlString(output, key->name);
+ fprintf(output, "</KeyName>\n");
+
+ if(key->notValidBefore < key->notValidAfter) {
+ fprintf(output, "<KeyValidity notValidBefore=\"%ld\" notValidAfter=\"%ld\"/>\n",
+ (unsigned long)key->notValidBefore,
+ (unsigned long)key->notValidAfter);
+ }
+
+ if(key->value != NULL) {
+ xmlSecKeyDataDebugXmlDump(key->value, output);
+ }
+ if(key->dataList != NULL) {
+ xmlSecPtrListDebugXmlDump(key->dataList, output);
+ }
+
+ fprintf(output, "</KeyInfo>\n");
+}
+
+/**
+ * xmlSecKeyGenerate:
+ * @dataId: the requested key klass (rsa, dsa, aes, ...).
+ * @sizeBits: the new key size (in bits!).
+ * @type: the new key type (session, permanent, ...).
+ *
+ * Generates new key of requested klass @dataId and @type.
+ *
+ * Returns: pointer to newly created key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyGenerate(xmlSecKeyDataId dataId, xmlSecSize sizeBits, xmlSecKeyDataType type) {
+ xmlSecKeyPtr key;
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, NULL);
+
+ data = xmlSecKeyDataCreate(dataId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecKeyDataGenerate(data, sizeBits, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyDataGenerate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d;type=%d", sizeBits, type);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "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,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ xmlSecKeyDestroy(key);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+/**
+ * xmlSecKeyGenerateByName:
+ * @name: the requested key klass name (rsa, dsa, aes, ...).
+ * @sizeBits: the new key size (in bits!).
+ * @type: the new key type (session, permanent, ...).
+ *
+ * Generates new key of requested @klass and @type.
+ *
+ * Returns: pointer to newly created key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyGenerateByName(const xmlChar* name, xmlSecSize sizeBits, xmlSecKeyDataType type) {
+ xmlSecKeyDataId dataId;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ dataId = xmlSecKeyDataIdListFindByName(xmlSecKeyDataIdsGet(), name, xmlSecKeyDataUsageAny);
+ if(dataId == xmlSecKeyDataIdUnknown) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(name),
+ XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecKeyGenerate(dataId, sizeBits, type));
+}
+
+/**
+ * xmlSecKeyReadBuffer:
+ * @dataId: the key value data klass.
+ * @buffer: the buffer that contains the binary data.
+ *
+ * Reads the key value of klass @dataId from a buffer.
+ *
+ * Returns: pointer to newly created key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyReadBuffer(xmlSecKeyDataId dataId, xmlSecBuffer* buffer) {
+ xmlSecKeyInfoCtx keyInfoCtx;
+ xmlSecKeyPtr key;
+ int ret;
+
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, NULL);
+ xmlSecAssert2(buffer != NULL, NULL);
+
+ /* create key data */
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ return(NULL);
+ }
+
+ keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
+ ret = xmlSecKeyDataBinRead(dataId, key,
+ xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer),
+ &keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyDataBinRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ xmlSecKeyDestroy(key);
+ return(NULL);
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+
+ return(key);
+}
+
+/**
+ * xmlSecKeyReadBinaryFile:
+ * @dataId: the key value data klass.
+ * @filename: the key binary filename.
+ *
+ * Reads the key value of klass @dataId from a binary file @filename.
+ *
+ * Returns: pointer to newly created key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyReadBinaryFile(xmlSecKeyDataId dataId, const char* filename) {
+ xmlSecKeyPtr key;
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, NULL);
+ xmlSecAssert2(filename != NULL, NULL);
+
+ /* read file to buffer */
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecBufferReadFile(&buffer, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ key = xmlSecKeyReadBuffer(dataId, &buffer);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyReadBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ xmlSecBufferFinalize(&buffer);
+ return (key);
+}
+
+/**
+ * xmlSecKeyReadMemory:
+ * @dataId: the key value data klass.
+ * @data: the memory containing the key
+ * @dataSize: the size of the memory block
+ *
+ * Reads the key value of klass @dataId from a memory block @data.
+ *
+ * Returns: pointer to newly created key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyReadMemory(xmlSecKeyDataId dataId, const xmlSecByte* data, xmlSecSize dataSize) {
+ xmlSecBuffer buffer;
+ xmlSecKeyPtr key;
+ int ret;
+
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, NULL);
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 0, NULL);
+
+ /* read file to buffer */
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ if (xmlSecBufferAppend(&buffer, data, dataSize) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ key = xmlSecKeyReadBuffer(dataId, &buffer);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
+ "xmlSecKeyReadBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ xmlSecBufferFinalize(&buffer);
+ return (key);
+}
+
+/**
+ * xmlSecKeysMngrGetKey:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context.
+ *
+ * Reads the <dsig:KeyInfo/> node @keyInfoNode and extracts the key.
+ *
+ * Returns: the pointer to key or NULL if the key is not found or
+ * an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeysMngrGetKey(xmlNodePtr keyInfoNode, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyPtr key;
+ int ret;
+
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+
+ /* first try to read data from <dsig:KeyInfo/> node */
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ if(keyInfoNode != NULL) {
+ ret = xmlSecKeyInfoNodeRead(keyInfoNode, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(keyInfoNode)));
+ xmlSecKeyDestroy(key);
+ return(NULL);
+ }
+
+ if((xmlSecKeyGetValue(key) != NULL) &&
+ (xmlSecKeyMatch(key, NULL, &(keyInfoCtx->keyReq)) != 0)) {
+ return(key);
+ }
+ }
+ xmlSecKeyDestroy(key);
+
+ /* if we have keys manager, try it */
+ if(keyInfoCtx->keysMngr != NULL) {
+ key = xmlSecKeysMngrFindKey(keyInfoCtx->keysMngr, NULL, keyInfoCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrFindKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ if(xmlSecKeyGetValue(key) != NULL) {
+ return(key);
+ }
+ xmlSecKeyDestroy(key);
+ }
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_KEY_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/***********************************************************************
+ *
+ * Keys list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyPtrListKlass = {
+ BAD_CAST "keys-list",
+ (xmlSecPtrDuplicateItemMethod)xmlSecKeyDuplicate, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecKeyDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecKeyDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecKeyDebugXmlDump,/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyPtrListGetKlass:
+ *
+ * The keys list klass.
+ *
+ * Returns: keys list id.
+ */
+xmlSecPtrListId
+xmlSecKeyPtrListGetKlass(void) {
+ return(&xmlSecKeyPtrListKlass);
+}
+
diff --git a/src/keysdata.c b/src/keysdata.c
new file mode 100644
index 00000000..1101f7f8
--- /dev/null
+++ b/src/keysdata.c
@@ -0,0 +1,1387 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Key data.
+ *
+ * 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/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/errors.h>
+
+
+/**************************************************************************
+ *
+ * Global xmlSecKeyDataIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllKeyDataIds;
+
+/**
+ * xmlSecKeyDataIdsGet:
+ *
+ * Gets global registered key data klasses list.
+ *
+ * Returns: the pointer to list of all registered key data klasses.
+ */
+xmlSecPtrListPtr
+xmlSecKeyDataIdsGet(void) {
+ return(&xmlSecAllKeyDataIds);
+}
+
+/**
+ * xmlSecKeyDataIdsInit:
+ *
+ * Initializes the key data klasses. This function is called from the
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyDataIdsInit(void) {
+ int ret;
+
+ ret = xmlSecPtrListInitialize(xmlSecKeyDataIdsGet(), xmlSecKeyDataIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListPtrInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyDataIdListId");
+ return(-1);
+ }
+
+ ret = xmlSecKeyDataIdsRegisterDefault();
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataIdsRegisterDefault",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataIdsShutdown:
+ *
+ * Shuts down the keys data klasses. This function is called from the
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+void
+xmlSecKeyDataIdsShutdown(void) {
+ xmlSecPtrListFinalize(xmlSecKeyDataIdsGet());
+}
+
+/**
+ * xmlSecKeyDataIdsRegister:
+ * @id: the key data klass.
+ *
+ * Registers @id in the global list of key data klasses.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyDataIdsRegister(xmlSecKeyDataId id) {
+ int ret;
+
+ xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+
+ ret = xmlSecPtrListAdd(xmlSecKeyDataIdsGet(), (xmlSecPtr)id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "dataId=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * key data klasses: <dsig:KeyName/> element processing klass,
+ * <dsig:KeyValue/> element processing klass, ...
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyDataIdsRegisterDefault(void) {
+ if(xmlSecKeyDataIdsRegister(xmlSecKeyDataNameId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyDataNameId");
+ return(-1);
+ }
+
+ if(xmlSecKeyDataIdsRegister(xmlSecKeyDataValueId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyDataValueId");
+ return(-1);
+ }
+
+ if(xmlSecKeyDataIdsRegister(xmlSecKeyDataRetrievalMethodId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyDataRetrievalMethodId");
+ return(-1);
+ }
+
+#ifndef XMLSEC_NO_XMLENC
+ if(xmlSecKeyDataIdsRegister(xmlSecKeyDataEncryptedKeyId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyDataEncryptedKeyId");
+ return(-1);
+ }
+#endif /* XMLSEC_NO_XMLENC */
+
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyData functions
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyDataCreate:
+ * @id: the data id.
+ *
+ * Allocates and initializes new key data of the specified type @id.
+ * Caller is responsible for destroing returend object with
+ * #xmlSecKeyDataDestroy function.
+ *
+ * Returns: the pointer to newly allocated key data structure
+ * or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecKeyDataCreate(xmlSecKeyDataId id) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id != NULL, NULL);
+ xmlSecAssert2(id->klassSize >= sizeof(xmlSecKeyDataKlass), NULL);
+ xmlSecAssert2(id->objSize >= sizeof(xmlSecKeyData), NULL);
+ xmlSecAssert2(id->name != NULL, NULL);
+
+ /* Allocate a new xmlSecKeyData and fill the fields. */
+ data = (xmlSecKeyDataPtr)xmlMalloc(id->objSize);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", id->objSize);
+ return(NULL);
+ }
+ memset(data, 0, id->objSize);
+ data->id = id;
+
+ if(id->initialize != NULL) {
+ ret = (id->initialize)(data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "id->initialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+ }
+
+ return(data);
+}
+
+/**
+ * xmlSecKeyDataDuplicate:
+ * @data: the pointer to the key data.
+ *
+ * Creates a duplicate of the given @data. Caller is responsible for
+ * destroing returend object with #xmlSecKeyDataDestroy function.
+ *
+ * Returns: the pointer to newly allocated key data structure
+ * or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecKeyDataDuplicate(xmlSecKeyDataPtr data) {
+ xmlSecKeyDataPtr newData;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(data->id->duplicate != NULL, NULL);
+
+ newData = xmlSecKeyDataCreate(data->id);
+ if(newData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = (data->id->duplicate)(newData, data);
+ if(newData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "id->duplicate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(newData);
+ return(NULL);
+ }
+
+ return(newData);
+}
+
+/**
+ * xmlSecKeyDataDestroy:
+ * @data: the pointer to the key data.
+ *
+ * Destroys the data and frees all allocated memory.
+ */
+void
+xmlSecKeyDataDestroy(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(data->id->objSize > 0);
+
+ if(data->id->finalize != NULL) {
+ (data->id->finalize)(data);
+ }
+ memset(data, 0, data->id->objSize);
+ xmlFree(data);
+}
+
+
+/**
+ * xmlSecKeyDataXmlRead:
+ * @id: the data klass.
+ * @key: the destination key.
+ * @node: the pointer to an XML node.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Reads the key data of klass @id from XML @node and adds them to @key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(id != NULL, -1);
+ xmlSecAssert2(id->xmlRead != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ return((id->xmlRead)(id, key, node, keyInfoCtx));
+}
+
+/**
+ * xmlSecKeyDataXmlWrite:
+ * @id: the data klass.
+ * @key: the source key.
+ * @node: the pointer to an XML node.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Writes the key data of klass @id from @key to an XML @node.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(id != NULL, -1);
+ xmlSecAssert2(id->xmlWrite != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ return((id->xmlWrite)(id, key, node, keyInfoCtx));
+}
+
+/**
+ * xmlSecKeyDataBinRead:
+ * @id: the data klass.
+ * @key: the destination key.
+ * @buf: the input binary buffer.
+ * @bufSize: the input buffer size.
+ * @keyInfoCtx: the <dsig:KeyInfo/> node processing context.
+ *
+ * Reads the key data of klass @id from binary buffer @buf to @key.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(id != NULL, -1);
+ xmlSecAssert2(id->binRead != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+
+ return((id->binRead)(id, key, buf, bufSize, keyInfoCtx));
+}
+
+/**
+ * xmlSecKeyDataBinWrite:
+ * @id: the data klass.
+ * @key: the source key.
+ * @buf: the output binary buffer.
+ * @bufSize: the output buffer size.
+ * @keyInfoCtx: the <dsig:KeyInfo/> node processing context.
+ *
+ * Writes the key data of klass @id from the @key to a binary buffer @buf.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(id != NULL, -1);
+ xmlSecAssert2(id->binWrite != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+
+ return((id->binWrite)(id, key, buf, bufSize, keyInfoCtx));
+}
+
+/**
+ * xmlSecKeyDataGenerate:
+ * @data: the pointer to key data.
+ * @sizeBits: the desired key data size (in bits).
+ * @type: the desired key data type.
+ *
+ * Generates new key data of given size and type.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits,
+ xmlSecKeyDataType type) {
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(data->id->generate != NULL, -1);
+
+ /* write data */
+ ret = data->id->generate(data, sizeBits, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "id->generate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", sizeBits);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataGetType:
+ * @data: the pointer to key data.
+ *
+ * Gets key data type.
+ *
+ * Returns: key data type.
+ */
+xmlSecKeyDataType
+xmlSecKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(data->id->getType != NULL, xmlSecKeyDataTypeUnknown);
+
+ return(data->id->getType(data));
+}
+
+/**
+ * xmlSecKeyDataGetSize:
+ * @data: the pointer to key data.
+ *
+ * Gets key data size.
+ *
+ * Returns: key data size (in bits).
+ */
+xmlSecSize
+xmlSecKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(data->id->getSize != NULL, 0);
+
+ return(data->id->getSize(data));
+}
+
+/**
+ * xmlSecKeyDataGetIdentifier:
+ * @data: the pointer to key data.
+ *
+ * Gets key data identifier string.
+ *
+ * Returns: key data id string.
+ */
+const xmlChar*
+xmlSecKeyDataGetIdentifier(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(data->id->getIdentifier != NULL, NULL);
+
+ return(data->id->getIdentifier(data));
+}
+
+/**
+ * xmlSecKeyDataDebugDump:
+ * @data: the pointer to key data.
+ * @output: the pointer to output FILE.
+ *
+ * Prints key data debug info.
+ */
+void
+xmlSecKeyDataDebugDump(xmlSecKeyDataPtr data, FILE *output) {
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(data->id->debugDump != NULL);
+ xmlSecAssert(output != NULL);
+
+ data->id->debugDump(data, output);
+}
+
+/**
+ * xmlSecKeyDataDebugXmlDump:
+ * @data: the pointer to key data.
+ * @output: the pointer to output FILE.
+ *
+ * Prints key data debug info in XML format.
+ */
+void
+xmlSecKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE *output) {
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(data->id->debugXmlDump != NULL);
+ xmlSecAssert(output != NULL);
+
+ data->id->debugXmlDump(data, output);
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyDataBinary methods
+ *
+ * key (xmlSecBuffer) is located after xmlSecKeyData structure
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyDataBinaryValueInitialize:
+ * @data: the pointer to binary key data.
+ *
+ * Initializes key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueInitialize(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), -1);
+
+ /* initialize buffer */
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ ret = xmlSecBufferInitialize(buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueDuplicate:
+ * @dst: the pointer to destination binary key data.
+ * @src: the pointer to source binary key data.
+ *
+ * Copies binary key data from @src to @dst.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecBufferPtr buffer;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecKeyDataBinarySize), -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecKeyDataBinarySize), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(src);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ /* copy data */
+ ret = xmlSecKeyDataBinaryValueSetBuffer(dst,
+ xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecKeyDataBinaryValueSetBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueFinalize:
+ * @data: the pointer to binary key data.
+ *
+ * Cleans up binary key data.
+ */
+void
+xmlSecKeyDataBinaryValueFinalize(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize));
+
+ /* initialize buffer */
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert(buffer != NULL);
+
+ xmlSecBufferFinalize(buffer);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueXmlRead:
+ * @id: the data klass.
+ * @key: the pointer to destination key.
+ * @node: the pointer to an XML node.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Reads binary key data from @node to the key by base64 decoding the @node content.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar* str;
+ xmlSecSize len;
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ str = xmlNodeGetContent(node);
+ if(str == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* usual trick: decode into the same buffer */
+ ret = xmlSecBase64Decode(str, (xmlSecByte*)str, xmlStrlen(str));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(str);
+ return(-1);
+ }
+ len = ret;
+
+ /* check do we have a key already */
+ data = xmlSecKeyGetValue(key);
+ if(data != NULL) {
+ xmlSecBufferPtr buffer;
+
+ if(!xmlSecKeyDataCheckId(data, id)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(str);
+ return(-1);
+ }
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ if((buffer != NULL) && ((xmlSecSize)xmlSecBufferGetSize(buffer) != len)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+ "cur-data-size=%d;new-data-size=%d",
+ xmlSecBufferGetSize(buffer), len);
+ xmlFree(str);
+ return(-1);
+ }
+ if((buffer != NULL) && (len > 0) && (memcmp(xmlSecBufferGetData(buffer), str, len) != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+ "key already has a different value");
+ xmlFree(str);
+ return(-1);
+ }
+ if(buffer != NULL) {
+ /* we already have exactly the same key */
+ xmlFree(str);
+ return(0);
+ }
+
+ /* we have binary key value with empty buffer */
+ }
+
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(str);
+ return(-1);
+ }
+
+ ret = xmlSecKeyDataBinaryValueSetBuffer(data, (xmlSecByte*)str, len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataBinaryValueSetBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", len);
+ xmlSecKeyDataDestroy(data);
+ xmlFree(str);
+ return(-1);
+ }
+ xmlFree(str);
+
+ if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), data) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyReqMatchKeyValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(0);
+ }
+
+ 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);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueXmlWrite:
+ * @id: the data klass.
+ * @key: the pointer to source key.
+ * @node: the pointer to an XML node.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Base64 encodes binary key data of klass @id from the @key and
+ * sets to the @node content.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecBufferPtr buffer;
+ xmlSecKeyDataPtr value;
+ xmlChar* str;
+
+ xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if((xmlSecKeyDataTypeSymmetric & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only symmetric key */
+ return(0);
+ }
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataIsValid(value), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(value);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ str = xmlSecBase64Encode(xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer),
+ keyInfoCtx->base64LineSize);
+ if(str == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlNodeSetContent(node, str);
+ xmlFree(str);
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueBinRead:
+ * @id: the data klass.
+ * @key: the pointer to destination key.
+ * @buf: the source binary buffer.
+ * @bufSize: the source binary buffer size.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Reads binary key data of the klass @id from @buf to the @key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ /* check do we have a key already */
+ data = xmlSecKeyGetValue(key);
+ if(data != NULL) {
+ xmlSecBufferPtr buffer;
+
+ if(!xmlSecKeyDataCheckId(data, id)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ if((buffer != NULL) && ((xmlSecSize)xmlSecBufferGetSize(buffer) != bufSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+ "cur-data-size=%d;new-data-size=%d",
+ xmlSecBufferGetSize(buffer), bufSize);
+ return(-1);
+ }
+ if((buffer != NULL) && (bufSize > 0) && (memcmp(xmlSecBufferGetData(buffer), buf, bufSize) != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+ "key already has a different value");
+ return(-1);
+ }
+ if(buffer != NULL) {
+ /* we already have exactly the same key */
+ return(0);
+ }
+
+ /* we have binary key value with empty buffer */
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKeyDataBinaryValueSetBuffer(data, buf, bufSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataBinaryValueSetBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", bufSize);
+ xmlSecKeyDataDestroy(data);
+ return(-1);
+ }
+
+ if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), data) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyReqMatchKeyValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(0);
+ }
+
+ 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);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueBinWrite:
+ * @id: the data klass.
+ * @key: the pointer to source key.
+ * @buf: the destination binary buffer.
+ * @bufSize: the destination binary buffer size.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Writes binary key data of klass @id from the @key to @buf.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if((xmlSecKeyDataTypeSymmetric & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only symmetric key */
+ return(0);
+ }
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataIsValid(value), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(key->value);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ (*bufSize) = xmlSecBufferGetSize(buffer);
+ (*buf) = (xmlSecByte*) xmlMalloc((*bufSize));
+ if((*buf) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ memcpy((*buf), xmlSecBufferGetData(buffer), (*bufSize));
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataBinaryValueDebugDump:
+ * @data: the pointer to binary key data.
+ * @output: the pointer to output FILE.
+ *
+ * Prints binary key data debug information to @output.
+ */
+void
+xmlSecKeyDataBinaryValueDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize));
+ xmlSecAssert(data->id->dataNodeName != NULL);
+ xmlSecAssert(output != NULL);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert(buffer != NULL);
+
+ /* print only size, everything else is sensitive */
+ fprintf(output, "=== %s: size=%d\n", data->id->dataNodeName,
+ xmlSecKeyDataGetSize(data));
+}
+
+/**
+ * xmlSecKeyDataBinaryValueDebugXmlDump:
+ * @data: the pointer to binary key data.
+ * @output: the pointer to output FILE.
+ *
+ * Prints binary key data debug information to @output in XML format.
+ */
+void
+xmlSecKeyDataBinaryValueDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize));
+ xmlSecAssert(data->id->dataNodeName != NULL);
+ xmlSecAssert(output != NULL);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert(buffer != NULL);
+
+ /* print only size, everything else is sensitive */
+ fprintf(output, "<%s size=\"%d\" />\n", data->id->dataNodeName,
+ xmlSecKeyDataGetSize(data));
+}
+
+/**
+ * xmlSecKeyDataBinaryValueGetSize:
+ * @data: the pointer to binary key data.
+ *
+ * Gets the binary key data size.
+ *
+ * Returns: binary key data size in bits.
+ */
+xmlSecSize
+xmlSecKeyDataBinaryValueGetSize(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), 0);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, 0);
+
+ /* return size in bits */
+ return(8 * xmlSecBufferGetSize(buffer));
+}
+
+/**
+ * xmlSecKeyDataBinaryValueGetBuffer:
+ * @data: the pointer to binary key data.
+ *
+ * Gets the binary key data buffer.
+ *
+ * Returns: pointer to binary key data buffer.
+ */
+xmlSecBufferPtr
+xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), NULL);
+
+ /* key (xmlSecBuffer) is located after xmlSecKeyData structure */
+ return((xmlSecBufferPtr)(((xmlSecByte*)data) + sizeof(xmlSecKeyData)));
+}
+
+/**
+ * xmlSecKeyDataBinaryValueSetBuffer:
+ * @data: the pointer to binary key data.
+ * @buf: the pointer to binary buffer.
+ * @bufSize: the binary buffer size.
+ *
+ * Sets the value of @data to @buf.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecKeyDataBinaryValueSetBuffer(xmlSecKeyDataPtr data,
+ const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+/***********************************************************************
+ *
+ * Keys Data list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyDataListKlass = {
+ BAD_CAST "key-data-list",
+ (xmlSecPtrDuplicateItemMethod)xmlSecKeyDataDuplicate, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecKeyDataDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecKeyDataDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecKeyDataDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyDataListGetKlass:
+ *
+ * The key data list klass.
+ *
+ * Returns: pointer to the key data list klass.
+ */
+xmlSecPtrListId
+xmlSecKeyDataListGetKlass(void) {
+ return(&xmlSecKeyDataListKlass);
+}
+
+
+/***********************************************************************
+ *
+ * Keys Data Ids list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyDataIdListKlass = {
+ BAD_CAST "key-data-ids-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyDataIdListGetKlass:
+ *
+ * The key data id list klass.
+ *
+ * Returns: pointer to the key data id list klass.
+ */
+xmlSecPtrListId
+xmlSecKeyDataIdListGetKlass(void) {
+ return(&xmlSecKeyDataIdListKlass);
+}
+
+/**
+ * xmlSecKeyDataIdListFind:
+ * @list: the pointer to key data ids list.
+ * @dataId: the key data klass.
+ *
+ * Lookups @dataId in @list.
+ *
+ * Returns: 1 if @dataId is found in the @list, 0 if not and a negative
+ * value if an error occurs.
+ */
+int
+xmlSecKeyDataIdListFind(xmlSecPtrListPtr list, xmlSecKeyDataId dataId) {
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), 0);
+ xmlSecAssert2(dataId != NULL, 0);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ if((xmlSecKeyDataId)xmlSecPtrListGetItem(list, i) == dataId) {
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecKeyDataIdListFindByNode:
+ * @list: the pointer to key data ids list.
+ * @nodeName: the desired key data klass XML node name.
+ * @nodeNs: the desired key data klass XML node namespace.
+ * @usage: the desired key data usage.
+ *
+ * Lookups data klass in the list with given @nodeName, @nodeNs and
+ * @usage in the @list.
+ *
+ * Returns: key data klass is found and NULL otherwise.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataIdListFindByNode(xmlSecPtrListPtr list, const xmlChar* nodeName,
+ const xmlChar* nodeNs, xmlSecKeyDataUsage usage) {
+ xmlSecKeyDataId dataId;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), xmlSecKeyDataIdUnknown);
+ xmlSecAssert2(nodeName != NULL, xmlSecKeyDataIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, xmlSecKeyDataIdUnknown);
+
+ if(((usage & dataId->usage) != 0) &&
+ xmlStrEqual(nodeName, dataId->dataNodeName) &&
+ xmlStrEqual(nodeNs, dataId->dataNodeNs)) {
+
+ return(dataId);
+ }
+ }
+ return(xmlSecKeyDataIdUnknown);
+}
+
+/**
+ * xmlSecKeyDataIdListFindByHref:
+ * @list: the pointer to key data ids list.
+ * @href: the desired key data klass href.
+ * @usage: the desired key data usage.
+ *
+ * Lookups data klass in the list with given @href and @usage in @list.
+ *
+ * Returns: key data klass is found and NULL otherwise.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataIdListFindByHref(xmlSecPtrListPtr list, const xmlChar* href,
+ xmlSecKeyDataUsage usage) {
+ xmlSecKeyDataId dataId;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), xmlSecKeyDataIdUnknown);
+ xmlSecAssert2(href != NULL, xmlSecKeyDataIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, xmlSecKeyDataIdUnknown);
+
+ if(((usage & dataId->usage) != 0) && (dataId->href != NULL) &&
+ xmlStrEqual(href, dataId->href)) {
+
+ return(dataId);
+ }
+ }
+ return(xmlSecKeyDataIdUnknown);
+}
+
+/**
+ * xmlSecKeyDataIdListFindByName:
+ * @list: the pointer to key data ids list.
+ * @name: the desired key data klass name.
+ * @usage: the desired key data usage.
+ *
+ * Lookups data klass in the list with given @name and @usage in @list.
+ *
+ * Returns: key data klass is found and NULL otherwise.
+ */
+xmlSecKeyDataId
+xmlSecKeyDataIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name,
+ xmlSecKeyDataUsage usage) {
+ xmlSecKeyDataId dataId;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), xmlSecKeyDataIdUnknown);
+ xmlSecAssert2(name != NULL, xmlSecKeyDataIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, xmlSecKeyDataIdUnknown);
+
+ if(((usage & dataId->usage) != 0) && (dataId->name != NULL) &&
+ xmlStrEqual(name, BAD_CAST dataId->name)) {
+
+ return(dataId);
+ }
+ }
+ return(xmlSecKeyDataIdUnknown);
+}
+
+/**
+ * xmlSecKeyDataIdListDebugDump:
+ * @list: the pointer to key data ids list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints binary key data debug information to @output.
+ */
+void
+xmlSecKeyDataIdListDebugDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecKeyDataId dataId;
+ xmlSecSize i, size;
+
+ xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId));
+ xmlSecAssert(output != NULL);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert(dataId != NULL);
+ xmlSecAssert(dataId->name != NULL);
+
+ if(i > 0) {
+ fprintf(output, ",\"%s\"", dataId->name);
+ } else {
+ fprintf(output, "\"%s\"", dataId->name);
+ }
+ }
+ fprintf(output, "\n");
+}
+
+/**
+ * xmlSecKeyDataIdListDebugXmlDump:
+ * @list: the pointer to key data ids list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints binary key data debug information to @output in XML format.
+ */
+void
+xmlSecKeyDataIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecKeyDataId dataId;
+ xmlSecSize i, size;
+
+ xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<KeyDataIdsList>\n");
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert(dataId != NULL);
+ xmlSecAssert(dataId->name != NULL);
+
+ fprintf(output, "<DataId name=\"");
+ xmlSecPrintXmlString(output, dataId->name);
+ fprintf(output, "\"/>");
+ }
+ fprintf(output, "</KeyDataIdsList>\n");
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyDataStore functions
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyDataStoreCreate:
+ * @id: the store id.
+ *
+ * Creates new key data store of the specified klass @id. Caller is responsible
+ * for freeng returned object with #xmlSecKeyDataStoreDestroy function.
+ *
+ * Returns: the pointer to newly allocated key data store structure
+ * or NULL if an error occurs.
+ */
+xmlSecKeyDataStorePtr
+xmlSecKeyDataStoreCreate(xmlSecKeyDataStoreId id) {
+ xmlSecKeyDataStorePtr store;
+ int ret;
+
+ xmlSecAssert2(id != NULL, NULL);
+ xmlSecAssert2(id->objSize > 0, NULL);
+
+ /* Allocate a new xmlSecKeyDataStore and fill the fields. */
+ store = (xmlSecKeyDataStorePtr)xmlMalloc(id->objSize);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", id->objSize);
+ return(NULL);
+ }
+ memset(store, 0, id->objSize);
+ store->id = id;
+
+ if(id->initialize != NULL) {
+ ret = (id->initialize)(store);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreKlassGetName(id)),
+ "id->initialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataStoreDestroy(store);
+ return(NULL);
+ }
+ }
+
+ return(store);
+}
+
+/**
+ * xmlSecKeyDataStoreDestroy:
+ * @store: the pointer to the key data store..
+ *
+ * Destroys the key data store created with #xmlSecKeyDataStoreCreate
+ * function.
+ */
+void
+xmlSecKeyDataStoreDestroy(xmlSecKeyDataStorePtr store) {
+ xmlSecAssert(xmlSecKeyDataStoreIsValid(store));
+ xmlSecAssert(store->id->objSize > 0);
+
+ if(store->id->finalize != NULL) {
+ (store->id->finalize)(store);
+ }
+ memset(store, 0, store->id->objSize);
+ xmlFree(store);
+}
+
+/***********************************************************************
+ *
+ * Keys Data Store list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyDataStorePtrListKlass = {
+ BAD_CAST "keys-data-store-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecKeyDataStoreDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyDataStorePtrListGetKlass:
+ *
+ * Key data stores list.
+ *
+ * Returns: key data stores list klass.
+ */
+xmlSecPtrListId
+xmlSecKeyDataStorePtrListGetKlass(void) {
+ return(&xmlSecKeyDataStorePtrListKlass);
+}
+
+
diff --git a/src/keysmngr.c b/src/keysmngr.c
new file mode 100644
index 00000000..e93cbb49
--- /dev/null
+++ b/src/keysmngr.c
@@ -0,0 +1,745 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Keys Manager
+ *
+ * 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 <errno.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/list.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/errors.h>
+
+/****************************************************************************
+ *
+ * Keys Manager
+ *
+ ***************************************************************************/
+/**
+ * xmlSecKeysMngrCreate:
+ *
+ * Creates new keys manager. Caller is responsible for freeing it with
+ * #xmlSecKeysMngrDestroy function.
+ *
+ * Returns: the pointer to newly allocated keys manager or NULL if
+ * an error occurs.
+ */
+xmlSecKeysMngrPtr
+xmlSecKeysMngrCreate(void) {
+ xmlSecKeysMngrPtr mngr;
+ int ret;
+
+ /* Allocate a new xmlSecKeysMngr and fill the fields. */
+ mngr = (xmlSecKeysMngrPtr)xmlMalloc(sizeof(xmlSecKeysMngr));
+ if(mngr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecKeysMngr)=%d",
+ sizeof(xmlSecKeysMngr));
+ return(NULL);
+ }
+ memset(mngr, 0, sizeof(xmlSecKeysMngr));
+
+ ret = xmlSecPtrListInitialize(&(mngr->storesList), xmlSecKeyDataStorePtrListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyDataStorePtrListId");
+ return(NULL);
+ }
+
+ return(mngr);
+}
+
+/**
+ * xmlSecKeysMngrDestroy:
+ * @mngr: the pointer to keys manager.
+ *
+ * Destroys keys manager created with #xmlSecKeysMngrCreate function.
+ */
+void
+xmlSecKeysMngrDestroy(xmlSecKeysMngrPtr mngr) {
+ xmlSecAssert(mngr != NULL);
+
+ /* destroy keys store */
+ if(mngr->keysStore != NULL) {
+ xmlSecKeyStoreDestroy(mngr->keysStore);
+ }
+
+ /* destroy other data stores */
+ xmlSecPtrListFinalize(&(mngr->storesList));
+
+ memset(mngr, 0, sizeof(xmlSecKeysMngr));
+ xmlFree(mngr);
+}
+
+/**
+ * xmlSecKeysMngrFindKey:
+ * @mngr: the pointer to keys manager.
+ * @name: the desired key name.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context.
+ *
+ * Lookups key in the keys manager keys store. The caller is responsible
+ * for destroying the returned key using #xmlSecKeyDestroy method.
+ *
+ * Returns: the pointer to a key or NULL if key is not found or an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeysMngrFindKey(xmlSecKeysMngrPtr mngr, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyStorePtr store;
+
+ xmlSecAssert2(mngr != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ /* no store. is it an error? */
+ return(NULL);
+ }
+
+ return(xmlSecKeyStoreFindKey(store, name, keyInfoCtx));
+}
+
+/**
+ * xmlSecKeysMngrAdoptKeysStore:
+ * @mngr: the pointer to keys manager.
+ * @store: the pointer to keys store.
+ *
+ * Adopts keys store in the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeysMngrAdoptKeysStore(xmlSecKeysMngrPtr mngr, xmlSecKeyStorePtr store) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(xmlSecKeyStoreIsValid(store), -1);
+
+ if(mngr->keysStore != NULL) {
+ xmlSecKeyStoreDestroy(mngr->keysStore);
+ }
+ mngr->keysStore = store;
+
+ return(0);
+}
+
+/**
+ * xmlSecKeysMngrGetKeysStore:
+ * @mngr: the pointer to keys manager.
+ *
+ * Gets the keys store.
+ *
+ * Returns: the keys store in the keys manager @mngr or NULL if
+ * there is no store or an error occurs.
+ */
+xmlSecKeyStorePtr
+xmlSecKeysMngrGetKeysStore(xmlSecKeysMngrPtr mngr) {
+ xmlSecAssert2(mngr != NULL, NULL);
+
+ return(mngr->keysStore);
+}
+
+/**
+ * xmlSecKeysMngrAdoptDataStore:
+ * @mngr: the pointer to keys manager.
+ * @store: the pointer to data store.
+ *
+ * Adopts data store in the keys manager.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecKeysMngrAdoptDataStore(xmlSecKeysMngrPtr mngr, xmlSecKeyDataStorePtr store) {
+ xmlSecKeyDataStorePtr tmp;
+ xmlSecSize pos, size;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataStoreIsValid(store), -1);
+
+ size = xmlSecPtrListGetSize(&(mngr->storesList));
+ for(pos = 0; pos < size; ++pos) {
+ tmp = (xmlSecKeyDataStorePtr)xmlSecPtrListGetItem(&(mngr->storesList), pos);
+ if((tmp != NULL) && (tmp->id == store->id)) {
+ return(xmlSecPtrListSet(&(mngr->storesList), store, pos));
+ }
+ }
+
+ return(xmlSecPtrListAdd(&(mngr->storesList), store));
+}
+
+
+/**
+ * xmlSecKeysMngrGetDataStore:
+ * @mngr: the pointer to keys manager.
+ * @id: the desired data store klass.
+ *
+ * Lookups the data store of given klass @id in the keys manager.
+ *
+ * Returns: pointer to data store or NULL if it is not found or an error
+ * occurs.
+ */
+xmlSecKeyDataStorePtr
+xmlSecKeysMngrGetDataStore(xmlSecKeysMngrPtr mngr, xmlSecKeyDataStoreId id) {
+ xmlSecKeyDataStorePtr tmp;
+ xmlSecSize pos, size;
+
+ xmlSecAssert2(mngr != NULL, NULL);
+ xmlSecAssert2(id != xmlSecKeyDataStoreIdUnknown, NULL);
+
+ size = xmlSecPtrListGetSize(&(mngr->storesList));
+ for(pos = 0; pos < size; ++pos) {
+ tmp = (xmlSecKeyDataStorePtr)xmlSecPtrListGetItem(&(mngr->storesList), pos);
+ if((tmp != NULL) && (tmp->id == id)) {
+ return(tmp);
+ }
+ }
+
+ return(NULL);
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyStore functions
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyStoreCreate:
+ * @id: the key store klass.
+ *
+ * Creates new store of the specified klass @klass. Caller is responsible
+ * for freeing the returned store by calling #xmlSecKeyStoreDestroy function.
+ *
+ * Returns: the pointer to newly allocated keys store or NULL if an error occurs.
+ */
+xmlSecKeyStorePtr
+xmlSecKeyStoreCreate(xmlSecKeyStoreId id) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(id != NULL, NULL);
+ xmlSecAssert2(id->objSize > 0, NULL);
+
+ /* Allocate a new xmlSecKeyStore and fill the fields. */
+ store = (xmlSecKeyStorePtr)xmlMalloc(id->objSize);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", id->objSize);
+ return(NULL);
+ }
+ memset(store, 0, id->objSize);
+ store->id = id;
+
+ if(id->initialize != NULL) {
+ ret = (id->initialize)(store);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreKlassGetName(id)),
+ "id->initialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyStoreDestroy(store);
+ return(NULL);
+ }
+ }
+
+ return(store);
+}
+
+/**
+ * xmlSecKeyStoreDestroy:
+ * @store: the pointer to keys store.
+ *
+ * Destroys the store created with #xmlSecKeyStoreCreate function.
+ */
+void
+xmlSecKeyStoreDestroy(xmlSecKeyStorePtr store) {
+ xmlSecAssert(xmlSecKeyStoreIsValid(store));
+ xmlSecAssert(store->id->objSize > 0);
+
+ if(store->id->finalize != NULL) {
+ (store->id->finalize)(store);
+ }
+ memset(store, 0, store->id->objSize);
+ xmlFree(store);
+}
+
+/**
+ * xmlSecKeyStoreFindKey:
+ * @store: the pointer to keys store.
+ * @name: the desired key name.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context.
+ *
+ * Lookups key in the store. The caller is responsible for destroying
+ * the returned key using #xmlSecKeyDestroy method.
+ *
+ * Returns: the pointer to a key or NULL if key is not found or an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecKeyStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecKeyStoreIsValid(store), NULL);
+ xmlSecAssert2(store->id->findKey != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ return(store->id->findKey(store, name, keyInfoCtx));
+}
+
+/****************************************************************************
+ *
+ * Simple Keys Store
+ *
+ * keys list (xmlSecPtrList) is located after xmlSecKeyStore
+ *
+ ***************************************************************************/
+#define xmlSecSimpleKeysStoreSize \
+ (sizeof(xmlSecKeyStore) + sizeof(xmlSecPtrList))
+#define xmlSecSimpleKeysStoreGetList(store) \
+ ((xmlSecKeyStoreCheckSize((store), xmlSecSimpleKeysStoreSize)) ? \
+ (xmlSecPtrListPtr)(((xmlSecByte*)(store)) + sizeof(xmlSecKeyStore)) : \
+ (xmlSecPtrListPtr)NULL)
+
+static int xmlSecSimpleKeysStoreInitialize (xmlSecKeyStorePtr store);
+static void xmlSecSimpleKeysStoreFinalize (xmlSecKeyStorePtr store);
+static xmlSecKeyPtr xmlSecSimpleKeysStoreFindKey (xmlSecKeyStorePtr store,
+ const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyStoreKlass xmlSecSimpleKeysStoreKlass = {
+ sizeof(xmlSecKeyStoreKlass),
+ xmlSecSimpleKeysStoreSize,
+
+ /* data */
+ BAD_CAST "simple-keys-store", /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecSimpleKeysStoreInitialize, /* xmlSecKeyStoreInitializeMethod initialize; */
+ xmlSecSimpleKeysStoreFinalize, /* xmlSecKeyStoreFinalizeMethod finalize; */
+ xmlSecSimpleKeysStoreFindKey, /* xmlSecKeyStoreFindKeyMethod findKey; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecSimpleKeysStoreGetKlass:
+ *
+ * The simple list based keys store klass.
+ *
+ * Returns: simple list based keys store klass.
+ */
+xmlSecKeyStoreId
+xmlSecSimpleKeysStoreGetKlass(void) {
+ return(&xmlSecSimpleKeysStoreKlass);
+}
+
+/**
+ * xmlSecSimpleKeysStoreAdoptKey:
+ * @store: the pointer to simple keys store.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the @store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecSimpleKeysStoreAdoptKey(xmlSecKeyStorePtr store, xmlSecKeyPtr key) {
+ xmlSecPtrListPtr list;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ list = xmlSecSimpleKeysStoreGetList(store);
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), -1);
+
+ ret = xmlSecPtrListAdd(list, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecSimpleKeysStoreLoad:
+ * @store: the pointer to simple keys store.
+ * @uri: the filename.
+ * @keysMngr: the pointer to associated keys manager.
+ *
+ * Reads keys from an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecSimpleKeysStoreLoad(xmlSecKeyStorePtr store, const char *uri,
+ xmlSecKeysMngrPtr keysMngr) {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr cur;
+ xmlSecKeyPtr key;
+ xmlSecKeyInfoCtx keyInfoCtx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ doc = xmlParseFile(uri);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlParseFile",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if(!xmlSecCheckNodeName(root, BAD_CAST "Keys", xmlSecNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(root)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=<xmlsec:Keys>");
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(root->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ keyInfoCtx.mode = xmlSecKeyInfoModeRead;
+ keyInfoCtx.keysMngr = keysMngr;
+ keyInfoCtx.flags = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
+ XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+ keyInfoCtx.keyReq.keyId = xmlSecKeyDataIdUnknown;
+ keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
+ keyInfoCtx.keyReq.keyUsage= xmlSecKeyDataUsageAny;
+
+ ret = xmlSecKeyInfoNodeRead(cur, key, &keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+
+ if(xmlSecKeyIsValid(key)) {
+ ret = xmlSecSimpleKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecSimpleKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ } else {
+ /* we have an unknown key in our file, just ignore it */
+ xmlSecKeyDestroy(key);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ xmlFreeDoc(doc);
+ return(0);
+
+}
+
+/**
+ * xmlSecSimpleKeysStoreSave:
+ * @store: the pointer to simple keys store.
+ * @filename: the filename.
+ * @type: the saved keys type (public, private, ...).
+ *
+ * Writes keys from @store to an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecSimpleKeysStoreSave(xmlSecKeyStorePtr store, const char *filename, xmlSecKeyDataType type) {
+ xmlSecKeyInfoCtx keyInfoCtx;
+ xmlSecPtrListPtr list;
+ xmlSecKeyPtr key;
+ xmlSecSize i, keysSize;
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ xmlSecKeyDataPtr data;
+ xmlSecPtrListPtr idsList;
+ xmlSecKeyDataId dataId;
+ xmlSecSize idsSize, j;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
+ xmlSecAssert2(filename != NULL, -1);
+
+ list = xmlSecSimpleKeysStoreGetList(store);
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), -1);
+
+ /* create doc */
+ doc = xmlSecCreateTree(BAD_CAST "Keys", xmlSecNs);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecCreateTree",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ idsList = xmlSecKeyDataIdsGet();
+ xmlSecAssert2(idsList != NULL, -1);
+
+ keysSize = xmlSecPtrListGetSize(list);
+ idsSize = xmlSecPtrListGetSize(idsList);
+ for(i = 0; i < keysSize; ++i) {
+ key = (xmlSecKeyPtr)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(key != NULL, -1);
+
+ cur = xmlSecAddChild(xmlDocGetRootElement(doc), xmlSecNodeKeyInfo, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ /* special data key name */
+ if(xmlSecKeyGetName(key) != NULL) {
+ if(xmlSecAddChild(cur, xmlSecNodeKeyName, xmlSecDSigNs) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyName));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ }
+
+ /* create nodes for other keys data */
+ for(j = 0; j < idsSize; ++j) {
+ dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(idsList, j);
+ xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, -1);
+
+ if(dataId->dataNodeName == NULL) {
+ continue;
+ }
+
+ data = xmlSecKeyGetData(key, dataId);
+ if(data == NULL) {
+ continue;
+ }
+
+ if(xmlSecAddChild(cur, dataId->dataNodeName, dataId->dataNodeNs) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(dataId->dataNodeName));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ keyInfoCtx.mode = xmlSecKeyInfoModeWrite;
+ keyInfoCtx.keyReq.keyId = xmlSecKeyDataIdUnknown;
+ keyInfoCtx.keyReq.keyType = type;
+ keyInfoCtx.keyReq.keyUsage = xmlSecKeyDataUsageAny;
+
+ /* finally write key in the node */
+ ret = xmlSecKeyInfoNodeWrite(cur, key, &keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ }
+
+ /* now write result */
+ ret = xmlSaveFormatFile(filename, doc, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSaveFormatFile",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ xmlFreeDoc(doc);
+ return(0);
+}
+
+/**
+ * xmlSecSimpleKeysStoreGetKeys:
+ * @store: the pointer to simple keys store.
+ *
+ * Gets list of keys from simple keys store.
+ *
+ * Returns: pointer to the list of keys stored in the keys store or NULL
+ * if an error occurs.
+ */
+xmlSecPtrListPtr
+xmlSecSimpleKeysStoreGetKeys(xmlSecKeyStorePtr store) {
+ xmlSecPtrListPtr list;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), NULL);
+
+ list = xmlSecSimpleKeysStoreGetList(store);
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), NULL);
+
+ return list;
+}
+
+static int
+xmlSecSimpleKeysStoreInitialize(xmlSecKeyStorePtr store) {
+ xmlSecPtrListPtr list;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
+
+ list = xmlSecSimpleKeysStoreGetList(store);
+ xmlSecAssert2(list != NULL, -1);
+
+ ret = xmlSecPtrListInitialize(list, xmlSecKeyPtrListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecKeyPtrListId");
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecSimpleKeysStoreFinalize(xmlSecKeyStorePtr store) {
+ xmlSecPtrListPtr list;
+
+ xmlSecAssert(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId));
+
+ list = xmlSecSimpleKeysStoreGetList(store);
+ xmlSecAssert(list != NULL);
+
+ xmlSecPtrListFinalize(list);
+}
+
+static xmlSecKeyPtr
+xmlSecSimpleKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecPtrListPtr list;
+ xmlSecKeyPtr key;
+ xmlSecSize pos, size;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ list = xmlSecSimpleKeysStoreGetList(store);
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), NULL);
+
+ size = xmlSecPtrListGetSize(list);
+ for(pos = 0; pos < size; ++pos) {
+ key = (xmlSecKeyPtr)xmlSecPtrListGetItem(list, pos);
+ if((key != NULL) && (xmlSecKeyMatch(key, name, &(keyInfoCtx->keyReq)) == 1)) {
+ return(xmlSecKeyDuplicate(key));
+ }
+ }
+ return(NULL);
+}
+
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 00000000..a4b6ad54
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,508 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * List of pointers.
+ *
+ * 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/list.h>
+#include <xmlsec/errors.h>
+
+
+static int xmlSecPtrListEnsureSize (xmlSecPtrListPtr list,
+ xmlSecSize size);
+
+static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble;
+static xmlSecSize gInitialSize = 64;
+
+/**
+ * xmlSecPtrListSetDefaultAllocMode:
+ * @defAllocMode: the new default memory allocation mode.
+ * @defInitialSize: the new default minimal initial size.
+ *
+ * Sets new default allocation mode and minimal initial list size.
+ */
+void
+xmlSecPtrListSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) {
+ xmlSecAssert(defInitialSize > 0);
+
+ gAllocMode = defAllocMode;
+ gInitialSize = defInitialSize;
+}
+
+/**
+ * xmlSecPtrListCreate:
+ * @id: the list klass.
+ *
+ * Creates new list object. Caller is responsible for freeing returned list
+ * by calling #xmlSecPtrListDestroy function.
+ *
+ * Returns: pointer to newly allocated list or NULL if an error occurs.
+ */
+xmlSecPtrListPtr
+xmlSecPtrListCreate(xmlSecPtrListId id) {
+ xmlSecPtrListPtr list;
+ int ret;
+
+ xmlSecAssert2(id != xmlSecPtrListIdUnknown, NULL);
+
+ /* Allocate a new xmlSecPtrList and fill the fields. */
+ list = (xmlSecPtrListPtr)xmlMalloc(sizeof(xmlSecPtrList));
+ if(list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecPtrList)=%d",
+ sizeof(xmlSecPtrList));
+ return(NULL);
+ }
+
+ ret = xmlSecPtrListInitialize(list, id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListKlassGetName(id)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(list);
+ return(NULL);
+ }
+
+ return(list);
+}
+
+/**
+ * xmlSecPtrListDestroy:
+ * @list: the pointer to list.
+ *
+ * Destroys @list created with #xmlSecPtrListCreate function.
+ */
+void
+xmlSecPtrListDestroy(xmlSecPtrListPtr list) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+ xmlSecPtrListFinalize(list);
+ xmlFree(list);
+}
+
+/**
+ * xmlSecPtrListInitialize:
+ * @list: the pointer to list.
+ * @id: the list klass.
+ *
+ * Initializes the list of given klass. Caller is responsible
+ * for cleaning up by calling #xmlSecPtrListFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListInitialize(xmlSecPtrListPtr list, xmlSecPtrListId id) {
+ xmlSecAssert2(id != xmlSecPtrListIdUnknown, -1);
+ xmlSecAssert2(list != NULL, -1);
+
+ memset(list, 0, sizeof(xmlSecPtrList));
+ list->id = id;
+ list->allocMode = gAllocMode;
+
+ return(0);
+}
+
+/**
+ * xmlSecPtrListFinalize:
+ * @list: the pointer to list.
+ *
+ * Cleans up the list initialized with #xmlSecPtrListInitialize
+ * function.
+ */
+void
+xmlSecPtrListFinalize(xmlSecPtrListPtr list) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+
+ xmlSecPtrListEmpty(list);
+ memset(list, 0, sizeof(xmlSecPtrList));
+}
+
+/**
+ * xmlSecPtrListEmpty:
+ * @list: the pointer to list.
+ *
+ * Remove all items from @list (if any).
+ */
+void
+xmlSecPtrListEmpty(xmlSecPtrListPtr list) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+
+ if(list->id->destroyItem != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < list->use; ++pos) {
+ xmlSecAssert(list->data != NULL);
+ if(list->data[pos] != NULL) {
+ list->id->destroyItem(list->data[pos]);
+ }
+ }
+ }
+ if(list->max > 0) {
+ xmlSecAssert(list->data != NULL);
+
+ memset(list->data, 0, sizeof(xmlSecPtr) * list->use);
+ xmlFree(list->data);
+ }
+ list->max = list->use = 0;
+ list->data = NULL;
+}
+
+/**
+ * xmlSecPtrListCopy:
+ * @dst: the pointer to destination list.
+ * @src: the pointer to source list.
+ *
+ * Copies @src list items to @dst list using #duplicateItem method
+ * of the list klass. If #duplicateItem method is NULL then
+ * we jsut copy pointers to items.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListCopy(xmlSecPtrListPtr dst, xmlSecPtrListPtr src) {
+ xmlSecSize i;
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(dst), -1);
+ xmlSecAssert2(xmlSecPtrListIsValid(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ /* allocate memory */
+ ret = xmlSecPtrListEnsureSize(dst, dst->use + src->use);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(src)),
+ "xmlSecPtrListEnsureSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", src->use);
+ return(-1);
+ }
+
+ /* copy one item after another */
+ for(i = 0; i < src->use; ++i, ++dst->use) {
+ xmlSecAssert2(src->data != NULL, -1);
+ xmlSecAssert2(dst->data != NULL, -1);
+
+ if((dst->id->duplicateItem != NULL) && (src->data[i] != NULL)) {
+ dst->data[dst->use] = dst->id->duplicateItem(src->data[i]);
+ if(dst->data[dst->use] == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(src)),
+ "duplicateItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ dst->data[dst->use] = src->data[i];
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecPtrListDuplicate:
+ * @list: the pointer to list.
+ *
+ * Creates a new copy of @list and all its items.
+ *
+ * Returns: pointer to newly allocated list or NULL if an error occurs.
+ */
+xmlSecPtrListPtr
+xmlSecPtrListDuplicate(xmlSecPtrListPtr list) {
+ xmlSecPtrListPtr newList;
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+
+ newList = xmlSecPtrListCreate(list->id);
+ if(newList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ "xmlSecPtrListCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecPtrListCopy(newList, list);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecPtrListDestroy(newList);
+ return(NULL);
+ }
+ return(newList);
+}
+
+/**
+ * xmlSecPtrListGetSize:
+ * @list: the pointer to list.
+ *
+ * Gets list size.
+ *
+ * Returns: the number of itmes in @list.
+ */
+xmlSecSize
+xmlSecPtrListGetSize(xmlSecPtrListPtr list) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), 0);
+
+ return(list->use);
+}
+
+/**
+ * xmlSecPtrListGetItem:
+ * @list: the pointer to list.
+ * @pos: the item position.
+ *
+ * Gets item from the list.
+ *
+ * Returns: the list item at position @pos or NULL if @pos is greater
+ * than the number of items in the list or an error occurs.
+ */
+xmlSecPtr
+xmlSecPtrListGetItem(xmlSecPtrListPtr list, xmlSecSize pos) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+ xmlSecAssert2(list->data != NULL, NULL);
+ xmlSecAssert2(pos < list->use, NULL);
+
+ return(list->data[pos]);
+}
+
+/**
+ * xmlSecPtrListAdd:
+ * @list: the pointer to list.
+ * @item: the item.
+ *
+ * Adds @item to the end of the @list.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListAdd(xmlSecPtrListPtr list, xmlSecPtr item) {
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+
+ ret = xmlSecPtrListEnsureSize(list, list->use + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", list->use + 1);
+ return(-1);
+ }
+
+ list->data[list->use++] = item;
+ return(0);
+}
+
+/**
+ * xmlSecPtrListSet:
+ * @list: the pointer to list.
+ * @item: the item.
+ * @pos: the pos.
+ *
+ * Sets the value of list item at position @pos. The old value
+ * is destroyed.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListSet(xmlSecPtrListPtr list, xmlSecPtr item, xmlSecSize pos) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+ xmlSecAssert2(list->data != NULL, -1);
+ xmlSecAssert2(pos < list->use, -1);
+
+ if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) {
+ list->id->destroyItem(list->data[pos]);
+ }
+ list->data[pos] = item;
+ return(0);
+}
+
+/**
+ * xmlSecPtrListRemove:
+ * @list: the pointer to list.
+ * @pos: the position.
+ *
+ * Destroys list item at the position @pos and sets it value to NULL.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListRemove(xmlSecPtrListPtr list, xmlSecSize pos) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+ xmlSecAssert2(list->data != NULL, -1);
+ xmlSecAssert2(pos < list->use, -1);
+
+ if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) {
+ list->id->destroyItem(list->data[pos]);
+ }
+ list->data[pos] = NULL;
+ if(pos == list->use - 1) {
+ --list->use;
+ }
+ return(0);
+}
+
+/**
+ * xmlSecPtrListDebugDump:
+ * @list: the pointer to list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @list to the @output.
+ */
+void
+xmlSecPtrListDebugDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== list size: %d\n", list->use);
+ if(list->id->debugDumpItem != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < list->use; ++pos) {
+ xmlSecAssert(list->data != NULL);
+ if(list->data[pos] != NULL) {
+ list->id->debugDumpItem(list->data[pos], output);
+ }
+ }
+ }
+}
+
+/**
+ * xmlSecPtrListDebugXmlDump:
+ * @list: the pointer to list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @list to the @output in XML format.
+ */
+void
+xmlSecPtrListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<List size=\"%d\">\n", list->use);
+ if(list->id->debugXmlDumpItem != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < list->use; ++pos) {
+ xmlSecAssert(list->data != NULL);
+ if(list->data[pos] != NULL) {
+ list->id->debugXmlDumpItem(list->data[pos], output);
+ }
+ }
+ }
+ fprintf(output, "</List>\n");
+}
+
+static int
+xmlSecPtrListEnsureSize(xmlSecPtrListPtr list, xmlSecSize size) {
+ xmlSecPtr* newData;
+ xmlSecSize newSize = 0;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+
+ if(size < list->max) {
+ return(0);
+ }
+
+ switch(list->allocMode) {
+ case xmlSecAllocModeExact:
+ newSize = size + 8;
+ break;
+ case xmlSecAllocModeDouble:
+ newSize = 2 * size + 32;
+ break;
+ }
+
+ if(newSize < gInitialSize) {
+ newSize = gInitialSize;
+ }
+
+ if(list->data != NULL) {
+ newData = (xmlSecPtr*)xmlRealloc(list->data, sizeof(xmlSecPtr) * newSize);
+ } else {
+ newData = (xmlSecPtr*)xmlMalloc(sizeof(xmlSecPtr) * newSize);
+ }
+ if(newData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecPtr)*%d=%d",
+ newSize, sizeof(xmlSecPtr) * newSize);
+ return(-1);
+ }
+
+ list->data = newData;
+ list->max = newSize;
+
+ return(0);
+}
+
+/***********************************************************************
+ *
+ * strings list
+ *
+ **********************************************************************/
+static xmlSecPtr xmlSecStringListDuplicateItem (xmlSecPtr ptr);
+static void xmlSecStringListDestroyItem (xmlSecPtr ptr);
+
+static xmlSecPtrListKlass xmlSecStringListKlass = {
+ BAD_CAST "strings-list",
+ xmlSecStringListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ xmlSecStringListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecStringListGetKlass:
+ *
+ * The strins list class.
+ *
+ * Returns: strings list klass.
+ */
+xmlSecPtrListId
+xmlSecStringListGetKlass(void) {
+ return(&xmlSecStringListKlass);
+}
+
+static xmlSecPtr
+xmlSecStringListDuplicateItem(xmlSecPtr ptr) {
+ xmlSecAssert2(ptr != NULL, NULL);
+
+ return(xmlStrdup((xmlChar*)ptr));
+}
+
+static void
+xmlSecStringListDestroyItem(xmlSecPtr ptr) {
+ xmlSecAssert(ptr != NULL);
+
+ xmlFree(ptr);
+}
+
+
diff --git a/src/membuf.c b/src/membuf.c
new file mode 100644
index 00000000..55053253
--- /dev/null
+++ b/src/membuf.c
@@ -0,0 +1,209 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Memory buffer transform
+ *
+ * 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/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/membuf.h>
+#include <xmlsec/errors.h>
+
+
+/*****************************************************************************
+ *
+ * Memory Buffer Transform
+ *
+ * xmlSecBuffer is located after xmlSecTransform
+ *
+ ****************************************************************************/
+#define xmlSecTransformMemBufSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
+#define xmlSecTransformMemBufGetBuf(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecTransformMemBufSize)) ? \
+ (xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlSecBufferPtr)NULL)
+
+static int xmlSecTransformMemBufInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformMemBufFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformMemBufExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecTransformMemBufKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecTransformMemBufSize, /* xmlSecSize objSize */
+
+ xmlSecNameMemBuf, /* const xmlChar* name; */
+ NULL, /* const xmlChar* href; */
+ 0, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecTransformMemBufInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformMemBufFinalize, /* xmlSecTransformFianlizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformMemBufExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformMemBufGetKlass:
+ *
+ * The memory buffer transorm (used to store the data that go through it).
+ *
+ * Returns: memory buffer transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformMemBufGetKlass(void) {
+ return(&xmlSecTransformMemBufKlass);
+}
+
+/**
+ * xmlSecTransformMemBufGetBuffer:
+ * @transform: the pointer to memory buffer transform.
+ *
+ * Gets the pointer to memory buffer transform buffer.
+ *
+ * Returns: pointer to the transform's #xmlSecBuffer.
+ */
+xmlSecBufferPtr
+xmlSecTransformMemBufGetBuffer(xmlSecTransformPtr transform) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformMemBufId), NULL);
+
+ buffer = xmlSecTransformMemBufGetBuf(transform);
+ xmlSecAssert2(buffer != NULL, NULL);
+
+ return(buffer);
+}
+
+static int
+xmlSecTransformMemBufInitialize(xmlSecTransformPtr transform) {
+ xmlSecBufferPtr buffer;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformMemBufId), -1);
+
+ buffer = xmlSecTransformMemBufGetBuf(transform);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ ret = xmlSecBufferInitialize(buffer, 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
+xmlSecTransformMemBufFinalize(xmlSecTransformPtr transform) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformMemBufId));
+
+ buffer = xmlSecTransformMemBufGetBuf(transform);
+ xmlSecAssert(buffer != NULL);
+
+ xmlSecBufferFinalize(xmlSecTransformMemBufGetBuf(transform));
+}
+
+static int
+xmlSecTransformMemBufExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBufferPtr buffer;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformMemBufId), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ buffer = xmlSecTransformMemBufGetBuf(transform);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ /* just copy everything from in to our buffer and out */
+ ret = xmlSecBufferAppend(buffer, xmlSecBufferGetData(in), inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferAppend(out, xmlSecBufferGetData(in), inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ 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);
+ }
+
+ if(last != 0) {
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(inSize == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
diff --git a/src/mscrypto/Makefile.am b/src/mscrypto/Makefile.am
new file mode 100644
index 00000000..318af513
--- /dev/null
+++ b/src/mscrypto/Makefile.am
@@ -0,0 +1,58 @@
+NULL =
+
+EXTRA_DIST = \
+ mingw-crypt32.def \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-mscrypto.la \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(MSCRYPTO_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_SOURCES =\
+ app.c \
+ certkeys.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ keysstore.c \
+ kt_rsa.c \
+ signatures.c \
+ symkeys.c \
+ x509.c \
+ x509vfy.c \
+ csp_calg.h \
+ csp_oid.h \
+ globals.h \
+ xmlsec-mingw.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_mscrypto_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_mscrypto_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(MSCRYPTO_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_DEPENDENCIES = \
+ mingw-crypt32.def \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/mscrypto/Makefile.in b/src/mscrypto/Makefile.in
new file mode 100644
index 00000000..61a9b6f3
--- /dev/null
+++ b/src/mscrypto/Makefile.in
@@ -0,0 +1,760 @@
+# Makefile.in generated by automake 1.11 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/mscrypto
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+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_mscrypto_la_SOURCES_DIST = app.c certkeys.c ciphers.c \
+ crypto.c digests.c keysstore.c kt_rsa.c signatures.c symkeys.c \
+ x509.c x509vfy.c csp_calg.h csp_oid.h globals.h xmlsec-mingw.h \
+ ../strings.c
+am__objects_1 =
+@SHAREDLIB_HACK_TRUE@am__objects_2 = \
+@SHAREDLIB_HACK_TRUE@ libxmlsec1_mscrypto_la-strings.lo
+am_libxmlsec1_mscrypto_la_OBJECTS = libxmlsec1_mscrypto_la-app.lo \
+ libxmlsec1_mscrypto_la-certkeys.lo \
+ libxmlsec1_mscrypto_la-ciphers.lo \
+ libxmlsec1_mscrypto_la-crypto.lo \
+ libxmlsec1_mscrypto_la-digests.lo \
+ libxmlsec1_mscrypto_la-keysstore.lo \
+ libxmlsec1_mscrypto_la-kt_rsa.lo \
+ libxmlsec1_mscrypto_la-signatures.lo \
+ libxmlsec1_mscrypto_la-symkeys.lo \
+ libxmlsec1_mscrypto_la-x509.lo \
+ libxmlsec1_mscrypto_la-x509vfy.lo $(am__objects_1) \
+ $(am__objects_2)
+libxmlsec1_mscrypto_la_OBJECTS = $(am_libxmlsec1_mscrypto_la_OBJECTS)
+libxmlsec1_mscrypto_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_mscrypto_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_mscrypto_la_SOURCES)
+DIST_SOURCES = $(am__libxmlsec1_mscrypto_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@
+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@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_ENABLED = @PKG_CONFIG_ENABLED@
+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_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_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 = \
+ mingw-crypt32.def \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-mscrypto.la \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(MSCRYPTO_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_SOURCES = app.c certkeys.c ciphers.c crypto.c \
+ digests.c keysstore.c kt_rsa.c signatures.c symkeys.c x509.c \
+ x509vfy.c csp_calg.h csp_oid.h globals.h xmlsec-mingw.h \
+ $(NULL) $(am__append_1)
+libxmlsec1_mscrypto_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(MSCRYPTO_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_mscrypto_la_DEPENDENCIES = \
+ mingw-crypt32.def \
+ $(NULL)
+
+libxmlsec1_mscrypto_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/mscrypto/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/mscrypto/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-mscrypto.la: $(libxmlsec1_mscrypto_la_OBJECTS) $(libxmlsec1_mscrypto_la_DEPENDENCIES)
+ $(libxmlsec1_mscrypto_la_LINK) -rpath $(libdir) $(libxmlsec1_mscrypto_la_OBJECTS) $(libxmlsec1_mscrypto_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-certkeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-ciphers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-digests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-keysstore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-kt_rsa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-signatures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-symkeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_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_mscrypto_la-app.lo: app.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-app.Tpo -c -o libxmlsec1_mscrypto_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-app.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-app.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+
+libxmlsec1_mscrypto_la-certkeys.lo: certkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-certkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-certkeys.Tpo -c -o libxmlsec1_mscrypto_la-certkeys.lo `test -f 'certkeys.c' || echo '$(srcdir)/'`certkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-certkeys.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-certkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='certkeys.c' object='libxmlsec1_mscrypto_la-certkeys.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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-certkeys.lo `test -f 'certkeys.c' || echo '$(srcdir)/'`certkeys.c
+
+libxmlsec1_mscrypto_la-ciphers.lo: ciphers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-ciphers.Tpo -c -o libxmlsec1_mscrypto_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-ciphers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+
+libxmlsec1_mscrypto_la-crypto.lo: crypto.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-crypto.Tpo -c -o libxmlsec1_mscrypto_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-crypto.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+
+libxmlsec1_mscrypto_la-digests.lo: digests.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-digests.Tpo -c -o libxmlsec1_mscrypto_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-digests.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-digests.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+
+libxmlsec1_mscrypto_la-keysstore.lo: keysstore.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-keysstore.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-keysstore.Tpo -c -o libxmlsec1_mscrypto_la-keysstore.lo `test -f 'keysstore.c' || echo '$(srcdir)/'`keysstore.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-keysstore.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-keysstore.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='keysstore.c' object='libxmlsec1_mscrypto_la-keysstore.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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-keysstore.lo `test -f 'keysstore.c' || echo '$(srcdir)/'`keysstore.c
+
+libxmlsec1_mscrypto_la-kt_rsa.lo: kt_rsa.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-kt_rsa.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-kt_rsa.Tpo -c -o libxmlsec1_mscrypto_la-kt_rsa.lo `test -f 'kt_rsa.c' || echo '$(srcdir)/'`kt_rsa.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-kt_rsa.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-kt_rsa.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kt_rsa.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-kt_rsa.lo `test -f 'kt_rsa.c' || echo '$(srcdir)/'`kt_rsa.c
+
+libxmlsec1_mscrypto_la-signatures.lo: signatures.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-signatures.Tpo -c -o libxmlsec1_mscrypto_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-signatures.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-signatures.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+
+libxmlsec1_mscrypto_la-symkeys.lo: symkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-symkeys.Tpo -c -o libxmlsec1_mscrypto_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-symkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+
+libxmlsec1_mscrypto_la-x509.lo: x509.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-x509.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-x509.Tpo -c -o libxmlsec1_mscrypto_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-x509.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-x509.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+
+libxmlsec1_mscrypto_la-x509vfy.lo: x509vfy.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-x509vfy.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-x509vfy.Tpo -c -o libxmlsec1_mscrypto_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-x509vfy.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-x509vfy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509vfy.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+
+libxmlsec1_mscrypto_la-strings.lo: ../strings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_mscrypto_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-strings.Tpo -c -o libxmlsec1_mscrypto_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-strings.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-strings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_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/mscrypto/README b/src/mscrypto/README
new file mode 100644
index 00000000..f7d45636
--- /dev/null
+++ b/src/mscrypto/README
@@ -0,0 +1,52 @@
+WHAT VERSION OF WINDOWS?
+------------------------------------------------------------------------
+
+The xmlsec-mscrypto lib is developed on a windows XP machine with MS Visual
+Studio (6 and .NET). The MS Crypto API has been evolving a lot with the
+new releases of windows and internet explorer. MS CryptoAPI libraries
+are distributed with ie and with the windows OS. Full functionality will
+only be achieved on windows XP. AES is for example not supported on pre
+XP versions of Windows (workarounds for this are possible, I believe).
+Direct RSA de/encryption, used by xmlsec-mscrypto, is only possible from
+Win 2000 (possibly also with a newer version of ie, with strong encryption
+patch installed). It's very likely more of these issues are lying around, a
+nd until it is tested on older windows systems it is uncertain what will work.
+
+KEYS MANAGER with MS Certificate store support.
+------------------------------------------------------------------------
+
+The default xmlsec-mscrypto keys manager is based upon the simple keys
+store, found in the xmlsec core library. If keys are not found in the
+simple keys store, than MS Certificate store is used to lookup keys.
+The certificate store is only used on a READONLY base, so it is not possible
+to store keys via the keys store into the MS certificate store. There are enough
+other tools that can do that for you.
+
+When the xmlsec application is started, with the config parameter the name of
+the (system) keystore can be given. That keystore will be used for certificates
+and keys lookup. With the keyname now two types of values can be given:
+ - simple name (called friendly name with MS);
+ - full subject name (recommended) of the key's certificate.
+
+KNOWN ISSUES.
+------------------------------------------------------------------------
+1) Default keys manager don't use trusted certs in MS Crypto Store
+(http://bugzilla.gnome.org/show_bug.cgi?id=123668).
+
+2) Missing crypto functionality:
+ - HMAC (http://bugzilla.gnome.org/show_bug.cgi?id=123670): does not look
+ like MS would support it soon.
+ - RSA-OAEP (http://bugzilla.gnome.org/show_bug.cgi?id=123671): MS says
+ that they will support this in the near future.
+ - AES KW (http://bugzilla.gnome.org/show_bug.cgi?id=123672): no native
+ support, might be possible to implement on top of AES cipher itself
+ - DES KW (http://bugzilla.gnome.org/show_bug.cgi?id=123673): no native
+ support, might be possible to implement on top of AES cipher itself
+
+3) Actual AES Crypto provider name is different from the "official" one
+(http://bugzilla.gnome.org/show_bug.cgi?id=123674).
+
+4) The only supported file formats are PKCS#12 and DER certificates
+(http://bugzilla.gnome.org/show_bug.cgi?id=123675).
+
+
diff --git a/src/mscrypto/app.c b/src/mscrypto/app.c
new file mode 100644
index 00000000..c3a4b0d8
--- /dev/null
+++ b/src/mscrypto/app.c
@@ -0,0 +1,1288 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/app.h>
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/certkeys.h>
+#include <xmlsec/mscrypto/keysstore.h>
+#include <xmlsec/mscrypto/x509.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+/* I don't see any other way then to use a global var to get the
+ * config info to the mscrypto keysstore :( WK
+ */
+static char *gXmlSecMSCryptoAppCertStoreName = NULL;
+
+/**
+ * xmlSecMSCryptoAppInit:
+ * @config: the name of another then the default ms certificate store.
+ *
+ * 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
+xmlSecMSCryptoAppInit(const char* config) {
+ /* initialize MSCrypto crypto engine */
+
+ /* config parameter can contain *another* ms certs store name
+ * then the default (MY)
+ */
+ if (NULL != config && strlen(config) > 0) {
+ if (gXmlSecMSCryptoAppCertStoreName) {
+ /* This should not happen, initialize twice */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "config=%s, config already set",
+ xmlSecErrorsSafeString(config));
+ return (-1);
+ }
+ gXmlSecMSCryptoAppCertStoreName = xmlStrdup(config);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppShutdown:
+ *
+ * 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
+xmlSecMSCryptoAppShutdown(void) {
+ /* shutdown MSCrypto crypto engine */
+ if (NULL != gXmlSecMSCryptoAppCertStoreName) {
+ xmlFree(gXmlSecMSCryptoAppCertStoreName);
+ gXmlSecMSCryptoAppCertStoreName = NULL;
+ }
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppGetCertStoreName:
+ *
+ * Gets the MS Crypto certs store name set by @xmlSecMSCryptoAppInit function.
+ *
+ * Returns: the MS Crypto certs name used by xmlsec-mscrypto.
+ */
+const char*
+xmlSecMSCryptoAppGetCertStoreName(void) {
+ return(gXmlSecMSCryptoAppCertStoreName);
+}
+
+/*************************************************************************************
+ * Keys
+ *************************************************************************************/
+
+/**
+ * xmlSecMSCryptoAppKeyLoad:
+ * @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
+xmlSecMSCryptoAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ xmlSecBuffer buffer;
+ xmlSecKeyPtr key = NULL;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch (format) {
+ case xmlSecKeyDataFormatPkcs12:
+ key = xmlSecMSCryptoAppPkcs12Load(filename, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoAppPkcs12Load",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ case xmlSecKeyDataFormatCertDer:
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecBufferReadFile(&buffer, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return (NULL);
+ }
+
+ key = xmlSecMSCryptoAppKeyLoadMemory(xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer), format,
+ pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoAppKeyLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+ xmlSecBufferFinalize(&buffer);
+ break;
+ default:
+ /* Any other format like PEM keys is currently not supported */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+/**
+ * xmlSecMSCryptoAppKeyLoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key data size.
+ * @format: the key format.
+ * @pwd: the key 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
+xmlSecMSCryptoAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ PCCERT_CONTEXT pCert = NULL;
+ PCCERT_CONTEXT tmpcert = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ xmlSecKeyDataPtr keyData = NULL;
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyPtr res = NULL;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 0, NULL);
+ xmlSecAssert2(format == xmlSecKeyDataFormatCertDer, NULL);
+
+ pCert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, data, dataSize);
+ if (NULL == pCert) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertCreateCertificateContext",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecMSCryptoKeyDataX509Id)));
+ goto done;
+ }
+
+ tmpcert = CertDuplicateCertificateContext(pCert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptKeyCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ CertFreeCertificateContext(tmpcert);
+ goto done;
+ }
+ tmpcert = NULL;
+
+ keyData = xmlSecMSCryptoCertAdopt(pCert, xmlSecKeyDataTypePublic);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoCertAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pCert = NULL;
+
+ 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, keyData);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ keyData = NULL;
+
+ ret = xmlSecKeyAdoptData(key, x509Data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyAdoptData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ x509Data = NULL;
+
+ /* success */
+ res = key;
+ key = NULL;
+done:
+ if(pCert != NULL) {
+ CertFreeCertificateContext(pCert);
+ }
+ if(tmpcert != NULL) {
+ CertFreeCertificateContext(tmpcert);
+ }
+ if(x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if(keyData != NULL) {
+ xmlSecKeyDataDestroy(keyData);
+ }
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ return(res);
+}
+
+
+/**********************************************************************************
+ * X509 certificates
+ **********************************************************************************/
+
+#ifndef XMLSEC_NO_X509
+
+/**
+ * xmlSecMSCryptoAppKeyCertLoad:
+ * @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
+xmlSecMSCryptoAppKeyCertLoad(xmlSecKeyPtr key, const char* filename,
+ xmlSecKeyDataFormat format) {
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferReadFile(&buffer, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return (-1);
+ }
+
+ ret = xmlSecMSCryptoAppKeyCertLoadMemory(key, xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer), format);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoAppKeyCertLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ xmlSecBufferFinalize(&buffer);
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppKeyCertLoadMemory:
+ * @key: the pointer to key.
+ * @data: the binary certificate.
+ * @dataSize: size of certificate binary (data)
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from $@data and adds it to key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ PCCERT_CONTEXT pCert;
+ xmlSecKeyDataPtr kdata;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ kdata = xmlSecKeyEnsureData(key, xmlSecMSCryptoKeyDataX509Id);
+ if(kdata == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecMSCryptoKeyDataX509Id)));
+ return(-1);
+ }
+
+ /* For now only DER certificates are supported */
+ /* adjust cert format */
+ switch(format) {
+ case xmlSecKeyDataFormatDer:
+ case xmlSecKeyDataFormatCertDer:
+ pCert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, data, dataSize);
+ if (NULL == pCert) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertCreateCertificateContext",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "format=%d", format);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(kdata, pCert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(kdata)));
+ CertFreeCertificateContext(pCert);
+ return(-1);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", (int)format);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppPkcs12Load:
+ * @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
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecMSCryptoAppPkcs12Load(const char *filename,
+ const char *pwd,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecBuffer buffer;
+ xmlSecKeyPtr key;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(pwd != NULL, NULL);
+
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecBufferReadFile(&buffer, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return (NULL);
+ }
+ if(xmlSecBufferGetData(&buffer) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ key = xmlSecMSCryptoAppPkcs12LoadMemory(xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer), pwd,
+ pwdCallback, pwdCallbackCtx);
+ if (key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoAppPkcs12LoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ xmlSecBufferFinalize(&buffer);
+ return(key);
+}
+
+/**
+ * xmlSecMSCryptoAppPkcs12LoadMemory:
+ * @data: the binary PKCS12 key in data.
+ * @dataSize: size of binary pkcs12 data
+ * @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 binary
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecMSCryptoAppPkcs12LoadMemory(const xmlSecByte* data,
+ xmlSecSize dataSize,
+ const char *pwd,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ int ret, len;
+ CRYPT_DATA_BLOB pfx;
+ HCERTSTORE hCertStore = NULL;
+ PCCERT_CONTEXT tmpcert = NULL;
+ PCCERT_CONTEXT pCert = NULL;
+ WCHAR* wcPwd = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ xmlSecKeyDataPtr keyData = NULL;
+ xmlSecKeyPtr key = NULL;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 1, NULL);
+ xmlSecAssert2(pwd != NULL, NULL);
+
+ memset(&pfx, 0, sizeof(pfx));
+ pfx.pbData = (BYTE *)data;
+ pfx.cbData = dataSize;
+
+ if(FALSE == PFXIsPFXBlob(&pfx)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PFXIsPFXBlob",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%ld",
+ pfx.cbData);
+ goto done;
+ }
+
+ len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pwd, -1, NULL, 0);
+ if(len <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "MultiByteToWideChar",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ wcPwd = (WCHAR *)xmlMalloc((len + 1) * sizeof(WCHAR));
+ if(wcPwd == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "len=%d", len);
+ goto done;
+ }
+
+ ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pwd, -1, wcPwd, len);
+ if (ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "MultiByteToWideChar",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ if (FALSE == PFXVerifyPassword(&pfx, wcPwd, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PFXVerifyPassword",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ hCertStore = PFXImportCertStore(&pfx, wcPwd, CRYPT_EXPORTABLE);
+ if (NULL == hCertStore) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PFXImportCertStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecMSCryptoKeyDataX509Id)));
+ goto done;
+ }
+
+ while (pCert = CertEnumCertificatesInStore(hCertStore, pCert)) {
+ DWORD dwData = 0;
+ DWORD dwDataLen = sizeof(DWORD);
+
+ /* Find the certificate that has the private key */
+ if((TRUE == CertGetCertificateContextProperty(pCert, CERT_KEY_SPEC_PROP_ID, &dwData, &dwDataLen)) && (dwData > 0)) {
+ tmpcert = CertDuplicateCertificateContext(pCert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ keyData = xmlSecMSCryptoCertAdopt(tmpcert, xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoCertAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ tmpcert = NULL;
+
+ tmpcert = CertDuplicateCertificateContext(pCert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptKeyCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ tmpcert = NULL;
+ }
+
+ /* load certificate in the x509 key data */
+ tmpcert = CertDuplicateCertificateContext(pCert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ tmpcert = NULL;
+ }
+
+ if (keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoAppPkcs12Load",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "private key not found in PKCS12 file");
+ 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, keyData);
+ 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;
+ }
+ keyData = 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(hCertStore != NULL) {
+ CertCloseStore(hCertStore, 0);
+ }
+ if(wcPwd != NULL) {
+ xmlFree(wcPwd);
+ }
+ if(x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if(keyData != NULL) {
+ xmlSecKeyDataDestroy(keyData);
+ }
+ if(tmpcert != NULL) {
+ CertFreeCertificateContext(tmpcert);
+ }
+ return(key);
+}
+
+/**
+ * xmlSecMSCryptoAppKeysMngrCertLoad:
+ * @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 (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferReadFile(&buffer, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return (-1);
+ }
+
+ ret = xmlSecMSCryptoAppKeysMngrCertLoadMemory(mngr, xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer), format, type);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoAppKeysMngrCertLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ xmlSecBufferFinalize(&buffer);
+ return(ret);
+}
+
+/**
+ * xmlSecMSCryptoAppKeysMngrCertLoadMemory:
+ * @mngr: the keys manager.
+ * @data: the binary certificate.
+ * @dataSize: size of binary certificate (data)
+ * @format: the certificate file format.
+ * @type: the flag that indicates is the certificate in @filename
+ * trusted or not.
+ *
+ * Reads cert from @data and adds to the list of trusted or known
+ * untrusted certs in @store.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecKeyDataStorePtr x509Store;
+ PCCERT_CONTEXT pCert = NULL;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCryptoX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecMSCryptoX509StoreId");
+ return(-1);
+ }
+
+ switch (format) {
+ case xmlSecKeyDataFormatDer:
+ case xmlSecKeyDataFormatCertDer:
+ pCert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ data, dataSize);
+ if (NULL == pCert) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertCreateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(-1);
+ }
+
+ xmlSecAssert2(pCert != NULL, -1);
+ ret = xmlSecMSCryptoX509StoreAdoptCert(x509Store, pCert, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509StoreAdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(pCert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrAdoptKeyStore:
+ * @mngr: the keys manager.
+ * @keyStore: the pointer to keys store.
+ *
+ * Adds @keyStore to the list of key stores in the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrAdoptKeyStore(xmlSecKeysMngrPtr mngr, HCERTSTORE keyStore)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2( mngr != NULL, -1 ) ;
+ xmlSecAssert2( keyStore != NULL, -1 ) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore( mngr, xmlSecMSCryptoX509StoreId) ;
+ if( x509Store == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecKeysMngrGetDataStore" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1) ;
+ }
+
+ if( xmlSecMSCryptoX509StoreAdoptKeyStore( x509Store, keyStore ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataStoreGetName( x509Store ) ) ,
+ "xmlSecMSCryptoX509StoreAdoptKeyStore" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1) ;
+ }
+
+ return (0) ;
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrAdoptTrustedStore:
+ * @mngr: the keys manager.
+ * @trustedStore: the pointer to certs store.
+ *
+ * Adds @trustedStore to the list of trusted cert stores in the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrAdoptTrustedStore(xmlSecKeysMngrPtr mngr, HCERTSTORE trustedStore)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2( mngr != NULL, -1 ) ;
+ xmlSecAssert2( trustedStore != NULL, -1 ) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore( mngr, xmlSecMSCryptoX509StoreId ) ;
+ if( x509Store == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecKeysMngrGetDataStore" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1) ;
+ }
+
+ if( xmlSecMSCryptoX509StoreAdoptTrustedStore( x509Store, trustedStore ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataStoreGetName( x509Store ) ) ,
+ "xmlSecMSCryptoX509StoreAdoptKeyStore" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1) ;
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrAdoptUntrustedStore:
+ * @mngr: the keys manager.
+ * @untrustedStore: the pointer to certs store.
+ *
+ * Adds @trustedStore to the list of un-trusted cert stores in the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrAdoptUntrustedStore(xmlSecKeysMngrPtr mngr, HCERTSTORE untrustedStore)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2( mngr != NULL, -1 ) ;
+ xmlSecAssert2( untrustedStore != NULL, -1 ) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore( mngr, xmlSecMSCryptoX509StoreId);
+ if( x509Store == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecKeysMngrGetDataStore" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecMSCryptoX509StoreAdoptUntrustedStore( x509Store, untrustedStore ) < 0) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataStoreGetName( x509Store ) ) ,
+ "xmlSecMSCryptoX509StoreAdoptKeyStore" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ return(0) ;
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId
+ * and a default MSCrypto crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* create MSCrypto keys store if needed */
+ if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) {
+ xmlSecKeyStorePtr keysStore;
+
+ keysStore = xmlSecKeyStoreCreate(xmlSecMSCryptoKeysStoreId);
+ if(keysStore == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecMSCryptoKeysStoreId");
+ 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 = xmlSecMSCryptoKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecMSCryptoAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrAdoptKey(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 = xmlSecMSCryptoKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecMSCryptoAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrLoad(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 = xmlSecMSCryptoKeysStoreLoad(store, uri, mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeysStoreLoad",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s", xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrSave:
+ * @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
+xmlSecMSCryptoAppDefaultKeysMngrSave(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 = xmlSecMSCryptoKeysStoreSave(store, filename, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeysStoreSave",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename%s", xmlSecErrorsSafeString(filename));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrPrivateKeyLoad:
+ * @mngr: the pointer to keys manager.
+ * @hKey: the key handle.
+ *
+ * Adds private key @hKey to the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrPrivateKeyLoad(xmlSecKeysMngrPtr mngr, HCRYPTKEY hKey) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(hKey != 0, -1);
+
+ /* TODO */
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrPublicKeyLoad:
+ * @mngr: the pointer to keys manager.
+ * @hKey: the key handle.
+ *
+ * Adds public key @hKey to the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrPublicKeyLoad(xmlSecKeysMngrPtr mngr, HCRYPTKEY hKey) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(hKey != 0, -1);
+
+ /* TODO */
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppDefaultKeysMngrSymKeyLoad:
+ * @mngr: the pointer to keys manager.
+ * @hKey: the key handle.
+ *
+ * Adds symmetric key @hKey to the keys manager @mngr.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoAppDefaultKeysMngrSymKeyLoad(xmlSecKeysMngrPtr mngr, HCRYPTKEY hKey) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(hKey != 0, -1);
+
+ /* TODO */
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecMSCryptoAppGetDefaultPwdCallback(void) {
+ return(NULL);
+}
+
diff --git a/src/mscrypto/certkeys.c b/src/mscrypto/certkeys.c
new file mode 100644
index 00000000..73a6c260
--- /dev/null
+++ b/src/mscrypto/certkeys.c
@@ -0,0 +1,2633 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#ifndef XMLSEC_NO_GOST
+#include "csp_oid.h"
+#include "csp_calg.h"
+#endif
+
+#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/bn.h>
+
+#include <xmlsec/mscrypto/certkeys.h>
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/x509.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+// GOST CSP don't support keys duplicating, so we use NT4 analogs for these...
+#ifndef XMLSEC_NO_GOST
+#ifndef XMLSEC_MSCRYPTO_NT4
+#define XMLSEC_MSCRYPTO_NT4
+#endif
+#endif
+
+#define XMLSEC_CONTAINER_NAME "xmlsec-key-container"
+
+/**************************************************************************
+ *
+ * Internal MSCrypto PCCERT_CONTEXT key CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecMSCryptoKeyDataCtx xmlSecMSCryptoKeyDataCtx,
+ *xmlSecMSCryptoKeyDataCtxPtr;
+
+#ifdef XMLSEC_MSCRYPTO_NT4
+/*-
+ * A wrapper of HCRYPTKEY, a reference countor is introduced, the function is
+ * the same as CryptDuplicateKey. Because the CryptDuplicateKey is not support
+ * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0
+ */
+struct _mscrypt_key {
+ HCRYPTKEY hKey ;
+ volatile LONG refcnt ;
+} ;
+
+/*-
+ * A wrapper of HCRYPTPROV, a reference countor is introduced, the function is
+ * the same as CryptContextAddRef. Because the CryptContextAddRef is not support
+ * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0
+ */
+struct _mscrypt_prov {
+ HCRYPTPROV hProv ;
+ BOOL fCallerFreeProv ;
+ volatile LONG refcnt ;
+} ;
+#endif /* XMLSEC_MSCRYPTO_NT4 */
+
+/*
+ * Since MSCrypto does not provide direct handles to private keys, we support
+ * only private keys linked to a certificate context. The certificate context
+ * also provides the public key. Only when no certificate context is used, and
+ * a public key from xml document is provided, we need HCRYPTKEY.... The focus
+ * now is however directed to certificates. Wouter
+ */
+struct _xmlSecMSCryptoKeyDataCtx {
+#ifndef XMLSEC_MSCRYPTO_NT4
+ HCRYPTPROV hProv;
+ BOOL fCallerFreeProv;
+ HCRYPTKEY hKey;
+#else /* XMLSEC_MSCRYPTO_NT4 */
+ struct _mscrypt_prov* p_prov ;
+ struct _mscrypt_key* p_key ;
+#endif /* XMLSEC_MSCRYPTO_NT4 */
+ PCCERT_CONTEXT pCert;
+ LPCTSTR providerName;
+ DWORD providerType;
+ DWORD dwKeySpec;
+ xmlSecKeyDataType type;
+};
+
+#ifndef XMLSEC_MSCRYPTO_NT4
+
+/******************************** Provider *****************************************/
+#define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (ctx)->hProv
+
+static void
+xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ ctx->hProv = 0;
+ ctx->fCallerFreeProv = FALSE;
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ if ((ctx->hProv != 0) && (ctx->fCallerFreeProv)) {
+ CryptReleaseContext(ctx->hProv, 0);
+ }
+ ctx->hProv = 0;
+ ctx->fCallerFreeProv = FALSE;
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
+{
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
+ ctx->hProv = hProv;
+ ctx->fCallerFreeProv = fCallerFreeProv;
+}
+
+static int
+xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
+
+ if(ctxSrc->hProv != 0) {
+ if(!CryptContextAddRef(ctxSrc->hProv, NULL, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptContextAddRef",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctxDst->hProv = ctxSrc->hProv;
+ ctxDst->fCallerFreeProv = TRUE;
+ }
+ return(0);
+}
+
+/******************************** Key *****************************************/
+#define xmlSecMSCryptoKeyDataCtxGetKey(ctx) ((ctx)->hKey)
+
+static void
+xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ ctx->hKey = 0;
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->hKey != 0) {
+ CryptDestroyKey(ctx->hKey);
+ }
+ ctx->hKey = 0;
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
+ ctx->hKey = hKey;
+}
+
+static int
+xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
+ if (ctxSrc->hKey != 0) {
+ if (!CryptDuplicateKey(ctxSrc->hKey, NULL, 0, &(ctxDst->hKey))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptDuplicateKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+#else /* XMLSEC_MSCRYPTO_NT4 */
+
+/******************************** Provider *****************************************/
+#define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (((ctx)->p_prov) ? ((ctx)->p_prov->hProv) : 0)
+
+static void
+xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ ctx->p_prov = (struct _mscrypt_prov*)xmlMalloc(sizeof(struct _mscrypt_prov));
+ if(ctx->p_prov == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE,
+ "mscrypt_create_prov" ,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE
+ );
+ }
+ memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->p_prov != NULL) {
+ if(InterlockedDecrement(&(ctx->p_prov->refcnt)) <= 0) {
+ if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) {
+ CryptReleaseContext(ctx->p_prov->hProv, 0) ;
+ }
+ memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
+ xmlFree(ctx->p_prov) ;
+ }
+ ctx->p_prov = NULL;
+ }
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
+{
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
+
+ if((ctx->p_prov != NULL) && (ctx->p_prov->refcnt == 1)) {
+ if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) {
+ CryptReleaseContext(ctx->p_prov->hProv, 0) ;
+ }
+ memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
+ } else {
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
+ xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
+ }
+
+ ctx->p_prov->hProv = hProv;
+ ctx->p_prov->fCallerFreeProv = fCallerFreeProv;
+ ctx->p_prov->refcnt = 1;
+}
+
+static int
+xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
+
+ if (ctxSrc->p_prov != NULL) {
+ ctxDst->p_prov = ctxSrc->p_prov;
+ InterlockedIncrement(&(ctxDst->p_prov->refcnt));
+ }
+
+ return(0);
+}
+
+/******************************** Key *****************************************/
+#define xmlSecMSCryptoKeyDataCtxGetKey(ctx) (((ctx)->p_key) ? ((ctx)->p_key->hKey) : 0)
+
+static void
+xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ ctx->p_key = (struct _mscrypt_key*)xmlMalloc(sizeof(struct _mscrypt_key));
+ if(ctx->p_key == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE,
+ "mscrypt_create_key" ,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE
+ );
+ }
+ memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->p_key != NULL) {
+ if(InterlockedDecrement(&(ctx->p_key->refcnt)) <= 0) {
+ if(ctx->p_key->hKey != 0) {
+ CryptDestroyKey(ctx->p_key->hKey) ;
+ }
+ memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
+ xmlFree(ctx->p_key) ;
+ }
+ ctx->p_key = NULL;
+ }
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
+ xmlSecAssert(ctx != NULL);
+
+ if((ctx->p_key != NULL) && (ctx->p_key->refcnt == 1)) {
+ if(ctx->p_key->hKey != 0) {
+ CryptDestroyKey(ctx->p_key->hKey) ;
+ }
+ memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
+ } else {
+ xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
+ xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
+ }
+ ctx->p_key->hKey = hKey;
+ ctx->p_key->refcnt = 1;
+}
+
+static int
+xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
+ if (ctxSrc->p_key != NULL) {
+ ctxDst->p_key = ctxSrc->p_key;
+ InterlockedIncrement(&(ctxDst->p_key->refcnt));
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_MSCRYPTO_NT4 */
+
+/******************************** Cert *****************************************/
+#define xmlSecMSCryptoKeyDataCtxGetCert(ctx) ((ctx)->pCert)
+
+static void
+xmlSecMSCryptoKeyDataCtxCreateCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ ctx->pCert = NULL;
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxDestroyCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->pCert != NULL) {
+ CertFreeCertificateContext(ctx->pCert);
+ }
+ ctx->pCert = NULL;
+}
+
+static void
+xmlSecMSCryptoKeyDataCtxSetCert(xmlSecMSCryptoKeyDataCtxPtr ctx, PCCERT_CONTEXT pCert) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
+ ctx->pCert = pCert;
+}
+
+static int
+xmlSecMSCryptoKeyDataCtxDuplicateCert(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxDestroyCert(ctxDst);
+ if(ctxSrc->pCert != NULL) {
+ ctxDst->pCert = xmlSecMSCryptoCertDup(ctxSrc->pCert);
+ if(ctxDst->pCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoPCCDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+/******************************************************************************
+ *
+ * xmlSecMSCryptoKeyDataCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecMSCryptoKeyDataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoKeyDataCtx))
+#define xmlSecMSCryptoKeyDataGetCtx(data) \
+ ((xmlSecMSCryptoKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecMSCryptoKeyDataDuplicate (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
+static void xmlSecMSCryptoKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataGetSize (xmlSecKeyDataPtr data);
+
+/**
+ * xmlSecMSCryptoKeyDataAdoptCert:
+ * @data: the pointer to MSCrypto pccert data.
+ * @pCert: the pointer to PCCERT key.
+ *
+ * Sets the value of key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+static int
+xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ HCRYPTKEY hKey = 0;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
+ xmlSecAssert2(pCert != NULL, -1);
+ xmlSecAssert2(pCert->pCertInfo != NULL, -1);
+ xmlSecAssert2((type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) != 0, -1);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
+ xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
+ xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
+
+ ctx->type = type;
+
+ /* Now we acquire a context for this key(pair). The context is needed
+ * for the real crypto stuff in MS Crypto.
+ */
+ if((type & xmlSecKeyDataTypePrivate) != 0){
+ HCRYPTPROV hProv = 0;
+ BOOL fCallerFreeProv = FALSE;
+
+ if (!CryptAcquireCertificatePrivateKey(pCert,
+ CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
+ NULL,
+ &hProv,
+ &(ctx->dwKeySpec),
+ &fCallerFreeProv)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptAcquireCertificatePrivateKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
+ } else if((type & xmlSecKeyDataTypePublic) != 0){
+ HCRYPTPROV hProv = 0;
+ if (!CryptAcquireContext(&hProv,
+ NULL,
+ NULL, /* ctx->providerName, */
+ ctx->providerType,
+ CRYPT_VERIFYCONTEXT)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE);
+ ctx->dwKeySpec = 0;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Unsupported keytype");
+ return(-1);
+ }
+
+ /* CryptImportPublicKeyInfo is only needed when a real key handle
+ * is needed. The key handle is needed for de/encrypting and for
+ * verifying of a signature, *not* for signing. We could call
+ * CryptImportPublicKeyInfo in xmlSecMSCryptoKeyDataGetKey instead
+ * so no unnessecary calls to CryptImportPublicKeyInfo are being
+ * made. WK
+ */
+ if(!CryptImportPublicKeyInfo(xmlSecMSCryptoKeyDataCtxGetProvider(ctx),
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ &(pCert->pCertInfo->SubjectPublicKeyInfo),
+ &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptImportPublicKeyInfo",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
+ xmlSecMSCryptoKeyDataCtxSetCert(ctx, pCert);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataAdoptKey(xmlSecKeyDataPtr data,
+ HCRYPTPROV hProv,
+ BOOL fCallerFreeProv,
+ HCRYPTKEY hKey,
+ DWORD dwKeySpec,
+ xmlSecKeyDataType type) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
+ xmlSecAssert2(hKey != 0, -1);
+ xmlSecAssert2(type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate), -1);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
+ xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
+ xmlSecMSCryptoKeyDataCtxSetCert(ctx, NULL);
+
+ ctx->dwKeySpec = dwKeySpec;
+ ctx->type = type;
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataGetKey:
+ * @data: the key data to retrieve certificate from.
+ * @type: type of key requested (public/private)
+ *
+ * Native MSCrypto key retrieval from xmlsec keydata. The
+ * returned HKEY must not be destroyed by the caller.
+ *
+ * Returns: HKEY on success or NULL otherwise.
+ */
+HCRYPTKEY
+xmlSecMSCryptoKeyDataGetKey(xmlSecKeyDataPtr data, xmlSecKeyDataType type) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(xmlSecMSCryptoKeyDataCtxGetKey(ctx));
+}
+
+/**
+ * xmlSecMSCryptoKeyDataGetDecryptKey:
+ * @data: the key data pointer
+ *
+ * Native MSCrypto decrypt key retrieval from xmlsec keydata. The
+ * returned HKEY must not be destroyed by the caller.
+ *
+ * Returns: HKEY on success or NULL otherwise.
+ */
+HCRYPTKEY
+xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ HCRYPTKEY hKey;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ if( !CryptGetUserKey(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), AT_KEYEXCHANGE, &(hKey))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetUserKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+ return (hKey);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataGetCert:
+ * @data: the key data to retrieve certificate from.
+ *
+ * Native MSCrypto certificate retrieval from xmlsec keydata. The
+ * returned PCCERT_CONTEXT must not be released by the caller.
+ *
+ * Returns: PCCERT_CONTEXT on success or NULL otherwise.
+ */
+PCCERT_CONTEXT
+xmlSecMSCryptoKeyDataGetCert(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(xmlSecMSCryptoKeyDataCtxGetCert(ctx));
+}
+
+HCRYPTPROV
+xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(xmlSecMSCryptoKeyDataCtxGetProvider(ctx));
+}
+
+DWORD
+xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->dwKeySpec);
+}
+
+static int
+xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecMSCryptoKeyDataCtxPtr ctxDst;
+ xmlSecMSCryptoKeyDataCtxPtr ctxSrc;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecMSCryptoKeyDataSize), -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecMSCryptoKeyDataSize), -1);
+
+ ctxDst = xmlSecMSCryptoKeyDataGetCtx(dst);
+ xmlSecAssert2(ctxDst != NULL, -1);
+
+ ctxSrc = xmlSecMSCryptoKeyDataGetCtx(src);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ if(xmlSecMSCryptoKeyDataCtxDuplicateProvider(ctxDst, ctxSrc) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecMSCryptoKeyDataCtxDuplicateProvider",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(xmlSecMSCryptoKeyDataCtxDuplicateKey(ctxDst, ctxSrc) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecMSCryptoKeyDataCtxDuplicateKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(xmlSecMSCryptoKeyDataCtxDuplicateCert(ctxDst, ctxSrc) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecMSCryptoKeyDataCtxDuplicateCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctxDst->dwKeySpec = ctxSrc->dwKeySpec;
+ ctxDst->providerName = ctxSrc->providerName;
+ ctxDst->providerType = ctxSrc->providerType;
+ ctxDst->type = ctxSrc->type;
+
+ return(0);
+}
+
+static void
+xmlSecMSCryptoKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
+
+ xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
+ xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
+ xmlSecMSCryptoKeyDataCtxCreateCert(ctx);
+}
+
+static void
+xmlSecMSCryptoKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
+ xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
+ xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
+}
+
+static int
+xmlSecMSCryptoKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ if(xmlSecMSCryptoKeyDataCtxGetCert(ctx) != NULL) {
+ xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo != NULL, 0);
+ return (CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ &(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo->SubjectPublicKeyInfo)));
+ } else if (xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0) {
+ DWORD length = 0;
+ DWORD lenlen = sizeof(DWORD);
+
+ if (!CryptGetKeyParam(xmlSecMSCryptoKeyDataCtxGetKey(ctx), KP_KEYLEN, (BYTE *)&length, &lenlen, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+ return(length);
+ }
+
+ return (0);
+}
+
+static xmlSecKeyDataType
+xmlSecMSCryptoKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown);
+
+ /* We could make a call to CryptFindCertificateKeyProvInfo here, to find out if
+ * we *really* have a private key or not. However if the certificate is not
+ * linked to a private key, the call takes an ridiculous amount of time.
+ * the way it is now is better I think. WK.
+ */
+ return(ctx->type);
+}
+
+/**
+ * xmlSecMSCryptoCertDup:
+ * @pCert: the pointer to cert.
+ *
+ * Duplicates the @pCert.
+ *
+ * Returns: pointer to newly created PCCERT_CONTEXT object or
+ * NULL if an error occurs.
+ */
+PCCERT_CONTEXT xmlSecMSCryptoCertDup(PCCERT_CONTEXT pCert) {
+ PCCERT_CONTEXT ret;
+
+ xmlSecAssert2(pCert != NULL, NULL);
+
+ ret = CertDuplicateCertificateContext(pCert);
+ if(ret == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(ret);
+}
+
+
+/**
+ * xmlSecMSCryptoCertAdopt:
+ * @pCert: the pointer to cert.
+ * @type: the expected key type.
+ *
+ * Creates key data value from the cert.
+ *
+ * Returns: pointer to newly created xmlsec key or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecMSCryptoCertAdopt(PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
+ xmlSecKeyDataPtr data = NULL;
+ int ret;
+
+ xmlSecAssert2(pCert != NULL, NULL);
+ xmlSecAssert2(pCert->pCertInfo != NULL, NULL);
+ xmlSecAssert2(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL, NULL);
+
+#ifndef XMLSEC_NO_RSA
+ if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_RSA_RSA)) {
+ data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataRsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecMSCryptoDataRsaId");
+ return(NULL);
+ }
+ }
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+ if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_X957_DSA /*szOID_DSALG_SIGN*/)) {
+ data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataDsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecMSCryptoKeyDataDsaId");
+ return(NULL);
+ }
+ }
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001_CP) ||
+ !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001) ||
+ !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_94_CP)) {
+ data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataGost2001Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecMSCryptoKeyDataGost2001Id");
+ return(NULL);
+ }
+ }
+#endif /* XMLSEC_NO_GOST*/
+
+ if (NULL == data) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "PCCERT_CONTEXT key type %s not supported", pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
+ return(NULL);
+ }
+
+ xmlSecAssert2(data != NULL, NULL);
+
+ ret = xmlSecMSCryptoKeyDataAdoptCert(data, pCert, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoPCCDataAdoptPCC",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+ return(data);
+}
+
+
+#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) >
+ *
+ * ============================================================================
+ *
+ *
+ *************************************************************************/
+
+static int xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
+static void xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data);
+static void xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output);
+static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output);
+
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecMSCryptoKeyDataSize,
+
+ /* data */
+ xmlSecNameRSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecMSCryptoKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecMSCryptoKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecMSCryptoKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecMSCryptoKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecMSCryptoKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecMSCryptoKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecMSCryptoKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecMSCryptoKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecMSCryptoKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataRsaGetKlass:
+ *
+ * The MSCrypto RSA CertKey data klass.
+ *
+ * Returns: pointer to MSCrypto RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataRsaGetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataRsaKlass);
+}
+
+static int
+xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), xmlSecKeyDataTypeUnknown);
+
+ xmlSecMSCryptoKeyDataInitialize(data);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ctx->providerName = MS_ENHANCED_PROV;
+ ctx->providerType = PROV_RSA_FULL;
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataRsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataRsaId), -1);
+
+ return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
+
+ xmlSecMSCryptoKeyDataFinalize(data);
+}
+
+static int
+xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecBn modulus, exponent;
+ xmlSecBuffer blob;
+ unsigned int blobBufferLen;
+ PUBLICKEYSTRUC* pubKeyStruc = NULL;
+ RSAPUBKEY* pubKey = NULL;
+ xmlSecByte* modulusBlob = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ HCRYPTPROV hProv = 0;
+ HCRYPTKEY hKey = 0;
+ xmlNodePtr cur;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -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);
+ }
+
+ /* initialize buffers */
+ ret = xmlSecBnInitialize(&modulus, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "modulus");
+ return(-1);
+ }
+
+ ret = xmlSecBnInitialize(&exponent, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "exponent");
+ xmlSecBnFinalize(&modulus);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&blob, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "blob");
+ xmlSecBnFinalize(&modulus);
+ xmlSecBnFinalize(&exponent);
+ return(-1);
+ }
+
+ /* read xml */
+ 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));
+ goto done;
+ }
+
+ ret = xmlSecBnGetNodeValue(&modulus, cur, xmlSecBnBase64, 1);
+ if((ret < 0) || (xmlSecBnGetSize(&modulus) == 0)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnGetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ goto done;
+ }
+ 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));
+ goto done;
+ }
+ ret = xmlSecBnGetNodeValue(&exponent, cur, xmlSecBnBase64, 1);
+ if((ret < 0) || (xmlSecBnGetSize(&exponent) == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnGetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * MSCrypto does not support it. We just ignore it */
+ 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");
+ goto done;
+ }
+
+ /* Now try to create the key */
+ blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + xmlSecBnGetSize(&modulus);
+ ret = xmlSecBufferSetSize(&blob, blobBufferLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blobBufferLen);
+ goto done;
+ }
+
+ /* Set the PUBLICKEYSTRUC */
+ pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob);
+ pubKeyStruc->bType = PUBLICKEYBLOB;
+ pubKeyStruc->bVersion = 0x02;
+ pubKeyStruc->reserved = 0;
+ pubKeyStruc->aiKeyAlg = CALG_RSA_KEYX | CALG_RSA_SIGN;
+
+ /* Set the public key header */
+ pubKey = (RSAPUBKEY*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC));
+ pubKey->magic = 0x31415352; /* == RSA1 public */
+ pubKey->bitlen = xmlSecBnGetSize(&modulus) * 8; /* Number of bits in prime modulus */
+ pubKey->pubexp = 0;
+ if(sizeof(pubKey->pubexp) < xmlSecBnGetSize(&exponent)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "exponent size=%d",
+ xmlSecBnGetSize(&exponent));
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBnGetData(&exponent) != NULL, -1);
+ memcpy(&(pubKey->pubexp), xmlSecBnGetData(&exponent), xmlSecBnGetSize(&exponent));
+
+ modulusBlob = (xmlSecByte*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
+ xmlSecAssert2(xmlSecBnGetData(&modulus) != NULL, -1);
+ memcpy(modulusBlob, xmlSecBnGetData(&modulus), xmlSecBnGetSize(&modulus));
+
+ /* Now that we have the blob, import */
+ if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) {
+ if(NTE_BAD_KEYSET == GetLastError()) {
+ if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptImportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ hProv = 0;
+ hKey = 0;
+
+ 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);
+ goto done;
+ }
+ data = NULL;
+
+ /* success */
+ res = 0;
+
+done:
+ if (hProv == 0) {
+ CryptReleaseContext(hProv, 0);
+ }
+ if (hKey != 0) {
+ CryptDestroyKey(hKey);
+ }
+ if (data != 0) {
+ xmlSecKeyDataDestroy(data);
+ }
+
+ xmlSecBnFinalize(&modulus);
+ xmlSecBnFinalize(&exponent);
+ xmlSecBufferFinalize(&blob);
+ return(res);
+}
+
+static int
+xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ xmlSecBuffer buf;
+ DWORD dwBlobLen;
+ xmlSecByte* blob;
+ PUBLICKEYSTRUC* pubKeyStruc;
+ RSAPUBKEY *pubKey;
+ xmlSecSize modulusLen, exponentLen;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataRsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
+
+ if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&buf, dwBlobLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%ld", dwBlobLen);
+ return(-1);
+ }
+
+ blob = xmlSecBufferGetData(&buf);
+ if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "blobLen=%ld", dwBlobLen);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* check PUBLICKEYSTRUC */
+ pubKeyStruc = (PUBLICKEYSTRUC*)blob;
+ if(pubKeyStruc->bVersion != 0x02) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ if(pubKeyStruc->bType != PUBLICKEYBLOB) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* check RSAPUBKEY */
+ pubKey = (RSAPUBKEY *)(blob + sizeof(PUBLICKEYSTRUC));
+ if(pubKey->magic != 0x31415352) { /* RSA public key magic */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKey->magic=0x%08lx", pubKey->magic);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ modulusLen = pubKey->bitlen / 8;
+
+ if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulusLen) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "blobLen=%ld; modulusLen=%d", dwBlobLen, modulusLen);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ blob += sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
+
+ /* 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));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ ret = xmlSecBnBlobSetNodeValue(blob, modulusLen, cur, xmlSecBnBase64, 1, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnBlobSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ xmlSecBufferFinalize(&buf);
+ 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));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* Remove leading zero's (from least significant end) */
+ blob = (xmlSecByte*)(&(pubKey->pubexp));
+ exponentLen = sizeof(pubKey->pubexp);
+ while (exponentLen > 0 && blob[exponentLen - 1] == 0) {
+ exponentLen--;
+ }
+
+ ret = xmlSecBnBlobSetNodeValue(blob, exponentLen, cur, xmlSecBnBase64, 1, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnBlobSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* next is PrivateExponent node: not supported in MSCrypto */
+
+ xmlSecBufferFinalize(&buf);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits,
+ xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ HCRYPTPROV hProv = 0;
+ HCRYPTKEY hKey = 0;
+ DWORD dwKeySpec;
+ DWORD dwSize;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if (!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, 0)) {
+ if (NTE_BAD_KEYSET == GetLastError()) {
+ if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+ }
+
+ dwKeySpec = AT_KEYEXCHANGE | AT_SIGNATURE;
+ dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE);
+ if (!CryptGenKey(hProv, CALG_RSA_SIGN, dwSize, &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CryptGenKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec,
+ xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ hProv = 0;
+ hKey = 0;
+
+ /* success */
+ res = 0;
+
+done:
+ if (hProv != 0) {
+ CryptReleaseContext(hProv, 0);
+ }
+
+ if (hKey != 0) {
+ CryptDestroyKey(hKey);
+ }
+
+ return(res);
+}
+
+static xmlSecKeyDataType
+xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data) {
+ return(xmlSecMSCryptoKeyDataGetType(data));
+}
+
+static xmlSecSize
+xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), 0);
+
+ return (xmlSecMSCryptoKeyDataGetSize(data));
+}
+
+static void
+xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== rsa key: size = %d\n",
+ xmlSecMSCryptoKeyDataRsaGetSize(data));
+}
+
+static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
+ xmlSecMSCryptoKeyDataRsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_RSA */
+
+#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 xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataDsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data);
+static void xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecMSCryptoKeyDataSize,
+
+ /* data */
+ xmlSecNameDSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecMSCryptoKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecMSCryptoKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecMSCryptoKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecMSCryptoKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecMSCryptoKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecMSCryptoKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecMSCryptoKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecMSCryptoKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecMSCryptoKeyDataDsaDebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataDsaGetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataDsaKlass);
+}
+
+
+static int
+xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), xmlSecKeyDataTypeUnknown);
+
+ xmlSecMSCryptoKeyDataInitialize(data);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ctx->providerName = MS_DEF_DSS_PROV;
+ ctx->providerType = PROV_DSS;
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataDsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataDsaId), -1);
+
+ return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
+
+ xmlSecMSCryptoKeyDataFinalize(data);
+}
+
+static int
+xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data = NULL;
+ xmlNodePtr cur;
+ xmlSecBn p, q, g, y;
+ xmlSecBuffer blob;
+ unsigned int blobBufferLen;
+ PUBLICKEYSTRUC *pubKeyStruc = NULL;
+ DSSPUBKEY *pubKey = NULL;
+ DSSSEED* seed = NULL;
+ BYTE *buf = NULL;
+ HCRYPTPROV hProv = 0;
+ HCRYPTKEY hKey = 0;
+ xmlSecSize i;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -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);
+ }
+
+ /* initialize buffers */
+ ret = xmlSecBnInitialize(&p, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "p");
+ return(-1);
+ }
+
+ ret = xmlSecBnInitialize(&q, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "q");
+ xmlSecBnFinalize(&p);
+ return(-1);
+ }
+
+ ret = xmlSecBnInitialize(&g, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "g");
+ xmlSecBnFinalize(&p);
+ xmlSecBnFinalize(&q);
+ return(-1);
+ }
+
+ ret = xmlSecBnInitialize(&y, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "y");
+ xmlSecBnFinalize(&p);
+ xmlSecBnFinalize(&q);
+ xmlSecBnFinalize(&g);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&blob, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "blob");
+ xmlSecBnFinalize(&p);
+ xmlSecBnFinalize(&q);
+ xmlSecBnFinalize(&g);
+ xmlSecBnFinalize(&y);
+ return(-1);
+ }
+
+ /* read xml */
+ 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));
+ goto done;
+ }
+
+ ret = xmlSecBnGetNodeValue(&p, cur, xmlSecBnBase64, 1);
+ if((ret < 0) || (xmlSecBnGetSize(&p) == 0)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnGetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ goto done;
+ }
+ 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));
+ goto done;
+ }
+ ret = xmlSecBnGetNodeValue(&q, cur, xmlSecBnBase64, 1);
+ if((ret < 0) || (xmlSecBnGetSize(&q) == 0)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnGetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ goto done;
+ }
+ 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));
+ goto done;
+ }
+ ret = xmlSecBnGetNodeValue(&g, cur, xmlSecBnBase64, 1);
+ if((ret < 0) || (xmlSecBnGetSize(&q) == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnGetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * MSCrypto does not support it, we just ignore it */
+
+ 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));
+ goto done;
+ }
+ ret = xmlSecBnGetNodeValue(&y, cur, xmlSecBnBase64, 1);
+ if((ret < 0) || (xmlSecBnGetSize(&y) == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnGetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ goto done;
+ }
+ 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);
+ goto done;
+ }
+
+ /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */
+ blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * xmlSecBnGetSize(&p) + 0x14 + sizeof(DSSSEED);
+ ret = xmlSecBufferSetSize(&blob, blobBufferLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blobBufferLen);
+ goto done;
+ }
+
+ /* Set PUBLICKEYSTRUC */
+ pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob);
+ pubKeyStruc->bType = PUBLICKEYBLOB;
+ pubKeyStruc->bVersion = 0x02;
+ pubKeyStruc->reserved = 0;
+ pubKeyStruc->aiKeyAlg = CALG_DSS_SIGN;
+
+ /* Set the public key header */
+ pubKey = (DSSPUBKEY *) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC));
+ pubKey->magic = 0x31535344; /* == DSS1 pub key */
+ pubKey->bitlen = xmlSecBnGetSize(&p) * 8; /* Number of bits in prime modulus */
+
+ /* copy the key data */
+ buf = (BYTE*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY));
+
+ /* set p */
+ xmlSecAssert2(xmlSecBnGetData(&p) != NULL, -1);
+ memcpy(buf, xmlSecBnGetData(&p), xmlSecBnGetSize(&p));
+ buf += xmlSecBnGetSize(&p);
+
+ /* set q */
+ if(xmlSecBnGetSize(&q) > 0x14) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "q",
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d > 0x14", xmlSecBnGetSize(&q));
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBnGetData(&q) != NULL, -1);
+ memcpy(buf, xmlSecBnGetData(&q), xmlSecBnGetSize(&q));
+ buf += xmlSecBnGetSize(&q);
+
+ /* Pad with zeros */
+ for(i = xmlSecBnGetSize(&q); i < 0x14; ++i) {
+ *(buf++) = 0;
+ }
+
+ /* set generator */
+ if(xmlSecBnGetSize(&g) > xmlSecBnGetSize(&p)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "g",
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d > %d",
+ xmlSecBnGetSize(&g),
+ xmlSecBnGetSize(&p));
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBnGetData(&g) != NULL, -1);
+ memcpy(buf, xmlSecBnGetData(&g), xmlSecBnGetSize(&g));
+ buf += xmlSecBnGetSize(&g);
+ /* Pad with zeros */
+ for(i = xmlSecBnGetSize(&g); i < xmlSecBnGetSize(&p); ++i) {
+ *(buf++) = 0;
+ }
+
+ /* Public key */
+ if(xmlSecBnGetSize(&y) > xmlSecBnGetSize(&p)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "y",
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d > %d",
+ xmlSecBnGetSize(&y),
+ xmlSecBnGetSize(&p));
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBnGetData(&y) != NULL, -1);
+ memcpy(buf, xmlSecBnGetData(&y), xmlSecBnGetSize(&y));
+ buf += xmlSecBnGetSize(&y);
+ /* Pad with zeros */
+ for(i = xmlSecBnGetSize(&y); i < xmlSecBnGetSize(&p); ++i) {
+ *(buf++) = 0;
+ }
+
+ /* Set seed to 0xFFFFFFFFF */
+ seed = (DSSSEED*)buf;
+ memset(seed, 0, sizeof(*seed));
+ seed->counter = 0xFFFFFFFF; /* SEED Counter set to 0xFFFFFFFF will cause seed to be ignored */
+
+ if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, 0)) {
+ if (NTE_BAD_KEYSET == GetLastError()) {
+ if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, CRYPT_NEWKEYSET)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ /* import the key blob */
+ if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptImportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ hProv = 0;
+ hKey = 0;
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ data = NULL;
+
+ /* success */
+ res = 0;
+
+done:
+ if (hKey != 0) {
+ CryptDestroyKey(hKey);
+ }
+ if (hProv != 0) {
+ CryptReleaseContext(hProv, 0);
+ }
+ if (data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+
+ xmlSecBufferFinalize(&blob);
+ xmlSecBnFinalize(&p);
+ xmlSecBnFinalize(&q);
+ xmlSecBnFinalize(&g);
+ xmlSecBnFinalize(&y);
+
+ return(res);
+}
+
+static int
+xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ xmlSecBuffer buf;
+ DWORD dwBlobLen;
+ xmlSecByte* blob;
+ PUBLICKEYSTRUC* pubKeyStruc;
+ DSSPUBKEY *pubKey;
+ xmlSecSize keyLen, len;
+ xmlNodePtr cur;
+ int ret;
+
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataDsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
+
+ if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&buf, dwBlobLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%ld", dwBlobLen);
+ return(-1);
+ }
+
+ blob = xmlSecBufferGetData(&buf);
+ if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "blobLen=%ld", dwBlobLen);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* check PUBLICKEYSTRUC */
+ pubKeyStruc = (PUBLICKEYSTRUC*)blob;
+ if(pubKeyStruc->bVersion != 0x02) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ if(pubKeyStruc->bType != PUBLICKEYBLOB) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* check DSSPUBKEY */
+ pubKey = (DSSPUBKEY*)(blob + sizeof(PUBLICKEYSTRUC));
+ if(pubKey->magic != 0x31535344) { /* DSS key magic */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKey->magic=0x%08lx", pubKey->magic);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ keyLen = pubKey->bitlen / 8;
+
+ /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */
+ if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * keyLen + 0x14 + sizeof(DSSSEED)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "blobLen=%ld; keyLen=%d", dwBlobLen, keyLen);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ blob += sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY);
+
+ /* first is P node */
+ 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));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ ret = xmlSecBnBlobSetNodeValue(blob, keyLen, cur, xmlSecBnBase64, 1, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnBlobSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ blob += keyLen;
+
+ /* next is Q node. */
+ 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));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* we think that the size of q is 0x14, skip trailing zeros */
+ for(len = 0x14; len > 0 && blob[len - 1] == 0; --len);
+
+ ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnBlobSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ blob += 0x14;
+
+ /* next is G node. */
+ 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));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* skip trailing zeros */
+ for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
+
+ ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnBlobSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ blob += keyLen;
+
+ /* next is X node: not supported in MSCrypto */
+
+ /* next is Y node. */
+ 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));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ /* skip trailing zeros */
+ for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
+
+ ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecBnBlobSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ blob += keyLen;
+
+ xmlSecBufferFinalize(&buf);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ HCRYPTPROV hProv = 0;
+ HCRYPTKEY hKey = 0;
+ DWORD dwKeySpec;
+ DWORD dwSize;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+
+ if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, 0)) {
+ if (NTE_BAD_KEYSET == GetLastError()) {
+ if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, CRYPT_NEWKEYSET)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ dwKeySpec = AT_SIGNATURE;
+ dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE);
+ if (!CryptGenKey(hProv, CALG_DSS_SIGN, dwSize, &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CryptGenKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec,
+ xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ hProv = 0;
+ hKey = 0;
+
+ /* success */
+ res = 0;
+
+done:
+ if (hProv != 0) {
+ CryptReleaseContext(hProv, 0);
+ }
+
+ if (hKey != 0) {
+ CryptDestroyKey(hKey);
+ }
+
+ return(res);
+}
+
+static xmlSecKeyDataType
+xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data) {
+ return(xmlSecMSCryptoKeyDataGetType(data));
+}
+
+static xmlSecSize
+xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), 0);
+
+ return xmlSecMSCryptoKeyDataGetSize(data);
+}
+
+static void
+xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== dsa key: size = %d\n",
+ xmlSecMSCryptoKeyDataDsaGetSize(data));
+}
+
+static void
+xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
+ xmlSecMSCryptoKeyDataDsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+
+#ifndef XMLSEC_NO_GOST
+/**************************************************************************
+ *
+ * GOST2001 xml key representation processing. Contain errors.
+ *
+ *************************************************************************/
+static int xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataGost2001XmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataGost2001XmlWrite(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataGost2001Generate(xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data);
+static void xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2001Klass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecMSCryptoKeyDataSize,
+
+ /* data */
+ xmlSecNameGOST2001KeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefGOST2001KeyValue, /* const xmlChar* href; */
+ xmlSecNodeGOST2001KeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoKeyDataGost2001Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecMSCryptoKeyDataGost2001Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecMSCryptoKeyDataGost2001Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/ /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecMSCryptoKeyDataGost2001GetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecMSCryptoKeyDataGost2001GetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecMSCryptoKeyDataGost2001DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecMSCryptoKeyDataGost2001DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataGost2001GetKlass:
+ *
+ * The GOST2001 key data klass.
+ *
+ * Returns: pointer to GOST2001 key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataGost2001GetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataGost2001Klass);
+}
+
+
+static int
+xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoKeyDataCtxPtr ctx;
+ HCRYPTPROV tmp_ctx = 0;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown);
+
+ xmlSecMSCryptoKeyDataInitialize(data);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* GOST Algorithm is provided by several CSP's, so we try to find any installed */
+ if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_MAGPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ ctx->providerName = "MagPro CSP";
+ ctx->providerType = PROV_MAGPRO_GOST;
+ } else {
+ if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_CRYPTOPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ ctx->providerName = "CryptoPro CSP";
+ ctx->providerType = PROV_CRYPTOPRO_GOST;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataGost2001Initialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+ }
+ CryptReleaseContext(tmp_ctx, 0);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2001Id), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2001Id), -1);
+
+ return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
+
+ xmlSecMSCryptoKeyDataFinalize(data);
+}
+
+static xmlSecKeyDataType
+xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data) {
+ return(xmlSecMSCryptoKeyDataGetType(data));
+}
+
+static xmlSecSize
+xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), 0);
+
+ return xmlSecMSCryptoKeyDataGetSize(data);
+}
+
+static void
+xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== dsa key: size = %d\n",
+ xmlSecMSCryptoKeyDataGost2001GetSize(data));
+}
+
+static void
+xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<GOST2001KeyValue size=\"%d\" />\n",
+ xmlSecMSCryptoKeyDataGost2001GetSize(data));
+}
+
+#endif /* XMLSEC_NO_GOST*/
diff --git a/src/mscrypto/ciphers.c b/src/mscrypto/ciphers.c
new file mode 100644
index 00000000..59161639
--- /dev/null
+++ b/src/mscrypto/ciphers.c
@@ -0,0 +1,1350 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+#ifndef MS_ENH_RSA_AES_PROV_PROTO
+#define MS_ENH_RSA_AES_PROV_PROTO "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
+#endif /* MS_ENH_RSA_AES_PROV_PROTO */
+
+static BOOL xmlSecMSCryptoCreatePrivateExponentOneKey (HCRYPTPROV hProv,
+ HCRYPTKEY *hPrivateKey);
+static BOOL xmlSecMSCryptoImportPlainSessionBlob (HCRYPTPROV hProv,
+ HCRYPTKEY hPrivateKey,
+ ALG_ID dwAlgId,
+ LPBYTE pbKeyMaterial,
+ DWORD dwKeyMaterial,
+ HCRYPTKEY *hSessionKey);
+
+/**************************************************************************
+ *
+ * Internal MSCrypto Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecMSCryptoBlockCipherCtx xmlSecMSCryptoBlockCipherCtx,
+ *xmlSecMSCryptoBlockCipherCtxPtr;
+struct _xmlSecMSCryptoBlockCipherCtx {
+ ALG_ID algorithmIdentifier;
+ int mode;
+ HCRYPTPROV cryptProvider;
+ HCRYPTKEY cryptKey;
+ HCRYPTKEY pubPrivKey;
+ xmlSecKeyDataId keyId;
+ LPCTSTR providerName;
+ int providerType;
+ int keyInitialized;
+ int ctxInitialized;
+ xmlSecSize keySize;
+};
+/* function declarations */
+static int xmlSecMSCryptoBlockCipherCtxUpdate (xmlSecMSCryptoBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+
+
+static int
+xmlSecMSCryptoBlockCipherCtxInit(xmlSecMSCryptoBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ int blockLen;
+ int ret;
+ DWORD dwBlockLen, dwBlockLenLen;
+
+ 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);
+
+ /* iv len == block len */
+ dwBlockLenLen = sizeof(DWORD);
+ if (!CryptGetKeyParam(ctx->cryptKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwBlockLenLen, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptGetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ blockLen = dwBlockLen / 8;
+ xmlSecAssert2(blockLen > 0, -1);
+ if(encrypt) {
+ unsigned char* iv;
+ size_t outSize;
+
+ /* allocate space for IV */
+ outSize = xmlSecBufferGetSize(out);
+ ret = xmlSecBufferSetSize(out, outSize + blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + blockLen);
+ return(-1);
+ }
+ iv = xmlSecBufferGetData(out) + outSize;
+
+ /* generate and use random iv */
+ if(!CryptGenRandom(ctx->cryptProvider, blockLen, iv)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptGenRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "len=%d", blockLen);
+ return(-1);
+ }
+
+ if(!CryptSetKeyParam(ctx->cryptKey, KP_IV, iv, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ /* if we don't have enough data, exit and hope that
+ * we'll have iv next time */
+ if(xmlSecBufferGetSize(in) < (size_t)blockLen) {
+ return(0);
+ }
+ xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
+
+ /* set iv */
+ if (!CryptSetKeyParam(ctx->cryptKey, KP_IV, xmlSecBufferGetData(in), 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* and remove from input */
+ ret = xmlSecBufferRemoveHead(in, blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blockLen);
+ return(-1);
+
+ }
+ }
+
+ ctx->ctxInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecMSCryptoBlockCipherCtxUpdate(xmlSecMSCryptoBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ size_t inSize, inBlocks, outSize;
+ int blockLen;
+ unsigned char* outBuf;
+ unsigned char* inBuf;
+ int ret;
+ DWORD dwBlockLen, dwBlockLenLen, dwCLen;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dwBlockLenLen = sizeof(DWORD);
+ if (!CryptGetKeyParam(ctx->cryptKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwBlockLenLen, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ blockLen = dwBlockLen / 8;
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(inSize < (size_t)blockLen) {
+ return(0);
+ }
+
+ if(encrypt) {
+ inBlocks = inSize / ((size_t)blockLen);
+ } else {
+ /* we want to have the last block in the input buffer
+ * for padding check */
+ inBlocks = (inSize - 1) / ((size_t)blockLen);
+ }
+ inSize = inBlocks * ((size_t)blockLen);
+
+ /* we write out the input size plus may be one block */
+ 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;
+ inBuf = xmlSecBufferGetData(in);
+ xmlSecAssert2(inBuf != NULL, -1);
+
+ memcpy(outBuf, inBuf, inSize);
+ dwCLen = inSize;
+ if(encrypt) {
+ if(!CryptEncrypt(ctx->cryptKey, 0, FALSE, 0, outBuf, &dwCLen, inSize + blockLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ if (!CryptDecrypt(ctx->cryptKey, 0, FALSE, 0, outBuf, &dwCLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptSetKeyDecrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ /* Check if we really have de/encrypted the numbers of bytes that we requested */
+ if (dwCLen != inSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptEn/Decrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%ld", dwCLen);
+ return(-1);
+ }
+
+ /* set correct output buffer size */
+ ret = xmlSecBufferSetSize(out, outSize + inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + inSize);
+ 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
+xmlSecMSCryptoBlockCipherCtxFinal(xmlSecMSCryptoBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ size_t inSize, outSize;
+ int blockLen, outLen = 0;
+ unsigned char* inBuf;
+ unsigned char* outBuf;
+ int ret;
+ DWORD dwBlockLen, dwBlockLenLen, dwCLen;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dwBlockLenLen = sizeof(DWORD);
+ if (!CryptGetKeyParam(ctx->cryptKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwBlockLenLen, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptGetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ blockLen = dwBlockLen / 8;
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(encrypt != 0) {
+ xmlSecAssert2(inSize < (size_t)blockLen, -1);
+
+ /* create padding */
+ ret = xmlSecBufferSetMaxSize(in, blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blockLen);
+ return(-1);
+ }
+ inBuf = xmlSecBufferGetData(in);
+
+ /* create random padding */
+ if((size_t)blockLen > (inSize + 1)) {
+ if (!CryptGenRandom(ctx->cryptProvider, blockLen - inSize - 1, inBuf + inSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptGenRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ inBuf[blockLen - 1] = blockLen - inSize;
+ inSize = blockLen;
+ } else {
+ if(inSize != (size_t)blockLen) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data=%d;block=%d", inSize, blockLen);
+ return(-1);
+ }
+ inBuf = xmlSecBufferGetData(in);
+ }
+
+ /* process last block */
+ 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;
+ memcpy(outBuf, inBuf, inSize);
+
+ dwCLen = inSize;
+ if(encrypt) {
+ /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+ * can be skipped. I hope this will work .... */
+ if(!CryptEncrypt(ctx->cryptKey, 0, FALSE, 0, outBuf, &dwCLen, inSize + blockLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ if (!CryptDecrypt(ctx->cryptKey, 0, FALSE, 0, outBuf, &dwCLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptDecrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* Check if we really have de/encrypted the numbers of bytes that we requested */
+ if (dwCLen != inSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "CryptEn/Decrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%ld", dwCLen);
+ return(-1);
+ }
+
+ if(encrypt == 0) {
+ /* check padding */
+ if(inSize < outBuf[blockLen - 1]) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "padding=%d;buffer=%d",
+ outBuf[blockLen - 1], inSize);
+ return(-1);
+ }
+ outLen = inSize - outBuf[blockLen - 1];
+ } else {
+ outLen = inSize;
+ }
+
+ /* 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);
+}
+
+/******************************************************************************
+ *
+ * Block Cipher transforms
+ *
+ * xmlSecMSCryptoBlockCipherCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecMSCryptoBlockCipherSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoBlockCipherCtx))
+#define xmlSecMSCryptoBlockCipherGetCtx(transform) \
+ ((xmlSecMSCryptoBlockCipherCtxPtr)(((unsigned char*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecMSCryptoBlockCipherInitialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoBlockCipherFinalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoBlockCipherSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoBlockCipherSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoBlockCipherExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoBlockCipherCheckId (xmlSecTransformPtr transform);
+
+static int
+xmlSecMSCryptoBlockCipherCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DES
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDes3CbcId)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformAes128CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformAes192CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformAes256CbcId)) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
+
+ ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoBlockCipherCtx));
+
+#ifndef XMLSEC_NO_DES
+ if(transform->id == xmlSecMSCryptoTransformDes3CbcId) {
+ ctx->algorithmIdentifier = CALG_3DES;
+ ctx->keyId = xmlSecMSCryptoKeyDataDesId;
+ ctx->providerName = MS_ENHANCED_PROV;
+ ctx->providerType = PROV_RSA_FULL;
+ ctx->keySize = 24;
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(transform->id == xmlSecMSCryptoTransformAes128CbcId) {
+ ctx->algorithmIdentifier = CALG_AES_128;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providerName = MS_ENH_RSA_AES_PROV_PROTO;
+ ctx->providerType = PROV_RSA_AES;
+ ctx->keySize = 16;
+ } else if(transform->id == xmlSecMSCryptoTransformAes192CbcId) {
+ ctx->algorithmIdentifier = CALG_AES_192;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providerName = MS_ENH_RSA_AES_PROV_PROTO;
+ ctx->providerType = PROV_RSA_AES;
+ ctx->keySize = 24;
+ } else if(transform->id == xmlSecMSCryptoTransformAes256CbcId) {
+ ctx->algorithmIdentifier = CALG_AES_256;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providerName = MS_ENH_RSA_AES_PROV_PROTO;
+ ctx->providerType = PROV_RSA_AES;
+ ctx->keySize = 32;
+ } 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);
+ }
+
+ if(!CryptAcquireContext(&ctx->cryptProvider, NULL /*"xmlSecMSCryptoTempContainer"*/,
+ ctx->providerName, ctx->providerType, 0)) {
+ DWORD dwError = GetLastError();
+ if (dwError == NTE_EXISTS) {
+ if (!CryptAcquireContext(&ctx->cryptProvider, "xmlSecMSCryptoTempContainer",
+ ctx->providerName, ctx->providerType, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+ } else if (dwError == NTE_BAD_KEYSET) {
+ /* This error can indicate that a newly installed provider
+ * does not have a usable key container yet. It needs to be
+ * created, and then we have to try again CryptAcquireContext.
+ * This is also referenced in
+ * http://www.microsoft.com/mind/0697/crypto.asp (inituser)
+ */
+ if(!CryptAcquireContext(&ctx->cryptProvider, NULL, ctx->providerName,
+ ctx->providerType, CRYPT_NEWKEYSET)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* Create dummy key to be able to import plain session keys */
+ if (!xmlSecMSCryptoCreatePrivateExponentOneKey(ctx->cryptProvider, &(ctx->pubPrivKey))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoCreatePrivateExponentOneKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ ctx->ctxInitialized = 0;
+ return(0);
+}
+
+static void
+xmlSecMSCryptoBlockCipherFinalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoBlockCipherCtxPtr ctx;
+
+ xmlSecAssert(xmlSecMSCryptoBlockCipherCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize));
+
+ ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->cryptKey) {
+ CryptDestroyKey(ctx->cryptKey);
+ }
+ if (ctx->pubPrivKey) {
+ CryptDestroyKey(ctx->pubPrivKey);
+ }
+ if (ctx->cryptProvider) {
+ CryptReleaseContext(ctx->cryptProvider, 0);
+ CryptAcquireContext(&ctx->cryptProvider, "xmlSecMSCryptoTempContainer",
+ MS_ENHANCED_PROV, ctx->providerType, CRYPT_DELETEKEYSET);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoBlockCipherCtx));
+}
+
+static int
+xmlSecMSCryptoBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecMSCryptoBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cryptProvider != 0, -1);
+
+ keyReq->keyId = ctx->keyId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+
+ keyReq->keyBitsSize = 8 * ctx->keySize;
+ return(0);
+}
+
+static int
+xmlSecMSCryptoBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ BYTE* bufData;
+
+ xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized == 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ xmlSecAssert2(ctx->keySize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) < ctx->keySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "keySize=%d;expected=%d",
+ xmlSecBufferGetSize(buffer), ctx->keySize);
+ return(-1);
+ }
+
+ bufData = xmlSecBufferGetData(buffer);
+ xmlSecAssert2(bufData != NULL, -1);
+
+ /* Import this key and get an HCRYPTKEY handle */
+ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->cryptProvider,
+ ctx->pubPrivKey,
+ ctx->algorithmIdentifier,
+ bufData,
+ ctx->keySize,
+ &(ctx->cryptKey))) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->keyInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecMSCryptoBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ if(ctx->ctxInitialized == 0) {
+ ret = xmlSecMSCryptoBlockCipherCtxInit(ctx,
+ in,
+ out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform),
+ transformCtx);
+
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoBlockCipherCtxInit",
+ 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 = xmlSecMSCryptoBlockCipherCtxUpdate(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoBlockCipherCtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(last) {
+ ret = xmlSecMSCryptoBlockCipherCtxFinal(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoBlockCipherCtxFinal",
+ 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 xmlSecMSCryptoAes128CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes128Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes128Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformAes128CbcGetKlass(void) {
+ return(&xmlSecMSCryptoAes128CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecMSCryptoAes192CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes192Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes192Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformAes192CbcGetKlass(void) {
+ return(&xmlSecMSCryptoAes192CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecMSCryptoAes256CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes256Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes256Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformAes256CbcGetKlass(void) {
+ return(&xmlSecMSCryptoAes256CbcKlass);
+}
+
+#endif /* XMLSEC_NO_AES */
+
+
+#ifndef XMLSEC_NO_DES
+static xmlSecTransformKlass xmlSecMSCryptoDes3CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoBlockCipherSize, /* size_t objSize */
+
+ xmlSecNameDes3Cbc, /* const xmlChar* name; */
+ xmlSecHrefDes3Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod,/* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformDes3CbcGetKlass(void) {
+ return(&xmlSecMSCryptoDes3CbcKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
+/*
+ * Low level helper routines for importing plain text keys in MS HKEY handle,
+ * since MSCrypto API does not support import of plain text (session) keys
+ * just like that.
+ * These functions are based upon MS kb article: 228786
+ *
+ * aleksey: also check "Base Provider Key BLOBs" article for priv key blob format
+ **/
+static BOOL
+xmlSecMSCryptoCreatePrivateExponentOneKey(HCRYPTPROV hProv, HCRYPTKEY *hPrivateKey)
+{
+ HCRYPTKEY hKey = 0;
+ LPBYTE keyBlob = NULL;
+ DWORD keyBlobLen;
+ PUBLICKEYSTRUC* pubKeyStruc;
+ RSAPUBKEY* rsaPubKey;
+ DWORD bitLen;
+ BYTE *ptr;
+ int n;
+ BOOL res = FALSE;
+
+ xmlSecAssert2(hProv != 0, FALSE);
+ xmlSecAssert2(hPrivateKey != NULL, FALSE);
+
+ /* just in case */
+ *hPrivateKey = 0;
+
+ /* Generate the private key */
+ if(!CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGenKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* Export the private key, we'll convert it to a private exponent of one key */
+ if(!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, NULL, &keyBlobLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyBlob = (LPBYTE)xmlMalloc(sizeof(BYTE) * keyBlobLen);
+ if(keyBlob == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ if(!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, keyBlob, &keyBlobLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ CryptDestroyKey(hKey);
+ hKey = 0;
+
+ /* Get the bit length of the key */
+ if(keyBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "len=%ld", keyBlobLen);
+ goto done;
+ }
+ pubKeyStruc = (PUBLICKEYSTRUC*)keyBlob;
+ if(pubKeyStruc->bVersion != 0x02) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
+ goto done;
+ }
+ if(pubKeyStruc->bType != PRIVATEKEYBLOB) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
+ goto done;
+ }
+
+ /* aleksey: don't ask me why it is RSAPUBKEY, just don't ask */
+ rsaPubKey = (RSAPUBKEY*)(keyBlob + sizeof(PUBLICKEYSTRUC));
+
+ /* check that we have RSA private key */
+ if(rsaPubKey->magic != 0x32415352) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "rsaPubKey->magic=0x%08lx", rsaPubKey->magic);
+ goto done;
+ }
+ bitLen = rsaPubKey->bitlen;
+
+ /* Modify the Exponent in Key BLOB format Key BLOB format is documented in SDK */
+ rsaPubKey->pubexp = 1;
+
+ /* Private-key BLOBs, type PRIVATEKEYBLOB, are used to store private keys outside a CSP.
+ * Base provider private-key BLOBs have the following format:
+ *
+ * PUBLICKEYSTRUC publickeystruc ;
+ * RSAPUBKEY rsapubkey;
+ * BYTE modulus[rsapubkey.bitlen/8]; 1/8
+ * BYTE prime1[rsapubkey.bitlen/16]; 1/16
+ * BYTE prime2[rsapubkey.bitlen/16]; 1/16
+ * BYTE exponent1[rsapubkey.bitlen/16]; 1/16
+ * BYTE exponent2[rsapubkey.bitlen/16]; 1/16
+ * BYTE coefficient[rsapubkey.bitlen/16]; 1/16
+ * BYTE privateExponent[rsapubkey.bitlen/8]; 1/8
+ */
+ if(keyBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + bitLen / 2 + bitLen / 16) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptExportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "len=%ld", keyBlobLen);
+ goto done;
+ }
+ ptr = (BYTE*)(keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
+
+ /* Skip modulus, prime1, prime2 */
+ ptr += bitLen / 8;
+ ptr += bitLen / 16;
+ ptr += bitLen / 16;
+
+ /* Convert exponent1 to 1 */
+ for (n = 0; n < (bitLen / 16); n++) {
+ if (n == 0) ptr[n] = 1;
+ else ptr[n] = 0;
+ }
+ ptr += bitLen / 16;
+
+ /* Convert exponent2 to 1 */
+ for (n = 0; n < (bitLen / 16); n++) {
+ if (n == 0) ptr[n] = 1;
+ else ptr[n] = 0;
+ }
+ ptr += bitLen / 16;
+
+ /* Skip coefficient */
+ ptr += bitLen / 16;
+
+ /* Convert privateExponent to 1 */
+ for (n = 0; n < (bitLen / 16); n++) {
+ if (n == 0) ptr[n] = 1;
+ else ptr[n] = 0;
+ }
+
+ /* Import the exponent-of-one private key. */
+ if (!CryptImportKey(hProv, keyBlob, keyBlobLen, 0, 0, &hKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptImportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ (*hPrivateKey) = hKey;
+ hKey = 0;
+ res = TRUE;
+
+done:
+ if(keyBlob != NULL) {
+ xmlFree(keyBlob);
+ }
+ if (hKey != 0) {
+ CryptDestroyKey(hKey);
+ }
+
+ return res;
+}
+
+static BOOL
+xmlSecMSCryptoImportPlainSessionBlob(HCRYPTPROV hProv, HCRYPTKEY hPrivateKey,
+ ALG_ID dwAlgId, LPBYTE pbKeyMaterial,
+ DWORD dwKeyMaterial, HCRYPTKEY *hSessionKey) {
+ ALG_ID dwPrivKeyAlg;
+ LPBYTE keyBlob = NULL;
+ DWORD keyBlobLen, rndBlobSize, dwSize, n;
+ PUBLICKEYSTRUC* pubKeyStruc;
+ ALG_ID* algId;
+ DWORD dwPublicKeySize;
+ DWORD dwProvSessionKeySize;
+ LPBYTE pbPtr;
+ DWORD dwFlags;
+ PROV_ENUMALGS_EX ProvEnum;
+ HCRYPTKEY hTempKey = 0;
+ BOOL fFound;
+ BOOL res = FALSE;
+
+ xmlSecAssert2(hProv != 0, FALSE);
+ xmlSecAssert2(hPrivateKey != 0, FALSE);
+ xmlSecAssert2(pbKeyMaterial != NULL, FALSE);
+ xmlSecAssert2(dwKeyMaterial > 0, FALSE);
+ xmlSecAssert2(hSessionKey != NULL, FALSE);
+
+ /* Double check to see if this provider supports this algorithm and key size */
+ fFound = FALSE;
+ dwFlags = CRYPT_FIRST;
+ dwSize = sizeof(ProvEnum);
+ while(CryptGetProvParam(hProv, PP_ENUMALGS_EX, (LPBYTE)&ProvEnum, &dwSize, dwFlags)) {
+ if (ProvEnum.aiAlgid == dwAlgId) {
+ fFound = TRUE;
+ break;
+ }
+ dwSize = sizeof(ProvEnum);
+ dwFlags = 0;
+ }
+ if(!fFound) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetProvParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "algId=%d is not supported", dwAlgId);
+ goto done;
+ }
+
+ /* We have to get the key size(including padding) from an HCRYPTKEY handle.
+ * PP_ENUMALGS_EX contains the key size without the padding so we can't use it.
+ */
+ if(!CryptGenKey(hProv, dwAlgId, 0, &hTempKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGenKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "algId=%d", dwAlgId);
+ goto done;
+ }
+
+ dwSize = sizeof(DWORD);
+ if(!CryptGetKeyParam(hTempKey, KP_KEYLEN, (LPBYTE)&dwProvSessionKeySize, &dwSize, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetKeyParam(KP_KEYLEN)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "algId=%d", dwAlgId);
+ goto done;
+ }
+ CryptDestroyKey(hTempKey);
+ hTempKey = 0;
+
+ /* Our key is too big, leave */
+ if ((dwKeyMaterial * 8) > dwProvSessionKeySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "dwKeyMaterial=%ld;dwProvSessionKeySize=%ld",
+ dwKeyMaterial, dwProvSessionKeySize);
+ goto done;
+ }
+
+ /* Get private key's algorithm */
+ dwSize = sizeof(ALG_ID);
+ if(!CryptGetKeyParam(hPrivateKey, KP_ALGID, (LPBYTE)&dwPrivKeyAlg, &dwSize, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetKeyParam(KP_ALGID)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "algId=%d", dwAlgId);
+ goto done;
+ }
+
+ /* Get private key's length in bits */
+ dwSize = sizeof(DWORD);
+ if(!CryptGetKeyParam(hPrivateKey, KP_KEYLEN, (LPBYTE)&dwPublicKeySize, &dwSize, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetKeyParam(KP_KEYLEN)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "algId=%d", dwAlgId);
+ goto done;
+ }
+
+ /* 3 is for the first reserved byte after the key material and the 2 reserved bytes at the end. */
+ if(dwPublicKeySize / 8 < dwKeyMaterial + 3) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "dwKeyMaterial=%ld;dwPublicKeySize=%ld",
+ dwKeyMaterial, dwPublicKeySize);
+ goto done;
+ }
+ rndBlobSize = dwPublicKeySize / 8 - (dwKeyMaterial + 3);
+
+ /* Simple key BLOBs, type SIMPLEBLOB, are used to store and transport session keys outside a CSP.
+ * Base provider simple-key BLOBs are always encrypted with a key exchange public key. The pbData
+ * member of the SIMPLEBLOB is a sequence of bytes in the following format:
+ *
+ * PUBLICKEYSTRUC publickeystruc ;
+ * ALG_ID algid;
+ * BYTE encryptedkey[rsapubkey.bitlen/8];
+ */
+
+ /* calculate Simple blob's length */
+ keyBlobLen = sizeof(PUBLICKEYSTRUC) + sizeof(ALG_ID) + (dwPublicKeySize / 8);
+
+ /* allocate simple blob buffer */
+ keyBlob = (LPBYTE)xmlMalloc(sizeof(BYTE) * keyBlobLen);
+ if(keyBlob == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ memset(keyBlob, 0, keyBlobLen);
+
+ /* initialize PUBLICKEYSTRUC */
+ pubKeyStruc = (PUBLICKEYSTRUC*)(keyBlob);
+ pubKeyStruc->bType = SIMPLEBLOB;
+ pubKeyStruc->bVersion = 0x02;
+ pubKeyStruc->reserved = 0;
+ pubKeyStruc->aiKeyAlg = dwAlgId;
+
+ /* Copy private key algorithm to buffer */
+ algId = (ALG_ID*)(keyBlob + sizeof(PUBLICKEYSTRUC));
+ (*algId) = dwPrivKeyAlg;
+
+ /* Place the key material in reverse order */
+ pbPtr = (BYTE*)(keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(ALG_ID));
+ for (n = 0; n < dwKeyMaterial; n++) {
+ pbPtr[n] = pbKeyMaterial[dwKeyMaterial - n - 1];
+ }
+ pbPtr += dwKeyMaterial;
+
+ /* skip reserved byte */
+ pbPtr += 1;
+
+ /* Generate random data for the rest of the buffer */
+ if((rndBlobSize > 0) && !CryptGenRandom(hProv, rndBlobSize, pbPtr)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGenRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "rndBlobSize=%ld", rndBlobSize);
+ goto done;
+ }
+ /* aleksey: why are we doing this? */
+ for (n = 0; n < rndBlobSize; n++) {
+ if (pbPtr[n] == 0) pbPtr[n] = 1;
+ }
+
+ /* set magic number at the end */
+ keyBlob[keyBlobLen - 2] = 2;
+
+ if(!CryptImportKey(hProv, keyBlob , keyBlobLen, hPrivateKey, CRYPT_EXPORTABLE, hSessionKey)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptImportKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "algId=%d", dwAlgId);
+ goto done;
+ }
+
+ /* success */
+ res = TRUE;
+
+done:
+ if(hTempKey != 0) {
+ CryptDestroyKey(hTempKey);
+ }
+ if(keyBlob != NULL) {
+ xmlFree(keyBlob);
+ }
+ return(res);
+}
+
diff --git a/src/mscrypto/crypto.c b/src/mscrypto/crypto.c
new file mode 100644
index 00000000..d60d3c60
--- /dev/null
+++ b/src/mscrypto/crypto.c
@@ -0,0 +1,387 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru).
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/private.h>
+
+#include <xmlsec/mscrypto/app.h>
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/x509.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecMSCryptoFunctions = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_mscrypto:
+ *
+ * Gets MSCrypto specific functions table.
+ *
+ * Returns: xmlsec-mscrypto functions table.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_mscrypto(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecMSCryptoFunctions != NULL) {
+ return(gXmlSecMSCryptoFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecMSCryptoFunctions = &functions;
+
+ /**
+ * Crypto Init/shutdown
+ */
+ gXmlSecMSCryptoFunctions->cryptoInit = xmlSecMSCryptoInit;
+ gXmlSecMSCryptoFunctions->cryptoShutdown = xmlSecMSCryptoShutdown;
+ gXmlSecMSCryptoFunctions->cryptoKeysMngrInit = xmlSecMSCryptoKeysMngrInit;
+
+ /**
+ * Key data ids
+ */
+#ifndef XMLSEC_NO_DES
+ gXmlSecMSCryptoFunctions->keyDataDesGetKlass = xmlSecMSCryptoKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ gXmlSecMSCryptoFunctions->keyDataAesGetKlass = xmlSecMSCryptoKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecMSCryptoFunctions->keyDataRsaGetKlass = xmlSecMSCryptoKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecMSCryptoFunctions->keyDataDsaGetKlass = xmlSecMSCryptoKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecMSCryptoFunctions->keyDataGost2001GetKlass = xmlSecMSCryptoKeyDataGost2001GetKlass;
+#endif /* XMLSEC_NO_GOST*/
+
+#ifndef XMLSEC_NO_X509
+ gXmlSecMSCryptoFunctions->keyDataX509GetKlass = xmlSecMSCryptoKeyDataX509GetKlass;
+ gXmlSecMSCryptoFunctions->keyDataRawX509CertGetKlass = xmlSecMSCryptoKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /**
+ * Key data store ids
+ */
+#ifndef XMLSEC_NO_X509
+ gXmlSecMSCryptoFunctions->x509StoreGetKlass = xmlSecMSCryptoX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /**
+ * Crypto transforms ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecMSCryptoFunctions->transformAes128CbcGetKlass = xmlSecMSCryptoTransformAes128CbcGetKlass;
+ gXmlSecMSCryptoFunctions->transformAes192CbcGetKlass = xmlSecMSCryptoTransformAes192CbcGetKlass;
+ gXmlSecMSCryptoFunctions->transformAes256CbcGetKlass = xmlSecMSCryptoTransformAes256CbcGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecMSCryptoFunctions->transformDes3CbcGetKlass = xmlSecMSCryptoTransformDes3CbcGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecMSCryptoFunctions->transformRsaSha1GetKlass = xmlSecMSCryptoTransformRsaSha1GetKlass;
+ gXmlSecMSCryptoFunctions->transformRsaPkcs1GetKlass = xmlSecMSCryptoTransformRsaPkcs1GetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecMSCryptoFunctions->transformDsaSha1GetKlass = xmlSecMSCryptoTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecMSCryptoFunctions->transformGost2001GostR3411_94GetKlass = xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecMSCryptoFunctions->transformSha1GetKlass = xmlSecMSCryptoTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecMSCryptoFunctions->transformGostR3411_94GetKlass = xmlSecMSCryptoTransformGostR3411_94GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+ /**
+ * High level routines form xmlsec command line utility
+ */
+ gXmlSecMSCryptoFunctions->cryptoAppInit = xmlSecMSCryptoAppInit;
+ gXmlSecMSCryptoFunctions->cryptoAppShutdown = xmlSecMSCryptoAppShutdown;
+ gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrInit = xmlSecMSCryptoAppDefaultKeysMngrInit;
+ gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecMSCryptoAppDefaultKeysMngrAdoptKey;
+ gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecMSCryptoAppDefaultKeysMngrLoad;
+ gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrSave = xmlSecMSCryptoAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecMSCryptoFunctions->cryptoAppKeysMngrCertLoad = xmlSecMSCryptoAppKeysMngrCertLoad;
+ gXmlSecMSCryptoFunctions->cryptoAppKeysMngrCertLoadMemory = xmlSecMSCryptoAppKeysMngrCertLoadMemory;
+ gXmlSecMSCryptoFunctions->cryptoAppPkcs12Load = xmlSecMSCryptoAppPkcs12Load;
+ gXmlSecMSCryptoFunctions->cryptoAppPkcs12LoadMemory = xmlSecMSCryptoAppPkcs12LoadMemory;
+ gXmlSecMSCryptoFunctions->cryptoAppKeyCertLoad = xmlSecMSCryptoAppKeyCertLoad;
+ gXmlSecMSCryptoFunctions->cryptoAppKeyCertLoadMemory = xmlSecMSCryptoAppKeyCertLoadMemory;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecMSCryptoFunctions->cryptoAppKeyLoad = xmlSecMSCryptoAppKeyLoad;
+ gXmlSecMSCryptoFunctions->cryptoAppKeyLoadMemory = xmlSecMSCryptoAppKeyLoadMemory;
+ gXmlSecMSCryptoFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecMSCryptoAppGetDefaultPwdCallback();
+
+ return(gXmlSecMSCryptoFunctions);
+}
+
+/**
+ * xmlSecMSCryptoInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoInit (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);
+ }
+
+ /* set default errors callback for xmlsec to us */
+ xmlSecErrorsSetCallback(xmlSecMSCryptoErrorsDefaultCallback);
+
+ /* register our klasses */
+ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_mscrypto()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoShutdown(void) {
+ /* TODO: if necessary, do additional shutdown here */
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds MSCrypto specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+#ifndef XMLSEC_NO_X509
+ /* create x509 store if needed */
+ if(xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCryptoX509StoreId) == NULL) {
+ xmlSecKeyDataStorePtr x509Store;
+
+ x509Store = xmlSecKeyDataStoreCreate(xmlSecMSCryptoX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecMSCryptoX509StoreId");
+ 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);
+}
+
+
+/**
+ * xmlSecMSCryptoGenerateRandom:
+ * @buffer: the destination buffer.
+ * @size: the numer of bytes to generate.
+ *
+ * Generates @size random bytes and puts result in @buffer
+ * (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecMSCryptoGenerateRandom(xmlSecBufferPtr buffer, size_t size) {
+ HCRYPTPROV hProv = 0;
+ 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);
+ }
+
+ if (FALSE == CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptAcquireContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if (FALSE == CryptGenRandom(hProv, (DWORD)size, xmlSecBufferGetData(buffer))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGenRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptReleaseContext(hProv,0);
+ return(-1);
+ }
+
+ CryptReleaseContext(hProv, 0);
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoErrorsDefaultCallback:
+ * @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 errors reporting callback function.
+ */
+void
+xmlSecMSCryptoErrorsDefaultCallback(const char* file, int line, const char* func,
+ const char* errorObject, const char* errorSubject,
+ int reason, const char* msg) {
+ DWORD dwError;
+ LPVOID lpMsgBuf;
+ xmlChar buf[500];
+
+ dwError = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL);
+ if((msg != NULL) && ((*msg) != '\0')) {
+ xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "%s;last error=%d (0x%08x);last error msg=%s", msg, dwError, dwError, (LPTSTR)lpMsgBuf);
+ } else {
+ xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "last error=%d (0x%08x);last error msg=%s", dwError, dwError, (LPTSTR)lpMsgBuf);
+ }
+ xmlSecErrorsDefaultCallback(file, line, func,
+ errorObject, errorSubject,
+ reason, (char*)buf);
+
+ LocalFree(lpMsgBuf);
+}
+
+/**
+ * xmlSecMSCryptoCertStrToName:
+ * @dwCertEncodingType: the encoding used.
+ * @pszX500: the string to convert.
+ * @dwStrType: the string type.
+ * @len: the result len.
+ *
+ * Converts input string to name by calling @CertStrToName function.
+ *
+ * Returns: a pointer to newly allocated string or NULL if an error occurs.
+ */
+BYTE*
+xmlSecMSCryptoCertStrToName(DWORD dwCertEncodingType, LPCTSTR pszX500, DWORD dwStrType, DWORD* len) {
+ BYTE* str = NULL;
+ LPCTSTR ppszError = NULL;
+
+ xmlSecAssert2(pszX500 != NULL, NULL);
+ xmlSecAssert2(len != NULL, NULL);
+
+ if (!CertStrToName(dwCertEncodingType, pszX500, dwStrType,
+ NULL, NULL, len, &ppszError)) {
+ /* this might not be an error, string might just not exist */
+ DWORD dw = GetLastError();
+ return(NULL);
+ }
+
+ str = (BYTE *)xmlMalloc((*len) + 1);
+ if(str == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "len=%ld", (*len));
+ return(NULL);
+ }
+ memset(str, 0, (*len) + 1);
+
+ if (!CertStrToName(dwCertEncodingType, pszX500, dwStrType,
+ NULL, str, len, NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertStrToName",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(str);
+ return(NULL);
+ }
+
+ return(str);
+}
+
+
diff --git a/src/mscrypto/csp_calg.h b/src/mscrypto/csp_calg.h
new file mode 100644
index 00000000..139b722a
--- /dev/null
+++ b/src/mscrypto/csp_calg.h
@@ -0,0 +1,92 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru).
+ * All rights reserved.
+ */
+#ifndef CRYPTOCOM_CSP_CALG_H
+#define CRYPTOCOM_CSP_CALG_H
+
+#define ALG_TYPE_GR3410 (7 << 9)
+
+#define ALG_SID_MAGPRO_R3410_94 64
+#define ALG_SID_MAGPRO_R3410_94_EPHEM 65
+#define ALG_SID_MAGPRO_R3410_2001 66
+#define ALG_SID_MAGPRO_R3410_2001_EPHEM 67
+#define ALG_SID_MAGPRO_28147_89 68
+#define ALG_SID_GR3411 30
+#define ALG_SID_G28147 30
+
+#define ALG_SID_GR3410 30
+#define ALG_SID_DH_EX_SF 30
+#define ALG_SID_DH_EX_EPHEM 31
+#define ALG_SID_PRO_AGREEDKEY_DH 33
+#define ALG_SID_PRO_SIMMETRYKEY 34
+#define ALG_SID_GR3410EL 35
+#define ALG_SID_DH_EL_SF 36
+#define ALG_SID_DH_EL_EPHEM 37
+
+/*! \defgroup CALG_MAGPRO CALG_MAGPRO
+ * \brief The description of CALG_MAGPRO
+ *
+ * @{
+ */
+
+
+#define CALG_MAGPRO_SIGN_R3410_94 (ALG_CLASS_SIGNATURE | ALG_TYPE_GR3410 | ALG_SID_MAGPRO_R3410_94)
+
+#define CALG_MAGPRO_SIGN_R3410_2001 (ALG_CLASS_SIGNATURE | ALG_TYPE_GR3410 | ALG_SID_MAGPRO_R3410_2001)
+
+#define CALG_MAGPRO_DH_R3410_94 (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_MAGPRO_R3410_94)
+
+#define CALG_MAGPRO_DH_R3410_2001 (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_MAGPRO_R3410_2001)
+
+#define CALG_MAGPRO_DH_R3410_94_EPHEM (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_MAGPRO_R3410_94_EPHEM)
+
+#define CALG_MAGPRO_DH_R3410_2001_EPHEM (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_MAGPRO_R3410_2001_EPHEM)
+
+#define CALG_MAGPRO_HASH_R3411_94 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_GR3411)
+
+#define CALG_MAGPRO_HASH_28147_89 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MAGPRO_28147_89)
+
+#define CALG_MAGPRO_ENCR_28147_89 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_G28147)
+
+#define CALG_GR3410 (ALG_CLASS_SIGNATURE | ALG_TYPE_GR3410 | ALG_SID_GR3410)
+
+#define CALG_GR3410EL (ALG_CLASS_SIGNATURE | ALG_TYPE_GR3410 | ALG_SID_GR3410EL)
+
+#define CALG_DH_EX_SF (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EX_SF)
+
+#define CALG_DH_EX_EPHEM (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EX_EPHEM)
+
+#define CALG_DH_EL_SF (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EL_SF)
+
+#define CALG_DH_EL_EPHEM (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EL_EPHEM)
+
+/*! @} */
+/*! \defgroup PROV_TYPE PROV_TYPE
+ * \brief The description of PROV_MAGPRO_GOST
+ *
+ * @{
+ */
+
+#define PROV_MAGPRO_GOST 501
+
+#define PROV_CRYPTOPRO_GOST 75
+
+/*! @} */
+/*! \defgroup PP_MAGPRO PP_MAGPRO
+ *
+ * @{
+ */
+
+#define PP_RNGTYPE 201
+#define PP_RNGSHARED 202
+#define PP_SETUP_UI 203
+
+/*! @} */
+
+#endif //CRYPTOCOM_CSP_CALG_H
diff --git a/src/mscrypto/csp_oid.h b/src/mscrypto/csp_oid.h
new file mode 100644
index 00000000..d3cd19e8
--- /dev/null
+++ b/src/mscrypto/csp_oid.h
@@ -0,0 +1,114 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru).
+ * All rights reserved.
+ */
+#ifndef CRYPTOCOM_OIDS_csp_H
+#define CRYPTOCOM_OIDS_csp_H
+/* Autogenerated from master.oid by oid2h.tcl */
+
+/*! \defgroup szOID_MAGPRO szOID_MAGPRO
+ * \brief The OIDs supported by MagPro CSP
+ *
+ * @{
+ */
+
+/*! GOST 34.10-94 Diffie-Hellman algorithm Cryptocom LTD */
+#define szOID_MAGPRO_DH_R3410_94 "1.2.643.2.9.1.3.1"
+
+/*! GOST 34.10-2001 Diffie-Hellman algorithm Cryptocom LTD */
+#define szOID_MAGPRO_DH_R3410_2001 "1.2.643.2.9.1.3.2"
+
+/* */
+#define szOID_MAGPRO_DH_R3410_94_EPHEM "1.2.643.2.9.1.3.1"
+
+/* */
+#define szOID_MAGPRO_DH_R3410_2001_EPHEM "1.2.643.2.9.1.3.2"
+
+/*! GOST 34.10/11-94 digital signature algorithm Cryptocom LTD with digest */
+#define szOID_MAGPRO_SIGN_R3410_94 "1.2.643.2.9.1.3.3"
+
+/*! GOST 34.10-2001 digital signature algorithm with digest */
+#define szOID_MAGPRO_SIGN_R3410_2001 "1.2.643.2.9.1.3.4"
+
+/*! GOST 28147-89 MAC algorithm Cryptocom LTD */
+#define szOID_MAGPRO_HASH_28147_89 "1.2.643.2.9.1.4.1"
+
+#define szOID_MAGPRO_PUBKEY_DH_R3410_94 "1.2.643.2.9.1.5.1"
+
+#define szOID_MAGPRO_PUBKEY_DH_R3410_2001 "1.2.643.2.9.1.5.2"
+
+/*! GOST 34.10/11-94 digital signature algorithm Cryptocom LTD */
+#define szOID_MAGPRO_PUBKEY_SIGN_R3410_94 "1.2.643.2.9.1.5.3"
+
+/*! GOST 34.10-2001 digital signature algorithm */
+#define szOID_MAGPRO_PUBKEY_SIGN_R3410_2001 "1.2.643.2.9.1.5.4"
+
+/*! GOST 28147-89 encryption parameters */
+#define szOID_MAGPRO_PARAM_ENCR_28147_89 "1.2.643.2.9.1.6.1"
+
+/*! GOST 34.10-2001 public key parameters */
+#define szOID_MAGPRO_PARAM_PK_CC_01 "1.2.643.2.9.1.8.1"
+
+/*! GOST 28147-89 symmetric cipher Cryptocom LTD */
+#define szOID_MAGPRO_ENCR_28147_89 "1.2.643.2.2.21"
+
+/*! GOST 34.10-2001 digital signature algorithm CryptoPro LTD */
+#define szOID_MAGPRO_SIGN_R3410_2001_CP "1.2.643.2.2.3"
+
+/*! GOST 34.10/11-94 digital signature algorithm CryptoPro LTD */
+#define szOID_MAGPRO_SIGN_R3410_94_CP "1.2.643.2.2.4"
+
+/*! GOST 34.11-94 digest algorithm Cryptocom LTD */
+#define szOID_MAGPRO_HASH_R3411_94 "1.2.643.2.2.9"
+
+/*! GOST 34.10-2001 digital signature algorithm CryptoPro LTD public key */
+#define szOID_MAGPRO_PUBKEY_SIGN_R3410_2001_CP "1.2.643.2.2.19"
+
+/*! GOST 34.10/11-94 digital signature algorithm CryptoPro LTD public key */
+#define szOID_MAGPRO_PUBKEY_SIGN_R3410_94_CP "1.2.643.2.2.20"
+
+/*! GostR3411-94-CryptoProParamSet */
+#define szOID_MAGPRO_PARAM_HASH_3411_94 "1.2.643.2.2.30.1"
+
+/*! GostR3410-94-CryptoPro-A-ParamSet */
+#define szOID_MAGPRO_PARAM_PK_CC_94 "1.2.643.2.2.32.2"
+
+
+#define szOID_CP_PARAM_R3411_94_DEF "1.2.643.2.2.30.1"
+#define szOID_CP_PARAM_R3411_94_1 "1.2.643.2.2.30.2"
+#define szOID_CP_PARAM_R3411_94_2 "1.2.643.2.2.30.3"
+#define szOID_CP_PARAM_R3411_94_3 "1.2.643.2.2.30.4"
+
+#define szOID_CP_PARAM_28147_89_DEF "1.2.643.2.2.31.1"
+#define szOID_CP_PARAM_28147_89_1 "1.2.643.2.2.31.2"
+#define szOID_CP_PARAM_28147_89_2 "1.2.643.2.2.31.3"
+#define szOID_CP_PARAM_28147_89_3 "1.2.643.2.2.31.4"
+#define szOID_CP_PARAM_28147_89_4 "1.2.643.2.2.31.5"
+#define szOID_CP_PARAM_28147_89_5 "1.2.643.2.2.31.6"
+#define szOID_CP_PARAM_28147_89_6 "1.2.643.2.2.31.7"
+
+/* OID for Signature 1024*/
+#define szOID_CP_PARAM_PK_R3410_94_DEF "1.2.643.2.2.32.2" /*VerbaO*/
+#define szOID_CP_PARAM_PK_R3410_94_S1 "1.2.643.2.2.32.3"
+#define szOID_CP_PARAM_PK_R3410_94_S2 "1.2.643.2.2.32.4"
+#define szOID_CP_PARAM_PK_R3410_94_S3 "1.2.643.2.2.32.5"
+/* OID for DH 1024*/
+#define szOID_CP_PARAM_PK_R3410_94_E1 "1.2.643.2.2.33.1"
+#define szOID_CP_PARAM_PK_R3410_94_E2 "1.2.643.2.2.33.2"
+#define szOID_CP_PARAM_PK_R3410_94_E3 "1.2.643.2.2.33.3"
+
+#define szOID_CP_PARAM_PK_R3410_2001_DEF "1.2.643.2.2.35.1"
+#define szOID_CP_PARAM_PK_R3410_2001_S0 "1.2.643.2.2.35.2"
+#define szOID_CP_PARAM_PK_R3410_2001_S1 "1.2.643.2.2.35.3"
+#define szOID_CP_PARAM_PK_R3410_2001_E0 "1.2.643.2.2.36.0"
+#define szOID_CP_PARAM_PK_R3410_2001_E1 "1.2.643.2.2.36.1"
+
+
+/*! @} */
+
+#endif
diff --git a/src/mscrypto/digests.c b/src/mscrypto/digests.c
new file mode 100644
index 00000000..19acc658
--- /dev/null
+++ b/src/mscrypto/digests.c
@@ -0,0 +1,413 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru).
+ */
+#include "globals.h"
+
+#include <string.h>
+#include <windows.h>
+#include <wincrypt.h>
+#ifndef XMLSEC_NO_GOST
+#include "csp_calg.h"
+#endif
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+
+#define MSCRYPTO_MAX_HASH_SIZE 256
+
+typedef struct _xmlSecMSCryptoDigestCtx xmlSecMSCryptoDigestCtx, *xmlSecMSCryptoDigestCtxPtr;
+struct _xmlSecMSCryptoDigestCtx {
+ HCRYPTPROV provider;
+ ALG_ID alg_id;
+ HCRYPTHASH mscHash;
+ unsigned char dgst[MSCRYPTO_MAX_HASH_SIZE];
+ size_t dgstSize; /* dgst size in bytes */
+};
+
+/******************************************************************************
+ *
+ * MSCrypto Digest transforms
+ *
+ * xmlSecMSCryptoDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecMSCryptoDigestSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoDigestCtx))
+#define xmlSecMSCryptoDigestGetCtx(transform) \
+ ((xmlSecMSCryptoDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+
+static int xmlSecMSCryptoDigestInitialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoDigestFinalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoDigestVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoDigestExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoDigestCheckId (xmlSecTransformPtr transform);
+
+
+static int
+xmlSecMSCryptoDigestCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_GOST
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_GOST*/
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoDigestInitialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoDigestSize), -1);
+
+ ctx = xmlSecMSCryptoDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecMSCryptoDigestCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha1Id)) {
+ ctx->alg_id = CALG_SHA;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_GOST
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) {
+ ctx->alg_id = CALG_MAGPRO_HASH_R3411_94;
+
+ /* TODO: Check what provider is best suited here.... */
+ if (!CryptAcquireContext(&ctx->provider, NULL, 0, PROV_MAGPRO_GOST, CRYPT_VERIFYCONTEXT)) {
+ if (!CryptAcquireContext(&ctx->provider, NULL, 0, PROV_CRYPTOPRO_GOST, CRYPT_VERIFYCONTEXT)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+ } else
+#endif /* XMLSEC_NO_GOST*/
+
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* TODO: Check what provider is best suited here.... */
+ if (!CryptAcquireContext(&ctx->provider, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ if (!CryptAcquireContext(&ctx->provider, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static void xmlSecMSCryptoDigestFinalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoDigestCtxPtr ctx;
+
+ xmlSecAssert(xmlSecMSCryptoDigestCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoDigestSize));
+
+ ctx = xmlSecMSCryptoDigestGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->mscHash != 0) {
+ CryptDestroyHash(ctx->mscHash);
+ }
+ CryptReleaseContext(ctx->provider, 0);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoDigestCtx));
+}
+
+static int
+xmlSecMSCryptoDigestVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoDigestSize), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoDigestGetCtx(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
+xmlSecMSCryptoDigestExecute(xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoDigestCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoDigestCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoDigestSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ xmlSecAssert2(in != NULL, -1);
+
+ out = &(transform->outBuf);
+ xmlSecAssert2(out != NULL, -1);
+
+ ctx = xmlSecMSCryptoDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ ret = CryptCreateHash(ctx->provider,
+ ctx->alg_id,
+ 0,
+ 0,
+ &(ctx->mscHash));
+
+ if((ret == 0) || (ctx->mscHash == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptHashData",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if (transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ ret = CryptHashData(ctx->mscHash,
+ xmlSecBufferGetData(in),
+ inSize,
+ 0);
+
+ if(ret == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptHashData",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", inSize);
+ 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);
+ }
+ }
+ if(last) {
+ /* TODO: make a MSCrypto compatible assert here */
+ /* xmlSecAssert2((xmlSecSize)EVP_MD_size(ctx->digest) <= sizeof(ctx->dgst), -1); */
+ DWORD retLen;
+ retLen = MSCRYPTO_MAX_HASH_SIZE;
+
+ ret = CryptGetHashParam(ctx->mscHash,
+ HP_HASHVAL,
+ ctx->dgst,
+ &retLen,
+ 0);
+
+ if (ret == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptGetHashParam",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ ctx->dgstSize = (size_t)retLen;
+
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ /* 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_SHA1
+/******************************************************************************
+ *
+ * SHA1
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoDigestSize, /* size_t objSize */
+
+ xmlSecNameSha1, /* const xmlChar* name; */
+ xmlSecHrefSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+ xmlSecMSCryptoDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformSha1GetKlass(void) {
+ return(&xmlSecMSCryptoSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_GOST
+/******************************************************************************
+ *
+ * GOSTR3411_94
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoGostR3411_94Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoDigestSize, /* size_t objSize */
+
+ xmlSecNameGostR3411_94, /* const xmlChar* name; */
+ xmlSecHrefGostR3411_94, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+ xmlSecMSCryptoDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformGostR3411_94GetKlass:
+ *
+ * GOSTR3411_94 digest transform klass.
+ *
+ * Returns: pointer to GOSTR3411_94 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformGostR3411_94GetKlass(void) {
+ return(&xmlSecMSCryptoGostR3411_94Klass);
+}
+#endif /* XMLSEC_NO_GOST*/
+
diff --git a/src/mscrypto/globals.h b/src/mscrypto/globals.h
new file mode 100644
index 00000000..b58931d5
--- /dev/null
+++ b/src/mscrypto/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.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ */
+#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/mscrypto/keysstore.c b/src/mscrypto/keysstore.c
new file mode 100644
index 00000000..6e2401b4
--- /dev/null
+++ b/src/mscrypto/keysstore.c
@@ -0,0 +1,678 @@
+/**
+ * XMLSec library
+ *
+ * MSCrypto keys store that uses Simple Keys Store under the hood. Uses the
+ * MS Certificate store as a backing store for the finding keys, but the
+ * MS Certificate store not written to by the keys store.
+ * So, if store->findkey is done and the key is not found in the simple
+ * keys store, the MS Certificate store is looked up.
+ * Thus, the MS Certificate store can be used to pre-load keys and becomes
+ * an alternate source of keys for xmlsec
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for precise wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/xmltree.h>
+
+#include <xmlsec/keysmngr.h>
+
+#include <xmlsec/mscrypto/app.h>
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/keysstore.h>
+#include <xmlsec/mscrypto/x509.h>
+#include <xmlsec/mscrypto/certkeys.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+#define XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME "MY"
+
+/****************************************************************************
+ *
+ * MSCrypto Keys Store. Uses Simple Keys Store under the hood
+ *
+ * Simple Keys Store ptr is located after xmlSecKeyStore
+ *
+ ***************************************************************************/
+#define xmlSecMSCryptoKeysStoreSize \
+ (sizeof(xmlSecKeyStore) + sizeof(xmlSecKeyStorePtr))
+
+#define xmlSecMSCryptoKeysStoreGetSS(store) \
+ ((xmlSecKeyStoreCheckSize((store), xmlSecMSCryptoKeysStoreSize)) ? \
+ (xmlSecKeyStorePtr*)(((xmlSecByte*)(store)) + sizeof(xmlSecKeyStore)) : \
+ (xmlSecKeyStorePtr*)NULL)
+
+static int xmlSecMSCryptoKeysStoreInitialize (xmlSecKeyStorePtr store);
+static void xmlSecMSCryptoKeysStoreFinalize (xmlSecKeyStorePtr store);
+static xmlSecKeyPtr xmlSecMSCryptoKeysStoreFindKey (xmlSecKeyStorePtr store,
+ const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyStoreKlass xmlSecMSCryptoKeysStoreKlass = {
+ sizeof(xmlSecKeyStoreKlass),
+ xmlSecMSCryptoKeysStoreSize,
+
+ /* data */
+ BAD_CAST "MSCrypto-keys-store", /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoKeysStoreInitialize, /* xmlSecKeyStoreInitializeMethod initialize; */
+ xmlSecMSCryptoKeysStoreFinalize, /* xmlSecKeyStoreFinalizeMethod finalize; */
+ xmlSecMSCryptoKeysStoreFindKey, /* xmlSecKeyStoreFindKeyMethod findKey; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeysStoreGetKlass:
+ *
+ * The MSCrypto list based keys store klass.
+ *
+ * Returns: MSCrypto list based keys store klass.
+ */
+xmlSecKeyStoreId
+xmlSecMSCryptoKeysStoreGetKlass(void) {
+ return(&xmlSecMSCryptoKeysStoreKlass);
+}
+
+/**
+ * xmlSecMSCryptoKeysStoreAdoptKey:
+ * @store: the pointer to MSCrypto keys store.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the @store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoKeysStoreAdoptKey(xmlSecKeyStorePtr store, xmlSecKeyPtr key) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId), -1);
+ xmlSecAssert2((key != NULL), -1);
+
+ ss = xmlSecMSCryptoKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
+ (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
+
+ return (xmlSecSimpleKeysStoreAdoptKey(*ss, key));
+}
+
+/**
+ * xmlSecMSCryptoKeysStoreLoad:
+ * @store: the pointer to MSCrypto keys store.
+ * @uri: the filename.
+ * @keysMngr: the pointer to associated keys manager.
+ *
+ * Reads keys from an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoKeysStoreLoad(xmlSecKeyStorePtr store, const char *uri,
+ xmlSecKeysMngrPtr keysMngr) {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr cur;
+ xmlSecKeyPtr key;
+ xmlSecKeyInfoCtx keyInfoCtx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId), -1);
+ xmlSecAssert2((uri != NULL), -1);
+
+ doc = xmlParseFile(uri);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlParseFile",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if(!xmlSecCheckNodeName(root, BAD_CAST "Keys", xmlSecNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(root)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=<xmlsec:Keys>");
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(root->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ keyInfoCtx.mode = xmlSecKeyInfoModeRead;
+ keyInfoCtx.keysMngr = keysMngr;
+ keyInfoCtx.flags = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
+ XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+ keyInfoCtx.keyReq.keyId = xmlSecKeyDataIdUnknown;
+ keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
+ keyInfoCtx.keyReq.keyUsage= xmlSecKeyDataUsageAny;
+
+ ret = xmlSecKeyInfoNodeRead(cur, key, &keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+
+ if(xmlSecKeyIsValid(key)) {
+ ret = xmlSecMSCryptoKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecMSCryptoKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ } else {
+ /* we have an unknown key in our file, just ignore it */
+ xmlSecKeyDestroy(key);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ xmlFreeDoc(doc);
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoKeysStoreSave:
+ * @store: the pointer to MSCrypto keys store.
+ * @filename: the filename.
+ * @type: the saved keys type (public, private, ...).
+ *
+ * Writes keys from @store to an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoKeysStoreSave(xmlSecKeyStorePtr store, const char *filename, xmlSecKeyDataType type) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId), -1);
+ xmlSecAssert2((filename != NULL), -1);
+
+ ss = xmlSecMSCryptoKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
+ (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
+
+ return (xmlSecSimpleKeysStoreSave(*ss, filename, type));
+}
+
+static int
+xmlSecMSCryptoKeysStoreInitialize(xmlSecKeyStorePtr store) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId), -1);
+
+ ss = xmlSecMSCryptoKeysStoreGetSS(store);
+ xmlSecAssert2((*ss == NULL), -1);
+
+ *ss = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId);
+ if(*ss == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecSimpleKeysStoreId");
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecMSCryptoKeysStoreFinalize(xmlSecKeyStorePtr store) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId));
+
+ ss = xmlSecMSCryptoKeysStoreGetSS(store);
+ xmlSecAssert((ss != NULL) && (*ss != NULL));
+
+ xmlSecKeyStoreDestroy(*ss);
+}
+
+static PCCERT_CONTEXT
+xmlSecMSCryptoKeysStoreFindCert(xmlSecKeyStorePtr store, const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ const char* storeName;
+ HCERTSTORE hStoreHandle = NULL;
+ PCCERT_CONTEXT pCertContext = NULL;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId), NULL);
+ xmlSecAssert2(name != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ storeName = xmlSecMSCryptoAppGetCertStoreName();
+ if(storeName == NULL) {
+ storeName = XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME;
+ }
+
+ hStoreHandle = CertOpenSystemStore(0, storeName);
+ if (NULL == hStoreHandle) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertOpenSystemStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "storeName=%s",
+ xmlSecErrorsSafeString(storeName));
+ return(NULL);
+ }
+
+ /* first attempt: search by cert id == name */
+ if(pCertContext == NULL) {
+ size_t len = xmlStrlen(name) + 1;
+ wchar_t * lpCertID;
+
+ /* aleksey todo: shouldn't we call MultiByteToWideChar first to get the buffer size? */
+ lpCertID = (wchar_t *)xmlMalloc(sizeof(wchar_t) * len);
+ if(lpCertID == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(hStoreHandle, 0);
+ return(NULL);
+ }
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, lpCertID, len);
+
+ pCertContext = CertFindCertificateInStore(
+ hStoreHandle,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_STR,
+ lpCertID,
+ NULL);
+ xmlFree(lpCertID);
+ }
+
+ /* We don't give up easily, now try to fetch the cert with a full blown
+ * subject dn
+ */
+ if (NULL == pCertContext) {
+ BYTE* bdata;
+ DWORD len;
+
+ bdata = xmlSecMSCryptoCertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ name,
+ CERT_OID_NAME_STR,
+ &len);
+ if(bdata != NULL) {
+ CERT_NAME_BLOB cnb;
+
+ cnb.cbData = len;
+ cnb.pbData = bdata;
+
+ pCertContext = CertFindCertificateInStore(hStoreHandle,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* We don't give up easily, now try to fetch the cert with a full blown
+ * subject dn, and try with a reversed dn
+ */
+ if (NULL == pCertContext) {
+ BYTE* bdata;
+ DWORD len;
+
+ bdata = xmlSecMSCryptoCertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ name,
+ CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &len);
+ if(bdata != NULL) {
+ CERT_NAME_BLOB cnb;
+
+ cnb.cbData = len;
+ cnb.pbData = bdata;
+
+ pCertContext = CertFindCertificateInStore(hStoreHandle,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /*
+ * Try ro find certificate with name="Friendly Name"
+ */
+ if (NULL == pCertContext) {
+ DWORD dwPropSize;
+ PBYTE pbFriendlyName;
+ PCCERT_CONTEXT pCertCtxIter = NULL;
+ size_t len = xmlStrlen(name) + 1;
+ wchar_t * lpFName;
+
+ lpFName = (wchar_t *)xmlMalloc(sizeof(wchar_t) * len);
+ if(lpFName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(hStoreHandle, 0);
+ return(NULL);
+ }
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, lpFName, len);
+
+ while (pCertCtxIter = CertEnumCertificatesInStore(hStoreHandle, pCertCtxIter)) {
+ if (TRUE != CertGetCertificateContextProperty(pCertCtxIter,
+ CERT_FRIENDLY_NAME_PROP_ID,
+ NULL,
+ &dwPropSize)) {
+ continue;
+ }
+
+ pbFriendlyName = xmlMalloc(dwPropSize);
+ if(pbFriendlyName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(lpFName);
+ CertCloseStore(hStoreHandle, 0);
+ return(NULL);
+ }
+ if (TRUE != CertGetCertificateContextProperty(pCertCtxIter,
+ CERT_FRIENDLY_NAME_PROP_ID,
+ pbFriendlyName,
+ &dwPropSize)) {
+ xmlFree(pbFriendlyName);
+ continue;
+ }
+
+ /* Compare FriendlyName to name */
+ if (!wcscmp(lpFName, (const wchar_t *)pbFriendlyName)) {
+ pCertContext = pCertCtxIter;
+ xmlFree(pbFriendlyName);
+ break;
+ }
+ xmlFree(pbFriendlyName);
+ }
+
+ xmlFree(lpFName);
+ }
+
+ /* We could do the following here:
+ * It would be nice if we could locate the cert with issuer name and
+ * serial number, the given keyname can be something like this:
+ * 'serial=1234567;issuer=CN=ikke, C=NL'
+ * to be implemented by the first person who reads this, and thinks it's
+ * a good idea :) WK
+ */
+
+ /* OK, I give up, I'm gone :( */
+
+ /* aleksey todo: is it a right idea to close store if we have a handle to
+ * a cert in this store? */
+ CertCloseStore(hStoreHandle, 0);
+ return(pCertContext);
+}
+
+
+static xmlSecKeyPtr
+xmlSecMSCryptoKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyStorePtr* ss;
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyReqPtr keyReq = NULL;
+ PCCERT_CONTEXT pCertContext = NULL;
+ PCCERT_CONTEXT pCertContext2 = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ xmlSecKeyPtr res = NULL;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecMSCryptoKeysStoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ss = xmlSecMSCryptoKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL)), NULL);
+
+ /* first try to find key in the simple keys store */
+ key = xmlSecKeyStoreFindKey(*ss, name, keyInfoCtx);
+ if (key != NULL) {
+ return (key);
+ }
+
+ /* Next try to find the key in the MS Certificate store, and construct an xmlSecKey.
+ * we must have a name to lookup keys in the certificate store.
+ */
+ if (name == NULL) {
+ goto done;
+ }
+
+ /* what type of key are we looking for?
+ * WK: For now, we'll look only for public/private keys using the
+ * name as a cert nickname. Then the name is regarded as the subject
+ * dn of the certificate to be searched for.
+ */
+ keyReq = &(keyInfoCtx->keyReq);
+ if (keyReq->keyType & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) {
+ pCertContext = xmlSecMSCryptoKeysStoreFindCert(store, name, keyInfoCtx);
+ if(pCertContext == NULL) {
+ goto done;
+ }
+
+ /* set cert in x509 data */
+ x509Data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ pCertContext2 = CertDuplicateCertificateContext(pCertContext);
+ if (NULL == pCertContext2) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(x509Data, pCertContext2);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ pCertContext2 = NULL;
+
+ pCertContext2 = CertDuplicateCertificateContext(pCertContext);
+ if (NULL == pCertContext2) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptKeyCert(x509Data, pCertContext2);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ pCertContext2 = NULL;
+
+ /* set cert in key data */
+ data = xmlSecMSCryptoCertAdopt(pCertContext, keyReq->keyType);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoCertAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pCertContext = NULL;
+
+ /* create key and add key data and x509 data to it */
+ 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(data)));
+ 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)));
+ goto done;
+ }
+ x509Data = NULL;
+
+ /* Set the name of the key to the given name */
+ ret = xmlSecKeySetName(key, name);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeySetName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* now that we have a key, make sure it is valid and let the simple
+ * store adopt it */
+ if (xmlSecKeyIsValid(key)) {
+ res = key;
+ key = NULL;
+ }
+ }
+
+done:
+ if (NULL != pCertContext) {
+ CertFreeCertificateContext(pCertContext);
+ }
+ if (NULL != pCertContext2) {
+ CertFreeCertificateContext(pCertContext2);
+ }
+ if (data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if (x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if (key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+
+ return (res);
+}
diff --git a/src/mscrypto/kt_rsa.c b/src/mscrypto/kt_rsa.c
new file mode 100644
index 00000000..ec86ac53
--- /dev/null
+++ b/src/mscrypto/kt_rsa.c
@@ -0,0 +1,410 @@
+/**
+ *
+ * XMLSec library
+ *
+ * RSA Algorithms support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_RSA
+
+#include <stdlib.h>
+#include <string.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/keyinfo.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/certkeys.h>
+
+/**************************************************************************
+ *
+ * Internal MSCRYPTO RSA PKCS1 CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecMSCryptoRsaPkcs1Ctx xmlSecMSCryptoRsaPkcs1Ctx,
+ *xmlSecMSCryptoRsaPkcs1CtxPtr;
+struct _xmlSecMSCryptoRsaPkcs1Ctx {
+ xmlSecKeyDataPtr data;
+ DWORD typeFlags;
+};
+
+/*********************************************************************
+ *
+ * RSA PKCS1 key transport transform
+ *
+ * xmlSecMSCryptoRsaPkcs1Ctx is located after xmlSecTransform
+ *
+ ********************************************************************/
+#define xmlSecMSCryptoRsaPkcs1Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoRsaPkcs1Ctx))
+#define xmlSecMSCryptoRsaPkcs1GetCtx(transform) \
+ ((xmlSecMSCryptoRsaPkcs1CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecMSCryptoRsaPkcs1Initialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoRsaPkcs1Finalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoRsaPkcs1SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoRsaPkcs1SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoRsaPkcs1Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoRsaPkcs1Process (xmlSecTransformPtr transform,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecMSCryptoRsaPkcs1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoRsaPkcs1Size, /* xmlSecSize objSize */
+
+ xmlSecNameRsaPkcs1, /* const xmlChar* name; */
+ xmlSecHrefRsaPkcs1, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoRsaPkcs1Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoRsaPkcs1Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoRsaPkcs1SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoRsaPkcs1SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoRsaPkcs1Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+
+/**
+ * xmlSecMSCryptoTransformRsaPkcs1GetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaPkcs1GetKlass(void) {
+ return(&xmlSecMSCryptoRsaPkcs1Klass);
+}
+
+static int
+xmlSecMSCryptoRsaPkcs1Initialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1Size), -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoRsaPkcs1Ctx));
+ return(0);
+}
+
+static void
+xmlSecMSCryptoRsaPkcs1Finalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1Size));
+
+ ctx = xmlSecMSCryptoRsaPkcs1GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->data != NULL) {
+ xmlSecKeyDataDestroy(ctx->data);
+ ctx->data = NULL;
+ }
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoRsaPkcs1Ctx));
+}
+
+static int
+xmlSecMSCryptoRsaPkcs1SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecMSCryptoRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecMSCryptoKeyDataRsaId;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ return(0);
+}
+
+static int
+xmlSecMSCryptoRsaPkcs1SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1Size), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataRsaId), -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->data == NULL, -1);
+
+ ctx->data = xmlSecKeyDataDuplicate(xmlSecKeyGetValue(key));
+ if(ctx->data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKeyDataDuplicate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoRsaPkcs1Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoRsaPkcs1CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != 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 = xmlSecMSCryptoRsaPkcs1Process(transform, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoRsaPkcs1Process",
+ 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
+xmlSecMSCryptoRsaPkcs1Process(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoRsaPkcs1CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ xmlSecSize keySize;
+ int ret;
+ HCRYPTKEY hKey = 0;
+ DWORD dwInLen;
+ DWORD dwBufLen;
+ DWORD dwOutLen;
+ BYTE * outBuf;
+ BYTE * inBuf;
+ int i;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->data != NULL, -1);
+
+ keySize = xmlSecKeyDataGetSize(ctx->data) / 8;
+ 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) {
+ BYTE ch;
+
+ if(inSize > outSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "inSize=%d;outSize=%d",
+ inSize, outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(out, xmlSecBufferGetData(in), inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ dwInLen = inSize;
+ dwBufLen = outSize;
+ if (0 == (hKey = xmlSecMSCryptoKeyDataGetKey(ctx->data, xmlSecKeyDataTypePublic))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataGetKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+
+ outBuf = xmlSecBufferGetData(out);
+ xmlSecAssert2(outBuf != NULL, -1);
+ if (!CryptEncrypt(hKey, 0, TRUE, 0, outBuf, &dwInLen, dwBufLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+
+ /* The output of CryptEncrypt is in little-endian format, so we have to convert to
+ * big-endian first.
+ */
+ for(i = 0; i < outSize / 2; i++) {
+ ch = outBuf[i];
+ outBuf[i] = outBuf[outSize - (i + 1)];
+ outBuf[outSize - (i + 1)] = ch;
+ }
+ } else {
+ dwOutLen = inSize;
+
+ /* The input of CryptDecrypt is expected to be little-endian,
+ * so we have to convert from big-endian to little endian.
+ */
+ inBuf = xmlSecBufferGetData(in);
+ outBuf = xmlSecBufferGetData(out);
+
+ xmlSecAssert2(inBuf != 0, -1);
+ xmlSecAssert2(outBuf != 0, -1);
+ for (i = 0; i < inSize; i++) {
+ outBuf[i] = inBuf[inSize - (i + 1)];
+ }
+
+ if (0 == (hKey = xmlSecMSCryptoKeyDataGetDecryptKey(ctx->data))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataGetKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+ if (!CryptDecrypt(hKey, 0, TRUE, 0, outBuf, &dwOutLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptDecrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ outSize = dwOutLen;
+ }
+
+ 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/mscrypto/mingw-crypt32.def b/src/mscrypto/mingw-crypt32.def
new file mode 100644
index 00000000..0857d558
--- /dev/null
+++ b/src/mscrypto/mingw-crypt32.def
@@ -0,0 +1,32 @@
+IMPORTS
+ CertAddCertificateContextToStore@16 = crypt32.CertAddCertificateContextToStore
+ CertAddCRLContextToStore@16 = crypt32.CertAddCRLContextToStore
+ CertAddStoreToCollection@16 = crypt32.CertAddStoreToCollection
+ CertCloseStore@8 = crypt32.CertCloseStore
+ CertCompareCertificateName@12 = crypt32.CertCompareCertificateName
+ CertCreateCertificateContext@12 = crypt32.CertCreateCertificateContext
+ CertCreateCRLContext@12 = crypt32.CertCreateCRLContext
+ CertDuplicateCertificateContext@4 = crypt32.CertDuplicateCertificateContext
+ CertDuplicateCRLContext@4 = crypt32.CertDuplicateCRLContext
+ CertEnumCertificatesInStore@8 = crypt32.CertEnumCertificatesInStore
+ CertEnumCRLsInStore@8 = crypt32.CertEnumCRLsInStore
+ CertFindCertificateInCRL@20 = crypt32.CertFindCertificateInCRL
+ CertFindCertificateInStore@24 = crypt32.CertFindCertificateInStore
+ CertFindExtension@12 = crypt32.CertFindExtension
+ CertFreeCertificateChain@4 = crypt32.CertFreeCertificateChain
+ CertFreeCertificateContext@4 = crypt32.CertFreeCertificateContext
+ CertFreeCRLContext@4 = crypt32.CertFreeCRLContext
+ CertGetCertificateChain@32 = crypt32.CertGetCertificateChain
+ CertGetCertificateContextProperty@16 = crypt32.CertGetCertificateContextProperty
+ CertGetNameStringA@24 = crypt32.CertGetNameStringA
+ CertGetPublicKeyLength@8 = crypt32.CertGetPublicKeyLength
+ CertNameToStrA@20 = crypt32.CertNameToStrA
+ CertOpenStore@20 = crypt32.CertOpenStore
+ CertOpenSystemStoreA@8 = crypt32.CertOpenSystemStoreA
+ CertStrToNameA@28 = crypt32.CertStrToNameA
+ CertVerifySubjectCertificateContext@12 = crypt32.CertVerifySubjectCertificateContext
+ CryptAcquireCertificatePrivateKey@24 = crypt32.CryptAcquireCertificatePrivateKey
+ CryptImportPublicKeyInfo@16 = crypt32.CryptImportPublicKeyInfo
+ PFXImportCertStore@12 = crypt32.PFXImportCertStore
+ PFXIsPFXBlob@4 = crypt32.PFXIsPFXBlob
+ PFXVerifyPassword@12 = crypt32.PFXVerifyPassword
diff --git a/src/mscrypto/signatures.c b/src/mscrypto/signatures.c
new file mode 100644
index 00000000..a567db7d
--- /dev/null
+++ b/src/mscrypto/signatures.c
@@ -0,0 +1,663 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru).
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+#ifndef XMLSEC_NO_GOST
+#include "csp_calg.h"
+#endif
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/symbols.h>
+#include <xmlsec/mscrypto/certkeys.h>
+#include <xmlsec/mscrypto/x509.h>
+
+/*FIXME: include header files*/
+extern HCRYPTPROV xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data);
+extern DWORD xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data);
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+/**************************************************************************
+ *
+ * Internal MSCrypto signatures ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecMSCryptoSignatureCtx xmlSecMSCryptoSignatureCtx,
+ *xmlSecMSCryptoSignatureCtxPtr;
+struct _xmlSecMSCryptoSignatureCtx {
+ xmlSecKeyDataPtr data;
+ ALG_ID alg_id;
+ HCRYPTHASH mscHash;
+ ALG_ID digestAlgId;
+ xmlSecKeyDataId keyId;
+};
+
+/******************************************************************************
+ *
+ * Signature transforms
+ *
+ * xmlSecMSCryptoSignatureCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecMSCryptoSignatureSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoSignatureCtx))
+#define xmlSecMSCryptoSignatureGetCtx(transform) \
+ ((xmlSecMSCryptoSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecMSCryptoSignatureCheckId (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoSignatureInitialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoSignatureFinalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoSignatureSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoSignatureSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoSignatureVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoSignatureExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+
+static int xmlSecMSCryptoSignatureCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_GOST*/
+
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_RSA */
+
+ return(0);
+}
+
+static int xmlSecMSCryptoSignatureInitialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoSignatureSize), -1);
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoSignatureCtx));
+
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ ctx->digestAlgId = CALG_SHA1;
+ ctx->keyId = xmlSecMSCryptoKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_GOST
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ ctx->digestAlgId = CALG_MAGPRO_HASH_R3411_94;
+ ctx->keyId = xmlSecMSCryptoKeyDataGost2001Id;
+ } else
+#endif /* XMLSEC_NO_GOST*/
+
+#ifndef XMLSEC_NO_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
+ ctx->digestAlgId = CALG_SHA1;
+ ctx->keyId = xmlSecMSCryptoKeyDataDsaId;
+ } else
+#endif /* XMLSEC_NO_DSA */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void xmlSecMSCryptoSignatureFinalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoSignatureCtxPtr ctx;
+
+ xmlSecAssert(xmlSecMSCryptoSignatureCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoSignatureSize));
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->mscHash) {
+ CryptDestroyHash(ctx->mscHash);
+ }
+
+ if (ctx->data != NULL) {
+ xmlSecKeyDataDestroy(ctx->data);
+ ctx->data = NULL;
+ }
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoSignatureCtx));
+}
+
+static int xmlSecMSCryptoSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoSignatureCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+
+ xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoSignatureSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestAlgId != 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(value != NULL, -1);
+
+ ctx->data = xmlSecKeyDataDuplicate(value);
+ if(ctx->data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKeyDataDuplicate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int xmlSecMSCryptoSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecMSCryptoSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoSignatureSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(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 xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoSignatureCtxPtr ctx;
+ xmlSecBuffer tmp;
+ HCRYPTKEY hKey;
+ DWORD dwError;
+ BYTE *tmpBuf, *j, *k, *l, *m;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoSignatureSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&tmp, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "dataSize=%d", dataSize);
+ return(-1);
+ }
+
+ tmpBuf = xmlSecBufferGetData(&tmp);
+ xmlSecAssert2(tmpBuf != NULL, -1);
+
+ /* Reverse the sig - Windows stores integers as octet streams in little endian
+ * order. The I2OSP algorithm used by XMLDSig to store integers is big endian */
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
+ j = (BYTE *)data;
+ k = (BYTE *)data + 20;
+ l = tmpBuf + 19;
+ m = tmpBuf + 39;
+ while (l >= tmpBuf) {
+ *l-- = *j++;
+ *m-- = *k++;
+ }
+#ifndef XMLSEC_NO_GOST
+ } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ j = (BYTE *)data;
+ l = tmpBuf + dataSize - 1;
+ while (l >= tmpBuf) {
+ *l-- = *j++;
+ }
+#endif /*ndef XMLSEC_NO_GOST*/
+ } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ j = (BYTE *)data;
+ l = tmpBuf + dataSize - 1;
+ while (l >= tmpBuf) {
+ *l-- = *j++;
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Invalid algo");
+ xmlSecBufferFinalize(&tmp);
+ return(-1);
+ }
+
+ hKey = xmlSecMSCryptoKeyDataGetKey(ctx->data, xmlSecKeyDataTypePublic);
+ if (hKey == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoKeyDataGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&tmp);
+ return(-1);
+ }
+ if (!CryptVerifySignature(ctx->mscHash,
+ tmpBuf,
+ dataSize,
+ hKey,
+ NULL,
+ 0)) {
+ dwError = GetLastError();
+ if (NTE_BAD_SIGNATURE == dwError) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptVerifySignature",
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "signature do not match");
+ transform->status = xmlSecTransformStatusFail;
+ xmlSecBufferFinalize(&tmp);
+ return(0);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptVerifySignature",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&tmp);
+ return (-1);
+ }
+ }
+ xmlSecBufferFinalize(&tmp);
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoSignatureCtxPtr ctx;
+ HCRYPTPROV hProv;
+ DWORD dwKeySpec;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ int ret;
+ DWORD dwSigLen;
+ BYTE *tmpBuf, *outBuf, *i, *j, *m, *n;
+
+ xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoSignatureSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ ctx = xmlSecMSCryptoSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestAlgId != 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if (0 == (hProv = xmlSecMSCryptoKeyDataGetMSCryptoProvider(ctx->data))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoKeyDataGetMSCryptoProvider",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+ if (!CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptCreateHash",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (inSize > 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if (!CryptHashData(ctx->mscHash, xmlSecBufferGetData(in), inSize, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptHashData",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ 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)) {
+ xmlSecBuffer tmp;
+
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ dwKeySpec = xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(ctx->data);
+ if (!CryptSignHash(ctx->mscHash, dwKeySpec, NULL, 0, NULL, &dwSigLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptSignHash",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = (xmlSecSize)dwSigLen;
+
+ ret = xmlSecBufferInitialize(&tmp, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+ tmpBuf = xmlSecBufferGetData(&tmp);
+ xmlSecAssert2(tmpBuf != NULL, -1);
+
+ if (!CryptSignHash(ctx->mscHash, dwKeySpec, NULL, 0, tmpBuf, &dwSigLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptSignHash",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&tmp);
+ return(-1);
+ }
+ outSize = (xmlSecSize)dwSigLen;
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ xmlSecBufferFinalize(&tmp);
+ return(-1);
+ }
+ outBuf = xmlSecBufferGetData(out);
+ xmlSecAssert2(outBuf != NULL, -1);
+
+ /* Now encode into a signature block,
+ * convert signature value to big endian */
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
+ i = tmpBuf;
+ j = tmpBuf + 20;
+ m = outBuf + 19;
+ n = outBuf + 39;
+ while (m >= outBuf) {
+ *m-- = *i++;
+ *n-- = *j++;
+ }
+#ifndef XMLSEC_NO_GOST
+ } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ i = tmpBuf;
+ j = outBuf + dwSigLen - 1;
+
+ while (j >= outBuf) {
+ *j-- = *i++;
+ }
+#endif /*ndef XMLSEC_NO_GOST*/
+ } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ i = tmpBuf;
+ j = outBuf + dwSigLen - 1;
+
+ while (j >= outBuf) {
+ *j-- = *i++;
+ }
+ } else {
+ /* We shouldn't get at this place */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Invalid algo");
+ xmlSecBufferFinalize(&tmp);
+ return(-1);
+ }
+ xmlSecBufferFinalize(&tmp);
+ }
+ 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_RSA
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha1, /* const xmlChar* name; */
+ xmlSecHrefRsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaSha1GetKlass(void) {
+ return(&xmlSecMSCryptoRsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+/****************************************************************************
+ *
+ * DSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+
+static xmlSecTransformKlass xmlSecMSCryptoDsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameDsaSha1, /* const xmlChar* name; */
+ xmlSecHrefDsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformDsaSha1GetKlass(void) {
+ return(&xmlSecMSCryptoDsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+/****************************************************************************
+ *
+ * GOST2001-GOSTR3411_94 signature transform
+ *
+ ***************************************************************************/
+
+static xmlSecTransformKlass xmlSecMSCryptoGost2001GostR3411_94Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameGost2001GostR3411_94, /* const xmlChar* name; */
+ xmlSecHrefGost2001GostR3411_94, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass:
+ *
+ * The GOST2001-GOSTR3411_94 signature transform klass.
+ *
+ * Returns: GOST2001-GOSTR3411_94 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass(void) {
+ return(&xmlSecMSCryptoGost2001GostR3411_94Klass);
+}
+
+#endif /* XMLSEC_NO_GOST*/
+
diff --git a/src/mscrypto/symkeys.c b/src/mscrypto/symkeys.c
new file mode 100644
index 00000000..371c52de
--- /dev/null
+++ b/src/mscrypto/symkeys.c
@@ -0,0 +1,333 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.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/mscrypto/crypto.h>
+
+/*****************************************************************************
+ *
+ * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary
+ *
+ ****************************************************************************/
+static int xmlSecMSCryptoSymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoSymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecMSCryptoSymKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoSymKeyDataXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoSymKeyDataXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoSymKeyDataBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const unsigned char* buf,
+ size_t bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ unsigned char** buf,
+ size_t* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ size_t sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecMSCryptoSymKeyDataGetType(xmlSecKeyDataPtr data);
+static size_t xmlSecMSCryptoSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecMSCryptoSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecMSCryptoSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecMSCryptoSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+#ifndef XMLSEC_NO_AES
+/**************************************************************************
+ *
+ * <xmlsec:AESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataAesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameAESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefAESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecMSCryptoSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecMSCryptoSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecMSCryptoSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecMSCryptoSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecMSCryptoSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecMSCryptoSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecMSCryptoSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecMSCryptoSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecMSCryptoSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecMSCryptoSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecMSCryptoSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataAesGetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataAesKlass);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataAesSet:
+ * @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
+xmlSecMSCryptoKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataAesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**************************************************************************
+ *
+ * <xmlsec:DESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameDESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecMSCryptoSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecMSCryptoSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecMSCryptoSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecMSCryptoSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecMSCryptoSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecMSCryptoSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecMSCryptoSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecMSCryptoSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecMSCryptoSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecMSCryptoSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecMSCryptoSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataDesGetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataDesKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
+/*
+ * GENERIC HELPER FUNCTIONS
+ */
+
+#define xmlSecMSCryptoSymKeyDataCheckId(data) \
+ (xmlSecKeyDataIsValid((data)) && \
+ xmlSecMSCryptoSymKeyDataKlassCheck((data)->id))
+
+static int
+xmlSecMSCryptoSymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataCheckId(data), -1);
+
+ return(xmlSecKeyDataBinaryValueInitialize(data));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataCheckId(dst), -1);
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataCheckId(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ return(xmlSecKeyDataBinaryValueDuplicate(dst, src));
+}
+
+static void
+xmlSecMSCryptoSymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecMSCryptoSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueFinalize(data);
+}
+
+static int
+xmlSecMSCryptoSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const unsigned char* buf, size_t bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ unsigned char** buf, size_t* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataGenerate(xmlSecKeyDataPtr data, size_t sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataCheckId(data), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecMSCryptoGenerateRandom(buffer, (sizeBits + 7) / 8));
+}
+
+static xmlSecKeyDataType
+xmlSecMSCryptoSymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown);
+
+ return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown);
+}
+
+static size_t
+xmlSecMSCryptoSymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataCheckId(data), 0);
+
+ return(xmlSecKeyDataBinaryValueGetSize(data));
+}
+
+static void
+xmlSecMSCryptoSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecMSCryptoSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugDump(data, output);
+}
+
+static void
+xmlSecMSCryptoSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecMSCryptoSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugXmlDump(data, output);
+}
+
+static int
+xmlSecMSCryptoSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) {
+#ifndef XMLSEC_NO_DES
+ if(klass == xmlSecMSCryptoKeyDataDesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(klass == xmlSecMSCryptoKeyDataAesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
diff --git a/src/mscrypto/x509.c b/src/mscrypto/x509.c
new file mode 100644
index 00000000..e065590e
--- /dev/null
+++ b/src/mscrypto/x509.c
@@ -0,0 +1,2270 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 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 <windows.h>
+#include <wincrypt.h>
+
+#include <libxml/tree.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/bn.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/x509.h>
+#include <xmlsec/mscrypto/certkeys.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+
+/*************************************************************************
+ *
+ * X509 utility functions
+ *
+ ************************************************************************/
+static int xmlSecMSCryptoX509DataNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509CertificateNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509CertificateNodeWrite (PCCERT_CONTEXT cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509SubjectNameNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509SubjectNameNodeWrite (PCCERT_CONTEXT cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509IssuerSerialNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509IssuerSerialNodeWrite (PCCERT_CONTEXT cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509SKINodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509SKINodeWrite (PCCERT_CONTEXT cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509CRLNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoX509CRLNodeWrite (PCCRL_CONTEXT crl,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data,
+ xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static PCCERT_CONTEXT xmlSecMSCryptoX509CertDerRead (const xmlSecByte* buf,
+ xmlSecSize size);
+static PCCERT_CONTEXT xmlSecMSCryptoX509CertBase64DerRead (xmlChar* buf);
+static xmlChar* xmlSecMSCryptoX509CertBase64DerWrite (PCCERT_CONTEXT cert,
+ int base64LineWrap);
+static PCCRL_CONTEXT xmlSecMSCryptoX509CrlDerRead (xmlSecByte* buf,
+ xmlSecSize size,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static PCCRL_CONTEXT xmlSecMSCryptoX509CrlBase64DerRead (xmlChar* buf,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlChar* xmlSecMSCryptoX509CrlBase64DerWrite (PCCRL_CONTEXT crl,
+ int base64LineWrap);
+static xmlChar* xmlSecMSCryptoX509NameWrite(PCERT_NAME_BLOB nm);
+static int xmlSecMSCryptoASN1IntegerWrite (xmlNodePtr node,
+ PCRYPT_INTEGER_BLOB num);
+static xmlChar* xmlSecMSCryptoX509SKIWrite (PCCERT_CONTEXT cert);
+static void xmlSecMSCryptoX509CertDebugDump (PCCERT_CONTEXT cert,
+ FILE* output);
+static void xmlSecMSCryptoX509CertDebugXmlDump (PCCERT_CONTEXT cert,
+ FILE* output);
+static int xmlSecMSCryptoX509CertGetTime (FILETIME t,
+ time_t* res);
+
+/*************************************************************************
+ *
+ * Internal MSCrypto X509 data CTX
+ *
+ ************************************************************************/
+typedef struct _xmlSecMSCryptoX509DataCtx xmlSecMSCryptoX509DataCtx,
+ *xmlSecMSCryptoX509DataCtxPtr;
+
+struct _xmlSecMSCryptoX509DataCtx {
+ PCCERT_CONTEXT keyCert;
+
+ HCERTSTORE hMemStore;
+ unsigned int numCerts;
+ unsigned int numCrls;
+};
+
+/**************************************************************************
+ *
+ * <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) >
+ *
+ * -----------------------------------------------------------------------
+ *
+ * xmlSecMSCryptoX509DataCtx is located after xmlSecTransform
+ *
+ *************************************************************************/
+#define xmlSecMSCryptoX509DataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoX509DataCtx))
+#define xmlSecMSCryptoX509DataGetCtx(data) \
+ ((xmlSecMSCryptoX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecMSCryptoKeyDataX509Initialize (xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataX509Duplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecMSCryptoKeyDataX509Finalize (xmlSecKeyDataPtr data);
+static int xmlSecMSCryptoKeyDataX509XmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoKeyDataX509XmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyDataType xmlSecMSCryptoKeyDataX509GetType (xmlSecKeyDataPtr data);
+static const xmlChar* xmlSecMSCryptoKeyDataX509GetIdentifier (xmlSecKeyDataPtr data);
+
+static void xmlSecMSCryptoKeyDataX509DebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecMSCryptoKeyDataX509DebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+
+
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataX509Klass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecMSCryptoX509DataSize,
+
+ /* data */
+ xmlSecNameX509Data,
+ xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefX509Data, /* const xmlChar* href; */
+ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecMSCryptoKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecMSCryptoKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecMSCryptoKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ xmlSecMSCryptoKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecMSCryptoKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecMSCryptoKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecMSCryptoKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecMSCryptoKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataX509GetKlass:
+ *
+ * The MSCrypto X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data).
+ *
+ * Returns: the X509 data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataX509GetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataX509Klass);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509GetKeyCert:
+ * @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.
+ */
+PCCERT_CONTEXT
+xmlSecMSCryptoKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->keyCert);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509AdoptKeyCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to MSCRYPTO X509 certificate.
+ *
+ * Sets the key's certificate in @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT cert) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->keyCert != NULL) {
+ CertFreeCertificateContext(ctx->keyCert);
+ ctx->keyCert = 0;
+ }
+ ctx->keyCert = cert;
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509AdoptCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to MSCRYPTO X509 certificate.
+ *
+ * Adds certificate to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoKeyDataX509AdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT cert) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->hMemStore != 0, -1);
+
+ if (!CertAddCertificateContextToStore(ctx->hMemStore, cert, CERT_STORE_ADD_ALWAYS, NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CertAddCertificateContextToStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ CertFreeCertificateContext(cert);
+ ctx->numCerts++;
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509GetCert:
+ * @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.
+ */
+PCCERT_CONTEXT
+xmlSecMSCryptoKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+ PCCERT_CONTEXT pCert = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->hMemStore != 0, NULL);
+ xmlSecAssert2(ctx->numCerts > pos, NULL);
+
+ while ((pCert = CertEnumCertificatesInStore(ctx->hMemStore, pCert)) && (pos > 0)) {
+ pos--;
+ }
+
+ return(pCert);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509GetCertsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of certificates in @data.
+ *
+ * Returns: te number of certificates in @data.
+ */
+xmlSecSize
+xmlSecMSCryptoKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), 0);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->numCerts);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509AdoptCrl:
+ * @data: the pointer to X509 key data.
+ * @crl: the pointer to MSCrypto X509 CRL.
+ *
+ * Adds CRL to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, PCCRL_CONTEXT crl) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(crl != 0, -1);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->hMemStore != 0, -1);
+
+ if (!CertAddCRLContextToStore(ctx->hMemStore, crl, CERT_STORE_ADD_ALWAYS, NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CertAddCRLContextToStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ctx->numCrls++;
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509GetCrl:
+ * @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.
+ */
+PCCRL_CONTEXT
+xmlSecMSCryptoKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+ PCCRL_CONTEXT pCRL = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL);
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->hMemStore != 0, NULL);
+ xmlSecAssert2(ctx->numCrls > pos, NULL);
+
+ while ((pCRL = CertEnumCRLsInStore(ctx->hMemStore, pCRL)) && (pos > 0)) {
+ pos--;
+ }
+
+ return(pCRL);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataX509GetCrlsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of CRLs in @data.
+ *
+ * Returns: te number of CRLs in @data.
+ */
+xmlSecSize
+xmlSecMSCryptoKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), 0);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->numCrls);
+}
+
+static int
+xmlSecMSCryptoKeyDataX509Initialize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoX509DataCtx));
+
+ ctx->hMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ 0,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if (ctx->hMemStore == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ PCCERT_CONTEXT certSrc, certDst;
+ PCCRL_CONTEXT crlSrc, crlDst;
+ xmlSecSize size, pos;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataX509Id), -1);
+
+ /* copy certsList */
+ size = xmlSecMSCryptoKeyDataX509GetCertsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ /* TBD: function below does linear scan, eliminate loop within
+ * loop
+ */
+ certSrc = xmlSecMSCryptoKeyDataX509GetCert(src, pos);
+ if(certSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecMSCryptoKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ certDst = CertDuplicateCertificateContext(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(certDst);
+ return(-1);
+ }
+ }
+
+ /* copy crls */
+ size = xmlSecMSCryptoKeyDataX509GetCrlsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ crlSrc = xmlSecMSCryptoKeyDataX509GetCrl(src, pos);
+ if(crlSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecMSCryptoKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ crlDst = CertDuplicateCRLContext(crlSrc);
+ if(crlDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CertDuplicateCRLContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCrl(dst, crlDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecMSCryptoKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCRLContext(crlDst);
+ return(-1);
+ }
+ }
+
+ /* copy key cert if exist */
+ certSrc = xmlSecMSCryptoKeyDataX509GetKeyCert(src);
+ if(certSrc != NULL) {
+ certDst = CertDuplicateCertificateContext(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ret = xmlSecMSCryptoKeyDataX509AdoptKeyCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecMSCryptoKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(certDst);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static void
+xmlSecMSCryptoKeyDataX509Finalize(xmlSecKeyDataPtr data) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id));
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->keyCert != NULL) {
+ CertFreeCertificateContext(ctx->keyCert);
+ ctx->keyCert = NULL;
+ }
+
+ if (ctx->hMemStore != 0) {
+ if (!CertCloseStore(ctx->hMemStore, CERT_CLOSE_STORE_FORCE_FLAG)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertCloseStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return;
+ }
+ }
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoX509DataCtx));
+}
+
+static int
+xmlSecMSCryptoKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataX509Id, -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 = xmlSecMSCryptoX509DataNodeRead(data, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoX509DataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
+ ret = xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ PCCERT_CONTEXT cert;
+ PCCRL_CONTEXT crl;
+ xmlSecSize size, pos;
+ int content = 0;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataX509Id, -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 = xmlSecMSCryptoKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecMSCryptoKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) {
+ ret = xmlSecMSCryptoX509CertificateNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoX509CertificateNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) {
+ ret = xmlSecMSCryptoX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoX509SubjectNameNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) {
+ ret = xmlSecMSCryptoX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoX509IssuerSerialNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SKI_NODE) != 0) {
+ ret = xmlSecMSCryptoX509SKINodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoX509SKINodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ /* write crls if needed */
+ if((content & XMLSEC_X509DATA_CRL_NODE) != 0) {
+ size = xmlSecMSCryptoKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ crl = xmlSecMSCryptoKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoX509CRLNodeWrite(crl, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoX509CRLNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+static xmlSecKeyDataType
+xmlSecMSCryptoKeyDataX509GetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), xmlSecKeyDataTypeUnknown);
+
+ /* TODO: return verified/not verified status */
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static const xmlChar*
+xmlSecMSCryptoKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL);
+
+ /* TODO */
+ return(NULL);
+}
+
+static void
+xmlSecMSCryptoKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ PCCERT_CONTEXT cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== X509 Data:\n");
+ cert = xmlSecMSCryptoKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "==== Key Certificate:\n");
+ xmlSecMSCryptoX509CertDebugDump(cert, output);
+ }
+
+ size = xmlSecMSCryptoKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecMSCryptoKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "==== Certificate:\n");
+ xmlSecMSCryptoX509CertDebugDump(cert, output);
+ }
+
+ /* we don't print out crls */
+}
+
+static void
+xmlSecMSCryptoKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ PCCERT_CONTEXT cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<X509Data>\n");
+ cert = xmlSecMSCryptoKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "<KeyCertificate>\n");
+ xmlSecMSCryptoX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</KeyCertificate>\n");
+ }
+
+ size = xmlSecMSCryptoKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecMSCryptoKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "<Certificate>\n");
+ xmlSecMSCryptoX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</Certificate>\n");
+ }
+
+ /* we don't print out crls */
+ fprintf(output, "</X509Data>\n");
+}
+
+static int
+xmlSecMSCryptoX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -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 = xmlSecMSCryptoX509CertificateNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+ ret = xmlSecMSCryptoX509SubjectNameNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+ ret = xmlSecMSCryptoX509IssuerSerialNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+ ret = xmlSecMSCryptoX509SKINodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+ ret = xmlSecMSCryptoX509CRLNodeRead(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
+xmlSecMSCryptoX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ PCCERT_CONTEXT cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -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 = xmlSecMSCryptoX509CertBase64DerRead(content);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoX509CertBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(cert);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoX509CertificateNodeWrite(PCCERT_CONTEXT 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 = xmlSecMSCryptoX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509CertBase64DerWrite",
+ 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
+xmlSecMSCryptoX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* subject;
+ PCCERT_CONTEXT cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId);
+ 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 = xmlSecMSCryptoX509StoreFindCert(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);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(cert);
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoX509SubjectNameNodeWrite(PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Subject));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Subject))",
+ 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
+xmlSecMSCryptoX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlNodePtr cur;
+ xmlChar *issuerName;
+ xmlChar *issuerSerial;
+ PCCERT_CONTEXT cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId);
+ 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 = xmlSecMSCryptoX509StoreFindCert(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);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(cert);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoX509IssuerSerialNodeWrite(PCCERT_CONTEXT cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlNodePtr cur;
+ xmlNodePtr issuerNameNode;
+ xmlNodePtr issuerNumberNode;
+ xmlChar* buf;
+ int ret;
+
+ 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 = xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Issuer));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Issuer))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNameNode, buf);
+ xmlFree(buf);
+
+ ret = xmlSecMSCryptoASN1IntegerWrite(issuerNumberNode, &(cert->pCertInfo->SerialNumber));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoASN1IntegerWrite(&(cert->serialNumber))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecMSCryptoX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* ski;
+ PCCERT_CONTEXT cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId);
+ 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 = xmlSecMSCryptoX509StoreFindCert(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);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(cert);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ xmlFree(ski);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoX509SKINodeWrite(PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar *buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecMSCryptoX509SKIWrite(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509SKIWrite",
+ 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
+xmlSecMSCryptoX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ PCCRL_CONTEXT crl;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -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 = xmlSecMSCryptoX509CrlBase64DerRead(content, keyInfoCtx);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoX509CrlBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ if (0 != xmlSecMSCryptoKeyDataX509AdoptCrl(data, crl)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ CertFreeCRLContext(crl);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecMSCryptoX509CRLNodeWrite(PCCRL_CONTEXT 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 = xmlSecMSCryptoX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509CrlBase64DerWrite",
+ 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
+xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecMSCryptoX509DataCtxPtr ctx;
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->hMemStore != 0, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId);
+ 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) && (xmlSecKeyGetValue(key) == NULL)) {
+ PCCERT_CONTEXT cert;
+
+ cert = xmlSecMSCryptoX509StoreVerify(x509Store, ctx->hMemStore, keyInfoCtx);
+ if(cert != NULL) {
+ xmlSecKeyDataPtr keyValue = NULL;
+ PCCERT_CONTEXT pCert = NULL;
+
+ ctx->keyCert = CertDuplicateCertificateContext(cert);
+ if(ctx->keyCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* search key according to KeyReq */
+ pCert = CertDuplicateCertificateContext( ctx->keyCert ) ;
+ if( pCert == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CertDuplicateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ if( ( keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate ) == xmlSecKeyDataTypePrivate ) {
+ keyValue = xmlSecMSCryptoCertAdopt( pCert, xmlSecKeyDataTypePrivate ) ;
+ if(keyValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoCertAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext( pCert ) ;
+ return(-1);
+ }
+ pCert = NULL ;
+ } else if( ( keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePublic ) == xmlSecKeyDataTypePublic ) {
+ keyValue = xmlSecMSCryptoCertAdopt( pCert, xmlSecKeyDataTypePublic ) ;
+ if(keyValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoCertAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext( pCert ) ;
+ return(-1);
+ }
+ pCert = NULL ;
+ }
+
+ /* 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);
+ }
+
+ ret = xmlSecMSCryptoX509CertGetTime(ctx->keyCert->pCertInfo->NotBefore, &(key->notValidBefore));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidBefore");
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoX509CertGetTime(ctx->keyCert->pCertInfo->NotAfter, &(key->notValidAfter));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidAfter");
+ return(-1);
+ }
+ } 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);
+}
+
+static int
+xmlSecMSCryptoX509CertGetTime(FILETIME t, time_t* res) {
+ LONGLONG result;
+
+ xmlSecAssert2(res != NULL, -1);
+
+ result = t.dwHighDateTime;
+ result = (result) << 32;
+ result |= t.dwLowDateTime;
+ result /= 10000; /* Convert from 100 nano-sec periods to seconds. */
+#if defined(__MINGW32__)
+ result -= 11644473600000ULL; /* Convert from Windows epoch to Unix epoch */
+#else
+ result -= 11644473600000; /* Convert from Windows epoch to Unix epoch */
+#endif
+
+ (*res) = (time_t)result;
+
+ return(0);
+}
+
+static PCCERT_CONTEXT
+xmlSecMSCryptoX509CertBase64DerRead(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(xmlSecMSCryptoX509CertDerRead((xmlSecByte*)buf, ret));
+}
+
+
+static PCCERT_CONTEXT
+xmlSecMSCryptoX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
+ PCCERT_CONTEXT cert;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ cert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, size);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertCreateCertificateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(cert);
+}
+
+static xmlChar*
+xmlSecMSCryptoX509CertBase64DerWrite(PCCERT_CONTEXT cert, int base64LineWrap) {
+ xmlChar *res = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ p = cert->pbCertEncoded;
+ size = cert->cbCertEncoded;
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cert->pbCertEncoded",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ 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);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+static PCCRL_CONTEXT
+xmlSecMSCryptoX509CrlBase64DerRead(xmlChar* buf,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ 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(xmlSecMSCryptoX509CrlDerRead((xmlSecByte*)buf, ret, keyInfoCtx));
+}
+
+
+static PCCRL_CONTEXT
+xmlSecMSCryptoX509CrlDerRead(xmlSecByte* buf, xmlSecSize size,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ PCCRL_CONTEXT crl = NULL;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ crl = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, size);
+
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertCreateCRLContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(crl);
+ }
+
+static xmlChar*
+xmlSecMSCryptoX509CrlBase64DerWrite(PCCRL_CONTEXT crl, int base64LineWrap) {
+ xmlChar *res = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(crl != NULL, NULL);
+
+ p = crl->pbCrlEncoded;
+ size = crl->cbCrlEncoded;
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "crl->pbCrlEncoded",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ 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);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+static xmlChar*
+xmlSecMSCryptoX509NameWrite(PCERT_NAME_BLOB nm) {
+ xmlChar *res = NULL;
+ char *str;
+ DWORD csz;
+
+
+ xmlSecAssert2(nm->pbData != NULL, NULL);
+ xmlSecAssert2(nm->cbData > 0, NULL);
+
+ csz = CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, nm, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, NULL, 0);
+ str = (char *)xmlMalloc(csz);
+ if (NULL == str) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ csz = CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, nm, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, str, csz);
+ if (csz < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertNameToStr",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(str);
+ return(NULL);
+ }
+
+ /* aleksey: this is a hack, but mscrypto can not read E= flag and wants Email= instead.
+ * don't ask me how is it possible not to read something you wrote yourself but also
+ * see comment in the xmlSecMSCryptoX509FindCert function.
+ */
+ if(strncmp(str, "E=", 2) == 0) {
+ res = xmlMalloc(strlen(str) + 13 + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d",
+ strlen(str) + 13 + 1);
+ xmlFree(str);
+ return(NULL);
+ }
+
+ memcpy(res, "emailAddress=", 13);
+ strcpy(res + 13, BAD_CAST (str + 2));
+ } else {
+ res = xmlStrdup(BAD_CAST str);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(str);
+ return(NULL);
+ }
+ }
+ xmlFree(str);
+ return(res);
+}
+
+
+
+static int
+xmlSecMSCryptoASN1IntegerWrite(xmlNodePtr node, PCRYPT_INTEGER_BLOB num) {
+ xmlSecBn bn;
+ int ret;
+
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(num != NULL, -1);
+
+ ret = xmlSecBnInitialize(&bn, num->cbData + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%ld", num->cbData + 1);
+ return(-1);
+ }
+
+ ret = xmlSecBnSetData(&bn, num->pbData, num->cbData);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBnFinalize(&bn);
+ return(-1);
+ }
+
+ /* I have no clue why at a sudden a swap is needed to
+ * convert from lsb... This code is purely based upon
+ * trial and error :( WK
+ */
+ ret = xmlSecBnSetNodeValue(&bn, node, xmlSecBnDec, 1, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnSetNodeValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBnFinalize(&bn);
+ return(-1);
+ }
+
+ xmlSecBnFinalize(&bn);
+ return(0);
+}
+
+static xmlChar*
+xmlSecMSCryptoX509SKIWrite(PCCERT_CONTEXT cert) {
+ xmlChar *res = NULL;
+ DWORD dwSize;
+ BYTE *bSKI = NULL;
+ PCERT_EXTENSION pCertExt;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* First check if the SKI extension actually exists, otherwise we get a SHA1 hash o fthe key/cert */
+ pCertExt = CertFindExtension(szOID_SUBJECT_KEY_IDENTIFIER, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
+ if (pCertExt == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertFindExtension",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ if (!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &dwSize) || dwSize < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertGetCertificateContextProperty",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+ bSKI = xmlMalloc(dwSize);
+ if (NULL == bSKI) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ if (!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, bSKI, &dwSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertGetCertificateContextProperty",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(bSKI);
+ return (NULL);
+ }
+
+ if (NULL == bSKI) {
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(bSKI, dwSize, 0);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(bSKI);
+ return(NULL);
+ }
+ xmlFree(bSKI);
+
+ return(res);
+}
+
+
+static void
+xmlSecMSCryptoX509CertDebugDump(PCCERT_CONTEXT cert, FILE* output) {
+ PCRYPT_INTEGER_BLOB sn;
+ unsigned int i;
+ LPSTR subject, issuer;
+ DWORD dwSize;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ /* todo: add error checks */
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, NULL, 0);
+ subject = (LPSTR)xmlMalloc(dwSize);
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, subject, dwSize);
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
+ issuer = (LPSTR)xmlMalloc(dwSize);
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer, dwSize);
+
+ fprintf(output, "=== X509 Certificate\n");
+ fprintf(output, "==== Subject Name: %s\n", subject);
+ fprintf(output, "==== Issuer Name: %s\n", issuer);
+ if (subject) xmlFree(subject);
+ if (issuer) xmlFree(issuer);
+ sn = &(cert->pCertInfo->SerialNumber);
+
+ for (i = 0; i < sn->cbData; i++) {
+ if (i != sn->cbData - 1) {
+ fprintf(output, "%02x:", sn->pbData[i]);
+ } else {
+ fprintf(output, "%02x", sn->pbData[i]);
+ }
+ }
+ fprintf(output, "\n");
+}
+
+
+static void
+xmlSecMSCryptoX509CertDebugXmlDump(PCCERT_CONTEXT cert, FILE* output) {
+ PCRYPT_INTEGER_BLOB sn;
+ unsigned int i;
+ LPSTR subject, issuer;
+ DWORD dwSize;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ /* todo: add error checks */
+
+ /* subject */
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, NULL, 0);
+ subject = (LPSTR)xmlMalloc(dwSize);
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, subject, dwSize);
+
+ fprintf(output, "<SubjectName>");
+ xmlSecPrintXmlString(output, BAD_CAST subject);
+ fprintf(output, "</SubjectName>\n");
+ xmlFree(subject);
+
+
+ /* issuer */
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
+ issuer = (LPSTR)xmlMalloc(dwSize);
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer, dwSize);
+
+ fprintf(output, "<IssuerName>");
+ xmlSecPrintXmlString(output, BAD_CAST issuer);
+ fprintf(output, "</IssuerName>\n");
+ xmlFree(issuer);
+
+ /* serial */
+ fprintf(output, "<SerialNumber>");
+ sn = &(cert->pCertInfo->SerialNumber);
+ for (i = 0; i < sn->cbData; i++) {
+ if (i != sn->cbData - 1) {
+ fprintf(output, "%02x:", sn->pbData[i]);
+ } else {
+ fprintf(output, "%02x", sn->pbData[i]);
+ }
+ }
+ fprintf(output, "</SerialNumber>\n");
+}
+
+
+/**************************************************************************
+ *
+ * Raw X509 Certificate processing
+ *
+ *
+ *************************************************************************/
+static int xmlSecMSCryptoKeyDataRawX509CertBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRawX509CertKlass = {
+ 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; */
+ xmlSecMSCryptoKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 certificates key data klass.
+ *
+ * Returns: raw X509 certificates key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataRawX509CertGetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataRawX509CertKlass);
+}
+
+static int
+xmlSecMSCryptoKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ PCCERT_CONTEXT cert;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecMSCryptoKeyDataRawX509CertId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ cert = xmlSecMSCryptoX509CertDerRead(buf, bufSize);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509CertDerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ data = xmlSecKeyEnsureData(key, xmlSecMSCryptoKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(cert);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertFreeCertificateContext(cert);
+ return(-1);
+ }
+
+ ret = xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/mscrypto/x509vfy.c b/src/mscrypto/x509vfy.c
new file mode 100644
index 00000000..d854e7a0
--- /dev/null
+++ b/src/mscrypto/x509vfy.c
@@ -0,0 +1,1062 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
+ * Copyright (C) 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 <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/bn.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+#include <xmlsec/mscrypto/x509.h>
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+/**************************************************************************
+ *
+ * Internal MSCRYPTO X509 store CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecMSCryptoX509StoreCtx xmlSecMSCryptoX509StoreCtx,
+ *xmlSecMSCryptoX509StoreCtxPtr;
+struct _xmlSecMSCryptoX509StoreCtx {
+ HCERTSTORE trusted;
+ HCERTSTORE untrusted;
+ int dont_use_system_trusted_certs;
+};
+
+/****************************************************************************
+ *
+ * xmlSecMSCryptoKeyDataStoreX509Id:
+ *
+ * xmlSecMSCryptoX509StoreCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecMSCryptoX509StoreGetCtx(store) \
+ ((xmlSecMSCryptoX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
+ sizeof(xmlSecKeyDataStoreKlass)))
+#define xmlSecMSCryptoX509StoreSize \
+ (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecMSCryptoX509StoreCtx))
+
+static int xmlSecMSCryptoX509StoreInitialize (xmlSecKeyDataStorePtr store);
+static void xmlSecMSCryptoX509StoreFinalize (xmlSecKeyDataStorePtr store);
+
+static xmlSecKeyDataStoreKlass xmlSecMSCryptoX509StoreKlass = {
+ sizeof(xmlSecKeyDataStoreKlass),
+ xmlSecMSCryptoX509StoreSize,
+
+ /* data */
+ xmlSecNameX509Store, /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecMSCryptoX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
+ xmlSecMSCryptoX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static PCCERT_CONTEXT xmlSecMSCryptoX509FindCert(HCERTSTORE store,
+ xmlChar *subjectName,
+ xmlChar *issuerName,
+ xmlChar *issuerSerial,
+ xmlChar *ski);
+
+
+/**
+ * xmlSecMSCryptoX509StoreGetKlass:
+ *
+ * The MSCrypto X509 certificates key data store klass.
+ *
+ * Returns: pointer to MSCrypto X509 certificates key data store klass.
+ */
+xmlSecKeyDataStoreId
+xmlSecMSCryptoX509StoreGetKlass(void) {
+ return(&xmlSecMSCryptoX509StoreKlass);
+}
+
+/**
+ * xmlSecMSCryptoX509StoreFindCert:
+ * @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.
+ */
+PCCERT_CONTEXT
+xmlSecMSCryptoX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
+ xmlChar *issuerName, xmlChar *issuerSerial,
+ xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+ PCCERT_CONTEXT pCert = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ /* search untrusted certs store */
+ if((ctx->untrusted != NULL) && (pCert == NULL)) {
+ pCert = xmlSecMSCryptoX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski);
+ }
+
+ /* search untrusted certs store */
+ if((ctx->trusted != NULL) && (pCert == NULL)) {
+ pCert = xmlSecMSCryptoX509FindCert(ctx->trusted, subjectName, issuerName, issuerSerial, ski);
+ }
+
+ return pCert;
+}
+
+
+static void
+xmlSecMSCryptoUnixTimeToFileTime(time_t t, LPFILETIME pft) {
+ /* Note that LONGLONG is a 64-bit value */
+ LONGLONG ll;
+
+ xmlSecAssert(pft != NULL);
+
+#if defined( __MINGW32__)
+ ll = Int32x32To64(t, 10000000) + 116444736000000000ULL;
+#else
+ ll = Int32x32To64(t, 10000000) + 116444736000000000;
+#endif
+ pft->dwLowDateTime = (DWORD)ll;
+ pft->dwHighDateTime = ll >> 32;
+}
+
+static BOOL
+xmlSecMSCrypoVerifyCertTime(PCCERT_CONTEXT pCert, LPFILETIME pft) {
+ xmlSecAssert2(pCert != NULL, FALSE);
+ xmlSecAssert2(pCert->pCertInfo != NULL, FALSE);
+ xmlSecAssert2(pft != NULL, FALSE);
+
+ if(1 == CompareFileTime(&(pCert->pCertInfo->NotBefore), pft)) {
+ return (FALSE);
+ }
+ if(-1 == CompareFileTime(&(pCert->pCertInfo->NotAfter), pft)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+static BOOL
+xmlSecMSCryptoCheckRevocation(HCERTSTORE hStore, PCCERT_CONTEXT pCert) {
+ PCCRL_CONTEXT pCrl = NULL;
+ PCRL_ENTRY pCrlEntry = NULL;
+
+ xmlSecAssert2(pCert != NULL, FALSE);
+ xmlSecAssert2(hStore != NULL, FALSE);
+
+ while((pCrl = CertEnumCRLsInStore(hStore, pCrl)) != NULL) {
+ if (CertFindCertificateInCRL(pCert, pCrl, 0, NULL, &pCrlEntry) && (pCrlEntry != NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertFindCertificateInCRL",
+ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+ "cert found in crl list");
+ return(FALSE);
+ }
+ }
+
+ return(TRUE);
+}
+
+static void
+xmlSecMSCryptoX509StoreCertError(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT cert, DWORD flags) {
+ LPSTR subject;
+ DWORD dwSize;
+
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(flags != 0);
+
+ /* get certs subject */
+ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, NULL, 0);
+ subject = xmlMalloc(dwSize + 1);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return;
+ }
+ memset(subject, 0, dwSize + 1);
+ if(dwSize > 0) {
+ CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, subject, dwSize);
+ }
+
+ /* print error */
+ if (flags & CERT_STORE_SIGNATURE_FLAG) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ xmlSecErrorsSafeString(subject),
+ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+ "signature");
+ } else if (flags & CERT_STORE_TIME_VALIDITY_FLAG) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ xmlSecErrorsSafeString(subject),
+ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ } else if (flags & CERT_STORE_REVOCATION_FLAG) {
+ if (flags & CERT_STORE_NO_CRL_FLAG) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ xmlSecErrorsSafeString(subject),
+ XMLSEC_ERRORS_R_CERT_REVOKED,
+ "no crl");
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ xmlSecErrorsSafeString(subject),
+ XMLSEC_ERRORS_R_CERT_REVOKED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ xmlSecErrorsSafeString(subject),
+ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+ xmlFree(subject);
+}
+
+/**
+ * xmlSecBuildChainUsingWinapi:
+ * @cert: the certificate we check
+ * @pfTime: pointer to FILETIME that we are interested in
+ * @store_untrusted: untrusted certificates added via API
+ * @store_doc: untrusted certificates/CRLs extracted from a document
+ *
+ * Builds certificates chain using Windows API.
+ *
+ * Returns: TRUE on success or FALSE otherwise.
+ */
+static BOOL
+xmlSecBuildChainUsingWinapi (PCCERT_CONTEXT cert, LPFILETIME pfTime,
+ HCERTSTORE store_untrusted, HCERTSTORE store_doc)
+{
+ PCCERT_CHAIN_CONTEXT pChainContext = NULL;
+ CERT_CHAIN_PARA chainPara;
+ BOOL rc = FALSE;
+ HCERTSTORE store_add = NULL;
+
+ /* Initialize data structures. */
+
+ memset(&chainPara, 0, sizeof(CERT_CHAIN_PARA));
+ chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
+
+ /* Create additional store for CertGetCertificateChain() */
+ store_add = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 0, NULL);
+ if (!store_add) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "chain additional collection store",
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ if (!CertAddStoreToCollection(store_add, store_doc, 0, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "adding document store",
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ if (!CertAddStoreToCollection(store_add, store_untrusted, 0, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "adding untrusted store",
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+
+ /* Build a chain using CertGetCertificateChain
+ and the certificate retrieved. */
+ if(!CertGetCertificateChain(
+ NULL, /* use the default chain engine */
+ cert,
+ pfTime,
+ store_add,
+ &chainPara,
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN,
+ NULL,
+ &pChainContext))
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "building certificate chain, checking root",
+ "CertGetCertificateChain",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ if (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_REVOCATION_STATUS_UNKNOWN) {
+ CertFreeCertificateChain(pChainContext); pChainContext = NULL;
+ if(!CertGetCertificateChain(
+ NULL, /* use the default chain engine */
+ cert,
+ pfTime,
+ store_add,
+ &chainPara,
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
+ NULL,
+ &pChainContext))
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "building certificate chain, excluding root",
+ "CertGetCertificateChain",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ }
+
+ if (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
+ rc = TRUE;
+
+end:
+ if (pChainContext) CertFreeCertificateChain(pChainContext);
+ if (store_add) CertCloseStore(store_add, 0);
+ return (rc);
+}
+
+/**
+ * xmlSecMSCryptoBuildCertChainManually:
+ * @cert: the certificate we check
+ * @pfTime: pointer to FILETIME that we are interested in
+ * @store_trusted: trusted certificates added via API
+ * @store_untrusted: untrusted certificates added via API
+ * @certs: untrusted certificates/CRLs extracted from a document
+ * @store: pointer to store klass passed to error functions
+ *
+ * Builds certificates chain manually.
+ *
+ * Returns: TRUE on success or FALSE otherwise.
+ */
+static BOOL
+xmlSecMSCryptoBuildCertChainManually (PCCERT_CONTEXT cert, LPFILETIME pfTime,
+ HCERTSTORE store_trusted, HCERTSTORE store_untrusted, HCERTSTORE certs,
+ xmlSecKeyDataStorePtr store) {
+ PCCERT_CONTEXT issuerCert = NULL;
+ DWORD flags;
+
+ if (!xmlSecMSCrypoVerifyCertTime(cert, pfTime)) {
+ xmlSecMSCryptoX509StoreCertError(store, cert, CERT_STORE_TIME_VALIDITY_FLAG);
+ return(FALSE);
+ }
+
+ if (!xmlSecMSCryptoCheckRevocation(certs, cert)) {
+ return(FALSE);
+ }
+
+ /*
+ * Try to find the cert in the trusted cert store. We will trust
+ * the certificate in the trusted store.
+ */
+ issuerCert = CertFindCertificateInStore(store_trusted,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &(cert->pCertInfo->Subject),
+ NULL);
+ if( issuerCert != NULL) {
+ /* We have found the trusted cert, so return true */
+ /* todo: do we want to verify the trusted cert's revocation? we must, I think */
+ CertFreeCertificateContext( issuerCert ) ;
+ return( TRUE ) ;
+ }
+
+ /* Check whether the certificate is self signed certificate */
+ if(CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(cert->pCertInfo->Subject), &(cert->pCertInfo->Issuer))) {
+ return(FALSE);
+ }
+
+ /* try to find issuer cert in the trusted cert in the store */
+ issuerCert = CertFindCertificateInStore(store_trusted,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &(cert->pCertInfo->Issuer),
+ NULL);
+ if(issuerCert != NULL) {
+ flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
+ if(!CertVerifySubjectCertificateContext(cert, issuerCert, &flags)) {
+ xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
+ CertFreeCertificateContext(issuerCert);
+ return(FALSE);
+ }
+ /* todo: do we want to verify the trusted cert? we must check
+ * revocation, I think */
+ CertFreeCertificateContext(issuerCert);
+ return(TRUE);
+ }
+
+ /* try the untrusted certs in the chain */
+ issuerCert = CertFindCertificateInStore(certs,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &(cert->pCertInfo->Issuer),
+ NULL);
+ if(issuerCert != NULL) {
+ flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
+ if(!CertVerifySubjectCertificateContext(cert, issuerCert, &flags)) {
+ xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
+ CertFreeCertificateContext(issuerCert);
+ return(FALSE);
+ }
+ if(!xmlSecMSCryptoBuildCertChainManually(issuerCert, pfTime, store_trusted, store_untrusted, certs, store)) {
+ xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
+ CertFreeCertificateContext(issuerCert);
+ return(FALSE);
+ }
+ CertFreeCertificateContext(issuerCert);
+ return(TRUE);
+ }
+
+ /* try the untrusted certs in the store */
+ issuerCert = CertFindCertificateInStore(store_untrusted,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &(cert->pCertInfo->Issuer),
+ NULL);
+ if(issuerCert != NULL) {
+ flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
+ if(!CertVerifySubjectCertificateContext(cert, issuerCert, &flags)) {
+ xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
+ CertFreeCertificateContext(issuerCert);
+ return(FALSE);
+ }
+ if(!xmlSecMSCryptoBuildCertChainManually(issuerCert, pfTime, store_trusted, store_untrusted, certs, store)) {
+ CertFreeCertificateContext(issuerCert);
+ return(FALSE);
+ }
+ CertFreeCertificateContext(issuerCert);
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+static BOOL
+xmlSecMSCryptoX509StoreConstructCertsChain(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT cert, HCERTSTORE certs,
+ xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+ PCCERT_CONTEXT tempCert = NULL;
+ FILETIME fTime;
+ BOOL res = FALSE;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), FALSE);
+ xmlSecAssert2(cert != NULL, FALSE);
+ xmlSecAssert2(cert->pCertInfo != NULL, FALSE);
+ xmlSecAssert2(certs != NULL, FALSE);
+ xmlSecAssert2(keyInfoCtx != NULL, FALSE);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, FALSE);
+ xmlSecAssert2(ctx->trusted != NULL, FALSE);
+ xmlSecAssert2(ctx->untrusted != NULL, FALSE);
+
+ if(keyInfoCtx->certsVerificationTime > 0) {
+ /* convert the time to FILETIME */
+ xmlSecMSCryptoUnixTimeToFileTime(keyInfoCtx->certsVerificationTime, &fTime);
+ } else {
+ /* Defaults to current time */
+ GetSystemTimeAsFileTime(&fTime);
+ }
+
+ /* try the certificates in the keys manager */
+ if(!res) {
+ tempCert = CertEnumCertificatesInStore(ctx->trusted, NULL);
+ if(tempCert) {
+ CertFreeCertificateContext(tempCert);
+ res = xmlSecMSCryptoBuildCertChainManually(cert, &fTime, ctx->trusted, ctx->untrusted, certs, store);
+ }
+ }
+
+ /* try the certificates in the system */
+ if(!res && !ctx->dont_use_system_trusted_certs) {
+ res = xmlSecBuildChainUsingWinapi(cert, &fTime, ctx->untrusted, certs);
+ }
+
+ /* done */
+ return res;
+}
+
+/**
+ * xmlSecMSCryptoX509StoreVerify:
+ * @store: the pointer to X509 certificate context store klass.
+ * @certs: the untrusted certificates stack.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Verifies @certs list.
+ *
+ * Returns: pointer to the first verified certificate from @certs.
+ */
+PCCERT_CONTEXT
+xmlSecMSCryptoX509StoreVerify(xmlSecKeyDataStorePtr store, HCERTSTORE certs,
+ xmlSecKeyInfoCtx* keyInfoCtx) {
+ PCCERT_CONTEXT cert = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), NULL);
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ while((cert = CertEnumCertificatesInStore(certs, cert)) != NULL){
+ PCCERT_CONTEXT nextCert = NULL;
+ unsigned char selected = 1;
+
+ xmlSecAssert2(cert->pCertInfo != NULL, NULL);
+
+ /* if cert is the issuer of any other cert in the list, then it is
+ * to be skipped except a case of a celf-signed cert*/
+ do {
+ nextCert = CertFindCertificateInStore(certs,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_ISSUER_NAME,
+ &(cert->pCertInfo->Subject),
+ nextCert);
+ if((nextCert != NULL) && !CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ &(nextCert->pCertInfo->Subject), &(nextCert->pCertInfo->Issuer))) {
+ selected = 0;
+ }
+ } while((selected == 1) && (nextCert != NULL));
+ if(nextCert != NULL) {
+ CertFreeCertificateContext(nextCert);
+ }
+
+ if((selected == 1) && xmlSecMSCryptoX509StoreConstructCertsChain(store, cert, certs, keyInfoCtx)) {
+ return(cert);
+ }
+ }
+
+ return (NULL);
+}
+
+/**
+ * xmlSecMSCryptoX509StoreAdoptCert:
+ * @store: the pointer to X509 key data store klass.
+ * @cert: the pointer to PCCERT_CONTEXT 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
+xmlSecMSCryptoX509StoreAdoptCert(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+ HCERTSTORE certStore;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
+ xmlSecAssert2(pCert != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->trusted != NULL, -1);
+ xmlSecAssert2(ctx->untrusted != NULL, -1);
+
+ if(type == xmlSecKeyDataTypeTrusted) {
+ certStore = ctx->trusted;
+ } else if(type == xmlSecKeyDataTypeNone) {
+ certStore = ctx->untrusted;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "type=%d", type);
+ return(-1);
+ }
+
+ /* TODO: The context to be added here is not duplicated first,
+ * hopefully this will not lead to errors when closing teh store
+ * and freeing the mem for all the context in the store.
+ */
+ xmlSecAssert2(certStore != NULL, -1);
+ if (!CertAddCertificateContextToStore(certStore, pCert, CERT_STORE_ADD_ALWAYS, NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertAddCertificateContextToStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/**
+ * xmlSecMSCryptoX509StoreAdoptKeyStore:
+ * @store: the pointer to X509 key data store klass.
+ * @keyStore: the pointer to keys store.
+ *
+ * Adds @keyStore to the list of key stores.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoX509StoreAdoptKeyStore (xmlSecKeyDataStorePtr store, HCERTSTORE keyStore) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
+ xmlSecAssert2( keyStore != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->trusted != NULL, -1);
+
+ if(!CertAddStoreToCollection ( ctx->trusted , keyStore , CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , 2)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoX509StoreAdoptTrustedStore:
+ * @store: the pointer to X509 key data store klass.
+ * @trustedStore: the pointer to certs store.
+ *
+ * Adds @trustedStore to the list of trusted certs stores.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoX509StoreAdoptTrustedStore (xmlSecKeyDataStorePtr store, HCERTSTORE trustedStore) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
+ xmlSecAssert2( trustedStore != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->trusted != NULL, -1);
+
+ if( !CertAddStoreToCollection ( ctx->trusted , trustedStore , CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , 3 ) ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoX509StoreAdoptUntrustedStore:
+ * @store: the pointer to X509 key data store klass.
+ * @untrustedStore: the pointer to certs store.
+ *
+ * Adds @trustedStore to the list of un-trusted certs stores.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecMSCryptoX509StoreAdoptUntrustedStore (xmlSecKeyDataStorePtr store, HCERTSTORE untrustedStore) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
+ xmlSecAssert2( untrustedStore != NULL, -1);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->untrusted != NULL, -1);
+
+ if( !CertAddStoreToCollection ( ctx->untrusted , untrustedStore , CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , 2 ) ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecMSCryptoX509StoreEnableSystemTrustedCerts:
+ * @store: the pointer to X509 key data store klass.
+ * @val: the enable/disable flag
+ *
+ * Enables/disables the system trusted certs.
+ */
+void
+xmlSecMSCryptoX509StoreEnableSystemTrustedCerts (xmlSecKeyDataStorePtr store, int val) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert(ctx != NULL);
+ xmlSecAssert(ctx->untrusted != NULL);
+
+ /* it is other way around to make default value 0 mimic old behaiviour */
+ ctx->dont_use_system_trusted_certs = !val;
+}
+
+static int
+xmlSecMSCryptoX509StoreInitialize(xmlSecKeyDataStorePtr store) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+ HCERTSTORE hTrustedMemStore ;
+ HCERTSTORE hUntrustedMemStore ;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoX509StoreCtx));
+
+ /* create trusted certs store collection */
+ ctx->trusted = CertOpenStore(CERT_STORE_PROV_COLLECTION,
+ 0,
+ 0,
+ 0,
+ NULL);
+ if(ctx->trusted == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* create trusted certs store */
+ hTrustedMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(hTrustedMemStore == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ ctx->trusted = NULL ;
+ return(-1);
+ }
+
+ /* add the memory trusted certs store to trusted certs store collection */
+ if( !CertAddStoreToCollection( ctx->trusted, hTrustedMemStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 1 ) ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ CertCloseStore(hTrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
+ ctx->trusted = NULL ;
+ return(-1);
+ }
+ CertCloseStore(hTrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
+
+ /* create untrusted certs store collection */
+ ctx->untrusted = CertOpenStore(CERT_STORE_PROV_COLLECTION,
+ 0,
+ 0,
+ 0,
+ NULL);
+ if(ctx->untrusted == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ ctx->trusted = NULL ;
+ return(-1);
+ }
+
+ /* create untrusted certs store */
+ hUntrustedMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(hUntrustedMemStore == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ CertCloseStore(ctx->untrusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ ctx->trusted = NULL ;
+ ctx->untrusted = NULL ;
+ return(-1);
+ }
+
+ /* add the memory trusted certs store to untrusted certs store collection */
+ if( !CertAddStoreToCollection( ctx->untrusted, hUntrustedMemStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 1 ) ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CertCloseStore(ctx->untrusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ CertCloseStore(hUntrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
+ ctx->trusted = NULL ;
+ ctx->untrusted = NULL ;
+ return(-1);
+ }
+ CertCloseStore(hUntrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
+
+ return(0);
+}
+
+static void
+xmlSecMSCryptoX509StoreFinalize(xmlSecKeyDataStorePtr store) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->trusted) {
+ CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ }
+ if (ctx->untrusted) {
+ CertCloseStore(ctx->untrusted, CERT_CLOSE_STORE_FORCE_FLAG);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoX509StoreCtx));
+}
+
+
+/*****************************************************************************
+ *
+ * Low-level x509 functions
+ *
+ *****************************************************************************/
+static PCCERT_CONTEXT
+xmlSecMSCryptoX509FindCert(HCERTSTORE store, xmlChar *subjectName, xmlChar *issuerName,
+ xmlChar *issuerSerial, xmlChar *ski) {
+ PCCERT_CONTEXT pCert = NULL;
+ int ret;
+
+ xmlSecAssert2(store != 0, NULL);
+
+ if((pCert == NULL) && (NULL != subjectName)) {
+ CERT_NAME_BLOB cnb;
+ BYTE *cName;
+ DWORD cNameLen;
+
+ cName = xmlSecMSCryptoCertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ subjectName,
+ CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &cNameLen);
+ if(cName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoCertStrToName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+ cnb.pbData = cName;
+ cnb.cbData = cNameLen;
+ pCert = CertFindCertificateInStore(store,
+ PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(cName);
+ }
+
+ if((pCert == NULL) && (NULL != issuerName) && (NULL != issuerSerial)) {
+ xmlSecBn issuerSerialBn;
+ xmlChar * p;
+ CERT_INFO certInfo;
+ CERT_NAME_BLOB cnb;
+ BYTE *cName = NULL;
+ DWORD cNameLen = 0;
+
+ /* aleksey: for some unknown to me reasons, mscrypto wants Email
+ * instead of emailAddress. This code is not bullet proof and may
+ * produce incorrect results if someone has "emailAddress=" string
+ * in one of the fields, but it is best I can suggest to fix this problem.
+ * Also see xmlSecMSCryptoX509NameWrite function.
+ */
+ while( (p = (xmlChar*)xmlStrstr(issuerName, BAD_CAST "emailAddress=")) != NULL) {
+ memcpy(p, " Email=", 13);
+ }
+
+
+
+ /* get issuer name */
+ cName = xmlSecMSCryptoCertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ issuerName,
+ CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &cNameLen);
+ if(cName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoCertStrToName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+ cnb.pbData = cName;
+ cnb.cbData = cNameLen;
+
+ /* get serial number */
+ ret = xmlSecBnInitialize(&issuerSerialBn, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(cName);
+ return(NULL);
+ }
+
+ ret = xmlSecBnFromDecString(&issuerSerialBn, issuerSerial);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBnFinalize(&issuerSerialBn);
+ xmlFree(cName);
+ return(NULL);
+ }
+
+ /* I have no clue why at a sudden a swap is needed to
+ * convert from lsb... This code is purely based upon
+ * trial and error :( WK
+ */
+ ret = xmlSecBnReverse(&issuerSerialBn);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBnReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBnFinalize(&issuerSerialBn);
+ xmlFree(cName);
+ return(NULL);
+ }
+
+ certInfo.Issuer.cbData = cnb.cbData ;
+ certInfo.Issuer.pbData = cnb.pbData ;
+ certInfo.SerialNumber.cbData = xmlSecBnGetSize( &issuerSerialBn ) ;
+ certInfo.SerialNumber.pbData = xmlSecBnGetData( &issuerSerialBn ) ;
+
+ pCert = CertFindCertificateInStore(
+ store,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_CERT,
+ &certInfo,
+ NULL
+ ) ;
+
+ xmlFree(cName);
+ xmlSecBnFinalize(&issuerSerialBn);
+ }
+
+ if((pCert == NULL) && (ski != NULL)) {
+ CRYPT_HASH_BLOB blob;
+ xmlChar* binSki;
+ int binSkiLen;
+
+ binSki = xmlStrdup(ski);
+ if(binSki == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ /* trick: base64 decode "in place" */
+ binSkiLen = xmlSecBase64Decode(binSki, (xmlSecByte*)binSki, xmlStrlen(binSki));
+ if(binSkiLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ski=%s",
+ xmlSecErrorsSafeString(ski));
+ xmlFree(binSki);
+ return(NULL);
+ }
+
+ blob.pbData = binSki;
+ blob.cbData = binSkiLen;
+ pCert = CertFindCertificateInStore(store,
+ PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+ 0,
+ CERT_FIND_KEY_IDENTIFIER,
+ &blob,
+ NULL);
+ xmlFree(binSki);
+ }
+
+ return(pCert);
+}
+
+
+#endif /* XMLSEC_NO_X509 */
+
+
diff --git a/src/mscrypto/xmlsec-mingw.h b/src/mscrypto/xmlsec-mingw.h
new file mode 100644
index 00000000..85d8cc3d
--- /dev/null
+++ b/src/mscrypto/xmlsec-mingw.h
@@ -0,0 +1,165 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2007 Roumen Petrov.
+ */
+
+#ifndef __XMLSEC_MSCRYPTO_XMLSEC_MINGW_H__
+#define __XMLSEC_MSCRYPTO_XMLSEC_MINGW_H__
+
+
+/*defines*/
+#ifndef CERT_CLOSE_STORE_FORCE_FLAG
+# define CERT_CLOSE_STORE_FORCE_FLAG 1
+#endif
+
+#ifndef CERT_CLOSE_STORE_CHECK_FLAG
+# define CERT_CLOSE_STORE_CHECK_FLAG 2
+#endif
+
+
+#ifndef CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
+# define CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG 1
+#endif
+
+
+#ifndef CERT_STORE_ADD_ALWAYS
+# define CERT_STORE_ADD_ALWAYS 4
+#endif
+
+#ifndef CERT_STORE_CREATE_NEW_FLAG
+# define CERT_STORE_CREATE_NEW_FLAG (2<<12)
+#endif
+
+#ifndef CERT_STORE_SIGNATURE_FLAG
+# define CERT_STORE_SIGNATURE_FLAG 1
+#endif
+
+#ifndef CERT_STORE_TIME_VALIDITY_FLAG
+# define CERT_STORE_TIME_VALIDITY_FLAG 2
+#endif
+
+#ifndef CERT_STORE_REVOCATION_FLAG
+# define CERT_STORE_REVOCATION_FLAG 4
+#endif
+
+#ifndef CERT_STORE_NO_CRL_FLAG
+# define CERT_STORE_NO_CRL_FLAG (1<<16)
+#endif
+
+
+#ifndef CERT_STORE_PROV_COLLECTION
+# define CERT_STORE_PROV_COLLECTION ((LPCSTR) 11)
+#endif
+
+#ifndef CERT_STORE_PROV_MEMORY
+# define CERT_STORE_PROV_MEMORY ((LPCSTR) 2)
+#endif
+
+
+#ifndef CERT_KEY_SPEC_PROP_ID
+# define CERT_KEY_SPEC_PROP_ID 6
+#endif
+
+#ifndef CERT_FRIENDLY_NAME_PROP_ID
+# define CERT_FRIENDLY_NAME_PROP_ID 11
+#endif
+
+#ifndef CERT_KEY_IDENTIFIER_PROP_ID
+# define CERT_KEY_IDENTIFIER_PROP_ID 20
+#endif
+
+
+#ifndef CERT_NAME_ISSUER_FLAG
+# define CERT_NAME_ISSUER_FLAG 1
+#endif
+
+#ifndef CERT_NAME_RDN_TYPE
+# define CERT_NAME_RDN_TYPE 2
+#endif
+
+#ifndef CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG
+# define CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG (4<<16)
+#endif
+
+
+#ifndef CERT_CHAIN_REVOCATION_CHECK_CHAIN
+# define CERT_CHAIN_REVOCATION_CHECK_CHAIN (2<<28)
+#endif
+
+#ifndef CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
+# define CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT (4<<28)
+#endif
+
+
+#ifndef szOID_SUBJECT_KEY_IDENTIFIER
+# define szOID_SUBJECT_KEY_IDENTIFIER "2.5.29.14"
+#endif
+
+
+#ifndef CRYPT_ACQUIRE_COMPARE_KEY_FLAG
+# define CRYPT_ACQUIRE_COMPARE_KEY_FLAG 4
+#endif
+
+
+/*structures/types*/
+typedef struct _PUBKEY {
+ DWORD magic;
+ DWORD bitlen;
+} DSSPUBKEY;
+
+typedef struct _DSSSEED {
+ DWORD counter;
+ BYTE seed[20];
+} DSSSEED;
+
+
+typedef struct _PROV_ENUMALGS_EX {
+ ALG_ID aiAlgid;
+ DWORD dwDefaultLen;
+ DWORD dwMinLen;
+ DWORD dwMaxLen;
+ DWORD dwProtocols;
+ DWORD dwNameLen;
+ CHAR szName[20];
+ DWORD dwLongNameLen;
+ CHAR szLongName[40];
+} PROV_ENUMALGS_EX;
+
+
+/*methods(functions)*/
+DWORD WINAPI CertGetPublicKeyLength(DWORD,PCERT_PUBLIC_KEY_INFO);
+
+BOOL WINAPI CertStrToNameA(DWORD,LPCSTR,DWORD,void*,BYTE*,DWORD*,LPCSTR*);
+BOOL WINAPI CertStrToNameW(DWORD,LPCWSTR,DWORD,void*,BYTE*,DWORD*,LPCWSTR*);
+#ifdef UNICODE
+#define CertStrToName CertStrToNameW
+#else
+#define CertStrToName CertStrToNameA
+#endif
+BOOL WINAPI CertCompareCertificateName(DWORD,PCERT_NAME_BLOB,PCERT_NAME_BLOB);
+
+BOOL WINAPI CertAddStoreToCollection(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
+
+PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD,const BYTE*,DWORD);
+BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT,DWORD,void*,DWORD*);
+BOOL WINAPI CertVerifySubjectCertificateContext(PCCERT_CONTEXT,PCCERT_CONTEXT,DWORD*);
+
+BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE,PCCRL_CONTEXT,DWORD,PCCRL_CONTEXT*);
+PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT);
+BOOL WINAPI CertFreeCRLContext(PCCRL_CONTEXT);
+
+BOOL WINAPI CertFindCertificateInCRL(PCCERT_CONTEXT,PCCRL_CONTEXT,DWORD,void*,PCRL_ENTRY*);
+PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE,PCCRL_CONTEXT);
+
+PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD,const BYTE*,DWORD);
+
+BOOL WINAPI CryptAcquireCertificatePrivateKey(PCCERT_CONTEXT,DWORD,void*,HCRYPTPROV*,DWORD*,BOOL*);
+BOOL WINAPI CryptDuplicateKey(HCRYPTKEY,DWORD*,DWORD,HCRYPTKEY*);
+BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV,DWORD,PCERT_PUBLIC_KEY_INFO,HCRYPTKEY*);
+
+
+#endif /*ndef __XMLSEC_MSCRYPTO_XMLSEC_MINGW_H__*/
diff --git a/src/nodeset.c b/src/nodeset.c
new file mode 100644
index 00000000..74c2d5b3
--- /dev/null
+++ b/src/nodeset.c
@@ -0,0 +1,599 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Enchanced nodes set
+ *
+ * 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 <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/nodeset.h>
+#include <xmlsec/errors.h>
+
+#define xmlSecGetParent(node) \
+ (((node)->type != XML_NAMESPACE_DECL) ? \
+ (node)->parent : \
+ (xmlNodePtr)((xmlNsPtr)(node))->next)
+
+static int xmlSecNodeSetOneContains (xmlSecNodeSetPtr nset,
+ xmlNodePtr node,
+ xmlNodePtr parent);
+static int xmlSecNodeSetWalkRecursive (xmlSecNodeSetPtr nset,
+ xmlSecNodeSetWalkCallback walkFunc,
+ void* data,
+ xmlNodePtr cur,
+ xmlNodePtr parent);
+
+/**
+ * xmlSecNodeSetCreate:
+ * @doc: the pointer to parent XML document.
+ * @nodes: the list of nodes.
+ * @type: the nodes set type.
+ *
+ * Creates new nodes set. Caller is responsible for freeng returend object
+ * by calling #xmlSecNodeSetDestroy function.
+ *
+ * Returns: pointer to newly allocated node set or NULL if an error occurs.
+ */
+xmlSecNodeSetPtr
+xmlSecNodeSetCreate(xmlDocPtr doc, xmlNodeSetPtr nodes, xmlSecNodeSetType type) {
+ xmlSecNodeSetPtr nset;
+
+ nset = (xmlSecNodeSetPtr)xmlMalloc(sizeof(xmlSecNodeSet));
+ if(nset == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecNodeSet)=%d",
+ sizeof(xmlSecNodeSet));
+ return(NULL);
+ }
+ memset(nset, 0, sizeof(xmlSecNodeSet));
+
+ nset->doc = doc;
+ nset->nodes = nodes;
+ nset->type = type;
+ nset->next = nset->prev = nset;
+ return(nset);
+}
+
+/**
+ * xmlSecNodeSetDestroy:
+ * @nset: the pointer to node set.
+ *
+ * Destroys the nodes set created with #xmlSecNodeSetCreate function.
+ */
+void
+xmlSecNodeSetDestroy(xmlSecNodeSetPtr nset) {
+ xmlSecNodeSetPtr tmp;
+
+ xmlSecAssert(nset != NULL);
+
+ while((tmp = nset) != NULL) {
+ if((nset->next != NULL) && (nset->next != nset)) {
+ nset->next->prev = nset->prev;
+ nset->prev->next = nset->next;
+ nset = nset->next;
+ } else {
+ nset = NULL;
+ }
+
+ if(tmp->nodes != NULL) {
+ xmlXPathFreeNodeSet(tmp->nodes);
+ }
+ if(tmp->children != NULL) {
+ xmlSecNodeSetDestroy(tmp->children);
+ }
+ if((tmp->doc != NULL) && (tmp->destroyDoc != 0)) {
+ xmlFreeDoc(tmp->doc);
+ }
+ memset(tmp, 0, sizeof(xmlSecNodeSet));
+ xmlFree(tmp);
+ }
+}
+
+/**
+ * xmlSecNodeSetDocDestroy:
+ * @nset: the pointer to node set.
+ *
+ * Instructs node set to destroy nodes parent doc when node set is destroyed.
+ */
+void
+xmlSecNodeSetDocDestroy(xmlSecNodeSetPtr nset) {
+ xmlSecAssert(nset != NULL);
+
+ nset->destroyDoc = 1;
+}
+
+static int
+xmlSecNodeSetOneContains(xmlSecNodeSetPtr nset, xmlNodePtr node, xmlNodePtr parent) {
+ int in_nodes_set = 1;
+
+ xmlSecAssert2(nset != NULL, 0);
+ xmlSecAssert2(node != NULL, 0);
+
+ /* special cases: */
+ switch(nset->type) {
+ case xmlSecNodeSetTreeWithoutComments:
+ case xmlSecNodeSetTreeWithoutCommentsInvert:
+ if(node->type == XML_COMMENT_NODE) {
+ return(0);
+ }
+ break;
+ case xmlSecNodeSetList:
+ return(xmlSecNodeSetContains(nset->children, node, parent));
+ default:
+ break;
+ }
+
+ if(nset->nodes != NULL) {
+ if(node->type != XML_NAMESPACE_DECL) {
+ in_nodes_set = xmlXPathNodeSetContains(nset->nodes, node);
+ } else {
+ xmlNs ns;
+
+ memcpy(&ns, node, sizeof(ns));
+
+ /* this is a libxml hack! check xpath.c for details */
+ if((parent != NULL) && (parent->type == XML_ATTRIBUTE_NODE)) {
+ ns.next = (xmlNsPtr)parent->parent;
+ } else {
+ ns.next = (xmlNsPtr)parent;
+ }
+
+ /*
+ * If the input is an XPath node-set, then the node-set must explicitly
+ * contain every node to be rendered to the canonical form.
+ */
+ in_nodes_set = (xmlXPathNodeSetContains(nset->nodes, (xmlNodePtr)&ns));
+ }
+ }
+
+ switch(nset->type) {
+ case xmlSecNodeSetNormal:
+ return(in_nodes_set);
+ case xmlSecNodeSetInvert:
+ return(!in_nodes_set);
+ case xmlSecNodeSetTree:
+ case xmlSecNodeSetTreeWithoutComments:
+ if(in_nodes_set) {
+ return(1);
+ }
+ if((parent != NULL) && (parent->type == XML_ELEMENT_NODE)) {
+ return(xmlSecNodeSetOneContains(nset, parent, parent->parent));
+ }
+ return(0);
+ case xmlSecNodeSetTreeInvert:
+ case xmlSecNodeSetTreeWithoutCommentsInvert:
+ if(in_nodes_set) {
+ return(0);
+ }
+ if((parent != NULL) && (parent->type == XML_ELEMENT_NODE)) {
+ return(xmlSecNodeSetOneContains(nset, parent, parent->parent));
+ }
+ return(1);
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "type=%d", nset->type);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNodeSetContains:
+ * @nset: the pointer to node set.
+ * @node: the pointer to XML node to check.
+ * @parent: the pointer to @node parent node.
+ *
+ * Checks whether the @node is in the nodes set or not.
+ *
+ * Returns: 1 if the @node is in the nodes set @nset, 0 if it is not
+ * and a negative value if an error occurs.
+ */
+int
+xmlSecNodeSetContains(xmlSecNodeSetPtr nset, xmlNodePtr node, xmlNodePtr parent) {
+ int status = 1;
+ xmlSecNodeSetPtr cur;
+
+ xmlSecAssert2(node != NULL, 0);
+
+ /* special cases: */
+ if(nset == NULL) {
+ return(1);
+ }
+
+ status = 1;
+ cur = nset;
+ do {
+ switch(cur->op) {
+ case xmlSecNodeSetIntersection:
+ if(status && !xmlSecNodeSetOneContains(cur, node, parent)) {
+ status = 0;
+ }
+ break;
+ case xmlSecNodeSetSubtraction:
+ if(status && xmlSecNodeSetOneContains(cur, node, parent)) {
+ status = 0;
+ }
+ break;
+ case xmlSecNodeSetUnion:
+ if(!status && xmlSecNodeSetOneContains(cur, node, parent)) {
+ status = 1;
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_OPERATION,
+ "operation=%d", cur->op);
+ return(-1);
+ }
+ cur = cur->next;
+ } while(cur != nset);
+
+ return(status);
+}
+
+/**
+ * xmlSecNodeSetAdd:
+ * @nset: the pointer to currrent nodes set (or NULL).
+ * @newNSet: the pointer to new nodes set.
+ * @op: the operation type.
+ *
+ * Adds @newNSet to the @nset using operation @op.
+ *
+ * Returns: the pointer to combined nodes set or NULL if an error
+ * occurs.
+ */
+xmlSecNodeSetPtr
+xmlSecNodeSetAdd(xmlSecNodeSetPtr nset, xmlSecNodeSetPtr newNSet,
+ xmlSecNodeSetOp op) {
+ xmlSecAssert2(newNSet != NULL, NULL);
+ xmlSecAssert2(newNSet->next == newNSet, NULL);
+
+ newNSet->op = op;
+ if(nset == NULL) {
+ return(newNSet);
+ }
+
+ newNSet->next = nset;
+ newNSet->prev = nset->prev;
+ nset->prev->next = newNSet;
+ nset->prev = newNSet;
+ return(nset);
+}
+
+/**
+ * xmlSecNodeSetAddList:
+ * @nset: the pointer to currrent nodes set (or NULL).
+ * @newNSet: the pointer to new nodes set.
+ * @op: the operation type.
+ *
+ * Adds @newNSet to the @nset as child using operation @op.
+ *
+ * Returns: the pointer to combined nodes set or NULL if an error
+ * occurs.
+ */
+xmlSecNodeSetPtr
+xmlSecNodeSetAddList(xmlSecNodeSetPtr nset, xmlSecNodeSetPtr newNSet, xmlSecNodeSetOp op) {
+ xmlSecNodeSetPtr tmp1, tmp2;
+
+ xmlSecAssert2(newNSet != NULL, NULL);
+
+ tmp1 = xmlSecNodeSetCreate(newNSet->doc, NULL, xmlSecNodeSetList);
+ if(tmp1 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ tmp1->children = newNSet;
+
+ tmp2 = xmlSecNodeSetAdd(nset, tmp1, op);
+ if(tmp2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecNodeSetDestroy(tmp1);
+ return(NULL);
+ }
+ return(tmp2);
+}
+
+
+/**
+ * xmlSecNodeSetWalk:
+ * @nset: the pointer to node set.
+ * @walkFunc: the callback functions.
+ * @data: the application specific data passed to the @walkFunc.
+ *
+ * Calls the function @walkFunc once per each node in the nodes set @nset.
+ * If the @walkFunc returns a negative value, then the walk procedure
+ * is interrupted.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNodeSetWalk(xmlSecNodeSetPtr nset, xmlSecNodeSetWalkCallback walkFunc, void* data) {
+ xmlNodePtr cur;
+ int ret = 0;
+
+ xmlSecAssert2(nset != NULL, -1);
+ xmlSecAssert2(nset->doc != NULL, -1);
+ xmlSecAssert2(walkFunc != NULL, -1);
+
+ /* special cases */
+ if(nset->nodes != NULL) {
+ int i;
+
+ switch(nset->type) {
+ case xmlSecNodeSetNormal:
+ case xmlSecNodeSetTree:
+ case xmlSecNodeSetTreeWithoutComments:
+ for(i = 0; (ret >= 0) && (i < nset->nodes->nodeNr); ++i) {
+ ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data,
+ nset->nodes->nodeTab[i],
+ xmlSecGetParent(nset->nodes->nodeTab[i]));
+ }
+ return(ret);
+ default:
+ break;
+ }
+ }
+
+ for(cur = nset->doc->children; (cur != NULL) && (ret >= 0); cur = cur->next) {
+ ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, cur, xmlSecGetParent(cur));
+ }
+ return(ret);
+}
+
+static int
+xmlSecNodeSetWalkRecursive(xmlSecNodeSetPtr nset, xmlSecNodeSetWalkCallback walkFunc,
+ void* data, xmlNodePtr cur, xmlNodePtr parent) {
+ int ret;
+
+ xmlSecAssert2(nset != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+ xmlSecAssert2(walkFunc != NULL, -1);
+
+ /* the node itself */
+ if(xmlSecNodeSetContains(nset, cur, parent)) {
+ ret = walkFunc(nset, cur, parent, data);
+
+ if(ret < 0) {
+ return(ret);
+ }
+ }
+
+ /* element node has attributes, namespaces */
+ if(cur->type == XML_ELEMENT_NODE) {
+ xmlAttrPtr attr;
+ xmlNodePtr node;
+ xmlNsPtr ns, tmp;
+
+ attr = (xmlAttrPtr)cur->properties;
+ while(attr != NULL) {
+ if(xmlSecNodeSetContains(nset, (xmlNodePtr)attr, cur)) {
+ ret = walkFunc(nset, (xmlNodePtr)attr, cur, data);
+ if(ret < 0) {
+ return(ret);
+ }
+ }
+ attr = attr->next;
+ }
+
+ node = cur;
+ while(node != NULL) {
+ ns = node->nsDef;
+ while(ns != NULL) {
+ tmp = xmlSearchNs(nset->doc, cur, ns->prefix);
+ if((tmp == ns) && xmlSecNodeSetContains(nset, (xmlNodePtr)ns, cur)) {
+ ret = walkFunc(nset, (xmlNodePtr)ns, cur, data);
+ if(ret < 0) {
+ return(ret);
+ }
+ }
+ ns = ns->next;
+ }
+ node = node->parent;
+ }
+ }
+
+ /* element and document nodes have children */
+ if((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE)) {
+ xmlNodePtr node;
+
+ node = cur->children;
+ while(node != NULL) {
+ ret = xmlSecNodeSetWalkRecursive(nset, walkFunc, data, node, cur);
+ if(ret < 0) {
+ return(ret);
+ }
+ node = node->next;
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecNodeSetGetChildren:
+ * @doc: the pointer to an XML document.
+ * @parent: the pointer to parent XML node or NULL if we want to include all document nodes.
+ * @withComments: the flag include comments or not.
+ * @invert: the "invert" flag.
+ *
+ * Creates a new nodes set that contains:
+ * - if @withComments is not 0 and @invert is 0:
+ * all nodes in the @parent subtree;
+ * - if @withComments is 0 and @invert is 0:
+ * all nodes in the @parent subtree except comment nodes;
+ * - if @withComments is not 0 and @invert not is 0:
+ * all nodes in the @doc except nodes in the @parent subtree;
+ * - if @withComments is 0 and @invert is 0:
+ * all nodes in the @doc except nodes in the @parent subtree
+ * and comment nodes.
+ *
+ * Returns: pointer to the newly created #xmlSecNodeSet structure
+ * or NULL if an error occurs.
+ */
+xmlSecNodeSetPtr
+xmlSecNodeSetGetChildren(xmlDocPtr doc, const xmlNodePtr parent, int withComments, int invert) {
+ xmlNodeSetPtr nodes;
+ xmlSecNodeSetType type;
+
+ xmlSecAssert2(doc != NULL, NULL);
+
+ nodes = xmlXPathNodeSetCreate(parent);
+ if(nodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathNodeSetCreate",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* if parent is NULL then we add all the doc children */
+ if(parent == NULL) {
+ xmlNodePtr cur;
+ for(cur = doc->children; cur != NULL; cur = cur->next) {
+ if(withComments || (cur->type != XML_COMMENT_NODE)) {
+ xmlXPathNodeSetAdd(nodes, cur);
+ }
+ }
+ }
+
+ if(withComments && invert) {
+ type = xmlSecNodeSetTreeInvert;
+ } else if(withComments && !invert) {
+ type = xmlSecNodeSetTree;
+ } else if(!withComments && invert) {
+ type = xmlSecNodeSetTreeWithoutCommentsInvert;
+ } else { /* if(!withComments && !invert) */
+ type = xmlSecNodeSetTreeWithoutComments;
+ }
+
+ return(xmlSecNodeSetCreate(doc, nodes, type));
+}
+
+static int
+xmlSecNodeSetDumpTextNodesWalkCallback(xmlSecNodeSetPtr nset, xmlNodePtr cur,
+ xmlNodePtr parent ATTRIBUTE_UNUSED,
+ void* data) {
+ xmlSecAssert2(nset != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+
+ if(cur->type == XML_TEXT_NODE) {
+ xmlOutputBufferWriteString((xmlOutputBufferPtr)data,
+ (char*)(cur->content));
+ }
+ return(0);
+}
+
+/**
+ * xmlSecNodeSetDumpTextNodes:
+ * @nset: the pointer to node set.
+ * @out: the output buffer.
+ *
+ * Dumps content of all the text nodes from @nset to @out.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNodeSetDumpTextNodes(xmlSecNodeSetPtr nset, xmlOutputBufferPtr out) {
+ xmlSecAssert2(nset != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ return(xmlSecNodeSetWalk(nset, xmlSecNodeSetDumpTextNodesWalkCallback, out));
+}
+
+/**
+ * xmlSecNodeSetDebugDump:
+ * @nset: the pointer to node set.
+ * @output: the pointer to output FILE.
+ *
+ * Prints information about @nset to the @output.
+ */
+void
+xmlSecNodeSetDebugDump(xmlSecNodeSetPtr nset, FILE *output) {
+ int i, l;
+ xmlNodePtr cur;
+
+ xmlSecAssert(nset != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "== Nodes set ");
+ switch(nset->type) {
+ case xmlSecNodeSetNormal:
+ fprintf(output, "(xmlSecNodeSetNormal)\n");
+ break;
+ case xmlSecNodeSetInvert:
+ fprintf(output, "(xmlSecNodeSetInvert)\n");
+ break;
+ case xmlSecNodeSetTree:
+ fprintf(output, "(xmlSecNodeSetTree)\n");
+ break;
+ case xmlSecNodeSetTreeWithoutComments:
+ fprintf(output, "(xmlSecNodeSetTreeWithoutComments)\n");
+ break;
+ case xmlSecNodeSetTreeInvert:
+ fprintf(output, "(xmlSecNodeSetTreeInvert)\n");
+ break;
+ case xmlSecNodeSetTreeWithoutCommentsInvert:
+ fprintf(output, "(xmlSecNodeSetTreeWithoutCommentsInvert)\n");
+ break;
+ case xmlSecNodeSetList:
+ fprintf(output, "(xmlSecNodeSetList)\n");
+ fprintf(output, ">>>\n");
+ xmlSecNodeSetDebugDump(nset->children, output);
+ fprintf(output, "<<<\n");
+ return;
+ default:
+ fprintf(output, "(unknown=%d)\n", nset->type);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "type=%d", nset->type);
+ }
+
+ l = xmlXPathNodeSetGetLength(nset->nodes);
+ for(i = 0; i < l; ++i) {
+ cur = xmlXPathNodeSetItem(nset->nodes, i);
+ if(cur->type != XML_NAMESPACE_DECL) {
+ fprintf(output, "%d: %s\n", cur->type,
+ (cur->name) ? cur->name : BAD_CAST "null");
+ } else {
+ xmlNsPtr ns = (xmlNsPtr)cur;
+ fprintf(output, "%d: %s=%s (%s:%s)\n", cur->type,
+ (ns->prefix) ? ns->prefix : BAD_CAST "null",
+ (ns->href) ? ns->href : BAD_CAST "null",
+ (((xmlNodePtr)ns->next)->ns &&
+ ((xmlNodePtr)ns->next)->ns->prefix) ?
+ ((xmlNodePtr)ns->next)->ns->prefix : BAD_CAST "null",
+ ((xmlNodePtr)ns->next)->name);
+ }
+ }
+}
diff --git a/src/nss/Makefile.am b/src/nss/Makefile.am
new file mode 100644
index 00000000..5209533f
--- /dev/null
+++ b/src/nss/Makefile.am
@@ -0,0 +1,57 @@
+NULL =
+
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-nss.la \
+ $(NULL)
+
+libxmlsec1_nss_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(NSS_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_nss_la_SOURCES =\
+ app.c \
+ bignum.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ hmac.c \
+ pkikeys.c \
+ signatures.c \
+ symkeys.c \
+ x509.c \
+ x509vfy.c \
+ keysstore.c \
+ keytrans.c \
+ kw_des.c \
+ kw_aes.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_nss_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_nss_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(NSS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_nss_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_nss_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/nss/Makefile.in b/src/nss/Makefile.in
new file mode 100644
index 00000000..d6bc31ec
--- /dev/null
+++ b/src/nss/Makefile.in
@@ -0,0 +1,786 @@
+# Makefile.in generated by automake 1.11 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/nss
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+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_nss_la_SOURCES_DIST = app.c bignum.c ciphers.c crypto.c \
+ digests.c hmac.c pkikeys.c signatures.c symkeys.c x509.c \
+ x509vfy.c keysstore.c keytrans.c kw_des.c kw_aes.c globals.h \
+ ../strings.c
+am__objects_1 =
+@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_nss_la-strings.lo
+am_libxmlsec1_nss_la_OBJECTS = libxmlsec1_nss_la-app.lo \
+ libxmlsec1_nss_la-bignum.lo libxmlsec1_nss_la-ciphers.lo \
+ libxmlsec1_nss_la-crypto.lo libxmlsec1_nss_la-digests.lo \
+ libxmlsec1_nss_la-hmac.lo libxmlsec1_nss_la-pkikeys.lo \
+ libxmlsec1_nss_la-signatures.lo libxmlsec1_nss_la-symkeys.lo \
+ libxmlsec1_nss_la-x509.lo libxmlsec1_nss_la-x509vfy.lo \
+ libxmlsec1_nss_la-keysstore.lo libxmlsec1_nss_la-keytrans.lo \
+ libxmlsec1_nss_la-kw_des.lo libxmlsec1_nss_la-kw_aes.lo \
+ $(am__objects_1) $(am__objects_2)
+libxmlsec1_nss_la_OBJECTS = $(am_libxmlsec1_nss_la_OBJECTS)
+libxmlsec1_nss_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_nss_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_nss_la_SOURCES)
+DIST_SOURCES = $(am__libxmlsec1_nss_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@
+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@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_ENABLED = @PKG_CONFIG_ENABLED@
+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_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_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-nss.la \
+ $(NULL)
+
+libxmlsec1_nss_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(NSS_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_nss_la_SOURCES = app.c bignum.c ciphers.c crypto.c \
+ digests.c hmac.c pkikeys.c signatures.c symkeys.c x509.c \
+ x509vfy.c keysstore.c keytrans.c kw_des.c kw_aes.c globals.h \
+ $(NULL) $(am__append_1)
+libxmlsec1_nss_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(NSS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_nss_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_nss_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/nss/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/nss/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-nss.la: $(libxmlsec1_nss_la_OBJECTS) $(libxmlsec1_nss_la_DEPENDENCIES)
+ $(libxmlsec1_nss_la_LINK) -rpath $(libdir) $(libxmlsec1_nss_la_OBJECTS) $(libxmlsec1_nss_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-bignum.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-ciphers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-digests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-keysstore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-keytrans.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-kw_aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-kw_des.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-pkikeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-signatures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-symkeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_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_nss_la-app.lo: app.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-app.Tpo -c -o libxmlsec1_nss_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-app.Tpo $(DEPDIR)/libxmlsec1_nss_la-app.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+
+libxmlsec1_nss_la-bignum.lo: bignum.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-bignum.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-bignum.Tpo -c -o libxmlsec1_nss_la-bignum.lo `test -f 'bignum.c' || echo '$(srcdir)/'`bignum.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-bignum.Tpo $(DEPDIR)/libxmlsec1_nss_la-bignum.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bignum.c' object='libxmlsec1_nss_la-bignum.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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-bignum.lo `test -f 'bignum.c' || echo '$(srcdir)/'`bignum.c
+
+libxmlsec1_nss_la-ciphers.lo: ciphers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-ciphers.Tpo -c -o libxmlsec1_nss_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_nss_la-ciphers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+
+libxmlsec1_nss_la-crypto.lo: crypto.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-crypto.Tpo -c -o libxmlsec1_nss_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-crypto.Tpo $(DEPDIR)/libxmlsec1_nss_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+
+libxmlsec1_nss_la-digests.lo: digests.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-digests.Tpo -c -o libxmlsec1_nss_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-digests.Tpo $(DEPDIR)/libxmlsec1_nss_la-digests.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+
+libxmlsec1_nss_la-hmac.lo: hmac.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-hmac.Tpo -c -o libxmlsec1_nss_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-hmac.Tpo $(DEPDIR)/libxmlsec1_nss_la-hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+
+libxmlsec1_nss_la-pkikeys.lo: pkikeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-pkikeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-pkikeys.Tpo -c -o libxmlsec1_nss_la-pkikeys.lo `test -f 'pkikeys.c' || echo '$(srcdir)/'`pkikeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-pkikeys.Tpo $(DEPDIR)/libxmlsec1_nss_la-pkikeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pkikeys.c' object='libxmlsec1_nss_la-pkikeys.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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-pkikeys.lo `test -f 'pkikeys.c' || echo '$(srcdir)/'`pkikeys.c
+
+libxmlsec1_nss_la-signatures.lo: signatures.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-signatures.Tpo -c -o libxmlsec1_nss_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-signatures.Tpo $(DEPDIR)/libxmlsec1_nss_la-signatures.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+
+libxmlsec1_nss_la-symkeys.lo: symkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-symkeys.Tpo -c -o libxmlsec1_nss_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_nss_la-symkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+
+libxmlsec1_nss_la-x509.lo: x509.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-x509.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-x509.Tpo -c -o libxmlsec1_nss_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-x509.Tpo $(DEPDIR)/libxmlsec1_nss_la-x509.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+
+libxmlsec1_nss_la-x509vfy.lo: x509vfy.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-x509vfy.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-x509vfy.Tpo -c -o libxmlsec1_nss_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-x509vfy.Tpo $(DEPDIR)/libxmlsec1_nss_la-x509vfy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509vfy.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+
+libxmlsec1_nss_la-keysstore.lo: keysstore.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-keysstore.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-keysstore.Tpo -c -o libxmlsec1_nss_la-keysstore.lo `test -f 'keysstore.c' || echo '$(srcdir)/'`keysstore.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-keysstore.Tpo $(DEPDIR)/libxmlsec1_nss_la-keysstore.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='keysstore.c' object='libxmlsec1_nss_la-keysstore.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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-keysstore.lo `test -f 'keysstore.c' || echo '$(srcdir)/'`keysstore.c
+
+libxmlsec1_nss_la-keytrans.lo: keytrans.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-keytrans.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-keytrans.Tpo -c -o libxmlsec1_nss_la-keytrans.lo `test -f 'keytrans.c' || echo '$(srcdir)/'`keytrans.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-keytrans.Tpo $(DEPDIR)/libxmlsec1_nss_la-keytrans.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='keytrans.c' object='libxmlsec1_nss_la-keytrans.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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-keytrans.lo `test -f 'keytrans.c' || echo '$(srcdir)/'`keytrans.c
+
+libxmlsec1_nss_la-kw_des.lo: kw_des.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-kw_des.Tpo -c -o libxmlsec1_nss_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_nss_la-kw_des.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+
+libxmlsec1_nss_la-kw_aes.lo: kw_aes.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-kw_aes.Tpo -c -o libxmlsec1_nss_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_nss_la-kw_aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+
+libxmlsec1_nss_la-strings.lo: ../strings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-strings.Tpo -c -o libxmlsec1_nss_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-strings.Tpo $(DEPDIR)/libxmlsec1_nss_la-strings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_nss_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_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_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/nss/README b/src/nss/README
new file mode 100644
index 00000000..884ade99
--- /dev/null
+++ b/src/nss/README
@@ -0,0 +1,137 @@
+WHAT VERSION OF NSS?
+------------------------------------------------------------------------
+NSS 3.8 or greater and NSPR 4.3 or greater are required.
+
+KEYS MANAGER
+------------------------------------------------------------------------
+
+xmlsec-nss key manager uses a custom Keys Store, and a custom X509 Store.
+The custom Keys Store and the X509 Store use the NSS database as the underlying
+store for public/private keys, Certs and CRLs.
+
+The NSS Keys store uses the Simple Keys Store on top of the NSS repository.
+The reason for this is that XMLSEC's generic adoptkey/getKey functions use a
+XMLSEC key object that contains more attributes than the raw NSS key object,
+and the getkey function may use a combination of one or more of these attributes
+(name, type, usage, Id) to find a key. There is no straightforward 1-1 mapping
+between XMLSEC's adoptkey/getkey and NSS's APIs.
+
+For example, the store may be asked to adopt a symmetric key, and later asked
+to find it just by name. Or the store may be asked to adopt a private key
+just by its type, and later asked to find it just by type. The key returned
+by getKey is expected to contain all the attributes that were present at the
+time of adoptkey - NSS store does not provide a way to store app-specific
+attributes.
+
+When a key is adopted by the NSS Keys Store, it is simply saved in the
+Simple Keys Store. It is not saved into the NSS database. The only
+way to load keys into the NSS database is with a load operation through
+the XMLSEC API or via an administrator operation.
+
+When a getKey is done on the NSS Keys Store, it first checks the Simple
+Keys Store. If the key is found there, it is returned. If not, the key
+is searched in the NSS database. If found, the key is stored in the
+Simple Keys Store before it is returned.
+
+
+Thus, the various sources for keys/certs/crls for an XMLSEC-NSS application
+are:
+- elements in XML documents
+- PKCS12 and DER files
+- NSS Database
+
+
+KNOWN ISSUES.
+------------------------------------------------------------------------
+1) NSS needs to provide a way to convert a DER integer string to an ASCII
+decimal string. Once NSS is fixed, the function xmlSecNssASN1IntegerWrite
+in src/nss/x509.c needs to be implemented.
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=212864
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118633
+
+2) RSA Encryption/Decryption using PKCS#1 v1.5 padding not currently exposed
+in NSS. This causes some tests to fail.
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=214236
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118628
+
+3) RSA-OAEP is not yet implemented in NSS. This is the only REQUIRED algorithm
+that is missing from xmlsec-nss.
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=158747
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118629
+
+4) There are 2 fixes in NSS that will be rolled into the next release (3.9).
+They are:
+ - http://bugzilla.mozilla.org/show_bug.cgi?id=208194
+ Once available, need to change src/nss/x509.c. Replace
+ PR_AtomicIncrement(&(crlSrc->referenceCount));
+ with
+ SEC_DupCrl(crlSrc);
+ (there is a comment there that already has the correct line)
+
+ - http://bugzilla.mozilla.org/show_bug.cgi?id=211384
+ No changes required. The "NSS_Shutdown failed" in some of the
+ current tests will go away
+
+xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118630
+
+5) CERT_FindCertByNameString does not work in all cases
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=210709
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118631
+
+6) CERT_FindCertBySubjectKeyID does not work in all cases
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=211051
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118632
+
+7) Finding a cert by Issuer & Serial Number needs the ability to
+convert an ASCII decimal string to a DER integer string. Filed
+an RFE against NSS. Once fixed, xmlSecNumToItem in x509vfy.c
+needs to be changed to use the new function(s) provided
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=212864
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118633
+
+8) RIPEMD160 Digest and RIPEMD160 HMAC is not supported by NSS
+
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118634
+
+9) AES Key wrap algorithm is implemented in NSS but not exposed due to
+some bug src/nss/kw_aes.c uses a workaround which should be removed
+when the bug is fixed
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=213795
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118635
+
+10) Not all file formats are supported
+
+- xmlSecNssAppKeyLoad(): This function loads a PKI key from a file.
+ The following formats are supported:
+ . xmlSecKeyDataFormatDer: This expects the private key to be in
+ PrivateKeyInfo format. Note that the DER files containing
+ private keys in the xmlsec test suite aren't in that format
+ . xmlsecKeyDataFormatPkcs12
+
+ The following formats are not supported:
+ . xmlSecKeyDataFormatPkcs8Pem
+ . xmlSecKeyDataFormatPkcs8Der
+
+
+- xmlSecNssAppCertLoad(): This function loads a cert from a file.
+ The following formats are supported:
+ xmlSecKeyDataFormatDer
+
+ The following formats are not supported:
+ xmlSecKeyDataFormatPem
+
+11) "Trusted" vs "Untrusted" certificates:
+The distinction between "trusted" and "untrusted" certificates in
+xmlsec-openssl is maintained because the OPENSSL application (and
+not the OPENSSL library) has to maintain a cert store and verify
+certificates. With NSS, no such distinction is necessary in the
+application.
+
+Aleksey: Not sure that I understand this point but thats what Tej wrote.
+
diff --git a/src/nss/app.c b/src/nss/app.c
new file mode 100644
index 00000000..8aaf3327
--- /dev/null
+++ b/src/nss/app.c
@@ -0,0 +1,1598 @@
+/**
+ * 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>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <cert.h>
+#include <keyhi.h>
+#include <pkcs12.h>
+#include <p12plcy.h>
+/*
+#include <ssl.h>
+*/
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+#include <xmlsec/nss/pkikeys.h>
+#include <xmlsec/nss/keysstore.h>
+
+/* workaround - NSS exports this but doesn't declare it */
+extern CERTCertificate * __CERT_NewTempCertificate (CERTCertDBHandle *handle,
+ SECItem *derCert,
+ char *nickname,
+ PRBool isperm,
+ PRBool copyDER);
+static int xmlSecNssAppCreateSECItem (SECItem *contents,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+static int xmlSecNssAppReadSECItem (SECItem *contents,
+ const char *fn);
+static PRBool xmlSecNssAppAscii2UCS2Conv (PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen,
+ PRBool swapBytes);
+static SECItem *xmlSecNssAppNicknameCollisionCallback (SECItem *old_nick,
+ PRBool *cancel,
+ void *wincx);
+static xmlSecKeyPtr xmlSecNssAppDerKeyLoadSECItem (SECItem* secItem);
+
+/**
+ * xmlSecNssAppInit:
+ * @config: the path to NSS database files.
+ *
+ * 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
+xmlSecNssAppInit(const char* config) {
+ SECStatus rv;
+
+ if(config) {
+ rv = NSS_InitReadWrite(config);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "NSS_InitReadWrite",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "config=%s",
+ xmlSecErrorsSafeString(config));
+ return(-1);
+ }
+ } else {
+ rv = NSS_NoDB_Init(NULL);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "NSS_NoDB_Init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* configure PKCS11 */
+ PK11_ConfigurePKCS11("manufacturesID", "libraryDescription",
+ "tokenDescription", "privateTokenDescription",
+ "slotDescription", "privateSlotDescription",
+ "fipsSlotDescription", "fipsPrivateSlotDescription",
+ 0, 0);
+
+ /* setup for PKCS12 */
+ PORT_SetUCS2_ASCIIConversionFunction(xmlSecNssAppAscii2UCS2Conv);
+ SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+ SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppShutdown:
+ *
+ * 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
+xmlSecNssAppShutdown(void) {
+ SECStatus rv;
+/*
+ SSL_ClearSessionCache();
+*/
+ PK11_LogoutAll();
+ rv = NSS_Shutdown();
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "NSS_Shutdown",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecNssAppCreateSECItem(SECItem *contents, const xmlSecByte* data, xmlSecSize dataSize) {
+ xmlSecAssert2(contents != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+
+ contents->data = 0;
+ if (!SECITEM_AllocItem(NULL, contents, dataSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECITEM_AllocItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(dataSize > 0) {
+ xmlSecAssert2(contents->data != NULL, -1);
+ memcpy(contents->data, data, dataSize);
+ }
+
+ return (0);
+}
+
+static int
+xmlSecNssAppReadSECItem(SECItem *contents, const char *fn) {
+ PRFileInfo info;
+ PRFileDesc *file = NULL;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ int ret = -1;
+
+ xmlSecAssert2(contents != NULL, -1);
+ xmlSecAssert2(fn != NULL, -1);
+
+ file = PR_Open(fn, PR_RDONLY, 00660);
+ if (file == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PR_Open",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(fn));
+ goto done;
+ }
+
+ prStatus = PR_GetOpenFileInfo(file, &info);
+ if (prStatus != PR_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PR_GetOpenFileInfo",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(fn));
+ goto done;
+ }
+
+ contents->data = 0;
+ if (!SECITEM_AllocItem(NULL, contents, info.size)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECITEM_AllocItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ numBytes = PR_Read(file, contents->data, info.size);
+ if (numBytes != info.size) {
+ SECITEM_FreeItem(contents, PR_FALSE);
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (file) {
+ PR_Close(file);
+ }
+
+ return (ret);
+}
+
+static PRBool
+xmlSecNssAppAscii2UCS2Conv(PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen,
+ PRBool swapBytes ATTRIBUTE_UNUSED)
+{
+ SECItem it;
+
+ if (toUnicode == PR_FALSE) {
+ return (PR_FALSE);
+ }
+
+ memset(&it, 0, sizeof(it));
+ it.data = inBuf;
+ it.len = inBufLen;
+
+ return(PORT_UCS2_UTF8Conversion(toUnicode, it.data, it.len,
+ outBuf, maxOutBufLen, outBufLen));
+}
+
+static SECItem *
+xmlSecNssAppNicknameCollisionCallback(SECItem *old_nick ATTRIBUTE_UNUSED,
+ PRBool *cancel,
+ void *wincx ATTRIBUTE_UNUSED)
+{
+ if (cancel == NULL) {
+ return (NULL);
+ }
+
+ /* XXX not handled yet */
+ *cancel = PR_TRUE;
+ return (NULL);
+}
+
+/**
+ * xmlSecNssAppKeyLoad:
+ * @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 a file
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+/**
+ * xmlSecNssAppKeyLoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the key data format.
+ * @pwd: the key data2 password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from a binary @data.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+/**
+ * xmlSecNssAppKeyLoadSECItem:
+ * @secItem: the pointer to sec item.
+ * @format: the key format.
+ * @pwd: the key password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from a file
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format,
+ const char *pwd,
+ void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecKeyPtr key = NULL;
+
+ xmlSecAssert2(secItem != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+#ifndef XMLSEC_NO_X509
+ case xmlSecKeyDataFormatPkcs12:
+ key = xmlSecNssAppPkcs12LoadSECItem(secItem, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12LoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ case xmlSecKeyDataFormatCertDer:
+ key = xmlSecNssAppKeyFromCertLoadSECItem(secItem, format);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyFromCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_X509 */
+ case xmlSecKeyDataFormatDer:
+ key = xmlSecNssAppDerKeyLoadSECItem(secItem);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppDerKeyLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyLoad",
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+static xmlSecKeyPtr
+xmlSecNssAppDerKeyLoadSECItem(SECItem* secItem) {
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyPtr retval = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ int ret;
+ SECKEYPublicKey *pubkey = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ CERTSubjectPublicKeyInfo *spki = NULL;
+ SECItem nickname;
+ PK11SlotInfo *slot = NULL;
+ SECStatus status;
+
+ xmlSecAssert2(secItem != NULL, NULL);
+
+ /* we're importing a key about which we know nothing yet, just use the
+ * internal slot
+ */
+ slot = xmlSecNssGetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetInternalKeySlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ nickname.len = 0;
+ nickname.data = NULL;
+
+
+ /* TRY PRIVATE KEY FIRST
+ * Note: This expects the key to be in PrivateKeyInfo format. The
+ * DER files created from PEM via openssl utilities aren't in that
+ * format
+ */
+ status = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secItem,
+ &nickname, NULL, PR_FALSE,
+ PR_TRUE, KU_ALL, &privkey, NULL);
+ if (status != SECSuccess) {
+ /* TRY PUBLIC KEY */
+ spki = SECKEY_DecodeDERSubjectPublicKeyInfo(secItem);
+ if (spki == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_DecodeDERSubjectPublicKeyInfo",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+
+ pubkey = SECKEY_ExtractPublicKey(spki);
+ if (pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ data = xmlSecNssPKIAdoptKey(privkey, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ privkey = NULL;
+ pubkey = NULL;
+
+ 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(data)));
+ goto done;
+ }
+ retval = key;
+ key = NULL;
+ data = NULL;
+
+
+done:
+ if(slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if(privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if(pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if(spki != NULL) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+ return (retval);
+}
+
+#ifndef XMLSEC_NO_X509
+/**
+ * xmlSecNssAppKeyCertLoad:
+ * @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
+xmlSecNssAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeyCertLoadMemory:
+ * @key: the pointer to key.
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the certificate format.
+ *
+ * Reads the certificate from @data and adds it to key
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeyCertLoadSECItem:
+ * @key: the pointer to key.
+ * @secItem: the pointer to SECItem.
+ * @format: the certificate format.
+ *
+ * Reads the certificate from @secItem and adds it to key
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyDataFormat format) {
+ CERTCertificate *cert=NULL;
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(secItem != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
+ return(-1);
+ }
+
+ switch(format) {
+ case xmlSecKeyDataFormatPkcs8Der:
+ case xmlSecKeyDataFormatDer:
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ secItem, NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "format=%d", format);
+ return(-1);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(-1);
+ }
+
+ xmlSecAssert2(cert != NULL, -1);
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppPkcs12Load:
+ * @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 xmlSecNssAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppPkcs12Load(const char *filename, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12LoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+/**
+ * xmlSecNssAppPkcs12LoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @pwd: the PKCS12 password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 binary data.
+ * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12LoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+
+/**
+ * xmlSecNssAppPkcs12LoadSECItem:
+ * @secItem: the @SECItem object.
+ * @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 SECItem.
+ * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppPkcs12LoadSECItem(SECItem* secItem, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ int ret;
+ PK11SlotInfo *slot = NULL;
+ SECItem pwditem;
+ SECItem uc2_pwditem;
+ SECStatus rv;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ CERTCertList *certlist = NULL;
+ CERTCertListNode *head = NULL;
+ CERTCertificate *cert = NULL;
+ CERTCertificate *tmpcert = NULL;
+ SEC_PKCS12DecoderContext *p12ctx = NULL;
+
+
+ xmlSecAssert2((secItem != NULL), NULL);
+
+ if (pwd == NULL) {
+ pwd = "";
+ }
+ memset(&uc2_pwditem, 0, sizeof(uc2_pwditem));
+
+ /* we're importing a key about which we know nothing yet, just use the
+ * internal slot. We have no criteria to choose a slot.
+ */
+ slot = xmlSecNssGetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetInternalKeySlot",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ pwditem.data = (unsigned char *)pwd;
+ pwditem.len = strlen(pwd)+1;
+ if (!SECITEM_AllocItem(NULL, &uc2_pwditem, 2*pwditem.len)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECITEM_AllocItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ if (PORT_UCS2_ASCIIConversion(PR_TRUE, pwditem.data, pwditem.len,
+ uc2_pwditem.data, 2*pwditem.len,
+ &(uc2_pwditem.len), 0) == PR_FALSE) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_UCS2_ASCIIConversion",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ p12ctx = SEC_PKCS12DecoderStart(&uc2_pwditem, slot, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (p12ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderStart",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderUpdate(p12ctx, secItem->data, secItem->len);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderVerify(p12ctx);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderVerify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderValidateBags(p12ctx, xmlSecNssAppNicknameCollisionCallback);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderValidateBags",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderImportBags(p12ctx);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderImportBags",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ certlist = SEC_PKCS12DecoderGetCerts(p12ctx);
+ if (certlist == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderGetCerts",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
+ goto done;
+ }
+
+ for (head = CERT_LIST_HEAD(certlist);
+ !CERT_LIST_END(head, certlist);
+ head = CERT_LIST_NEXT(head)) {
+ cert = head->cert;
+ privkey = PK11_FindKeyByAnyCert(cert, NULL);
+
+ if (privkey != NULL) {
+ if (data != NULL) {
+ /* we already found a private key.
+ * assume the first private key we find is THE ONE
+ */
+ SECKEY_DestroyPrivateKey(privkey);
+ privkey = NULL;
+ } else {
+ pubkey = CERT_ExtractPublicKey(cert);
+ if (pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ data = xmlSecNssPKIAdoptKey(privkey, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ pubkey = NULL;
+ privkey = NULL;
+
+ tmpcert = CERT_DupCertificate(cert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ CERT_DestroyCertificate(tmpcert);
+ goto done;
+ }
+
+ }
+ }
+
+ tmpcert = CERT_DupCertificate(cert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ ret = xmlSecNssKeyDataX509AdoptCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ CERT_DestroyCertificate(tmpcert);
+ goto done;
+ }
+
+ } /* end for loop */
+
+ if (data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12Load",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "private key not found in PKCS12 file");
+ 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 (p12ctx) {
+ SEC_PKCS12DecoderFinish(p12ctx);
+ }
+ SECITEM_FreeItem(&uc2_pwditem, PR_FALSE);
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (certlist) {
+ CERT_DestroyCertList(certlist);
+ }
+ if(x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if (privkey) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (pubkey) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+
+ return(key);
+}
+
+/**
+ * xmlSecNssAppKeyFromCertLoadSECItem:
+ * @secItem: the @SECItem object.
+ * @format: the cert format.
+ *
+ * Loads public key from cert.
+ *
+ * Returns: pointer to key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyFromCertLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format) {
+ xmlSecKeyPtr key;
+ xmlSecKeyDataPtr keyData;
+ xmlSecKeyDataPtr certData;
+ CERTCertificate *cert=NULL;
+ int ret;
+
+ xmlSecAssert2(secItem != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* load cert */
+ switch(format) {
+ case xmlSecKeyDataFormatCertDer:
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ secItem, NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "format=%d", format);
+ return(NULL);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ /* get key value */
+ keyData = xmlSecNssX509CertGetKey(cert);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CertGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(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);
+ CERT_DestroyCertificate(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);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ /* create cert data */
+ certData = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id);
+ if(certData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ /* put cert in the cert data */
+ ret = xmlSecNssKeyDataX509AdoptCert(certData, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+
+/**
+ * xmlSecNssAppKeysMngrCertLoad:
+ * @mngr: the pointer to keys manager.
+ * @filename: the certificate file.
+ * @format: the certificate file format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * 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
+xmlSecNssAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeysMngrCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeysMngrCertLoadMemory:
+ * @mngr: the pointer to keys manager.
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the certificate format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Reads cert from @data and adds to the list of trusted or known
+ * untrusted certs in @store
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeysMngrCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeysMngrCertLoadSECItem:
+ * @mngr: the pointer to keys manager.
+ * @secItem: the pointer to SECItem.
+ * @format: the certificate format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Reads cert from @secItem and adds to the list of trusted or known
+ * untrusted certs in @store
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeysMngrCertLoadSECItem(xmlSecKeysMngrPtr mngr, SECItem* secItem,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ xmlSecKeyDataStorePtr x509Store;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(secItem != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssX509StoreId");
+ return(-1);
+ }
+
+ switch(format) {
+ case xmlSecKeyDataFormatDer:
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ secItem, NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "format=%d", format);
+ return(-1);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(-1);
+ }
+
+ ret = xmlSecNssX509StoreAdoptCert(x509Store, cert, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509StoreAdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecNssAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with NSS keys store #xmlSecNssKeysStoreId
+ * and a default NSS crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* create NSS keys store if needed */
+ if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) {
+ xmlSecKeyStorePtr keysStore;
+
+ keysStore = xmlSecKeyStoreCreate(xmlSecNssKeysStoreId);
+ if(keysStore == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssKeysStoreId");
+ 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 = xmlSecNssKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecNssAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecNssAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrAdoptKey(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 = xmlSecNssKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecNssAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrLoad(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 = xmlSecNssKeysStoreLoad(store, uri, mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysStoreLoad",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s", xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppDefaultKeysMngrSave:
+ * @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
+xmlSecNssAppDefaultKeysMngrSave(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 = xmlSecNssKeysStoreSave(store, filename, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysStoreSave",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename%s", xmlSecErrorsSafeString(filename));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecNssAppGetDefaultPwdCallback(void) {
+ return(NULL);
+}
+
diff --git a/src/nss/bignum.c b/src/nss/bignum.c
new file mode 100644
index 00000000..40bd5359
--- /dev/null
+++ b/src/nss/bignum.c
@@ -0,0 +1,163 @@
+/**
+ * XMLSec library
+ *
+ * Reading/writing bignum values
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for precise wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <nss.h>
+#include <secitem.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/bignum.h>
+
+/**
+ * xmlSecNssNodeGetBigNumValue:
+ * @arena: the arena from which to allocate memory
+ * @cur: the poitner to an XML node.
+ * @a: a SECItem object to hold the BigNum value
+ *
+ * Converts the node content from CryptoBinary format
+ * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
+ * to a SECItem. If no SECItem object provided then a new
+ * one is created (caller is responsible for freeing it).
+ *
+ * Returns: a pointer to SECItem produced from CryptoBinary string
+ * or NULL if an error occurs.
+ */
+SECItem *
+xmlSecNssNodeGetBigNumValue(PRArenaPool *arena, const xmlNodePtr cur,
+ SECItem *a) {
+ xmlSecBuffer buf;
+ int ret;
+ SECItem *rv;
+ int len;
+
+ xmlSecAssert2(arena != NULL, NULL);
+ 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);
+ }
+
+ len = xmlSecBufferGetSize(&buf);
+
+ if (a == NULL) {
+ rv = SECITEM_AllocItem(arena, NULL, len);
+ } else {
+ rv = a;
+ xmlSecAssert2(rv->data == NULL, NULL);
+ rv->len = len;
+ rv->data = PORT_ArenaZAlloc(arena, len);
+ }
+
+ PORT_Memcpy(rv->data, xmlSecBufferGetData(&buf), len);
+
+ xmlSecBufferFinalize(&buf);
+ return(rv);
+}
+
+/**
+ * xmlSecNssNodeSetBigNumValue:
+ * @cur: the pointer to an XML node.
+ * @a: a SECItem containing the BigNum value.
+ * @addLineBreaks: if the flag is equal to 1 then
+ * linebreaks will be added before and after
+ * new buffer content.
+ *
+ * Converts SECItem 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
+xmlSecNssNodeSetBigNumValue(xmlNodePtr cur, const SECItem *a, int addLineBreaks) {
+ xmlSecBuffer buf;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&buf, a->len + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", a->len + 1);
+ return(-1);
+ }
+
+ PORT_Memcpy(xmlSecBufferGetData(&buf), a->data, a->len);
+
+ ret = xmlSecBufferSetSize(&buf, a->len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", a->len);
+ 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/nss/ciphers.c b/src/nss/ciphers.c
new file mode 100644
index 00000000..48bd6e11
--- /dev/null
+++ b/src/nss/ciphers.c
@@ -0,0 +1,838 @@
+/**
+ * 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>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <secoid.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+#define XMLSEC_NSS_MAX_KEY_SIZE 32
+#define XMLSEC_NSS_MAX_IV_SIZE 32
+#define XMLSEC_NSS_MAX_BLOCK_SIZE 32
+
+/**************************************************************************
+ *
+ * Internal Nss Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssBlockCipherCtx xmlSecNssBlockCipherCtx,
+ *xmlSecNssBlockCipherCtxPtr;
+struct _xmlSecNssBlockCipherCtx {
+ CK_MECHANISM_TYPE cipher;
+ PK11Context* cipherCtx;
+ xmlSecKeyDataId keyId;
+ int keyInitialized;
+ int ctxInitialized;
+ xmlSecByte key[XMLSEC_NSS_MAX_KEY_SIZE];
+ xmlSecSize keySize;
+ xmlSecByte iv[XMLSEC_NSS_MAX_IV_SIZE];
+ xmlSecSize ivSize;
+};
+static int xmlSecNssBlockCipherCtxInit (xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssBlockCipherCtxUpdate (xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssBlockCipherCtxFinal (xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int
+xmlSecNssBlockCipherCtxInit(xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ SECItem keyItem;
+ SECItem ivItem;
+ PK11SlotInfo* slot;
+ PK11SymKey* symKey;
+ int ivLen;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx == 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 = PK11_GetIVLength(ctx->cipher);
+ xmlSecAssert2(ivLen > 0, -1);
+ xmlSecAssert2((xmlSecSize)ivLen <= sizeof(ctx->iv), -1);
+
+ if(encrypt) {
+ /* generate random iv */
+ rv = PK11_GenerateRandom(ctx->iv, ivLen);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_GenerateRandom",
+ 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);
+ }
+ }
+
+ memset(&keyItem, 0, sizeof(keyItem));
+ keyItem.data = ctx->key;
+ keyItem.len = ctx->keySize;
+ memset(&ivItem, 0, sizeof(ivItem));
+ ivItem.data = ctx->iv;
+ ivItem.len = ctx->ivSize;
+
+ slot = PK11_GetBestSlot(ctx->cipher, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ symKey = PK11_ImportSymKey(slot, ctx->cipher, PK11_OriginDerive,
+ CKA_SIGN, &keyItem, NULL);
+ if(symKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ ctx->cipherCtx = PK11_CreateContextBySymKey(ctx->cipher,
+ (encrypt) ? CKA_ENCRYPT : CKA_DECRYPT,
+ symKey, &ivItem);
+ if(ctx->cipherCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ ctx->ctxInitialized = 1;
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherCtxUpdate(xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, inBlocks, outSize;
+ int blockLen;
+ int outLen = 0;
+ xmlSecByte* outBuf;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = PK11_GetBlockSize(ctx->cipher, NULL);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(inSize < (xmlSecSize)blockLen) {
+ return(0);
+ }
+
+ if(encrypt) {
+ inBlocks = inSize / ((xmlSecSize)blockLen);
+ } else {
+ /* we want to have the last block in the input buffer
+ * for padding check */
+ inBlocks = (inSize - 1) / ((xmlSecSize)blockLen);
+ }
+ inSize = inBlocks * ((xmlSecSize)blockLen);
+
+ /* we write out the input size plus may be one block */
+ 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;
+
+ rv = PK11_CipherOp(ctx->cipherCtx, outBuf, &outLen, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2((xmlSecSize)outLen == inSize, -1);
+
+ /* 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
+xmlSecNssBlockCipherCtxFinal(xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, outSize;
+ int blockLen, outLen = 0;
+ xmlSecByte* inBuf;
+ xmlSecByte* outBuf;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = PK11_GetBlockSize(ctx->cipher, NULL);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(encrypt != 0) {
+ xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1);
+
+ /* create padding */
+ ret = xmlSecBufferSetMaxSize(in, blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blockLen);
+ return(-1);
+ }
+ inBuf = xmlSecBufferGetData(in);
+
+ /* generate random padding */
+ if((xmlSecSize)blockLen > (inSize + 1)) {
+ rv = PK11_GenerateRandom(inBuf + inSize, blockLen - inSize - 1);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", blockLen - inSize - 1);
+ return(-1);
+ }
+ }
+ inBuf[blockLen - 1] = blockLen - inSize;
+ inSize = blockLen;
+ } else {
+ if(inSize != (xmlSecSize)blockLen) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data=%d;block=%d", inSize, blockLen);
+ return(-1);
+ }
+ }
+
+ /* process last block */
+ 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;
+
+ rv = PK11_CipherOp(ctx->cipherCtx, outBuf, &outLen, 2 * blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2((xmlSecSize)outLen == inSize, -1);
+
+ if(encrypt == 0) {
+ /* check padding */
+ if(outLen < outBuf[blockLen - 1]) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "padding=%d;buffer=%d",
+ outBuf[blockLen - 1], outLen);
+ return(-1);
+ }
+ outLen -= outBuf[blockLen - 1];
+ }
+
+ /* 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);
+}
+
+
+/******************************************************************************
+ *
+ * EVP Block Cipher transforms
+ *
+ * xmlSecNssBlockCipherCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecNssBlockCipherSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssBlockCipherCtx))
+#define xmlSecNssBlockCipherGetCtx(transform) \
+ ((xmlSecNssBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssBlockCipherInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssBlockCipherFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssBlockCipherSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssBlockCipherSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssBlockCipherExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssBlockCipherCheckId (xmlSecTransformPtr transform);
+
+
+
+static int
+xmlSecNssBlockCipherCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DES
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformDes3CbcId)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformAes128CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecNssTransformAes192CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecNssTransformAes256CbcId)) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssBlockCipherCtx));
+
+#ifndef XMLSEC_NO_DES
+ if(transform->id == xmlSecNssTransformDes3CbcId) {
+ ctx->cipher = CKM_DES3_CBC;
+ ctx->keyId = xmlSecNssKeyDataDesId;
+ ctx->keySize = 24;
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(transform->id == xmlSecNssTransformAes128CbcId) {
+ ctx->cipher = CKM_AES_CBC;
+ ctx->keyId = xmlSecNssKeyDataAesId;
+ ctx->keySize = 16;
+ } else if(transform->id == xmlSecNssTransformAes192CbcId) {
+ ctx->cipher = CKM_AES_CBC;
+ ctx->keyId = xmlSecNssKeyDataAesId;
+ ctx->keySize = 24;
+ } else if(transform->id == xmlSecNssTransformAes256CbcId) {
+ ctx->cipher = CKM_AES_CBC;
+ ctx->keyId = xmlSecNssKeyDataAesId;
+ ctx->keySize = 32;
+ } 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);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssBlockCipherFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssBlockCipherCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize));
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->cipherCtx != NULL) {
+ PK11_DestroyContext(ctx->cipherCtx, PR_TRUE);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssBlockCipherCtx));
+}
+
+static int
+xmlSecNssBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != 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;
+ }
+ keyReq->keyBitsSize = 8 * ctx->keySize;
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->keyInitialized == 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ xmlSecAssert2(ctx->keySize > 0, -1);
+ xmlSecAssert2(ctx->keySize <= sizeof(ctx->key), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) < ctx->keySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "keySize=%d;expected=%d",
+ xmlSecBufferGetSize(buffer), ctx->keySize);
+ return(-1);
+ }
+
+ xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
+ memcpy(ctx->key, xmlSecBufferGetData(buffer), ctx->keySize);
+
+ ctx->keyInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ if(ctx->ctxInitialized == 0) {
+ ret = xmlSecNssBlockCipherCtxInit(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssBlockCipherCtxInit",
+ 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 = xmlSecNssBlockCipherCtxUpdate(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssBlockCipherCtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(last) {
+ ret = xmlSecNssBlockCipherCtxFinal(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssBlockCipherCtxFinal",
+ 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 xmlSecNssAes128CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes128Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes128Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformAes128CbcGetKlass(void) {
+ return(&xmlSecNssAes128CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecNssAes192CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes192Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes192Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformAes192CbcGetKlass(void) {
+ return(&xmlSecNssAes192CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecNssAes256CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes256Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes256Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformAes256CbcGetKlass(void) {
+ return(&xmlSecNssAes256CbcKlass);
+}
+
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+static xmlSecTransformKlass xmlSecNssDes3CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameDes3Cbc, /* const xmlChar* name; */
+ xmlSecHrefDes3Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformDes3CbcGetKlass(void) {
+ return(&xmlSecNssDes3CbcKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/nss/crypto.c b/src/nss/crypto.c
new file mode 100644
index 00000000..141ceeac
--- /dev/null
+++ b/src/nss/crypto.c
@@ -0,0 +1,366 @@
+/**
+ * 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>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+#include <prinit.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/xmltree.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecNssFunctions = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_nss:
+ *
+ * Gets the pointer to xmlsec-nss functions table.
+ *
+ * Returns: the xmlsec-nss functions table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_nss(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecNssFunctions != NULL) {
+ return(gXmlSecNssFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecNssFunctions = &functions;
+
+ /**
+ * Crypto Init/shutdown
+ */
+ gXmlSecNssFunctions->cryptoInit = xmlSecNssInit;
+ gXmlSecNssFunctions->cryptoShutdown = xmlSecNssShutdown;
+ gXmlSecNssFunctions->cryptoKeysMngrInit = xmlSecNssKeysMngrInit;
+
+ /**
+ * Key data ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecNssFunctions->keyDataAesGetKlass = xmlSecNssKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecNssFunctions->keyDataDesGetKlass = xmlSecNssKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecNssFunctions->keyDataDsaGetKlass = xmlSecNssKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecNssFunctions->keyDataHmacGetKlass = xmlSecNssKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecNssFunctions->keyDataRsaGetKlass = xmlSecNssKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_X509
+ gXmlSecNssFunctions->keyDataX509GetKlass = xmlSecNssKeyDataX509GetKlass;
+ gXmlSecNssFunctions->keyDataRawX509CertGetKlass = xmlSecNssKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /**
+ * Key data store ids
+ */
+#ifndef XMLSEC_NO_X509
+ gXmlSecNssFunctions->x509StoreGetKlass = xmlSecNssX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /**
+ * Crypto transforms ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecNssFunctions->transformAes128CbcGetKlass = xmlSecNssTransformAes128CbcGetKlass;
+ gXmlSecNssFunctions->transformAes192CbcGetKlass = xmlSecNssTransformAes192CbcGetKlass;
+ gXmlSecNssFunctions->transformAes256CbcGetKlass = xmlSecNssTransformAes256CbcGetKlass;
+ gXmlSecNssFunctions->transformKWAes128GetKlass = xmlSecNssTransformKWAes128GetKlass;
+ gXmlSecNssFunctions->transformKWAes192GetKlass = xmlSecNssTransformKWAes192GetKlass;
+ gXmlSecNssFunctions->transformKWAes256GetKlass = xmlSecNssTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecNssFunctions->transformDes3CbcGetKlass = xmlSecNssTransformDes3CbcGetKlass;
+ gXmlSecNssFunctions->transformKWDes3GetKlass = xmlSecNssTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecNssFunctions->transformDsaSha1GetKlass = xmlSecNssTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecNssFunctions->transformHmacSha1GetKlass = xmlSecNssTransformHmacSha1GetKlass;
+ gXmlSecNssFunctions->transformHmacRipemd160GetKlass = xmlSecNssTransformHmacRipemd160GetKlass;
+ gXmlSecNssFunctions->transformHmacMd5GetKlass = xmlSecNssTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecNssFunctions->transformRsaSha1GetKlass = xmlSecNssTransformRsaSha1GetKlass;
+ gXmlSecNssFunctions->transformRsaPkcs1GetKlass = xmlSecNssTransformRsaPkcs1GetKlass;
+
+/* RSA OAEP is not supported by NSS yet */
+#ifdef TODO
+ gXmlSecNssFunctions->transformRsaOaepGetKlass = xmlSecNssTransformRsaOaepGetKlass;
+#endif /* TODO: RSA OAEP is not supported by NSS yet */
+
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformSha1GetKlass = xmlSecNssTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+ /**
+ * High level routines form xmlsec command line utility
+ */
+ gXmlSecNssFunctions->cryptoAppInit = xmlSecNssAppInit;
+ gXmlSecNssFunctions->cryptoAppShutdown = xmlSecNssAppShutdown;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrInit = xmlSecNssAppDefaultKeysMngrInit;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecNssAppDefaultKeysMngrAdoptKey;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecNssAppDefaultKeysMngrLoad;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrSave = xmlSecNssAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecNssFunctions->cryptoAppKeysMngrCertLoad = xmlSecNssAppKeysMngrCertLoad;
+ gXmlSecNssFunctions->cryptoAppKeysMngrCertLoadMemory= xmlSecNssAppKeysMngrCertLoadMemory;
+ gXmlSecNssFunctions->cryptoAppPkcs12Load = xmlSecNssAppPkcs12Load;
+ gXmlSecNssFunctions->cryptoAppPkcs12LoadMemory = xmlSecNssAppPkcs12LoadMemory;
+ gXmlSecNssFunctions->cryptoAppKeyCertLoad = xmlSecNssAppKeyCertLoad;
+ gXmlSecNssFunctions->cryptoAppKeyCertLoadMemory = xmlSecNssAppKeyCertLoadMemory;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecNssFunctions->cryptoAppKeyLoad = xmlSecNssAppKeyLoad;
+ gXmlSecNssFunctions->cryptoAppKeyLoadMemory = xmlSecNssAppKeyLoadMemory;
+ gXmlSecNssFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecNssAppGetDefaultPwdCallback();
+
+ return(gXmlSecNssFunctions);
+}
+
+/**
+ * xmlSecNssInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssInit (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);
+ }
+
+ /* set default errors callback for xmlsec to us */
+ xmlSecErrorsSetCallback(xmlSecNssErrorsDefaultCallback);
+
+ /* register our klasses */
+ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_nss()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssShutdown(void) {
+ return(0);
+}
+
+/**
+ * xmlSecNssKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds NSS specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+#ifndef XMLSEC_NO_X509
+ /* create x509 store if needed */
+ if(xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId) == NULL) {
+ xmlSecKeyDataStorePtr x509Store;
+
+ x509Store = xmlSecKeyDataStoreCreate(xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssX509StoreId");
+ 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);
+}
+
+/**
+ * xmlSecNssGetInternalKeySlot:
+ *
+ * Gets internal NSS key slot.
+ *
+ * Returns: internal key slot and initializes it if needed.
+ */
+PK11SlotInfo *
+xmlSecNssGetInternalKeySlot()
+{
+ PK11SlotInfo *slot = NULL;
+ SECStatus rv;
+
+ slot = PK11_GetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetInternalKeySlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return NULL;
+ }
+
+ if (PK11_NeedUserInit(slot)) {
+ rv = PK11_InitPin(slot, NULL, NULL);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_Authenticate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return NULL;
+ }
+ }
+
+ if(PK11_IsLoggedIn(slot, NULL) != PR_TRUE) {
+ rv = PK11_Authenticate(slot, PR_TRUE, NULL);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_Authenticate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return NULL;
+ }
+ }
+
+ return(slot);
+}
+
+/**
+ * xmlSecNssGenerateRandom:
+ * @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
+xmlSecNssGenerateRandom(xmlSecBufferPtr buffer, xmlSecSize size) {
+ SECStatus rv;
+ 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 */
+ rv = PK11_GenerateRandom((xmlSecByte*)xmlSecBufferGetData(buffer), size);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecNssErrorsDefaultCallback:
+ * @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 errors reporting callback function.
+ */
+void
+xmlSecNssErrorsDefaultCallback(const char* file, int line, const char* func,
+ const char* errorObject, const char* errorSubject,
+ int reason, const char* msg) {
+ xmlChar buf[500];
+ int err;
+
+ err = PORT_GetError();
+ xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "%s;last nss error=%d (0x%08X)", msg, err, err);
+ xmlSecErrorsDefaultCallback(file, line, func,
+ errorObject, errorSubject,
+ reason, (char*)buf);
+}
diff --git a/src/nss/digests.c b/src/nss/digests.c
new file mode 100644
index 00000000..5a1db916
--- /dev/null
+++ b/src/nss/digests.c
@@ -0,0 +1,331 @@
+/**
+ * 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>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <secoid.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+
+#define XMLSEC_NSS_MAX_DIGEST_SIZE 32
+
+/**************************************************************************
+ *
+ * Internal NSS Digest CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssDigestCtx xmlSecNssDigestCtx, *xmlSecNssDigestCtxPtr;
+struct _xmlSecNssDigestCtx {
+ SECOidData* digest;
+ PK11Context* digestCtx;
+ xmlSecByte dgst[XMLSEC_NSS_MAX_DIGEST_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+/******************************************************************************
+ *
+ * Digest transforms
+ *
+ * xmlSecNssDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssDigestSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssDigestCtx))
+#define xmlSecNssDigestGetCtx(transform) \
+ ((xmlSecNssDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssDigestInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssDigestFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssDigestVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssDigestExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssDigestCheckId (xmlSecTransformPtr transform);
+
+static int
+xmlSecNssDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+ return(0);
+}
+
+static int
+xmlSecNssDigestInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1);
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecNssDigestCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha1Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(ctx->digest == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SECOID_FindOIDByTag",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ctx->digestCtx = PK11_CreateDigestContext(ctx->digest->offset);
+ if(ctx->digestCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_CreateDigestContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssDigestFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssDigestCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssDigestCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize));
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ PK11_DestroyContext(ctx->digestCtx, PR_TRUE);
+ }
+ memset(ctx, 0, sizeof(xmlSecNssDigestCtx));
+}
+
+static int
+xmlSecNssDigestVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssDigestGetCtx(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_DATA,
+ "data and digest sizes are different (data=%d, dgst=%d)",
+ dataSize, ctx->dgstSize);
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ if(memcmp(ctx->dgst, data, dataSize) != 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
+xmlSecNssDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssDigestCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1);
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ rv = PK11_DigestBegin(ctx->digestCtx);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ rv = PK11_DigestOp(ctx->digestCtx, xmlSecBufferGetData(in), inSize);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ 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);
+ }
+ }
+ if(last) {
+ rv = PK11_DigestFinal(ctx->digestCtx, ctx->dgst, &ctx->dgstSize, sizeof(ctx->dgst));
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ 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(&(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_SHA1
+/******************************************************************************
+ *
+ * SHA1 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha1, /* const xmlChar* name; */
+ xmlSecHrefSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecNssDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha1GetKlass(void) {
+ return(&xmlSecNssSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+
+
diff --git a/src/nss/globals.h b/src/nss/globals.h
new file mode 100644
index 00000000..272a27b8
--- /dev/null
+++ b/src/nss/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/nss/hmac.c b/src/nss/hmac.c
new file mode 100644
index 00000000..98bf0c12
--- /dev/null
+++ b/src/nss/hmac.c
@@ -0,0 +1,633 @@
+/**
+ * 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>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#ifndef XMLSEC_NO_HMAC
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <secoid.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+
+/* sizes in bits */
+#define XMLSEC_NSS_MIN_HMAC_SIZE 80
+#define XMLSEC_NSS_MAX_HMAC_SIZE (128 * 8)
+
+/**************************************************************************
+ *
+ * Configuration
+ *
+ *****************************************************************************/
+static int g_xmlsec_nss_hmac_min_length = XMLSEC_NSS_MIN_HMAC_SIZE;
+
+/**
+ * xmlSecNssHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecNssHmacGetMinOutputLength(void)
+{
+ return g_xmlsec_nss_hmac_min_length;
+}
+
+/**
+ * xmlSecNssHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecNssHmacSetMinOutputLength(int min_length)
+{
+ g_xmlsec_nss_hmac_min_length = min_length;
+}
+
+/**************************************************************************
+ *
+ * Internal NSS HMAC CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssHmacCtx xmlSecNssHmacCtx, *xmlSecNssHmacCtxPtr;
+struct _xmlSecNssHmacCtx {
+ CK_MECHANISM_TYPE digestType;
+ PK11Context* digestCtx;
+ xmlSecByte dgst[XMLSEC_NSS_MAX_HMAC_SIZE / 8];
+ xmlSecSize dgstSize; /* dgst size in bits */
+};
+
+/******************************************************************************
+ *
+ * HMAC transforms
+ *
+ * xmlSecNssHmacCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssHmacGetCtx(transform) \
+ ((xmlSecNssHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecNssHmacSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssHmacCtx))
+#define xmlSecNssHmacCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecNssTransformHmacSha1Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformHmacMd5Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformHmacRipemd160Id))
+
+static int xmlSecNssHmacInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssHmacFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssHmacNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssHmacSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssHmacSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssHmacVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssHmacExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecNssHmacInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssHmacCtx));
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha1Id)) {
+ ctx->digestType = CKM_SHA_1_HMAC;
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacMd5Id)) {
+ ctx->digestType = CKM_MD5_HMAC;
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacRipemd160Id)) {
+ ctx->digestType = CKM_RIPEMD160_HMAC;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecNssHmacFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssHmacCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssHmacCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize));
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ PK11_DestroyContext(ctx->digestCtx, PR_TRUE);
+ }
+ memset(ctx, 0, sizeof(xmlSecNssHmacCtx));
+}
+
+/**
+ * xmlSecNssHmacNodeRead:
+ *
+ * HMAC (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>
+ *
+ * Schema Definition:
+ *
+ * <simpleType name="HMACOutputLengthType">
+ * <restriction base="integer"/>
+ * </simpleType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT HMACOutputLength (#PCDATA)>
+ */
+static int
+xmlSecNssHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssHmacCtxPtr ctx;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(node!= NULL, -1);
+ xmlSecAssert2(transformCtx!= NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(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 lenght to 0 or very
+ small value
+ */
+ if((int)ctx->dgstSize < xmlSecNssHmacGetMinOutputLength()) {
+ 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_INVALID_NODE,
+ "no nodes expected");
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecNssHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataHmacId;
+ keyReq->keyType= xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssHmacCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+ SECItem keyItem;
+ SECItem ignore;
+ PK11SlotInfo* slot;
+ PK11SymKey* symKey;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestType != 0, -1);
+ xmlSecAssert2(ctx->digestCtx == NULL, -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecNssKeyDataHmacId), -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,
+ "key is empty");
+ return(-1);
+ }
+
+ memset(&ignore, 0, sizeof(ignore));
+ memset(&keyItem, 0, sizeof(keyItem));
+ keyItem.data = xmlSecBufferGetData(buffer);
+ keyItem.len = xmlSecBufferGetSize(buffer);
+
+ slot = PK11_GetBestSlot(ctx->digestType, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ symKey = PK11_ImportSymKey(slot, ctx->digestType, PK11_OriginDerive,
+ CKA_SIGN, &keyItem, NULL);
+ if(symKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ ctx->digestCtx = PK11_CreateContextBySymKey(ctx->digestType, CKA_SIGN, symKey, &ignore);
+ if(ctx->digestCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(0);
+}
+
+static int
+xmlSecNssHmacVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ static xmlSecByte last_byte_masks[] =
+ { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+
+ xmlSecNssHmacCtxPtr ctx;
+ xmlSecByte mask;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ /* compare the digest size in bytes */
+ if(dataSize != ((ctx->dgstSize + 7) / 8)){
+ 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
+xmlSecNssHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssHmacCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ rv = PK11_DigestBegin(ctx->digestCtx);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ rv = PK11_DigestOp(ctx->digestCtx, xmlSecBufferGetData(in), inSize);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ 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);
+ }
+ }
+ if(last) {
+ xmlSecSize dgstSize;
+
+ rv = PK11_DigestFinal(ctx->digestCtx, ctx->dgst, &dgstSize, sizeof(ctx->dgst));
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ xmlSecAssert2(dgstSize > 0, -1);
+
+ /* check/set the result digest size */
+ if(ctx->dgstSize == 0) {
+ ctx->dgstSize = dgstSize * 8; /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= 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);
+ }
+
+ 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(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "size=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * HMAC SHA1
+ */
+static xmlSecTransformKlass xmlSecNssHmacSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha1, /* const xmlChar* name; */
+ xmlSecHrefHmacSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha1GetKlass(void) {
+ return(&xmlSecNssHmacSha1Klass);
+}
+
+/**
+ * HMAC Ripemd160
+ */
+static xmlSecTransformKlass xmlSecNssHmacRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacRipemd160, /* const xmlChar* name; */
+ xmlSecHrefHmacRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacRipemd160GetKlass(void) {
+ return(&xmlSecNssHmacRipemd160Klass);
+}
+
+/**
+ * HMAC Md5
+ */
+static xmlSecTransformKlass xmlSecNssHmacMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacMd5, /* const xmlChar* name; */
+ xmlSecHrefHmacMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacMd5GetKlass(void) {
+ return(&xmlSecNssHmacMd5Klass);
+}
+
+
+#endif /* XMLSEC_NO_HMAC */
+
+
diff --git a/src/nss/keysstore.c b/src/nss/keysstore.c
new file mode 100644
index 00000000..a583f604
--- /dev/null
+++ b/src/nss/keysstore.c
@@ -0,0 +1,485 @@
+/**
+ * XMLSec library
+ *
+ * Nss keys store that uses Simple Keys Store under the hood. Uses the
+ * Nss DB as a backing store for the finding keys, but the NSS DB is
+ * not written to by the keys store.
+ * So, if store->findkey is done and the key is not found in the simple
+ * keys store, the NSS DB is looked up.
+ * If store is called to adopt a key, that key is not written to the NSS
+ * DB.
+ * Thus, the NSS DB can be used to pre-load keys and becomes an alternate
+ * source of keys for xmlsec
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for precise wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <nss.h>
+#include <cert.h>
+#include <pk11func.h>
+#include <keyhi.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/xmltree.h>
+
+#include <xmlsec/keysmngr.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/keysstore.h>
+#include <xmlsec/nss/x509.h>
+#include <xmlsec/nss/pkikeys.h>
+
+/****************************************************************************
+ *
+ * Nss Keys Store. Uses Simple Keys Store under the hood
+ *
+ * Simple Keys Store ptr is located after xmlSecKeyStore
+ *
+ ***************************************************************************/
+#define xmlSecNssKeysStoreSize \
+ (sizeof(xmlSecKeyStore) + sizeof(xmlSecKeyStorePtr))
+
+#define xmlSecNssKeysStoreGetSS(store) \
+ ((xmlSecKeyStoreCheckSize((store), xmlSecNssKeysStoreSize)) ? \
+ (xmlSecKeyStorePtr*)(((xmlSecByte*)(store)) + sizeof(xmlSecKeyStore)) : \
+ (xmlSecKeyStorePtr*)NULL)
+
+static int xmlSecNssKeysStoreInitialize (xmlSecKeyStorePtr store);
+static void xmlSecNssKeysStoreFinalize (xmlSecKeyStorePtr store);
+static xmlSecKeyPtr xmlSecNssKeysStoreFindKey (xmlSecKeyStorePtr store,
+ const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyStoreKlass xmlSecNssKeysStoreKlass = {
+ sizeof(xmlSecKeyStoreKlass),
+ xmlSecNssKeysStoreSize,
+
+ /* data */
+ BAD_CAST "NSS-keys-store", /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecNssKeysStoreInitialize, /* xmlSecKeyStoreInitializeMethod initialize; */
+ xmlSecNssKeysStoreFinalize, /* xmlSecKeyStoreFinalizeMethod finalize; */
+ xmlSecNssKeysStoreFindKey, /* xmlSecKeyStoreFindKeyMethod findKey; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeysStoreGetKlass:
+ *
+ * The Nss list based keys store klass.
+ *
+ * Returns: Nss list based keys store klass.
+ */
+xmlSecKeyStoreId
+xmlSecNssKeysStoreGetKlass(void) {
+ return(&xmlSecNssKeysStoreKlass);
+}
+
+/**
+ * xmlSecNssKeysStoreAdoptKey:
+ * @store: the pointer to Nss keys store.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the @store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeysStoreAdoptKey(xmlSecKeyStorePtr store, xmlSecKeyPtr key) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+ xmlSecAssert2((key != NULL), -1);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
+ (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
+
+ return (xmlSecSimpleKeysStoreAdoptKey(*ss, key));
+}
+
+/**
+ * xmlSecNssKeysStoreLoad:
+ * @store: the pointer to Nss keys store.
+ * @uri: the filename.
+ * @keysMngr: the pointer to associated keys manager.
+ *
+ * Reads keys from an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeysStoreLoad(xmlSecKeyStorePtr store, const char *uri,
+ xmlSecKeysMngrPtr keysMngr) {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr cur;
+ xmlSecKeyPtr key;
+ xmlSecKeyInfoCtx keyInfoCtx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+ xmlSecAssert2((uri != NULL), -1);
+
+ doc = xmlParseFile(uri);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlParseFile",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if(!xmlSecCheckNodeName(root, BAD_CAST "Keys", xmlSecNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(root)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=<xmlsec:Keys>");
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(root->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ keyInfoCtx.mode = xmlSecKeyInfoModeRead;
+ keyInfoCtx.keysMngr = keysMngr;
+ keyInfoCtx.flags = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
+ XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+ keyInfoCtx.keyReq.keyId = xmlSecKeyDataIdUnknown;
+ keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
+ keyInfoCtx.keyReq.keyUsage= xmlSecKeyDataUsageAny;
+
+ ret = xmlSecKeyInfoNodeRead(cur, key, &keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+
+ if(xmlSecKeyIsValid(key)) {
+ ret = xmlSecNssKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecNssKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ } else {
+ /* we have an unknown key in our file, just ignore it */
+ xmlSecKeyDestroy(key);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ xmlFreeDoc(doc);
+ return(0);
+}
+
+/**
+ * xmlSecNssKeysStoreSave:
+ * @store: the pointer to Nss keys store.
+ * @filename: the filename.
+ * @type: the saved keys type (public, private, ...).
+ *
+ * Writes keys from @store to an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeysStoreSave(xmlSecKeyStorePtr store, const char *filename, xmlSecKeyDataType type) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+ xmlSecAssert2((filename != NULL), -1);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
+ (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
+
+ return (xmlSecSimpleKeysStoreSave(*ss, filename, type));
+}
+
+static int
+xmlSecNssKeysStoreInitialize(xmlSecKeyStorePtr store) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2((*ss == NULL), -1);
+
+ *ss = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId);
+ if(*ss == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecSimpleKeysStoreId");
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKeysStoreFinalize(xmlSecKeyStorePtr store) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId));
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert((ss != NULL) && (*ss != NULL));
+
+ xmlSecKeyStoreDestroy(*ss);
+}
+
+static xmlSecKeyPtr
+xmlSecNssKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyStorePtr* ss;
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyPtr retval = NULL;
+ xmlSecKeyReqPtr keyReq = NULL;
+ CERTCertificate *cert = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL)), NULL);
+
+ key = xmlSecKeyStoreFindKey(*ss, name, keyInfoCtx);
+ if (key != NULL) {
+ return (key);
+ }
+
+ /* Try to find the key in the NSS DB, and construct an xmlSecKey.
+ * we must have a name to lookup keys in NSS DB.
+ */
+ if (name == NULL) {
+ goto done;
+ }
+
+ /* what type of key are we looking for?
+ * TBD: For now, we'll look only for public/private keys using the
+ * name as a cert nickname. Later on, we can attempt to find
+ * symmetric keys using PK11_FindFixedKey
+ */
+ keyReq = &(keyInfoCtx->keyReq);
+ if (keyReq->keyType &
+ (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) {
+ cert = CERT_FindCertByNickname (CERT_GetDefaultCertDB(), (char *)name);
+ if (cert == NULL) {
+ goto done;
+ }
+
+ if (keyReq->keyType & xmlSecKeyDataTypePublic) {
+ pubkey = CERT_ExtractPublicKey(cert);
+ if (pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ if (keyReq->keyType & xmlSecKeyDataTypePrivate) {
+ privkey = PK11_FindKeyByAnyCert(cert, NULL);
+ if (privkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_FindKeyByAnyCert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ data = xmlSecNssPKIAdoptKey(privkey, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ privkey = NULL;
+ pubkey = NULL;
+
+ key = xmlSecKeyCreate();
+ if (key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
+ goto done;
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, cert);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ cert = CERT_DupCertificate(cert);
+ if (cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(x509Data, cert);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ cert = NULL;
+
+ ret = xmlSecKeySetValue(key, data);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ 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)));
+ goto done;
+ }
+ x509Data = NULL;
+
+ retval = key;
+ key = NULL;
+ }
+
+done:
+ if (cert != NULL) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if (x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if (key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+
+ return (retval);
+}
diff --git a/src/nss/keytrans.c b/src/nss/keytrans.c
new file mode 100644
index 00000000..5d256c22
--- /dev/null
+++ b/src/nss/keytrans.c
@@ -0,0 +1,744 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright .................................
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+#include <keyhi.h>
+#include <key.h>
+#include <hasht.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/pkikeys.h>
+
+/*********************************************************************
+ *
+ * key transform transforms
+ *
+ ********************************************************************/
+typedef struct _xmlSecNssKeyTransportCtx xmlSecNssKeyTransportCtx;
+typedef struct _xmlSecNssKeyTransportCtx* xmlSecNssKeyTransportCtxPtr;
+
+#define xmlSecNssKeyTransportSize \
+ ( sizeof( xmlSecTransform ) + sizeof( xmlSecNssKeyTransportCtx ) )
+#define xmlSecNssKeyTransportGetCtx( transform ) \
+ ( ( xmlSecNssKeyTransportCtxPtr )( ( ( xmlSecByte* )( transform ) ) + sizeof( xmlSecTransform ) ) )
+
+struct _xmlSecNssKeyTransportCtx {
+ CK_MECHANISM_TYPE cipher ;
+ SECKEYPublicKey* pubkey ;
+ SECKEYPrivateKey* prikey ;
+ xmlSecKeyDataId keyId ;
+ xmlSecBufferPtr material ; /* to be encrypted/decrypted material */
+} ;
+
+static int xmlSecNssKeyTransportInitialize(xmlSecTransformPtr transform);
+static void xmlSecNssKeyTransportFinalize(xmlSecTransformPtr transform);
+static int xmlSecNssKeyTransportSetKeyReq(xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKeyTransportSetKey(xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKeyTransportExecute(xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecNssKeyTransportCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_RSA
+ if( xmlSecTransformCheckId( transform, xmlSecNssTransformRsaPkcs1Id )
+/* RSA OAEP is not supported by NSS yet */
+#ifdef TODO
+ || xmlSecTransformCheckId( transform, xmlSecNssTransformRsaOaepId )
+#endif /* TODO: RSA OAEP is not supported by NSS yet */
+
+ ) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_RSA */
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssKeyTransportCtxPtr context ;
+ xmlSecAssert2(xmlSecNssKeyTransportCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize), -1);
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ xmlSecAssert2( context != NULL , -1 ) ;
+
+#ifndef XMLSEC_NO_RSA
+ if( transform->id == xmlSecNssTransformRsaPkcs1Id ) {
+ context->cipher = CKM_RSA_PKCS ;
+ context->keyId = xmlSecNssKeyDataRsaId ;
+/* RSA OAEP is not supported by NSS yet */
+#ifdef TODO
+ } else if( transform->id == xmlSecNssTransformRsaOaepId ) {
+ context->cipher = CKM_RSA_PKCS_OAEP ;
+ context->keyId = xmlSecNssKeyDataRsaId ;
+#endif /* TODO: RSA OAEP is not supported by NSS yet */
+ } else
+#endif /* XMLSEC_NO_RSA */
+
+ if( 1 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ context->pubkey = NULL ;
+ context->prikey = NULL ;
+ context->material = NULL ;
+
+ return(0);
+}
+
+static void
+xmlSecNssKeyTransportFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssKeyTransportCtxPtr context ;
+
+ xmlSecAssert(xmlSecNssKeyTransportCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize));
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ xmlSecAssert( context != NULL ) ;
+
+ if( context->pubkey != NULL ) {
+ SECKEY_DestroyPublicKey( context->pubkey ) ;
+ context->pubkey = NULL ;
+ }
+
+ if( context->prikey != NULL ) {
+ SECKEY_DestroyPrivateKey( context->prikey ) ;
+ context->prikey = NULL ;
+ }
+
+ if( context->material != NULL ) {
+ xmlSecBufferDestroy(context->material);
+ context->material = NULL ;
+ }
+}
+
+static int
+xmlSecNssKeyTransportSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssKeyTransportCtxPtr context ;
+
+ xmlSecAssert2(xmlSecNssKeyTransportCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ xmlSecAssert2( context != NULL , -1 ) ;
+
+ keyReq->keyId = context->keyId;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssKeyTransportCtxPtr context = NULL ;
+ xmlSecKeyDataPtr keyData = NULL ;
+ SECKEYPublicKey* pubkey = NULL ;
+ SECKEYPrivateKey* prikey = NULL ;
+
+ xmlSecAssert2(xmlSecNssKeyTransportCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ if( (context == NULL) || (context->keyId == NULL) || (context->pubkey != NULL) ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportGetCtx" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ xmlSecAssert2( xmlSecKeyCheckId( key, context->keyId ), -1 ) ;
+
+ keyData = xmlSecKeyGetValue( key ) ;
+ if( keyData == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyGetName( key ) ) ,
+ "xmlSecKeyGetValue" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ if( ( pubkey = xmlSecNssPKIKeyDataGetPubKey( keyData ) ) == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataGetName( keyData ) ) ,
+ "xmlSecNssPKIKeyDataGetPubKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ context->pubkey = pubkey ;
+ } else {
+ if( ( prikey = xmlSecNssPKIKeyDataGetPrivKey( keyData ) ) == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataGetName( keyData ) ) ,
+ "xmlSecNssPKIKeyDataGetPrivKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ context->prikey = prikey ;
+ }
+
+ return(0) ;
+}
+
+/**
+ * key wrap transform
+ */
+static int
+xmlSecNssKeyTransportCtxInit(
+ xmlSecNssKeyTransportCtxPtr ctx ,
+ xmlSecBufferPtr in ,
+ xmlSecBufferPtr out ,
+ int encrypt ,
+ xmlSecTransformCtxPtr transformCtx
+) {
+ int blockSize ;
+
+ xmlSecAssert2( ctx != NULL , -1 ) ;
+ xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ;
+ xmlSecAssert2( ( ctx->pubkey != NULL && encrypt ) || ( ctx->prikey != NULL && !encrypt ), -1 ) ;
+ xmlSecAssert2( ctx->keyId != NULL , -1 ) ;
+ xmlSecAssert2( in != NULL , -1 ) ;
+ xmlSecAssert2( out != NULL , -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ if( ctx->material != NULL ) {
+ xmlSecBufferDestroy( ctx->material ) ;
+ ctx->material = NULL ;
+ }
+
+ if( ctx->pubkey != NULL ) {
+ blockSize = SECKEY_PublicKeyStrength( ctx->pubkey ) ;
+ } else if( ctx->prikey != NULL ) {
+ blockSize = PK11_SignatureLen( ctx->prikey ) ;
+ } else {
+ blockSize = -1 ;
+ }
+
+ if( blockSize < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ ctx->material = xmlSecBufferCreate( blockSize ) ;
+ if( ctx->material == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferCreate" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ /* read raw key material into context */
+ if( xmlSecBufferSetData( ctx->material, xmlSecBufferGetData(in), xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferSetData" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferRemoveHead( in , xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferRemoveHead" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * key wrap transform update
+ */
+static int
+xmlSecNssKeyTransportCtxUpdate(
+ xmlSecNssKeyTransportCtxPtr ctx ,
+ xmlSecBufferPtr in ,
+ xmlSecBufferPtr out ,
+ int encrypt ,
+ xmlSecTransformCtxPtr transformCtx
+) {
+ xmlSecAssert2( ctx != NULL , -1 ) ;
+ xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ;
+ xmlSecAssert2( ( ctx->pubkey != NULL && encrypt ) || ( ctx->prikey != NULL && !encrypt ), -1 ) ;
+ xmlSecAssert2( ctx->keyId != NULL , -1 ) ;
+ xmlSecAssert2( ctx->material != NULL , -1 ) ;
+ xmlSecAssert2( in != NULL , -1 ) ;
+ xmlSecAssert2( out != NULL , -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ /* read raw key material and append into context */
+ if( xmlSecBufferAppend( ctx->material, xmlSecBufferGetData(in), xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferAppend" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferRemoveHead( in , xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferRemoveHead" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * Block cipher transform final
+ */
+static int
+xmlSecNssKeyTransportCtxFinal(xmlSecNssKeyTransportCtxPtr ctx, xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt, xmlSecTransformCtxPtr transformCtx) {
+ PK11SymKey* symKey ;
+ PK11SlotInfo* slot ;
+ SECItem oriskv ;
+ int blockSize ;
+ xmlSecBufferPtr result ;
+
+ xmlSecAssert2( ctx != NULL , -1 ) ;
+ xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ;
+ xmlSecAssert2( ( ctx->pubkey != NULL && encrypt ) || ( ctx->prikey != NULL && !encrypt ), -1 ) ;
+ xmlSecAssert2( ctx->keyId != NULL , -1 ) ;
+ xmlSecAssert2( ctx->material != NULL , -1 ) ;
+ xmlSecAssert2( in != NULL , -1 ) ;
+ xmlSecAssert2( out != NULL , -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ /* read raw key material and append into context */
+ if( xmlSecBufferAppend( ctx->material, xmlSecBufferGetData(in), xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferAppend" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferRemoveHead( in , xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferRemoveHead" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ /* Now we get all of the key materail */
+ /* from now on we will wrap or unwrap the key */
+ if( ctx->pubkey != NULL ) {
+ blockSize = SECKEY_PublicKeyStrength( ctx->pubkey ) ;
+ } else if( ctx->prikey != NULL ) {
+ blockSize = PK11_SignatureLen( ctx->prikey ) ;
+ } else {
+ blockSize = -1 ;
+ }
+
+ if( blockSize < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_GetBlockSize" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ result = xmlSecBufferCreate( blockSize * 2 ) ;
+ if( result == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL,
+ "xmlSecBufferCreate" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return(-1);
+ }
+
+ oriskv.type = siBuffer ;
+ oriskv.data = xmlSecBufferGetData( ctx->material ) ;
+ oriskv.len = xmlSecBufferGetSize( ctx->material ) ;
+
+ if( encrypt != 0 ) {
+ CK_OBJECT_HANDLE id ;
+ SECItem wrpskv ;
+
+ /* Create template symmetric key from material */
+ slot = ctx->pubkey->pkcs11Slot;
+ if( slot == NULL ) {
+ slot = PK11_GetBestSlot( ctx->cipher, NULL ) ;
+ if( slot == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecNssSlotGet" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ id = PK11_ImportPublicKey( slot, ctx->pubkey, PR_FALSE ) ;
+ if( id == CK_INVALID_HANDLE ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_ImportPublicKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+ }
+
+ /* pay attention to mechanism */
+ symKey = PK11_ImportSymKey( slot, ctx->cipher, PK11_OriginUnwrap, CKA_WRAP, &oriskv, NULL ) ;
+ if( symKey == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_ImportSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+
+ wrpskv.type = siBuffer ;
+ wrpskv.data = xmlSecBufferGetData( result ) ;
+ wrpskv.len = xmlSecBufferGetMaxSize( result ) ;
+
+ if( PK11_PubWrapSymKey( ctx->cipher, ctx->pubkey, symKey, &wrpskv ) != SECSuccess ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_PubWrapSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferSetSize( result , wrpskv.len ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferSetSize" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+ PK11_FreeSymKey( symKey ) ;
+ PK11_FreeSlot( slot ) ;
+ } else {
+ SECItem* keyItem ;
+
+ /* pay attention to mechanism */
+ symKey = PK11_PubUnwrapSymKey( ctx->prikey, &oriskv, ctx->cipher, CKA_UNWRAP, 0 );
+ if( symKey == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_PubUnwrapSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ /* Extract raw data from symmetric key */
+ if( PK11_ExtractKeyValue( symKey ) != SECSuccess ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_ExtractKeyValue" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ keyItem = PK11_GetKeyData( symKey );
+ if( keyItem == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_GetKeyData" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ if( xmlSecBufferSetData( result, keyItem->data, keyItem->len ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_PubUnwrapSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+ PK11_FreeSymKey( symKey ) ;
+ }
+
+ /* Write output */
+ if( xmlSecBufferAppend( out, xmlSecBufferGetData(result), xmlSecBufferGetSize(result) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferAppend" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+ xmlSecBufferDestroy(result);
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssKeyTransportCtxPtr context = NULL ;
+ xmlSecBufferPtr inBuf, outBuf ;
+ int operation ;
+ int rtv ;
+
+ xmlSecAssert2( xmlSecNssKeyTransportCheckId( transform ), -1 ) ;
+ xmlSecAssert2( xmlSecTransformCheckSize( transform, xmlSecNssKeyTransportSize ), -1 ) ;
+ xmlSecAssert2( ( transform->operation == xmlSecTransformOperationEncrypt ) || ( transform->operation == xmlSecTransformOperationDecrypt ), -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ if( context == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportGetCtx" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ inBuf = &( transform->inBuf ) ;
+ outBuf = &( transform->outBuf ) ;
+
+ if( transform->status == xmlSecTransformStatusNone ) {
+ transform->status = xmlSecTransformStatusWorking ;
+ }
+
+ operation = ( transform->operation == xmlSecTransformOperationEncrypt ) ? 1 : 0 ;
+ if( transform->status == xmlSecTransformStatusWorking ) {
+ if( context->material == NULL ) {
+ rtv = xmlSecNssKeyTransportCtxInit( context, inBuf , outBuf , operation , transformCtx ) ;
+ if( rtv < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportCtxInit" ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ }
+
+ if( (context->material == NULL) && (last != 0) ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ NULL ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ "No enough data to intialize transform" ) ;
+ return(-1);
+ }
+
+ if( context->material != NULL ) {
+ rtv = xmlSecNssKeyTransportCtxUpdate( context, inBuf , outBuf , operation , transformCtx ) ;
+ if( rtv < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportCtxUpdate" ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ }
+
+ if( last ) {
+ rtv = xmlSecNssKeyTransportCtxFinal( context, inBuf , outBuf , operation , transformCtx ) ;
+ if( rtv < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportCtxFinal" ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished ;
+ }
+ } else if( transform->status == xmlSecTransformStatusFinished ) {
+ if( xmlSecBufferGetSize( inBuf ) != 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ NULL ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ "status=%d", transform->status ) ;
+ return(-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_RSA
+
+static xmlSecTransformKlass xmlSecNssRsaPkcs1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKeyTransportSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaPkcs1, /* const xmlChar* name; */
+ xmlSecHrefRsaPkcs1, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKeyTransportInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKeyTransportFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKeyTransportSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKeyTransportSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKeyTransportExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaPkcs1GetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaPkcs1GetKlass(void) {
+ return(&xmlSecNssRsaPkcs1Klass);
+}
+
+
+/* RSA OAEP is not supported by NSS yet */
+#ifdef TODO
+
+static xmlSecTransformKlass xmlSecNssRsaOaepKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKeyTransportSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaOaep, /* const xmlChar* name; */
+ xmlSecHrefRsaOaep, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKeyTransportInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKeyTransportFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKeyTransportSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKeyTransportSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKeyTransportExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaOaepGetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaOaepGetKlass(void) {
+ return(&xmlSecNssRsaOaepKlass);
+}
+#endif /* TODO: RSA OAEP is not supported by NSS yet */
+
+#endif /* XMLSEC_NO_RSA */
+
diff --git a/src/nss/kw_aes.c b/src/nss/kw_aes.c
new file mode 100644
index 00000000..0c3a5708
--- /dev/null
+++ b/src/nss/kw_aes.c
@@ -0,0 +1,857 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#ifndef XMLSEC_NO_AES
+
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+#define XMLSEC_NSS_AES128_KEY_SIZE 16
+#define XMLSEC_NSS_AES192_KEY_SIZE 24
+#define XMLSEC_NSS_AES256_KEY_SIZE 32
+#define XMLSEC_NSS_AES_IV_SIZE 16
+#define XMLSEC_NSS_AES_BLOCK_SIZE 16
+
+#ifndef NSS_AES_KEYWRAP_BUG_FIXED
+static PK11SymKey* xmlSecNssMakeAesKey(const xmlSecByte *key,
+ xmlSecSize keySize, int enc);
+static void xmlSecNssAesOp(PK11SymKey *aeskey,
+ const xmlSecByte *in, xmlSecByte *out,
+ int enc);
+#endif /* NSS_AES_KEYWRAP_BUG_FIXED */
+
+/*********************************************************************
+ *
+ * AES KW transforms
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+#define xmlSecNssKWAesGetKey(transform) \
+ ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecNssKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
+
+static int xmlSecNssKWAesInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssKWAesFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssKWAesSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKWAesSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKWAesExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecSize xmlSecNssKWAesGetKeySize (xmlSecTransformPtr transform);
+static int xmlSecNssKWAesOp (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte* in,
+ xmlSecSize inSize,
+ xmlSecByte* out,
+ xmlSecSize outSize,
+ int enc);
+
+static xmlSecTransformKlass xmlSecNssKWAes128Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes128, /* const xmlChar* name; */
+ xmlSecHrefKWAes128, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static xmlSecTransformKlass xmlSecNssKWAes192Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes192, /* const xmlChar* name; */
+ xmlSecHrefKWAes192, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static xmlSecTransformKlass xmlSecNssKWAes256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes256, /* const xmlChar* name; */
+ xmlSecHrefKWAes256, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+#define XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE 8
+
+#define xmlSecNssKWAesCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes128Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes192Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes256Id))
+
+/**
+ * xmlSecNssTransformKWAes128GetKlass:
+ *
+ * The AES-128 key wrapper transform klass.
+ *
+ * Returns: AES-128 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes128GetKlass(void) {
+ return(&xmlSecNssKWAes128Klass);
+}
+
+/**
+ * xmlSecNssTransformKWAes192GetKlass:
+ *
+ * The AES-192 key wrapper transform klass.
+ *
+ * Returns: AES-192 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes192GetKlass(void) {
+ return(&xmlSecNssKWAes192Klass);
+}
+
+/**
+ * xmlSecNssTransformKWAes256GetKlass:
+ *
+ * The AES-256 key wrapper transform klass.
+ *
+ * Returns: AES-256 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes256GetKlass(void) {
+ return(&xmlSecNssKWAes256Klass);
+}
+
+static int
+xmlSecNssKWAesInitialize(xmlSecTransformPtr transform) {
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+
+ ret = xmlSecBufferInitialize(xmlSecNssKWAesGetKey(transform), 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
+xmlSecNssKWAesFinalize(xmlSecTransformPtr transform) {
+ xmlSecAssert(xmlSecNssKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize));
+
+ if(xmlSecNssKWAesGetKey(transform) != NULL) {
+ xmlSecBufferFinalize(xmlSecNssKWAesGetKey(transform));
+ }
+}
+
+static int
+xmlSecNssKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataAesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * xmlSecNssKWAesGetKeySize(transform);
+
+ return(0);
+}
+
+static int
+xmlSecNssKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ xmlSecSize expectedKeySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(xmlSecNssKWAesGetKey(transform) != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataAesId), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ expectedKeySize = xmlSecNssKWAesGetKeySize(transform);
+ if(keySize < expectedKeySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, expectedKeySize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(xmlSecNssKWAesGetKey(transform),
+ xmlSecBufferGetData(buffer),
+ expectedKeySize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d", expectedKeySize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBufferPtr in, out, key;
+ xmlSecSize inSize, outSize, keySize, expectedKeySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ key = xmlSecNssKWAesGetKey(transform);
+ xmlSecAssert2(key != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(key);
+ expectedKeySize = xmlSecNssKWAesGetKeySize(transform);
+ xmlSecAssert2(keySize == expectedKeySize, -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_NSS_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_NSS_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_NSS_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) {
+ ret = xmlSecNssKWAesOp(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssKWAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecNssKWAesOp(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssKWAesOp",
+ 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 xmlSecSize
+xmlSecNssKWAesGetKeySize(xmlSecTransformPtr transform) {
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes128Id)) {
+ return(XMLSEC_NSS_AES128_KEY_SIZE);
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes192Id)) {
+ return(XMLSEC_NSS_AES192_KEY_SIZE);
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes256Id)) {
+ return(XMLSEC_NSS_AES256_KEY_SIZE);
+ }
+ return(0);
+}
+
+/**
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap:
+ *
+ * Assume that the data to be wrapped consists of N 64-bit data blocks
+ * denoted P(1), P(2), P(3) ... P(N). The result of wrapping will be N+1
+ * 64-bit blocks denoted C(0), C(1), C(2), ... C(N). The key encrypting
+ * key is represented by K. Assume integers i, j, and t and intermediate
+ * 64-bit register A, 128-bit register B, and array of 64-bit quantities
+ * R(1) through R(N).
+ *
+ * "|" represents concatentation so x|y, where x and y and 64-bit quantities,
+ * is the 128-bit quantity with x in the most significant bits and y in the
+ * least significant bits. AES(K)enc(x) is the operation of AES encrypting
+ * the 128-bit quantity x under the key K. AES(K)dec(x) is the corresponding
+ * decryption opteration. XOR(x,y) is the bitwise exclusive or of x and y.
+ * MSB(x) and LSB(y) are the most significant 64 bits and least significant
+ * 64 bits of x and y respectively.
+ *
+ * If N is 1, a single AES operation is performed for wrap or unwrap.
+ * If N>1, then 6*N AES operations are performed for wrap or unwrap.
+ *
+ * The key wrap algorithm is as follows:
+ *
+ * 1. If N is 1:
+ * * B=AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
+ * * C(0)=MSB(B)
+ * * C(1)=LSB(B)
+ * If N>1, perform the following steps:
+ * 2. Initialize variables:
+ * * Set A to 0xA6A6A6A6A6A6A6A6
+ * * Fori=1 to N,
+ * R(i)=P(i)
+ * 3. Calculate intermediate values:
+ * * Forj=0 to 5,
+ * o For i=1 to N,
+ * t= i + j*N
+ * B=AES(K)enc(A|R(i))
+ * A=XOR(t,MSB(B))
+ * R(i)=LSB(B)
+ * 4. Output the results:
+ * * Set C(0)=A
+ * * For i=1 to N,
+ * C(i)=R(i)
+ *
+ * The key unwrap algorithm is as follows:
+ *
+ * 1. If N is 1:
+ * * B=AES(K)dec(C(0)|C(1))
+ * * P(1)=LSB(B)
+ * * If MSB(B) is 0xA6A6A6A6A6A6A6A6, return success. Otherwise,
+ * return an integrity check failure error.
+ * If N>1, perform the following steps:
+ * 2. Initialize the variables:
+ * * A=C(0)
+ * * For i=1 to N,
+ * R(i)=C(i)
+ * 3. Calculate intermediate values:
+ * * For j=5 to 0,
+ * o For i=N to 1,
+ * t= i + j*N
+ * B=AES(K)dec(XOR(t,A)|R(i))
+ * A=MSB(B)
+ * R(i)=LSB(B)
+ * 4. Output the results:
+ * * For i=1 to N,
+ * P(i)=R(i)
+ * * If A is 0xA6A6A6A6A6A6A6A6, return success. Otherwise, return
+ * an integrity check failure error.
+ */
+
+#ifndef NSS_AES_KEYWRAP_BUG_FIXED
+static const xmlSecByte xmlSecNssKWAesMagicBlock[XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE] = {
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
+};
+
+static int
+xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize, int enc) {
+ xmlSecByte block[XMLSEC_NSS_AES_BLOCK_SIZE];
+ xmlSecByte *p;
+ int N, i, j, t;
+ int result = -1;
+ PK11SymKey *aeskey = NULL;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize > 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 8, -1);
+
+ if (enc == 1) {
+ aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* prepend magic block */
+ if(in != out) {
+ memcpy(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
+ } else {
+ memmove(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
+ }
+ memcpy(out, xmlSecNssKWAesMagicBlock, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
+
+ N = (inSize / 8);
+ if(N == 1) {
+ xmlSecNssAesOp(aeskey, out, out, enc);
+ } else {
+ for(j = 0; j <= 5; ++j) {
+ for(i = 1; i <= N; ++i) {
+ t = i + (j * N);
+ p = out + i * 8;
+
+ memcpy(block, out, 8);
+ memcpy(block + 8, p, 8);
+
+ xmlSecNssAesOp(aeskey, block, block, enc);
+ block[7] ^= t;
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+
+ result = inSize + 8;
+ } else {
+ aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* copy input */
+ if(in != out) {
+ memcpy(out, in, inSize);
+ }
+
+ N = (inSize / 8) - 1;
+ if(N == 1) {
+ xmlSecNssAesOp(aeskey, out, out, enc);
+ } else {
+ for(j = 5; j >= 0; --j) {
+ for(i = N; i > 0; --i) {
+ t = i + (j * N);
+ p = out + i * 8;
+
+ memcpy(block, out, 8);
+ memcpy(block + 8, p, 8);
+ block[7] ^= t;
+
+ xmlSecNssAesOp(aeskey, block, block, enc);
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+ /* do not left data in memory */
+ memset(block, 0, sizeof(block));
+
+ if(memcmp(xmlSecNssKWAesMagicBlock, out, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "bad magic block");
+ goto done;
+ }
+
+ memmove(out, out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
+ result = (inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
+ }
+
+done:
+ if (aeskey != NULL) {
+ PK11_FreeSymKey(aeskey);
+ }
+
+ return (result);
+}
+
+static PK11SymKey *
+xmlSecNssMakeAesKey(const xmlSecByte *key, xmlSecSize keySize, int enc) {
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* aeskey = NULL;
+ SECItem keyItem;
+
+ xmlSecAssert2(key != NULL, NULL);
+ xmlSecAssert2(keySize > 0, NULL);
+
+ cipherMech = CKM_AES_ECB;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyItem.data = (unsigned char *)key;
+ keyItem.len = keySize;
+ aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ if (aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+done:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+
+ return(aeskey);
+}
+
+/* encrypt a block (XMLSEC_NSS_AES_BLOCK_SIZE), in and out can overlap */
+static void
+xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out,
+ int enc) {
+
+ CK_MECHANISM_TYPE cipherMech;
+ SECItem* SecParam = NULL;
+ PK11Context* EncContext = NULL;
+ SECStatus rv;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+
+ xmlSecAssert(in != NULL);
+ xmlSecAssert(out != NULL);
+
+ cipherMech = CKM_AES_ECB;
+ SecParam = PK11_ParamFromIV(cipherMech, NULL);
+ if (SecParam == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ EncContext = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ aeskey, SecParam);
+ if (EncContext == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ rv = PK11_CipherOp(EncContext, out, &tmp1_outlen,
+ XMLSEC_NSS_AES_BLOCK_SIZE, (unsigned char *)in,
+ XMLSEC_NSS_AES_BLOCK_SIZE);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
+ &tmp2_outlen, XMLSEC_NSS_AES_BLOCK_SIZE-tmp1_outlen);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+done:
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ }
+ if (EncContext) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ }
+
+}
+
+#else /* NSS_AES_KEYWRAP_BUG_FIXED */
+
+/* Note: When the bug gets fixed, it is not enough to just remove
+ * the #ifdef (NSS_AES_KEYWRAP_BUG_FIXED). The code also has
+ * to change from doing the Init/Update/Final to just a straight
+ * encrypt or decrypt. PK11 wrappers have to be exposed by
+ * NSS, and these should be used.
+ * Follow the NSS bug system for more details on the fix
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=213795
+ */
+
+/* NSS implements the AES Key Wrap algorithm described at
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
+ */
+
+static int
+xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize, int enc) {
+
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* aeskey = NULL;
+ SECItem* SecParam = NULL;
+ PK11Context* EncContext = NULL;
+ SECItem keyItem;
+ SECStatus rv;
+ int result_len = -1;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize > 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 8, -1);
+
+ cipherMech = CKM_NETSCAPE_AES_KEY_WRAP;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyItem.data = (unsigned char *)key;
+ keyItem.len = keySize;
+ aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ if (aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ SecParam = PK11_ParamFromIV(cipherMech, NULL);
+ if (SecParam == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ EncContext = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ aeskey, SecParam);
+ if (EncContext == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize,
+ (unsigned char *)in, inSize);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
+ &tmp2_outlen, outSize-tmp1_outlen);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ result_len = tmp1_outlen + tmp2_outlen;
+
+done:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (aeskey) {
+ PK11_FreeSymKey(aeskey);
+ }
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ }
+ if (EncContext) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ }
+
+ return(result_len);
+}
+#endif /* NSS_AES_KEYWRAP_BUG_FIXED */
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/nss/kw_des.c b/src/nss/kw_des.c
new file mode 100644
index 00000000..0cb6f24a
--- /dev/null
+++ b/src/nss/kw_des.c
@@ -0,0 +1,758 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for precise wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+
+#ifndef XMLSEC_NO_DES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+#include <hasht.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+#define XMLSEC_NSS_DES3_KEY_LENGTH 24
+#define XMLSEC_NSS_DES3_IV_LENGTH 8
+#define XMLSEC_NSS_DES3_BLOCK_LENGTH 8
+
+static xmlSecByte *xmlSecNssComputeSHA1(const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize);
+
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+#define xmlSecNssKWDes3GetKey(transform) \
+ ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecNssKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
+
+static int xmlSecNssKWDes3Initialize (xmlSecTransformPtr transform);
+static void xmlSecNssKWDes3Finalize (xmlSecTransformPtr transform);
+static int xmlSecNssKWDes3SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKWDes3SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKWDes3Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssKWDes3Encode (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3Decode (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3Encrypt (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *iv,
+ xmlSecSize ivSize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize,
+ int enc);
+static int xmlSecNssKWDes3BufferReverse (xmlSecByte *buf,
+ xmlSecSize size);
+
+static xmlSecTransformKlass xmlSecNssKWDes3Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWDes3Size, /* xmlSecSize objSize */
+
+ xmlSecNameKWDes3, /* const xmlChar* name; */
+ xmlSecHrefKWDes3, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWDes3GetKlass(void) {
+ return(&xmlSecNssKWDes3Klass);
+}
+
+static int
+xmlSecNssKWDes3Initialize(xmlSecTransformPtr transform) {
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+
+ ret = xmlSecBufferInitialize(xmlSecNssKWDes3GetKey(transform), 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
+xmlSecNssKWDes3Finalize(xmlSecTransformPtr transform) {
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size));
+
+ if(xmlSecNssKWDes3GetKey(transform) != NULL) {
+ xmlSecBufferFinalize(xmlSecNssKWDes3GetKey(transform));
+ }
+}
+
+static int
+xmlSecNssKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_NSS_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecNssKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(xmlSecNssKWDes3GetKey(transform) != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataDesId), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_NSS_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_NSS_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(xmlSecNssKWDes3GetKey(transform),
+ xmlSecBufferGetData(buffer),
+ XMLSEC_NSS_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_NSS_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBufferPtr in, out, key;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ key = xmlSecNssKWDes3GetKey(transform);
+ xmlSecAssert2(key != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(key);
+ xmlSecAssert2(keySize == XMLSEC_NSS_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_NSS_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_NSS_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_NSS_DES3_IV_LENGTH +
+ XMLSEC_NSS_DES3_BLOCK_LENGTH +
+ XMLSEC_NSS_DES3_BLOCK_LENGTH;
+ } else {
+ outSize = inSize + XMLSEC_NSS_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 = xmlSecNssKWDes3Encode(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecNssKWDes3Decode(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssKWDes3Decode",
+ 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);
+}
+
+static xmlSecByte xmlSecNssKWDes3Iv[XMLSEC_NSS_DES3_IV_LENGTH] = {
+ 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05
+};
+/**
+ * CMS Triple DES Key Wrap
+ *
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
+ *
+ * The following algorithm wraps (encrypts) a key (the wrapped key, WK)
+ * under a TRIPLEDES key-encryption-key (KEK) as specified in [CMS-Algorithms]:
+ *
+ * 1. Represent the key being wrapped as an octet sequence. If it is a
+ * TRIPLEDES key, this is 24 octets (192 bits) with odd parity bit as
+ * the bottom bit of each octet.
+ * 2. Compute the CMS key checksum (section 5.6.1) call this CKS.
+ * 3. Let WKCKS = WK || CKS, where || is concatenation.
+ * 4. Generate 8 random octets [RANDOM] and call this IV.
+ * 5. Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+ * initialization vector. Call the results TEMP1.
+ * 6. Left TEMP2 = IV || TEMP1.
+ * 7. Reverse the order of the octets in TEMP2 and call the result TEMP3.
+ * 8. Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+ * of 0x4adda22c79e82105. The resulting cipher text is the desired result.
+ * It is 40 octets long if a 168 bit key is being wrapped.
+ *
+ */
+static int
+xmlSecNssKWDes3Encode(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte sha1[SHA1_LENGTH];
+ xmlSecByte iv[XMLSEC_NSS_DES3_IV_LENGTH];
+ xmlSecSize s;
+ int ret;
+ SECStatus status;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_NSS_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 16, -1);
+
+ /* step 2: calculate sha1 and CMS */
+ if(xmlSecNssComputeSHA1(in, inSize, sha1, SHA1_LENGTH) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssComputeSHA1",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 3: construct WKCKS */
+ memcpy(out, in, inSize);
+ memcpy(out + inSize, sha1, XMLSEC_NSS_DES3_BLOCK_LENGTH);
+
+ /* step 4: generate random iv */
+ status = PK11_GenerateRandom(iv, XMLSEC_NSS_DES3_IV_LENGTH);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 5: first encryption, result is TEMP1 */
+ ret = xmlSecNssKWDes3Encrypt(key, keySize,
+ iv, XMLSEC_NSS_DES3_IV_LENGTH,
+ out, inSize + XMLSEC_NSS_DES3_BLOCK_LENGTH,
+ out, outSize, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 6: construct TEMP2=IV || TEMP1 */
+ memmove(out + XMLSEC_NSS_DES3_IV_LENGTH, out,
+ inSize + XMLSEC_NSS_DES3_IV_LENGTH);
+ memcpy(out, iv, XMLSEC_NSS_DES3_IV_LENGTH);
+ s = ret + XMLSEC_NSS_DES3_IV_LENGTH;
+
+ /* step 7: reverse octets order, result is TEMP3 */
+ ret = xmlSecNssKWDes3BufferReverse(out, s);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3BufferReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 8: second encryption with static IV */
+ ret = xmlSecNssKWDes3Encrypt(key, keySize,
+ xmlSecNssKWDes3Iv, XMLSEC_NSS_DES3_IV_LENGTH,
+ out, s, out, outSize, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ s = ret;
+ return(s);
+}
+
+/**
+ * CMS Triple DES Key Wrap
+ *
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
+ *
+ * The following algorithm unwraps (decrypts) a key as specified in
+ * [CMS-Algorithms]:
+ *
+ * 1. Check if the length of the cipher text is reasonable given the key type.
+ * It must be 40 bytes for a 168 bit key and either 32, 40, or 48 bytes for
+ * a 128, 192, or 256 bit key. If the length is not supported or inconsistent
+ * with the algorithm for which the key is intended, return error.
+ * 2. Decrypt the cipher text with TRIPLEDES in CBC mode using the KEK and
+ * an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
+ * 3. Reverse the order of the octets in TEMP3 and call the result TEMP2.
+ * 4. Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining
+ * octets.
+ * 5. Decrypt TEMP1 using TRIPLEDES in CBC mode using the KEK and the IV found
+ * in the previous step. Call the result WKCKS.
+ * 6. Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
+ * those octets before the CKS.
+ * 7. Calculate a CMS key checksum (section 5.6.1) over the WK and compare
+ * with the CKS extracted in the above step. If they are not equal, return
+ * error.
+ * 8. WK is the wrapped key, now extracted for use in data decryption.
+ */
+static int
+xmlSecNssKWDes3Decode(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte sha1[SHA1_LENGTH];
+ xmlSecSize s;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_NSS_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ /* step 2: first decryption with static IV, result is TEMP3 */
+ ret = xmlSecNssKWDes3Encrypt(key, keySize,
+ xmlSecNssKWDes3Iv, XMLSEC_NSS_DES3_IV_LENGTH,
+ in, inSize, out, outSize, 0);
+ if((ret < 0) || (ret < XMLSEC_NSS_DES3_IV_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ s = ret;
+
+ /* step 3: reverse octets order in TEMP3, result is TEMP2 */
+ ret = xmlSecNssKWDes3BufferReverse(out, s);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3BufferReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* steps 4 and 5: get IV and decrypt second time, result is WKCKS */
+ ret = xmlSecNssKWDes3Encrypt(key, keySize,
+ out, XMLSEC_NSS_DES3_IV_LENGTH,
+ out + XMLSEC_NSS_DES3_IV_LENGTH,
+ s - XMLSEC_NSS_DES3_IV_LENGTH,
+ out, outSize, 0);
+ if((ret < 0) || (ret < XMLSEC_NSS_DES3_BLOCK_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ s = ret - XMLSEC_NSS_DES3_BLOCK_LENGTH;
+
+ /* steps 6 and 7: calculate SHA1 and validate it */
+ if(xmlSecNssComputeSHA1(out, s, sha1, SHA1_LENGTH) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssComputeSHA1",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(memcmp(sha1, out + s, XMLSEC_NSS_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "SHA1 does not match");
+ return(-1);
+ }
+
+ return(s);
+}
+
+static int
+xmlSecNssKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *iv, xmlSecSize ivSize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize, int enc) {
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* SymKey = NULL;
+ SECItem* SecParam = NULL;
+ PK11Context* EncContext = NULL;
+ SECItem keyItem, ivItem;
+ SECStatus rv;
+ int result_len = -1;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_NSS_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize == XMLSEC_NSS_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ cipherMech = CKM_DES3_CBC;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyItem.data = (unsigned char *)key;
+ keyItem.len = keySize;
+ SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ if (SymKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ivItem.data = (unsigned char *)iv;
+ ivItem.len = ivSize;
+
+ SecParam = PK11_ParamFromIV(cipherMech, &ivItem);
+ if (SecParam == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ EncContext = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ SymKey, SecParam);
+ if (EncContext == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize,
+ (unsigned char *)in, inSize);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
+ &tmp2_outlen, outSize-tmp1_outlen);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ result_len = tmp1_outlen + tmp2_outlen;
+
+done:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (SymKey) {
+ PK11_FreeSymKey(SymKey);
+ }
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ }
+ if (EncContext) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ }
+
+ return(result_len);
+}
+
+static int
+xmlSecNssKWDes3BufferReverse(xmlSecByte *buf, xmlSecSize size) {
+ xmlSecSize s;
+ xmlSecSize i;
+ xmlSecByte c;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ s = size / 2;
+ --size;
+ for(i = 0; i < s; ++i) {
+ c = buf[i];
+ buf[i] = buf[size - i];
+ buf[size - i] = c;
+ }
+ return(0);
+}
+
+static xmlSecByte *
+xmlSecNssComputeSHA1(const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize)
+{
+ PK11Context *context = NULL;
+ SECStatus s;
+ xmlSecByte *digest = NULL;
+ unsigned int len;
+
+ xmlSecAssert2(in != NULL, NULL);
+ xmlSecAssert2(out != NULL, NULL);
+ xmlSecAssert2(outSize >= SHA1_LENGTH, NULL);
+
+ /* Create a context for hashing (digesting) */
+ context = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (context == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateDigestContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ s = PK11_DigestBegin(context);
+ if (s != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ s = PK11_DigestOp(context, in, inSize);
+ if (s != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ s = PK11_DigestFinal(context, out, &len, outSize);
+ if (s != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ xmlSecAssert2(len == SHA1_LENGTH, NULL);
+
+ digest = out;
+
+done:
+ if (context != NULL) {
+ PK11_DestroyContext(context, PR_TRUE);
+ }
+ return (digest);
+}
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/nss/pkikeys.c b/src/nss/pkikeys.c
new file mode 100644
index 00000000..f8549352
--- /dev/null
+++ b/src/nss/pkikeys.c
@@ -0,0 +1,1554 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <pk11func.h>
+#include <keyhi.h>
+#include <pk11pqg.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/nss/crypto.h>
+#include <xmlsec/nss/bignum.h>
+#include <xmlsec/nss/pkikeys.h>
+
+/**************************************************************************
+ *
+ * Internal NSS PKI key CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecNssPKIKeyDataCtx xmlSecNssPKIKeyDataCtx,
+ *xmlSecNssPKIKeyDataCtxPtr;
+struct _xmlSecNssPKIKeyDataCtx {
+ SECKEYPublicKey *pubkey;
+ SECKEYPrivateKey *privkey;
+};
+
+/******************************************************************************
+ *
+ * PKI key (dsa/rsa)
+ *
+ * xmlSecNssPKIKeyDataCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssPKIKeyDataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecNssPKIKeyDataCtx))
+#define xmlSecNssPKIKeyDataGetCtx(data) \
+ ((xmlSecNssPKIKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+
+static int xmlSecNssPKIKeyDataInitialize (xmlSecKeyDataPtr data);
+static void xmlSecNssPKIKeyDataFinalize (xmlSecKeyDataPtr data);
+
+
+static void xmlSecNSSPKIKeyDataCtxFree (xmlSecNssPKIKeyDataCtxPtr ctx);
+static int xmlSecNSSPKIKeyDataCtxDup (xmlSecNssPKIKeyDataCtxPtr ctxDst,
+ xmlSecNssPKIKeyDataCtxPtr ctxSrc);
+static int xmlSecNssPKIKeyDataAdoptKey (xmlSecKeyDataPtr data,
+ SECKEYPrivateKey *privkey,
+ SECKEYPublicKey *pubkey);
+
+
+static int
+xmlSecNssPKIKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), -1);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssPKIKeyDataCtx));
+
+ return(0);
+}
+
+
+static void
+xmlSecNssPKIKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize));
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecNSSPKIKeyDataCtxFree(ctx);
+ memset(ctx, 0, sizeof(xmlSecNssPKIKeyDataCtx));
+}
+
+
+static void
+xmlSecNSSPKIKeyDataCtxFree(xmlSecNssPKIKeyDataCtxPtr ctx)
+{
+ xmlSecAssert(ctx != NULL);
+ if (ctx->privkey != NULL) {
+ SECKEY_DestroyPrivateKey(ctx->privkey);
+ ctx->privkey = NULL;
+ }
+
+ if (ctx->pubkey)
+ {
+ SECKEY_DestroyPublicKey(ctx->pubkey);
+ ctx->pubkey = NULL;
+ }
+
+}
+
+static int
+xmlSecNSSPKIKeyDataCtxDup(xmlSecNssPKIKeyDataCtxPtr ctxDst,
+ xmlSecNssPKIKeyDataCtxPtr ctxSrc)
+{
+ xmlSecNSSPKIKeyDataCtxFree(ctxDst);
+ if (ctxSrc->privkey != NULL) {
+ ctxDst->privkey = SECKEY_CopyPrivateKey(ctxSrc->privkey);
+ if(ctxDst->privkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_CopyPrivateKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ if (ctxSrc->pubkey != NULL) {
+ ctxDst->pubkey = SECKEY_CopyPublicKey(ctxSrc->pubkey);
+ if(ctxDst->pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_CopyPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+ return (0);
+}
+
+static int
+xmlSecNssPKIKeyDataAdoptKey(xmlSecKeyDataPtr data,
+ SECKEYPrivateKey *privkey,
+ SECKEYPublicKey *pubkey)
+{
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ KeyType pubType = nullKey ;
+ KeyType priType = nullKey ;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), -1);
+
+ if( privkey != NULL ) {
+ priType = SECKEY_GetPrivateKeyType( privkey ) ;
+ }
+
+ if( pubkey != NULL ) {
+ pubType = SECKEY_GetPublicKeyType( pubkey ) ;
+ }
+
+ if( priType != nullKey && pubType != nullKey ) {
+ if( pubType != priType ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ "different type of private and public key" ) ;
+ return -1 ;
+ }
+ }
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if (ctx->privkey) {
+ SECKEY_DestroyPrivateKey(ctx->privkey);
+ }
+ ctx->privkey = privkey;
+
+ if (ctx->pubkey) {
+ SECKEY_DestroyPublicKey(ctx->pubkey);
+ }
+ ctx->pubkey = pubkey;
+
+ return(0);
+}
+
+/**
+ * xmlSecNssPKIAdoptKey:
+ * @privkey: the NSS Private Key handle
+ * @pubkey: the NSS Public Key handle
+ *
+ * Build a KeyData object from the given Private Key and Public
+ * Key handles.
+ *
+ * Returns: pointer to KeyData object or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecNssPKIAdoptKey(SECKEYPrivateKey *privkey,
+ SECKEYPublicKey *pubkey)
+{
+ xmlSecKeyDataPtr data = NULL;
+ int ret;
+ KeyType pubType = nullKey ;
+ KeyType priType = nullKey ;
+
+ if( privkey != NULL ) {
+ priType = SECKEY_GetPrivateKeyType( privkey ) ;
+ }
+
+ if( pubkey != NULL ) {
+ pubType = SECKEY_GetPublicKeyType( pubkey ) ;
+ }
+
+ if( priType != nullKey && pubType != nullKey ) {
+ if( pubType != priType ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ "different type of private and public key" ) ;
+ return( NULL ) ;
+ }
+ }
+
+ pubType = priType != nullKey ? priType : pubType ;
+ switch(pubType) {
+#ifndef XMLSEC_NO_RSA
+ case rsaKey:
+ data = xmlSecKeyDataCreate(xmlSecNssKeyDataRsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssKeyDataRsaId");
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_RSA */
+#ifndef XMLSEC_NO_DSA
+ case dsaKey:
+ data = xmlSecKeyDataCreate(xmlSecNssKeyDataDsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssKeyDataDsaId");
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_DSA */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "PKI key type %d not supported", pubType);
+ return(NULL);
+ }
+
+ xmlSecAssert2(data != NULL, NULL);
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+ return(data);
+}
+
+/**
+ * xmlSecNssPKIKeyDataGetPubKey:
+ * @data: the pointer to NSS Key data.
+ *
+ * Gets the Public Key from the key data.
+ *
+ * Returns: pointer to SECKEYPublicKey or NULL if an error occurs.
+ * Caller is responsible for freeing the key when done
+ */
+SECKEYPublicKey *
+xmlSecNssPKIKeyDataGetPubKey(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ SECKEYPublicKey *ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), NULL);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->pubkey != NULL, NULL);
+
+ ret = SECKEY_CopyPublicKey(ctx->pubkey);
+ return(ret);
+}
+
+/**
+ * xmlSecNssPKIKeyDataGetPrivKey:
+ * @data: the pointer to NSS Key data.
+ *
+ * Gets the Private Key from the key data.
+ *
+ * Returns: pointer to SECKEYPrivateKey or NULL if an error occurs.
+ * Caller is responsible for freeing the key when done
+ */
+SECKEYPrivateKey*
+xmlSecNssPKIKeyDataGetPrivKey(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ SECKEYPrivateKey* ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), NULL);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->privkey != NULL, NULL);
+
+ ret = SECKEY_CopyPrivateKey(ctx->privkey);
+ return(ret);
+}
+
+/**
+ * xmlSecNssPKIKeyDataGetKeyType:
+ * @data: the pointer to NSS Key data.
+ *
+ * Gets the Key Type from the key data.
+ *
+ * Returns: Key Type
+ */
+KeyType
+xmlSecNssPKIKeyDataGetKeyType(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ KeyType kt;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), nullKey);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), nullKey);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, nullKey);
+
+ if (ctx->pubkey != NULL) {
+ kt = SECKEY_GetPublicKeyType(ctx->pubkey);
+ } else {
+ kt = SECKEY_GetPrivateKeyType(ctx->privkey);
+ }
+ return(kt);
+}
+
+/**
+ * xmlSecNssPKIKeyDataDuplicate
+ * @dst: the pointer to NSS Key data to copy to.
+ * @src: the pointer to NSS Key data to copy from.
+ *
+ * Duplicates the keydata from src to dst
+ *
+ * Returns: -1 on error, 0 on success
+ */
+int
+xmlSecNssPKIKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecNssPKIKeyDataCtxPtr ctxDst;
+ xmlSecNssPKIKeyDataCtxPtr ctxSrc;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecNssPKIKeyDataSize), -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecNssPKIKeyDataSize), -1);
+
+ ctxDst = xmlSecNssPKIKeyDataGetCtx(dst);
+ xmlSecAssert2(ctxDst != NULL, -1);
+
+ ctxSrc = xmlSecNssPKIKeyDataGetCtx(src);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ if (xmlSecNSSPKIKeyDataCtxDup(ctxDst, ctxSrc) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssPKIKeydataCtxDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#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 xmlSecNssKeyDataDsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataDsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssKeyDataDsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataDsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataDsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataDsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecNssKeyDataDsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecNssKeyDataDsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecNssKeyDataDsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssKeyDataDsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataDsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecNssPKIKeyDataSize,
+
+ /* data */
+ xmlSecNameDSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssKeyDataDsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataDsaGetKlass(void) {
+ return(&xmlSecNssKeyDataDsaKlass);
+}
+
+
+static int
+xmlSecNssKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), -1);
+
+ return(xmlSecNssPKIKeyDataInitialize(data));
+}
+
+static int
+xmlSecNssKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataDsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataDsaId), -1);
+
+ return(xmlSecNssPKIKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecNssKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId));
+
+ xmlSecNssPKIKeyDataFinalize(data);
+}
+
+static int
+xmlSecNssKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data = NULL;
+ xmlNodePtr cur;
+ int ret;
+ PK11SlotInfo *slot = NULL;
+ CK_OBJECT_HANDLE handle;
+ SECKEYPublicKey *pubkey=NULL;
+ PRArenaPool *arena = NULL;
+
+
+ xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -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);
+ ret = -1;
+ goto done;
+ }
+
+ slot = PK11_GetBestSlot(CKM_DSA, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if(arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ ret = -1;
+ goto done;
+ }
+
+ pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(SECKEYPublicKey));
+ if(pubkey == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_ArenaZAlloc",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PORT_FreeArena(arena, PR_FALSE);
+ ret = -1;
+ goto done;
+ }
+ pubkey->arena = arena;
+ pubkey->u.dsa.params.arena = arena;
+ pubkey->keyType = dsaKey;
+
+ 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));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.params.prime)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ ret = -1;
+ goto done;
+ }
+ 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));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.params.subPrime)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ ret = -1;
+ goto done;
+ }
+ 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));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.params.base)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * NSS does not support it, we just ignore it */
+
+ 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));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.publicValue)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ ret = -1;
+ goto done;
+ }
+ 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);
+ ret = -1;
+ goto done;
+ }
+
+ handle = PK11_ImportPublicKey(slot, pubkey, PR_FALSE);
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pubkey = NULL;
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ data = NULL;
+
+ ret = 0;
+
+done:
+ if (slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if (ret != 0) {
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ }
+ return(ret);
+}
+
+static int
+xmlSecNssKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataDsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(xmlSecKeyGetValue(key));
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1);
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* first is P node */
+ 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 = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.params.prime), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ return(-1);
+ }
+
+ /* next is Q node. */
+ 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 = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.params.subPrime), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ return(-1);
+ }
+
+ /* next is G node. */
+ 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 = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.params.base), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ return(-1);
+ }
+
+ /* next is X node: not supported in NSS */
+
+ /* next is Y node. */
+ 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 = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.publicValue), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ PQGParams *pqgParams = NULL;
+ PQGVerify *pqgVerify = NULL;
+ SECStatus rv;
+ SECStatus res;
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ int ret = -1;
+ int j;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ j = PQG_PBITS_TO_INDEX(sizeBits);
+ rv = PK11_PQG_ParamGen(j, &pqgParams, &pqgVerify);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_PQG_ParamGen",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", sizeBits);
+ goto done;
+ }
+
+ rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &res);
+ if (rv != SECSuccess || res != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_PQG_VerifyParams",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", sizeBits);
+ goto done;
+ }
+
+ slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
+ PK11_Authenticate(slot, PR_TRUE, NULL /* default pwd callback */);
+ privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, pqgParams,
+ &pubkey, PR_FALSE, PR_TRUE, NULL);
+
+ if((privkey == NULL) || (pubkey == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_GenerateKeyPair",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if (pqgParams != NULL) {
+ PK11_PQG_DestroyParams(pqgParams);
+ }
+ if (pqgVerify != NULL) {
+ PK11_PQG_DestroyVerify(pqgVerify);
+ }
+ if (ret == 0) {
+ return (0);
+ }
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ return(-1);
+}
+
+static xmlSecKeyDataType
+xmlSecNssKeyDataDsaGetType(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), xmlSecKeyDataTypeUnknown);
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1);
+ if (ctx->privkey != NULL) {
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else {
+ return(xmlSecKeyDataTypePublic);
+ }
+
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecNssKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), 0);
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1);
+
+ return(8 * SECKEY_PublicKeyStrength(ctx->pubkey));
+}
+
+static void
+xmlSecNssKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== dsa key: size = %d\n",
+ xmlSecNssKeyDataDsaGetSize(data));
+}
+
+static void
+xmlSecNssKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
+ xmlSecNssKeyDataDsaGetSize(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 xmlSecNssKeyDataRsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataRsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssKeyDataRsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataRsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataRsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataRsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecNssKeyDataRsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecNssKeyDataRsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecNssKeyDataRsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssKeyDataRsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataRsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecNssPKIKeyDataSize,
+
+ /* data */
+ xmlSecNameRSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataRsaGetKlass:
+ *
+ * The RSA key data klass.
+ *
+ * Returns: pointer to RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataRsaGetKlass(void) {
+ return(&xmlSecNssKeyDataRsaKlass);
+}
+
+static int
+xmlSecNssKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), -1);
+
+ return(xmlSecNssPKIKeyDataInitialize(data));
+}
+
+static int
+xmlSecNssKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataRsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataRsaId), -1);
+
+ return(xmlSecNssPKIKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecNssKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId));
+
+ xmlSecNssPKIKeyDataFinalize(data);
+}
+
+static int
+xmlSecNssKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data = NULL;
+ xmlNodePtr cur;
+ int ret;
+ PK11SlotInfo *slot = NULL;
+ SECKEYPublicKey *pubkey=NULL;
+ PRArenaPool *arena = NULL;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -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");
+ ret = -1;
+ goto done;
+ }
+
+ slot = PK11_GetBestSlot(CKM_RSA_PKCS, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if(arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ ret = -1;
+ goto done;
+ }
+
+ pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(SECKEYPublicKey));
+ if(pubkey == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_ArenaZAlloc",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PORT_FreeArena(arena, PR_FALSE);
+ ret = -1;
+ goto done;
+ }
+ pubkey->arena = arena;
+ pubkey->keyType = rsaKey;
+
+ 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));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.rsa.modulus)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ ret = -1;
+ goto done;
+ }
+ 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));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.rsa.publicExponent)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * NSS does not support it. We just ignore it */
+ 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");
+ ret = -1;
+ goto done;
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ goto done;
+ }
+ pubkey = NULL;
+
+ 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);
+ goto done;
+ }
+ data = NULL;
+
+ ret = 0;
+
+done:
+ if (slot != 0) {
+ PK11_FreeSlot(slot);
+ }
+ if (ret != 0) {
+ if (pubkey != 0) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (data != 0) {
+ xmlSecKeyDataDestroy(data);
+ }
+ }
+ return(ret);
+}
+
+static int
+xmlSecNssKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataRsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(xmlSecKeyGetValue(key));
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -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 = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.rsa.modulus), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ 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 = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.rsa.publicExponent), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ return(-1);
+ }
+
+ /* next is PrivateExponent node: not supported in NSS */
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ PK11RSAGenParams params;
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ int ret = -1;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ params.keySizeInBits = sizeBits;
+ params.pe = 65537;
+
+ slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, NULL);
+ PK11_Authenticate(slot, PR_TRUE, NULL /* default pwd callback */);
+ privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &params,
+ &pubkey, PR_FALSE, PR_TRUE, NULL);
+
+ if(privkey == NULL || pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_GenerateKeyPair",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if (ret == 0) {
+ return (0);
+ }
+
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ return(-1);
+}
+
+static xmlSecKeyDataType
+xmlSecNssKeyDataRsaGetType(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), xmlSecKeyDataTypeUnknown);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pubkey == NULL || SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -1);
+ if (ctx->privkey != NULL) {
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else {
+ return(xmlSecKeyDataTypePublic);
+ }
+
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecNssKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), 0);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -1);
+
+ return(8 * SECKEY_PublicKeyStrength(ctx->pubkey));
+}
+
+static void
+xmlSecNssKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== rsa key: size = %d\n",
+ xmlSecNssKeyDataRsaGetSize(data));
+}
+
+static void
+xmlSecNssKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
+ xmlSecNssKeyDataRsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_RSA */
+
+
+
diff --git a/src/nss/signatures.c b/src/nss/signatures.c
new file mode 100644
index 00000000..3c9639c3
--- /dev/null
+++ b/src/nss/signatures.c
@@ -0,0 +1,550 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <secerr.h>
+#include <prmem.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/pkikeys.h>
+
+
+/**************************************************************************
+ *
+ * Internal NSS signatures ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssSignatureCtx xmlSecNssSignatureCtx,
+ *xmlSecNssSignatureCtxPtr;
+struct _xmlSecNssSignatureCtx {
+ xmlSecKeyDataId keyId;
+ SECOidTag alg;
+
+ union {
+ struct {
+ SGNContext *sigctx;
+ SECKEYPrivateKey *privkey;
+ } sig;
+
+ struct {
+ VFYContext *vfyctx;
+ SECKEYPublicKey *pubkey;
+ } vfy;
+ } u;
+};
+
+/******************************************************************************
+ *
+ * Signature transforms
+ *
+ * xmlSecNssSignatureCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssSignatureSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssSignatureCtx))
+#define xmlSecNssSignatureGetCtx(transform) \
+ ((xmlSecNssSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssSignatureCheckId (xmlSecTransformPtr transform);
+static int xmlSecNssSignatureInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssSignatureFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssSignatureSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssSignatureSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssSignatureVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssSignatureExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecNssSignatureCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformDsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_RSA */
+
+ return(0);
+}
+
+static int
+xmlSecNssSignatureInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssSignatureCtx));
+
+#ifndef XMLSEC_NO_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformDsaSha1Id)) {
+ ctx->keyId = xmlSecNssKeyDataDsaId;
+
+ /* This creates a signature which is ASN1 encoded */
+ /*ctx->alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;*/
+
+ /* Fortezza uses the same DSA signature format as XML does.
+ * DSA and FORTEZZA keys are treated as equivalent keys for doing
+ * DSA signatures (which is how they are supposed to be treated).
+ */
+ ctx->alg = SEC_OID_MISSI_DSS;
+ } else
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha1Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+ } else
+#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);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssSignatureFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssSignatureCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssSignatureCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize));
+ xmlSecAssert((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify));
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (transform->operation == xmlSecTransformOperationSign) {
+ SGN_DestroyContext(ctx->u.sig.sigctx, PR_TRUE);
+ if (ctx->u.sig.privkey) {
+ SECKEY_DestroyPrivateKey(ctx->u.sig.privkey);
+ }
+ } else {
+ VFY_DestroyContext(ctx->u.vfy.vfyctx, PR_TRUE);
+ if (ctx->u.vfy.pubkey) {
+ SECKEY_DestroyPublicKey(ctx->u.vfy.pubkey);
+ }
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssSignatureCtx));
+}
+
+static int
+xmlSecNssSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssSignatureCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(value != NULL, -1);
+
+ if (transform->operation == xmlSecTransformOperationSign) {
+ if (ctx->u.sig.privkey)
+ SECKEY_DestroyPrivateKey(ctx->u.sig.privkey);
+ ctx->u.sig.privkey = xmlSecNssPKIKeyDataGetPrivKey(value);
+ if(ctx->u.sig.privkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssPKIKeyDataGetPrivKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->u.sig.sigctx = SGN_NewContext(ctx->alg, ctx->u.sig.privkey);
+ if (ctx->u.sig.sigctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_NewContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ } else {
+ if (ctx->u.vfy.pubkey)
+ SECKEY_DestroyPublicKey(ctx->u.vfy.pubkey);
+ ctx->u.vfy.pubkey = xmlSecNssPKIKeyDataGetPubKey(value);
+ if(ctx->u.vfy.pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssPKIKeyDataGetPubKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->u.vfy.vfyctx = VFY_CreateContext(ctx->u.vfy.pubkey, NULL,
+ ctx->alg, NULL);
+ if (ctx->u.vfy.vfyctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_CreateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(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
+xmlSecNssSignatureVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssSignatureCtxPtr ctx;
+ SECStatus status;
+ SECItem signature;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ signature.data = (unsigned char *)data;
+ signature.len = dataSize;
+ status = VFY_EndWithSignature(ctx->u.vfy.vfyctx, &signature);
+
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_Update, VFY_End",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+
+ if (PORT_GetError() == SEC_ERROR_PKCS7_BAD_SIGNATURE) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_End",
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "signature does not verify");
+ transform->status = xmlSecTransformStatusFail;
+ }
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecNssSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssSignatureCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ SECStatus status;
+ SECItem signature;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ if(transform->operation == xmlSecTransformOperationSign) {
+ xmlSecAssert2(ctx->u.sig.sigctx != NULL, -1);
+ xmlSecAssert2(ctx->u.sig.privkey != NULL, -1);
+ } else {
+ xmlSecAssert2(ctx->u.vfy.vfyctx != NULL, -1);
+ xmlSecAssert2(ctx->u.vfy.pubkey != NULL, -1);
+ }
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ status = SGN_Begin(ctx->u.sig.sigctx);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_Begin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ } else {
+ status = VFY_Begin(ctx->u.vfy.vfyctx);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_Begin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (inSize > 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ status = SGN_Update(ctx->u.sig.sigctx, xmlSecBufferGetData(in), inSize);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_Update",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ } else {
+ status = VFY_Update(ctx->u.vfy.vfyctx, xmlSecBufferGetData(in), inSize);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_Update",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ 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) {
+ memset(&signature, 0, sizeof(signature));
+ status = SGN_End(ctx->u.sig.sigctx, &signature);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_End",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ outSize = signature.len;
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ PR_Free(signature.data);
+ return(-1);
+ }
+
+ memcpy(xmlSecBufferGetData(out), signature.data, signature.len);
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ PR_Free(signature.data);
+ return(-1);
+ }
+ PR_Free(signature.data);
+ }
+ 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
+/****************************************************************************
+ *
+ * DSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+
+static xmlSecTransformKlass xmlSecNssDsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameDsaSha1, /* const xmlChar* name; */
+ xmlSecHrefDsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformDsaSha1GetKlass(void) {
+ return(&xmlSecNssDsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha1, /* const xmlChar* name; */
+ xmlSecHrefRsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha1GetKlass(void) {
+ return(&xmlSecNssRsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+
diff --git a/src/nss/symkeys.c b/src/nss/symkeys.c
new file mode 100644
index 00000000..fb23f4fd
--- /dev/null
+++ b/src/nss/symkeys.c
@@ -0,0 +1,440 @@
+/**
+ *
+ * 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 <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/nss/crypto.h>
+
+/*****************************************************************************
+ *
+ * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary
+ *
+ ****************************************************************************/
+static int xmlSecNssSymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecNssSymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssSymKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecNssSymKeyDataXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlSecByte** buf,
+ xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecNssSymKeyDataGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecNssSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecNssSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecNssSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+#define xmlSecNssSymKeyDataCheckId(data) \
+ (xmlSecKeyDataIsValid((data)) && \
+ xmlSecNssSymKeyDataKlassCheck((data)->id))
+
+static int
+xmlSecNssSymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), -1);
+
+ return(xmlSecKeyDataBinaryValueInitialize(data));
+}
+
+static int
+xmlSecNssSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(dst), -1);
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ return(xmlSecKeyDataBinaryValueDuplicate(dst, src));
+}
+
+static void
+xmlSecNssSymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecNssSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueFinalize(data);
+}
+
+static int
+xmlSecNssSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecNssGenerateRandom(buffer, (sizeBits + 7) / 8));
+}
+
+static xmlSecKeyDataType
+xmlSecNssSymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown);
+
+ return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecNssSymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), 0);
+
+ return(xmlSecKeyDataBinaryValueGetSize(data));
+}
+
+static void
+xmlSecNssSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecNssSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugDump(data, output);
+}
+
+static void
+xmlSecNssSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecNssSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugXmlDump(data, output);
+}
+
+static int
+xmlSecNssSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) {
+#ifndef XMLSEC_NO_DES
+ if(klass == xmlSecNssKeyDataDesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(klass == xmlSecNssKeyDataAesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_HMAC
+ if(klass == xmlSecNssKeyDataHmacId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_HMAC */
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_AES
+/**************************************************************************
+ *
+ * <xmlsec:AESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecNssKeyDataAesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameAESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefAESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecNssSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataAesGetKlass(void) {
+ return(&xmlSecNssKeyDataAesKlass);
+}
+
+/**
+ * xmlSecNssKeyDataAesSet:
+ * @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
+xmlSecNssKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataAesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**************************************************************************
+ *
+ * <xmlsec:DESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecNssKeyDataDesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameDESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecNssSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataDesGetKlass(void) {
+ return(&xmlSecNssKeyDataDesKlass);
+}
+
+/**
+ * xmlSecNssKeyDataDesSet:
+ * @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
+xmlSecNssKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDesId), -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 xmlSecNssKeyDataHmacKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameHMACKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefHMACKeyValue, /* const xmlChar* href; */
+ xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecNssSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataHmacGetKlass(void) {
+ return(&xmlSecNssKeyDataHmacKlass);
+}
+
+/**
+ * xmlSecNssKeyDataHmacSet:
+ * @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
+xmlSecNssKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataHmacId), -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/nss/x509.c b/src/nss/x509.c
new file mode 100644
index 00000000..aea40122
--- /dev/null
+++ b/src/nss/x509.c
@@ -0,0 +1,2205 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#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 <prmem.h>
+#include <pratom.h>
+#include <keyhi.h>
+#include <cert.h>
+#include <certdb.h>
+#include <pk11func.h>
+
+#include <libxml/tree.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/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+#include <xmlsec/nss/pkikeys.h>
+
+
+/* workaround - NSS exports this but doesn't declare it */
+extern CERTCertificate * __CERT_NewTempCertificate(CERTCertDBHandle *handle,
+ SECItem *derCert,
+ char *nickname,
+ PRBool isperm,
+ PRBool copyDER);
+
+/*************************************************************************
+ *
+ * X509 utility functions
+ *
+ ************************************************************************/
+static int xmlSecNssX509DataNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CertificateNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CertificateNodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SubjectNameNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SubjectNameNodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509IssuerSerialNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509IssuerSerialNodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SKINodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SKINodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CRLNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CRLNodeWrite (CERTSignedCrl* crl,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data,
+ xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static CERTCertificate* xmlSecNssX509CertDerRead (const xmlSecByte* buf,
+ xmlSecSize size);
+static CERTCertificate* xmlSecNssX509CertBase64DerRead (xmlChar* buf);
+static xmlChar* xmlSecNssX509CertBase64DerWrite (CERTCertificate* cert,
+ int base64LineWrap);
+static CERTSignedCrl* xmlSecNssX509CrlDerRead (xmlSecByte* buf,
+ xmlSecSize size,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static CERTSignedCrl* xmlSecNssX509CrlBase64DerRead (xmlChar* buf,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlChar* xmlSecNssX509CrlBase64DerWrite (CERTSignedCrl* crl,
+ int base64LineWrap);
+static xmlChar* xmlSecNssX509NameWrite (CERTName* nm);
+static xmlChar* xmlSecNssASN1IntegerWrite (SECItem *num);
+static xmlChar* xmlSecNssX509SKIWrite (CERTCertificate* cert);
+static void xmlSecNssX509CertDebugDump (CERTCertificate* cert,
+ FILE* output);
+static void xmlSecNssX509CertDebugXmlDump (CERTCertificate* cert,
+ FILE* output);
+static int xmlSecNssX509CertGetTime (PRTime* t,
+ time_t* res);
+
+/*************************************************************************
+ *
+ * Internal NSS X509 data CTX
+ *
+ ************************************************************************/
+typedef struct _xmlSecNssX509DataCtx xmlSecNssX509DataCtx,
+ *xmlSecNssX509DataCtxPtr;
+typedef struct _xmlSecNssX509CrlNode xmlSecNssX509CrlNode,
+ *xmlSecNssX509CrlNodePtr;
+struct _xmlSecNssX509CrlNode {
+ xmlSecNssX509CrlNodePtr next;
+ CERTSignedCrl *crl;
+};
+
+struct _xmlSecNssX509DataCtx {
+ CERTCertificate* keyCert;
+
+ CERTCertList* certsList;
+ unsigned int numCerts;
+
+ xmlSecNssX509CrlNodePtr crlsList;
+ unsigned int numCrls;
+};
+
+/**************************************************************************
+ *
+ * <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) >
+ *
+ * -----------------------------------------------------------------------
+ *
+ * xmlSecNssX509DataCtx is located after xmlSecTransform
+ *
+ *************************************************************************/
+#define xmlSecNssX509DataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecNssX509DataCtx))
+#define xmlSecNssX509DataGetCtx(data) \
+ ((xmlSecNssX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecNssKeyDataX509Initialize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataX509Duplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssKeyDataX509Finalize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataX509XmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataX509XmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyDataType xmlSecNssKeyDataX509GetType (xmlSecKeyDataPtr data);
+static const xmlChar* xmlSecNssKeyDataX509GetIdentifier (xmlSecKeyDataPtr data);
+
+static void xmlSecNssKeyDataX509DebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data,
+ FILE* output);
+
+
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataX509Klass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecNssX509DataSize,
+
+ /* data */
+ xmlSecNameX509Data,
+ xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefX509Data, /* const xmlChar* href; */
+ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ xmlSecNssKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataX509GetKlass:
+ *
+ * The NSS X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data).
+ *
+ * Returns: the X509 data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataX509GetKlass(void) {
+ return(&xmlSecNssKeyDataX509Klass);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetKeyCert:
+ * @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.
+ */
+CERTCertificate*
+xmlSecNssKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->keyCert);
+}
+
+/**
+ * xmlSecNssKeyDataX509AdoptKeyCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to NSS X509 certificate.
+ *
+ * Sets the key's certificate in @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, CERTCertificate* cert) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->keyCert != NULL) {
+ CERT_DestroyCertificate(ctx->keyCert);
+ }
+ ctx->keyCert = cert;
+ return(0);
+}
+
+/**
+ * xmlSecNssKeyDataX509AdoptCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to NSS X509 certificate.
+ *
+ * Adds certificate to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataX509AdoptCert(xmlSecKeyDataPtr data, CERTCertificate* cert) {
+ xmlSecNssX509DataCtxPtr ctx;
+ SECStatus ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->certsList == NULL) {
+ ctx->certsList = CERT_NewCertList();
+ if(ctx->certsList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CERT_NewCertList",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ ret = CERT_AddCertToListTail(ctx->certsList, cert);
+ if(ret != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CERT_AddCertToListTail",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ ctx->numCerts++;
+
+ return(0);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCert:
+ * @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.
+ */
+CERTCertificate*
+xmlSecNssKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecNssX509DataCtxPtr ctx;
+ CERTCertListNode* head;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->certsList != NULL, NULL);
+ xmlSecAssert2(pos < ctx->numCerts, NULL);
+
+ head = CERT_LIST_HEAD(ctx->certsList);
+ while (pos > 0)
+ {
+ head = CERT_LIST_NEXT(head);
+ pos--;
+ }
+
+ return (head->cert);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCertsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of certificates in @data.
+ *
+ * Returns: te number of certificates in @data.
+ */
+xmlSecSize
+xmlSecNssKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), 0);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->numCerts);
+}
+
+/**
+ * xmlSecNssKeyDataX509AdoptCrl:
+ * @data: the pointer to X509 key data.
+ * @crl: the pointer to NSS X509 CRL.
+ *
+ * Adds CRL to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, CERTSignedCrl* crl) {
+ xmlSecNssX509DataCtxPtr ctx;
+ xmlSecNssX509CrlNodePtr crlnode;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(crl != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ crlnode = (xmlSecNssX509CrlNodePtr)PR_Malloc(sizeof(xmlSecNssX509CrlNode));
+
+ if(crlnode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PR_Malloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ memset(crlnode, 0, sizeof(xmlSecNssX509CrlNode));
+ crlnode->next = ctx->crlsList;
+ crlnode->crl = crl;
+ ctx->crlsList = crlnode;
+ ctx->numCrls++;
+
+ return(0);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCrl:
+ * @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.
+ */
+CERTSignedCrl *
+xmlSecNssKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecNssX509DataCtxPtr ctx;
+ xmlSecNssX509CrlNodePtr head;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ xmlSecAssert2(ctx->crlsList != NULL, NULL);
+ xmlSecAssert2(pos < ctx->numCrls, NULL);
+
+ head = ctx->crlsList;
+ while (pos > 0)
+ {
+ head = head->next;
+ pos--;
+ }
+
+ return (head->crl);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCrlsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of CRLs in @data.
+ *
+ * Returns: te number of CRLs in @data.
+ */
+xmlSecSize
+xmlSecNssKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), 0);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->numCrls);
+}
+
+static int
+xmlSecNssKeyDataX509Initialize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssX509DataCtx));
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ CERTCertificate* certSrc;
+ CERTCertificate* certDst;
+ CERTSignedCrl* crlSrc;
+ CERTSignedCrl* crlDst;
+ xmlSecSize size, pos;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataX509Id), -1);
+
+ /* copy certsList */
+ size = xmlSecNssKeyDataX509GetCertsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ /* TBD: function below does linear scan, eliminate loop within
+ * loop
+ */
+ certSrc = xmlSecNssKeyDataX509GetCert(src, pos);
+ if(certSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ certDst = CERT_DupCertificate(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(certDst);
+ return(-1);
+ }
+ }
+
+ /* copy crls */
+ size = xmlSecNssKeyDataX509GetCrlsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ crlSrc = xmlSecNssKeyDataX509GetCrl(src, pos);
+ if(crlSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecNssKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ /* TBD: SEC_DupCrl isn't exported by NSS yet */
+ /*crlDst = SEC_DupCrl(crlSrc);*/
+ crlDst = crlSrc;
+ PR_AtomicIncrement(&(crlSrc->referenceCount));
+
+ if(crlDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "SEC_DupCrl",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCrl(dst, crlDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SEC_DestroyCrl(crlDst);
+ return(-1);
+ }
+ }
+
+ /* copy key cert if exist */
+ certSrc = xmlSecNssKeyDataX509GetKeyCert(src);
+ if(certSrc != NULL) {
+ certDst = CERT_DupCertificate(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ ret = xmlSecNssKeyDataX509AdoptKeyCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(certDst);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static void
+xmlSecNssKeyDataX509Finalize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id));
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->certsList != NULL) {
+ CERT_DestroyCertList(ctx->certsList);
+ }
+
+ if(ctx->crlsList != NULL) {
+ xmlSecNssX509CrlNodePtr head;
+ xmlSecNssX509CrlNodePtr tmp;
+
+ head = ctx->crlsList;
+ while (head)
+ {
+ tmp = head->next;
+ SEC_DestroyCrl(head->crl);
+ PR_Free(head);
+ head = tmp;
+ }
+ }
+
+ if(ctx->keyCert != NULL) {
+ CERT_DestroyCertificate(ctx->keyCert);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssX509DataCtx));
+}
+
+static int
+xmlSecNssKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataX509Id, -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 = xmlSecNssX509DataNodeRead(data, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509DataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
+ ret = xmlSecNssKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ CERTCertificate* cert;
+ CERTSignedCrl* crl;
+ xmlSecSize size, pos;
+ int content = 0;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataX509Id, -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 = xmlSecNssKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecNssKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) {
+ ret = xmlSecNssX509CertificateNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509CertificateNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) {
+ ret = xmlSecNssX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509SubjectNameNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) {
+ ret = xmlSecNssX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509IssuerSerialNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SKI_NODE) != 0) {
+ ret = xmlSecNssX509SKINodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509SKINodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ /* write crls if needed */
+ if((content & XMLSEC_X509DATA_CRL_NODE) != 0) {
+ size = xmlSecNssKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ crl = xmlSecNssKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ ret = xmlSecNssX509CRLNodeWrite(crl, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509CRLNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+static xmlSecKeyDataType
+xmlSecNssKeyDataX509GetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), xmlSecKeyDataTypeUnknown);
+
+ /* TODO: return verified/not verified status */
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static const xmlChar*
+xmlSecNssKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+
+ /* TODO */
+ return(NULL);
+}
+
+static void
+xmlSecNssKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ CERTCertificate* cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== X509 Data:\n");
+ cert = xmlSecNssKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "==== Key Certificate:\n");
+ xmlSecNssX509CertDebugDump(cert, output);
+ }
+
+ size = xmlSecNssKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecNssKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "==== Certificate:\n");
+ xmlSecNssX509CertDebugDump(cert, output);
+ }
+
+ /* we don't print out crls */
+}
+
+static void
+xmlSecNssKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ CERTCertificate* cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<X509Data>\n");
+ cert = xmlSecNssKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "<KeyCertificate>\n");
+ xmlSecNssX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</KeyCertificate>\n");
+ }
+
+ size = xmlSecNssKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecNssKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "<Certificate>\n");
+ xmlSecNssX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</Certificate>\n");
+ }
+
+ /* we don't print out crls */
+ fprintf(output, "</X509Data>\n");
+}
+
+static int
+xmlSecNssX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -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 = xmlSecNssX509CertificateNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+ ret = xmlSecNssX509SubjectNameNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+ ret = xmlSecNssX509IssuerSerialNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+ ret = xmlSecNssX509SKINodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+ ret = xmlSecNssX509CRLNodeRead(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
+xmlSecNssX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -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 = xmlSecNssX509CertBase64DerRead(content);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecNssX509CertificateNodeWrite(CERTCertificate* 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 = xmlSecNssX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CertBase64DerWrite",
+ 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
+xmlSecNssX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* subject;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ 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 = xmlSecNssX509StoreFindCert(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);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+}
+
+static int
+xmlSecNssX509SubjectNameNodeWrite(CERTCertificate* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecNssX509NameWrite(&(cert->subject));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameWrite(&(cert->subject))",
+ 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
+xmlSecNssX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlNodePtr cur;
+ xmlChar *issuerName;
+ xmlChar *issuerSerial;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ 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 = xmlSecNssX509StoreFindCert(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);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+}
+
+static int
+xmlSecNssX509IssuerSerialNodeWrite(CERTCertificate* 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 = xmlSecNssX509NameWrite(&(cert->issuer));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameWrite(&(cert->issuer))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNameNode, buf);
+ xmlFree(buf);
+
+ buf = xmlSecNssASN1IntegerWrite(&(cert->serialNumber));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssASN1IntegerWrite(&(cert->serialNumber))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlNodeSetContent(issuerNumberNode, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+static int
+xmlSecNssX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* ski;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ 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 = xmlSecNssX509StoreFindCert(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);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ xmlFree(ski);
+ return(0);
+}
+
+static int
+xmlSecNssX509SKINodeWrite(CERTCertificate* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar *buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecNssX509SKIWrite(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509SKIWrite",
+ 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
+xmlSecNssX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ CERTSignedCrl* crl;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -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 = xmlSecNssX509CrlBase64DerRead(content, keyInfoCtx);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CrlBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ SEC_DestroyCrl(crl);
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecNssX509CRLNodeWrite(CERTSignedCrl* 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 = xmlSecNssX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CrlBase64DerWrite",
+ 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
+xmlSecNssKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecNssX509DataCtxPtr ctx;
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+ SECStatus status;
+ PRTime notBefore, notAfter;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ 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)) {
+ CERTCertificate* cert;
+
+ cert = xmlSecNssX509StoreVerify(x509Store, ctx->certsList, keyInfoCtx);
+ if(cert != NULL) {
+ xmlSecKeyDataPtr keyValue;
+
+ ctx->keyCert = CERT_DupCertificate(cert);
+ if(ctx->keyCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ keyValue = xmlSecNssX509CertGetKey(ctx->keyCert);
+ if(keyValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertGetKey",
+ 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);
+ }
+
+ status = CERT_GetCertTimes(ctx->keyCert, &notBefore, &notAfter);
+ if (status == SECSuccess) {
+ ret = xmlSecNssX509CertGetTime(&notBefore, &(key->notValidBefore));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidBefore");
+ return(-1);
+ }
+ ret = xmlSecNssX509CertGetTime(&notAfter, &(key->notValidAfter));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertGetTime",
+ 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);
+}
+
+static int
+xmlSecNssX509CertGetTime(PRTime* t, time_t* res) {
+
+ PRTime tmp64_1, tmp64_2;
+ PRUint32 tmp32 = 1000000;
+
+ xmlSecAssert2(t != NULL, -1);
+ xmlSecAssert2(res != NULL, -1);
+
+ /* PRTime is time in microseconds since epoch. Divide by 1000000 to
+ * convert to seconds, then convert to an unsigned 32 bit number
+ */
+ (*res) = 0;
+ LL_UI2L(tmp64_1, tmp32);
+ LL_DIV(tmp64_2, *t, tmp64_1);
+ LL_L2UI(tmp32, tmp64_2);
+
+ (*res) = (time_t)(tmp32);
+
+ return(0);
+}
+
+/**
+ * xmlSecNssX509CertGetKey:
+ * @cert: the certificate.
+ *
+ * Extracts public key from the @cert.
+ *
+ * Returns: public key value or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecNssX509CertGetKey(CERTCertificate* cert) {
+ xmlSecKeyDataPtr data;
+ SECKEYPublicKey *pubkey = NULL;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ pubkey = CERT_ExtractPublicKey(cert);
+ if(pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(NULL);
+ }
+
+ data = xmlSecNssPKIAdoptKey(NULL, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECKEY_DestroyPublicKey(pubkey);
+ return(NULL);
+ }
+
+ return(data);
+}
+
+static CERTCertificate*
+xmlSecNssX509CertBase64DerRead(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(xmlSecNssX509CertDerRead((xmlSecByte*)buf, ret));
+}
+
+
+static CERTCertificate*
+xmlSecNssX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
+ CERTCertificate *cert;
+ SECItem derCert;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ derCert.data = (unsigned char *)buf;
+ derCert.len = size;
+
+ /* decode cert and import to temporary cert db */
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
+ NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(NULL);
+ }
+
+
+ return(cert);
+}
+
+static xmlChar*
+xmlSecNssX509CertBase64DerWrite(CERTCertificate* cert, int base64LineWrap) {
+ xmlChar *res = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ p = cert->derCert.data;
+ size = cert->derCert.len;
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cert->derCert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ 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);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+static CERTSignedCrl*
+xmlSecNssX509CrlBase64DerRead(xmlChar* buf,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ 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(xmlSecNssX509CrlDerRead((xmlSecByte*)buf, ret, keyInfoCtx));
+}
+
+
+static CERTSignedCrl*
+xmlSecNssX509CrlDerRead(xmlSecByte* buf, xmlSecSize size,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ CERTSignedCrl *crl = NULL;
+ SECItem derCrl;
+ PK11SlotInfo *slot = NULL;
+ PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ derCrl.data = buf;
+ derCrl.len = size;
+
+ /* we're importing a CRL, it is ok to use the internal slot.
+ * crlutil does it :)
+ */
+ slot = xmlSecNssGetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetInternalKeySlot",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return NULL;
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS) != 0)
+ importOptions |= CRL_IMPORT_BYPASS_CHECKS;
+
+ crl = PK11_ImportCRL(slot, &derCrl, NULL, SEC_CRL_TYPE, NULL,
+ importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
+
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportCRL",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PK11_FreeSlot(slot);
+ return(NULL);
+ }
+
+ PK11_FreeSlot(slot);
+ return(crl);
+}
+
+static xmlChar*
+xmlSecNssX509CrlBase64DerWrite(CERTSignedCrl* crl, int base64LineWrap) {
+ xmlChar *res = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(crl != NULL && crl->derCrl != NULL, NULL);
+
+ p = crl->derCrl->data;
+ size = crl->derCrl->len;
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "crl->derCrl",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ 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);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+static xmlChar*
+xmlSecNssX509NameWrite(CERTName* nm) {
+ xmlChar *res = NULL;
+ char *str;
+
+ xmlSecAssert2(nm != NULL, NULL);
+
+ str = CERT_NameToAscii(nm);
+ if (str == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_NameToAscii",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlStrdup(BAD_CAST str);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PORT_Free(str);
+ return(NULL);
+ }
+ PORT_Free(str);
+ return(res);
+}
+
+static xmlChar*
+xmlSecNssASN1IntegerWrite(SECItem *num) {
+ xmlChar *res = NULL;
+
+ xmlSecAssert2(num != NULL, NULL);
+
+ /* TODO : to be implemented after
+ * NSS bug http://bugzilla.mozilla.org/show_bug.cgi?id=212864 is fixed
+ */
+ return(res);
+}
+
+static xmlChar*
+xmlSecNssX509SKIWrite(CERTCertificate* cert) {
+ xmlChar *res = NULL;
+ SECItem ski;
+ SECStatus rv;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ memset(&ski, 0, sizeof(ski));
+
+ rv = CERT_FindSubjectKeyIDExtension(cert, &ski);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_FindSubjectKeyIDExtension",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&ski, PR_FALSE);
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(ski.data, ski.len, 0);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&ski, PR_FALSE);
+ return(NULL);
+ }
+ SECITEM_FreeItem(&ski, PR_FALSE);
+
+ return(res);
+}
+
+
+static void
+xmlSecNssX509CertDebugDump(CERTCertificate* cert, FILE* output) {
+ SECItem *sn;
+ unsigned int i;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "==== Subject Name: %s\n", cert->subjectName);
+ fprintf(output, "==== Issuer Name: %s\n", cert->issuerName);
+ sn = &cert->serialNumber;
+
+ for (i = 0; i < sn->len; i++) {
+ if (i != sn->len - 1) {
+ fprintf(output, "%02x:", sn->data[i]);
+ } else {
+ fprintf(output, "%02x", sn->data[i]);
+ }
+ }
+ fprintf(output, "\n");
+}
+
+
+static void
+xmlSecNssX509CertDebugXmlDump(CERTCertificate* cert, FILE* output) {
+ SECItem *sn;
+ unsigned int i;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<SubjectName>");
+ xmlSecPrintXmlString(output, BAD_CAST cert->subjectName);
+ fprintf(output, "</SubjectName>\n");
+
+ fprintf(output, "<IssuerName>");
+ xmlSecPrintXmlString(output, BAD_CAST cert->issuerName);
+ fprintf(output, "</IssuerName>\n");
+
+ fprintf(output, "<SerialNumber>");
+ sn = &cert->serialNumber;
+ for (i = 0; i < sn->len; i++) {
+ if (i != sn->len - 1) {
+ fprintf(output, "%02x:", sn->data[i]);
+ } else {
+ fprintf(output, "%02x", sn->data[i]);
+ }
+ }
+ fprintf(output, "</SerialNumber>\n");
+}
+
+
+/**************************************************************************
+ *
+ * Raw X509 Certificate processing
+ *
+ *
+ *************************************************************************/
+static int xmlSecNssKeyDataRawX509CertBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataRawX509CertKlass = {
+ 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; */
+ xmlSecNssKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 certificates key data klass.
+ *
+ * Returns: raw X509 certificates key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataRawX509CertGetKlass(void) {
+ return(&xmlSecNssKeyDataRawX509CertKlass);
+}
+
+static int
+xmlSecNssKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataRawX509CertId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ cert = xmlSecNssX509CertDerRead(buf, bufSize);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CertDerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/nss/x509vfy.c b/src/nss/x509vfy.c
new file mode 100644
index 00000000..25bf5042
--- /dev/null
+++ b/src/nss/x509vfy.c
@@ -0,0 +1,704 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <cert.h>
+#include <secerr.h>
+
+#include <libxml/tree.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/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+
+/**************************************************************************
+ *
+ * Internal NSS X509 store CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecNssX509StoreCtx xmlSecNssX509StoreCtx,
+ *xmlSecNssX509StoreCtxPtr;
+struct _xmlSecNssX509StoreCtx {
+ CERTCertList* certsList; /* just keeping a reference to destroy later */
+};
+
+/****************************************************************************
+ *
+ * xmlSecNssKeyDataStoreX509Id:
+ *
+ * xmlSecNssX509StoreCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecNssX509StoreGetCtx(store) \
+ ((xmlSecNssX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
+ sizeof(xmlSecKeyDataStoreKlass)))
+#define xmlSecNssX509StoreSize \
+ (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecNssX509StoreCtx))
+
+static int xmlSecNssX509StoreInitialize (xmlSecKeyDataStorePtr store);
+static void xmlSecNssX509StoreFinalize (xmlSecKeyDataStorePtr store);
+static int xmlSecNssX509NameStringRead (xmlSecByte **str,
+ int *strLen,
+ xmlSecByte *res,
+ int resLen,
+ xmlSecByte delim,
+ int ingoreTrailingSpaces);
+static xmlSecByte * xmlSecNssX509NameRead (xmlSecByte *str,
+ int len);
+
+static void xmlSecNssNumToItem(SECItem *it, unsigned long num);
+
+
+static xmlSecKeyDataStoreKlass xmlSecNssX509StoreKlass = {
+ sizeof(xmlSecKeyDataStoreKlass),
+ xmlSecNssX509StoreSize,
+
+ /* data */
+ xmlSecNameX509Store, /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecNssX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
+ xmlSecNssX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static CERTCertificate* xmlSecNssX509FindCert(xmlChar *subjectName,
+ xmlChar *issuerName,
+ xmlChar *issuerSerial,
+ xmlChar *ski);
+
+
+/**
+ * xmlSecNssX509StoreGetKlass:
+ *
+ * The NSS X509 certificates key data store klass.
+ *
+ * Returns: pointer to NSS X509 certificates key data store klass.
+ */
+xmlSecKeyDataStoreId
+xmlSecNssX509StoreGetKlass(void) {
+ return(&xmlSecNssX509StoreKlass);
+}
+
+/**
+ * xmlSecNssX509StoreFindCert:
+ * @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.
+ */
+CERTCertificate *
+xmlSecNssX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
+ xmlChar *issuerName, xmlChar *issuerSerial,
+ xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecNssX509StoreCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(xmlSecNssX509FindCert(subjectName, issuerName, issuerSerial, ski));
+}
+
+/**
+ * xmlSecNssX509StoreVerify:
+ * @store: the pointer to X509 key data store klass.
+ * @certs: the untrusted certificates stack.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Verifies @certs list.
+ *
+ * Returns: pointer to the first verified certificate from @certs.
+ */
+CERTCertificate *
+xmlSecNssX509StoreVerify(xmlSecKeyDataStorePtr store, CERTCertList* certs,
+ xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ CERTCertListNode* head;
+ CERTCertificate* cert = NULL;
+ CERTCertListNode* head1;
+ CERTCertificate* cert1 = NULL;
+ SECStatus status = SECFailure;
+ int64 timeboundary;
+ int64 tmp1, tmp2;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), NULL);
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ for (head = CERT_LIST_HEAD(certs);
+ !CERT_LIST_END(head, certs);
+ head = CERT_LIST_NEXT(head)) {
+ cert = head->cert;
+ if(keyInfoCtx->certsVerificationTime > 0) {
+ /* convert the time since epoch in seconds to microseconds */
+ LL_UI2L(timeboundary, keyInfoCtx->certsVerificationTime);
+ tmp1 = (int64)PR_USEC_PER_SEC;
+ tmp2 = timeboundary;
+ LL_MUL(timeboundary, tmp1, tmp2);
+ } else {
+ timeboundary = PR_Now();
+ }
+
+ /* if cert is the issuer of any other cert in the list, then it is
+ * to be skipped */
+ for (head1 = CERT_LIST_HEAD(certs);
+ !CERT_LIST_END(head1, certs);
+ head1 = CERT_LIST_NEXT(head1)) {
+
+ cert1 = head1->cert;
+ if (cert1 == cert) {
+ continue;
+ }
+
+ if (SECITEM_CompareItem(&cert1->derIssuer, &cert->derSubject)
+ == SECEqual) {
+ break;
+ }
+ }
+
+ if (!CERT_LIST_END(head1, certs)) {
+ continue;
+ }
+
+ status = CERT_VerifyCertificate(CERT_GetDefaultCertDB(),
+ cert, PR_FALSE,
+ (SECCertificateUsage)0,
+ timeboundary , NULL, NULL, NULL);
+ if (status == SECSuccess) {
+ break;
+ }
+ }
+
+ if (status == SECSuccess) {
+ return (cert);
+ }
+
+ switch(PORT_GetError()) {
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ case SEC_ERROR_CA_CERT_INVALID:
+ case SEC_ERROR_UNKNOWN_SIGNER:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
+ "cert with subject name %s could not be verified because the issuer's cert is expired/invalid or not found",
+ cert->subjectName);
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
+ "cert with subject name %s has expired",
+ cert->subjectName);
+ break;
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_REVOKED,
+ "cert with subject name %s has been revoked",
+ cert->subjectName);
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+ "cert with subject name %s could not be verified, errcode %d",
+ cert->subjectName,
+ PORT_GetError());
+ break;
+ }
+
+ return (NULL);
+}
+
+/**
+ * xmlSecNssX509StoreAdoptCert:
+ * @store: the pointer to X509 key data store klass.
+ * @cert: the pointer to NSS 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
+xmlSecNssX509StoreAdoptCert(xmlSecKeyDataStorePtr store, CERTCertificate* cert, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->certsList == NULL) {
+ ctx->certsList = CERT_NewCertList();
+ if(ctx->certsList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CERT_NewCertList",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ ret = CERT_AddCertToListTail(ctx->certsList, cert);
+ if(ret != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CERT_AddCertToListTail",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssX509StoreInitialize(xmlSecKeyDataStorePtr store) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), -1);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssX509StoreCtx));
+
+ return(0);
+}
+
+static void
+xmlSecNssX509StoreFinalize(xmlSecKeyDataStorePtr store) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId));
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->certsList) {
+ CERT_DestroyCertList(ctx->certsList);
+ ctx->certsList = NULL;
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssX509StoreCtx));
+}
+
+
+/*****************************************************************************
+ *
+ * Low-level x509 functions
+ *
+ *****************************************************************************/
+static CERTCertificate*
+xmlSecNssX509FindCert(xmlChar *subjectName, xmlChar *issuerName,
+ xmlChar *issuerSerial, xmlChar *ski) {
+ CERTCertificate *cert = NULL;
+ xmlChar *p = NULL;
+ CERTName *name = NULL;
+ SECItem *nameitem = NULL;
+ PRArenaPool *arena = NULL;
+
+ if (subjectName != NULL) {
+ p = xmlSecNssX509NameRead(subjectName, xmlStrlen(subjectName));
+ if (p == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "subject=%s",
+ xmlSecErrorsSafeString(subjectName));
+ goto done;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ name = CERT_AsciiToName((char*)p);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_AsciiToName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
+ SEC_ASN1_GET(CERT_NameTemplate));
+ if (nameitem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_ASN1EncodeItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PORT_GetError());
+ goto done;
+ }
+
+ cert = CERT_FindCertByName(CERT_GetDefaultCertDB(), nameitem);
+ goto done;
+ }
+
+ if((issuerName != NULL) && (issuerSerial != NULL)) {
+ CERTIssuerAndSN issuerAndSN;
+
+ p = xmlSecNssX509NameRead(issuerName, xmlStrlen(issuerName));
+ if (p == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "issuer=%s",
+ xmlSecErrorsSafeString(issuerName));
+ goto done;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ name = CERT_AsciiToName((char*)p);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_AsciiToName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
+ SEC_ASN1_GET(CERT_NameTemplate));
+ if (nameitem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_ASN1EncodeItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PORT_GetError());
+ goto done;
+ }
+
+ memset(&issuerAndSN, 0, sizeof(issuerAndSN));
+
+ issuerAndSN.derIssuer.data = nameitem->data;
+ issuerAndSN.derIssuer.len = nameitem->len;
+
+ /* TBD: serial num can be arbitrarily long */
+ xmlSecNssNumToItem(&issuerAndSN.serialNumber, PORT_Atoi((char *)issuerSerial));
+
+ cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(),
+ &issuerAndSN);
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ goto done;
+ }
+
+ if(ski != NULL) {
+ SECItem subjKeyID;
+ int len;
+
+ 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));
+ goto done;
+ }
+
+ memset(&subjKeyID, 0, sizeof(subjKeyID));
+ subjKeyID.data = ski;
+ subjKeyID.len = xmlStrlen(ski);
+ cert = CERT_FindCertBySubjectKeyID(CERT_GetDefaultCertDB(),
+ &subjKeyID);
+ }
+
+done:
+ if (p != NULL) {
+ PORT_Free(p);
+ }
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if (name != NULL) {
+ CERT_DestroyName(name);
+ }
+
+ return(cert);
+}
+
+static xmlSecByte *
+xmlSecNssX509NameRead(xmlSecByte *str, int len) {
+ xmlSecByte name[256];
+ xmlSecByte value[256];
+ xmlSecByte *retval = NULL;
+ xmlSecByte *p = NULL;
+ int nameLen, valueLen;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* return string should be no longer than input string */
+ retval = (xmlSecByte *)PORT_Alloc(len+1);
+ if(retval == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_Alloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ p = retval;
+
+ while(len > 0) {
+ /* skip spaces after comma or semicolon */
+ while((len > 0) && isspace(*str)) {
+ ++str; --len;
+ }
+
+ nameLen = xmlSecNssX509NameStringRead(&str, &len, name, sizeof(name), '=', 0);
+ if(nameLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ memcpy(p, name, nameLen);
+ p+=nameLen;
+ *p++='=';
+ if(len > 0) {
+ ++str; --len;
+ if((*str) == '\"') {
+ valueLen = xmlSecNssX509NameStringRead(&str, &len,
+ value, sizeof(value), '"', 1);
+ if(valueLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ /* 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");
+ goto done;
+ }
+ if(len > 0) {
+ ++str; --len;
+ }
+ *p++='\"';
+ memcpy(p, value, valueLen);
+ p+=valueLen;
+ *p++='\"';
+ } 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");
+ goto done;
+ } else {
+ valueLen = xmlSecNssX509NameStringRead(&str, &len,
+ value, sizeof(value), ',', 1);
+ if(valueLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ memcpy(p, value, valueLen);
+ p+=valueLen;
+ if (len > 0)
+ *p++=',';
+ }
+ } else {
+ valueLen = 0;
+ }
+ if(len > 0) {
+ ++str; --len;
+ }
+ }
+
+ *p = 0;
+ return(retval);
+
+done:
+ PORT_Free(retval);
+ return (NULL);
+}
+
+static int
+xmlSecNssX509NameStringRead(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);
+}
+
+/* code lifted from NSS */
+static void
+xmlSecNssNumToItem(SECItem *it, unsigned long ui)
+{
+ unsigned char bb[5];
+ int len;
+
+ bb[0] = 0;
+ bb[1] = (unsigned char) (ui >> 24);
+ bb[2] = (unsigned char) (ui >> 16);
+ bb[3] = (unsigned char) (ui >> 8);
+ bb[4] = (unsigned char) (ui);
+
+ /*
+ ** Small integers are encoded in a single byte. Larger integers
+ ** require progressively more space.
+ */
+ if (ui > 0x7f) {
+ if (ui > 0x7fff) {
+ if (ui > 0x7fffffL) {
+ if (ui >= 0x80000000L) {
+ len = 5;
+ } else {
+ len = 4;
+ }
+ } else {
+ len = 3;
+ }
+ } else {
+ len = 2;
+ }
+ } else {
+ len = 1;
+ }
+
+ it->data = (unsigned char *)PORT_Alloc(len);
+ if (it->data == NULL) {
+ return;
+ }
+
+ it->len = len;
+ PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len);
+}
+#endif /* XMLSEC_NO_X509 */
+
+
diff --git a/src/openssl/Makefile.am b/src/openssl/Makefile.am
new file mode 100644
index 00000000..db2cd43e
--- /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 = \
+ ../libxmlsec1.la \
+ $(OPENSSL_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(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..1cb63c49
--- /dev/null
+++ b/src/openssl/Makefile.in
@@ -0,0 +1,778 @@
+# Makefile.in generated by automake 1.11 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)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+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@
+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@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_ENABLED = @PKG_CONFIG_ENABLED@
+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_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_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 = \
+ ../libxmlsec1.la \
+ $(OPENSSL_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(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..462b1842
--- /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..88dbc090
--- /dev/null
+++ b/src/openssl/app.c
@@ -0,0 +1,1581 @@
+/**
+ * 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);
+
+/**
+ * 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 */
+ pKey = PEM_read_bio_PrivateKey(bio, NULL,
+ (pwd != NULL) ? xmlSecOpenSSLDummyPasswordCallback : (pem_password_cb*)pwdCallback,
+ (pwd != NULL) ? pwd : 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, (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, (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, (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 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;
+ }
+
+ 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;
+ }
+
+ /* 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;
+ }
+ }
+
+ 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((void*)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, void *userdata) {
+ char* password = (char*)userdata;
+
+ if((password == NULL) || (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..28025d14
--- /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..4799cb52
--- /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..fa226620
--- /dev/null
+++ b/src/openssl/crypto.c
@@ -0,0 +1,474 @@
+/**
+ * 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..c681e857
--- /dev/null
+++ b/src/openssl/digests.c
@@ -0,0 +1,679 @@
+/**
+ * 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) {
+ xmlSecAssert2((xmlSecSize)EVP_MD_size(ctx->digest) <= sizeof(ctx->dgst), -1);
+
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_DigestFinal(&(ctx->digestCtx), ctx->dgst, &ctx->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, &ctx->dgstSize);
+#endif /* XMLSEC_OPENSSL_096 */
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ /* 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..e9d87295
--- /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..272a27b8
--- /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..0b6605b8
--- /dev/null
+++ b/src/openssl/hmac.c
@@ -0,0 +1,841 @@
+/**
+ *
+ * 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 */
+
+ {
+ return(0);
+ }
+
+ 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 lenght 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) {
+ xmlSecSize dgstSize;
+
+ HMAC_Final(&(ctx->hmacCtx), ctx->dgst, &dgstSize);
+ xmlSecAssert2(dgstSize > 0, -1);
+
+ /* check/set the result digest size */
+ if(ctx->dgstSize == 0) {
+ ctx->dgstSize = dgstSize * 8; /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= 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..1ed3685e
--- /dev/null
+++ b/src/openssl/kt_rsa.c
@@ -0,0 +1,877 @@
+/**
+ *
+ * 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 OAPE 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);
+ if((cur != NULL) && 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);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if((cur != NULL) && 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);
+
+ 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
+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..94cfeddb
--- /dev/null
+++ b/src/openssl/kw_aes.c
@@ -0,0 +1,622 @@
+/**
+ *
+ * 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>
+
+#define XMLSEC_OPENSSL_AES128_KEY_SIZE 16
+#define XMLSEC_OPENSSL_AES192_KEY_SIZE 24
+#define XMLSEC_OPENSSL_AES256_KEY_SIZE 32
+#define XMLSEC_OPENSSL_AES_IV_SIZE 16
+#define XMLSEC_OPENSSL_AES_BLOCK_SIZE 16
+
+
+/*********************************************************************
+ *
+ * AES KW transforms
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+#define xmlSecOpenSSLKWAesGetKey(transform) \
+ ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecOpenSSLKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
+
+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 xmlSecSize xmlSecOpenSSLKWAesGetKeySize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLKWAesEncode (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte* in,
+ xmlSecSize inSize,
+ xmlSecByte* out,
+ xmlSecSize outSize);
+static int xmlSecOpenSSLKWAesDecode (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte* in,
+ xmlSecSize inSize,
+ xmlSecByte* out,
+ xmlSecSize outSize);
+
+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; */
+};
+
+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; */
+};
+
+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; */
+};
+
+#define XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE 8
+
+#define xmlSecOpenSSLKWAesCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes128Id) || \
+ xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes192Id) || \
+ xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes256Id))
+
+/**
+ * xmlSecOpenSSLTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWAes128GetKlass(void) {
+ return(&xmlSecOpenSSLKWAes128Klass);
+}
+
+/**
+ * xmlSecOpenSSLTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWAes192GetKlass(void) {
+ return(&xmlSecOpenSSLKWAes192Klass);
+}
+
+/**
+ * xmlSecOpenSSLTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWAes256GetKlass(void) {
+ return(&xmlSecOpenSSLKWAes256Klass);
+}
+
+static int
+xmlSecOpenSSLKWAesInitialize(xmlSecTransformPtr transform) {
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+
+ ret = xmlSecBufferInitialize(xmlSecOpenSSLKWAesGetKey(transform), 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) {
+ xmlSecAssert(xmlSecOpenSSLKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize));
+
+ if(xmlSecOpenSSLKWAesGetKey(transform) != NULL) {
+ xmlSecBufferFinalize(xmlSecOpenSSLKWAesGetKey(transform));
+ }
+}
+
+static int
+xmlSecOpenSSLKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataAesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * xmlSecOpenSSLKWAesGetKeySize(transform);
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ xmlSecSize expectedKeySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+ xmlSecAssert2(xmlSecOpenSSLKWAesGetKey(transform) != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataAesId), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ expectedKeySize = xmlSecOpenSSLKWAesGetKeySize(transform);
+ if(keySize < expectedKeySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, expectedKeySize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(xmlSecOpenSSLKWAesGetKey(transform),
+ xmlSecBufferGetData(buffer),
+ expectedKeySize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d", expectedKeySize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBufferPtr in, out, key;
+ xmlSecSize inSize, outSize, keySize, expectedKeySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ key = xmlSecOpenSSLKWAesGetKey(transform);
+ xmlSecAssert2(key != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(key);
+ expectedKeySize = xmlSecOpenSSLKWAesGetKeySize(transform);
+ xmlSecAssert2(keySize == expectedKeySize, -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_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_OPENSSL_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_OPENSSL_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) {
+ ret = xmlSecOpenSSLKWAesEncode(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecOpenSSLKWAesDecode(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKWAesDecode",
+ 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 xmlSecSize
+xmlSecOpenSSLKWAesGetKeySize(xmlSecTransformPtr transform) {
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes128Id)) {
+ return(XMLSEC_OPENSSL_AES128_KEY_SIZE);
+ } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes192Id)) {
+ return(XMLSEC_OPENSSL_AES192_KEY_SIZE);
+ } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes256Id)) {
+ return(XMLSEC_OPENSSL_AES256_KEY_SIZE);
+ }
+ return(0);
+}
+
+/**
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap:
+ *
+ * Assume that the data to be wrapped consists of N 64-bit data blocks
+ * denoted P(1), P(2), P(3) ... P(N). The result of wrapping will be N+1
+ * 64-bit blocks denoted C(0), C(1), C(2), ... C(N). The key encrypting
+ * key is represented by K. Assume integers i, j, and t and intermediate
+ * 64-bit register A, 128-bit register B, and array of 64-bit quantities
+ * R(1) through R(N).
+ *
+ * "|" represents concatentation so x|y, where x and y and 64-bit quantities,
+ * is the 128-bit quantity with x in the most significant bits and y in the
+ * least significant bits. AES(K)enc(x) is the operation of AES encrypting
+ * the 128-bit quantity x under the key K. AES(K)dec(x) is the corresponding
+ * decryption opteration. XOR(x,y) is the bitwise exclusive or of x and y.
+ * MSB(x) and LSB(y) are the most significant 64 bits and least significant
+ * 64 bits of x and y respectively.
+ *
+ * If N is 1, a single AES operation is performed for wrap or unwrap.
+ * If N>1, then 6*N AES operations are performed for wrap or unwrap.
+ *
+ * The key wrap algorithm is as follows:
+ *
+ * 1. If N is 1:
+ * * B=AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
+ * * C(0)=MSB(B)
+ * * C(1)=LSB(B)
+ * If N>1, perform the following steps:
+ * 2. Initialize variables:
+ * * Set A to 0xA6A6A6A6A6A6A6A6
+ * * Fori=1 to N,
+ * R(i)=P(i)
+ * 3. Calculate intermediate values:
+ * * Forj=0 to 5,
+ * o For i=1 to N,
+ * t= i + j*N
+ * B=AES(K)enc(A|R(i))
+ * A=XOR(t,MSB(B))
+ * R(i)=LSB(B)
+ * 4. Output the results:
+ * * Set C(0)=A
+ * * For i=1 to N,
+ * C(i)=R(i)
+ *
+ * The key unwrap algorithm is as follows:
+ *
+ * 1. If N is 1:
+ * * B=AES(K)dec(C(0)|C(1))
+ * * P(1)=LSB(B)
+ * * If MSB(B) is 0xA6A6A6A6A6A6A6A6, return success. Otherwise,
+ * return an integrity check failure error.
+ * If N>1, perform the following steps:
+ * 2. Initialize the variables:
+ * * A=C(0)
+ * * For i=1 to N,
+ * R(i)=C(i)
+ * 3. Calculate intermediate values:
+ * * For j=5 to 0,
+ * o For i=N to 1,
+ * t= i + j*N
+ * B=AES(K)dec(XOR(t,A)|R(i))
+ * A=MSB(B)
+ * R(i)=LSB(B)
+ * 4. Output the results:
+ * * For i=1 to N,
+ * P(i)=R(i)
+ * * If A is 0xA6A6A6A6A6A6A6A6, return success. Otherwise, return
+ * an integrity check failure error.
+ */
+static const xmlSecByte xmlSecOpenSSLKWAesMagicBlock[XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE] = {
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
+};
+
+static int
+xmlSecOpenSSLKWAesEncode(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ AES_KEY aesKey;
+ xmlSecByte block[XMLSEC_OPENSSL_AES_BLOCK_SIZE];
+ xmlSecByte *p;
+ int N, i, j, t;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize > 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 8, -1);
+
+ ret = AES_set_encrypt_key(key, 8 * keySize, &aesKey);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "AES_set_encrypt_key",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* prepend magic block */
+ if(in != out) {
+ memcpy(out + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
+ } else {
+ memmove(out + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
+ }
+ memcpy(out, xmlSecOpenSSLKWAesMagicBlock, XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE);
+
+ N = (inSize / 8);
+ if(N == 1) {
+ AES_encrypt(out, out, &aesKey);
+ } else {
+ for(j = 0; j <= 5; ++j) {
+ for(i = 1; i <= N; ++i) {
+ t = i + (j * N);
+ p = out + i * 8;
+
+ memcpy(block, out, 8);
+ memcpy(block + 8, p, 8);
+
+ AES_encrypt(block, block, &aesKey);
+ block[7] ^= t;
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+
+ return(inSize + 8);
+}
+
+static int
+xmlSecOpenSSLKWAesDecode(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ AES_KEY aesKey;
+ xmlSecByte block[XMLSEC_OPENSSL_AES_BLOCK_SIZE];
+ xmlSecByte *p;
+ int N, i, j, t;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize > 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = AES_set_decrypt_key(key, 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);
+ }
+
+ /* copy input */
+ if(in != out) {
+ memcpy(out, in, inSize);
+ }
+
+ N = (inSize / 8) - 1;
+ if(N == 1) {
+ AES_decrypt(out, out, &aesKey);
+ } else {
+ for(j = 5; j >= 0; --j) {
+ for(i = N; i > 0; --i) {
+ t = i + (j * N);
+ p = out + i * 8;
+
+ memcpy(block, out, 8);
+ memcpy(block + 8, p, 8);
+ block[7] ^= t;
+
+ AES_decrypt(block, block, &aesKey);
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+ /* do not left data in memory */
+ memset(block, 0, sizeof(block));
+
+ if(memcmp(xmlSecOpenSSLKWAesMagicBlock, out, XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "bad magic block");
+ return(-1);
+ }
+
+ memmove(out, out + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE);
+ return(inSize - XMLSEC_OPENSSL_KW_AES_MAGIC_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..f5ebf435
--- /dev/null
+++ b/src/openssl/kw_des.c
@@ -0,0 +1,628 @@
+/**
+ *
+ * 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>
+ */
+#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>
+
+#define XMLSEC_OPENSSL_DES3_KEY_LENGTH 24
+#define XMLSEC_OPENSSL_DES3_IV_LENGTH 8
+#define XMLSEC_OPENSSL_DES3_BLOCK_LENGTH 8
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+#define xmlSecOpenSSLKWDes3GetKey(transform) \
+ ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecOpenSSLKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
+
+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 int xmlSecOpenSSLKWDes3Encode (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize);
+static int xmlSecOpenSSLKWDes3Decode (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize);
+static int xmlSecOpenSSLKWDes3Encrypt (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *iv,
+ xmlSecSize ivSize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize,
+ int enc);
+static int xmlSecOpenSSLKWDes3BufferReverse (xmlSecByte *buf,
+ xmlSecSize size);
+
+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) {
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1);
+
+ ret = xmlSecBufferInitialize(xmlSecOpenSSLKWDes3GetKey(transform), 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) {
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size));
+
+ if(xmlSecOpenSSLKWDes3GetKey(transform) != NULL) {
+ xmlSecBufferFinalize(xmlSecOpenSSLKWDes3GetKey(transform));
+ }
+}
+
+static int
+xmlSecOpenSSLKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_OPENSSL_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ 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(xmlSecOpenSSLKWDes3GetKey(transform) != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataDesId), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_OPENSSL_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_OPENSSL_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(xmlSecOpenSSLKWDes3GetKey(transform),
+ xmlSecBufferGetData(buffer),
+ XMLSEC_OPENSSL_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_OPENSSL_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBufferPtr in, out, key;
+ 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);
+
+ key = xmlSecOpenSSLKWDes3GetKey(transform);
+ xmlSecAssert2(key != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(key);
+ xmlSecAssert2(keySize == XMLSEC_OPENSSL_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_OPENSSL_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_OPENSSL_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_OPENSSL_DES3_IV_LENGTH +
+ XMLSEC_OPENSSL_DES3_BLOCK_LENGTH +
+ XMLSEC_OPENSSL_DES3_BLOCK_LENGTH;
+ } else {
+ outSize = inSize + XMLSEC_OPENSSL_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 = xmlSecOpenSSLKWDes3Encode(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecOpenSSLKWDes3Decode(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKWDes3Decode",
+ 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);
+}
+
+static xmlSecByte xmlSecOpenSSLKWDes3Iv[XMLSEC_OPENSSL_DES3_IV_LENGTH] = {
+ 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05
+};
+/**
+ * CMS Triple DES Key Wrap
+ *
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
+ *
+ * The following algorithm wraps (encrypts) a key (the wrapped key, WK)
+ * under a TRIPLEDES key-encryption-key (KEK) as specified in [CMS-Algorithms]:
+ *
+ * 1. Represent the key being wrapped as an octet sequence. If it is a
+ * TRIPLEDES key, this is 24 octets (192 bits) with odd parity bit as
+ * the bottom bit of each octet.
+ * 2. Compute the CMS key checksum (section 5.6.1) call this CKS.
+ * 3. Let WKCKS = WK || CKS, where || is concatenation.
+ * 4. Generate 8 random octets [RANDOM] and call this IV.
+ * 5. Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+ * initialization vector. Call the results TEMP1.
+ * 6. Left TEMP2 = IV || TEMP1.
+ * 7. Reverse the order of the octets in TEMP2 and call the result TEMP3.
+ * 8. Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+ * of 0x4adda22c79e82105. The resulting cipher text is the desired result.
+ * It is 40 octets long if a 168 bit key is being wrapped.
+ *
+ */
+static int
+xmlSecOpenSSLKWDes3Encode(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte sha1[SHA_DIGEST_LENGTH];
+ xmlSecByte iv[XMLSEC_OPENSSL_DES3_IV_LENGTH];
+ xmlSecSize s;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_OPENSSL_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 16, -1);
+
+ /* step 2: calculate sha1 and CMS */
+ if(SHA1(in, inSize, sha1) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SHA1",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 3: construct WKCKS */
+ memcpy(out, in, inSize);
+ memcpy(out + inSize, sha1, XMLSEC_OPENSSL_DES3_BLOCK_LENGTH);
+
+ /* step 4: generate random iv */
+ ret = RAND_bytes(iv, XMLSEC_OPENSSL_DES3_IV_LENGTH);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "RAND_bytes",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* step 5: first encryption, result is TEMP1 */
+ ret = xmlSecOpenSSLKWDes3Encrypt(key, keySize,
+ iv, XMLSEC_OPENSSL_DES3_IV_LENGTH,
+ out, inSize + XMLSEC_OPENSSL_DES3_BLOCK_LENGTH,
+ out, outSize, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 6: construct TEMP2=IV || TEMP1 */
+ memmove(out + XMLSEC_OPENSSL_DES3_IV_LENGTH, out,
+ inSize + XMLSEC_OPENSSL_DES3_IV_LENGTH);
+ memcpy(out, iv, XMLSEC_OPENSSL_DES3_IV_LENGTH);
+ s = ret + XMLSEC_OPENSSL_DES3_IV_LENGTH;
+
+ /* step 7: reverse octets order, result is TEMP3 */
+ ret = xmlSecOpenSSLKWDes3BufferReverse(out, s);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3BufferReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* step 8: second encryption with static IV */
+ ret = xmlSecOpenSSLKWDes3Encrypt(key, keySize,
+ xmlSecOpenSSLKWDes3Iv, XMLSEC_OPENSSL_DES3_IV_LENGTH,
+ out, s, out, outSize, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ s = ret;
+ return(s);
+}
+
+/**
+ * CMS Triple DES Key Wrap
+ *
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
+ *
+ * The following algorithm unwraps (decrypts) a key as specified in
+ * [CMS-Algorithms]:
+ *
+ * 1. Check if the length of the cipher text is reasonable given the key type.
+ * It must be 40 bytes for a 168 bit key and either 32, 40, or 48 bytes for
+ * a 128, 192, or 256 bit key. If the length is not supported or inconsistent
+ * with the algorithm for which the key is intended, return error.
+ * 2. Decrypt the cipher text with TRIPLEDES in CBC mode using the KEK and
+ * an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
+ * 3. Reverse the order of the octets in TEMP3 and call the result TEMP2.
+ * 4. Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining
+ * octets.
+ * 5. Decrypt TEMP1 using TRIPLEDES in CBC mode using the KEK and the IV found
+ * in the previous step. Call the result WKCKS.
+ * 6. Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
+ * those octets before the CKS.
+ * 7. Calculate a CMS key checksum (section 5.6.1) over the WK and compare
+ * with the CKS extracted in the above step. If they are not equal, return
+ * error.
+ * 8. WK is the wrapped key, now extracted for use in data decryption.
+ */
+static int
+xmlSecOpenSSLKWDes3Decode(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte sha1[SHA_DIGEST_LENGTH];
+ xmlSecSize s;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_OPENSSL_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ /* step 2: first decryption with static IV, result is TEMP3 */
+ ret = xmlSecOpenSSLKWDes3Encrypt(key, keySize,
+ xmlSecOpenSSLKWDes3Iv, XMLSEC_OPENSSL_DES3_IV_LENGTH,
+ in, inSize, out, outSize, 0);
+ if((ret < 0) || (ret < XMLSEC_OPENSSL_DES3_IV_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ s = ret;
+
+ /* step 3: reverse octets order in TEMP3, result is TEMP2 */
+ ret = xmlSecOpenSSLKWDes3BufferReverse(out, s);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3BufferReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* steps 4 and 5: get IV and decrypt second time, result is WKCKS */
+ ret = xmlSecOpenSSLKWDes3Encrypt(key, keySize,
+ out, XMLSEC_OPENSSL_DES3_IV_LENGTH,
+ out + XMLSEC_OPENSSL_DES3_IV_LENGTH,
+ s - XMLSEC_OPENSSL_DES3_IV_LENGTH,
+ out, outSize, 0);
+ if((ret < 0) || (ret < XMLSEC_OPENSSL_DES3_BLOCK_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ s = ret - XMLSEC_OPENSSL_DES3_BLOCK_LENGTH;
+
+ /* steps 6 and 7: calculate SHA1 and validate it */
+ if(SHA1(out, s, sha1) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SHA1",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(memcmp(sha1, out + s, XMLSEC_OPENSSL_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "SHA1 does not match");
+ return(-1);
+ }
+
+ return(s);
+}
+
+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);
+}
+
+static int
+xmlSecOpenSSLKWDes3BufferReverse(xmlSecByte *buf, xmlSecSize size) {
+ xmlSecSize s;
+ xmlSecSize i;
+ xmlSecByte c;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ s = size / 2;
+ --size;
+ for(i = 0; i < s; ++i) {
+ c = buf[i];
+ buf[i] = buf[size - i];
+ buf[size - i] = c;
+ }
+ return(0);
+}
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/openssl/signatures.c b/src/openssl/signatures.c
new file mode 100644
index 00000000..2a16983a
--- /dev/null
+++ b/src/openssl/signatures.c
@@ -0,0 +1,1061 @@
+/**
+ * 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, 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) {
+ /* this is a hack: for rsa signatures
+ * we get size from EVP_PKEY_size(),
+ * for dsa signature we use a fixed constant */
+ outSize = EVP_PKEY_size(ctx->pKey);
+#ifndef XMLSEC_NO_DSA
+ if(outSize < XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE) {
+ outSize = XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE;
+ }
+#endif /* XMLSEC_NO_DSA */
+
+ 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);
+ }
+
+ ret = EVP_SignFinal(&(ctx->digestCtx), xmlSecBufferGetData(out), &outSize, 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, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ 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,unsigned long count)
+{
+ return SHA1_Update(ctx->md_data,data,count);
+}
+
+static int
+xmlSecOpenSSLDsaSha1EvpFinal(EVP_MD_CTX *ctx,xmlSecByte *md)
+{
+ return SHA1_Final(md,ctx->md_data);
+}
+#endif /* XMLSEC_OPENSSL_096 */
+
+static int
+xmlSecOpenSSLDsaSha1EvpSign(int type ATTRIBUTE_UNUSED,
+ const xmlSecByte *dgst, int dlen,
+ xmlSecByte *sig, unsigned int *siglen, DSA *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 xmlSecByte *dgst, int dgst_len,
+ const xmlSecByte *sigbuf, int siglen, DSA *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..fdcf2876
--- /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..74dd4096
--- /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..3b6c6af8
--- /dev/null
+++ b/src/openssl/x509vfy.c
@@ -0,0 +1,1286 @@
+/**
+ * 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 **a,
+ const X509_NAME_ENTRY **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) {
+ 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) {
+ 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) {
+ 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 && keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN){
+ ret = 1;
+ keyInfoCtx->flags2 |= XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN;
+ }
+
+ 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 */
+ sk_X509_NAME_ENTRY_set_cmp_func(a1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
+ sk_X509_NAME_ENTRY_sort(a1->entries);
+ 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 **a, const X509_NAME_ENTRY **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 */
+
+
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 00000000..74c15229
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,571 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * XML Parser transform and utility functions.
+ *
+ * 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 <libxml/parser.h>
+#include <libxml/parserInternals.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/parser.h>
+#include <xmlsec/errors.h>
+
+/**************************************************************************
+ *
+ * Internal parser
+ *
+ *****************************************************************************/
+typedef struct _xmlSecParserCtx xmlSecParserCtx,
+ *xmlSecParserCtxPtr;
+struct _xmlSecParserCtx {
+ xmlParserCtxtPtr parserCtx;
+};
+
+/**************************************************************************
+ *
+ * XML Parser transform
+ *
+ * xmlSecParserCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecParserSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecParserCtx))
+#define xmlSecParserGetCtx(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecParserSize)) ? \
+ ((xmlSecParserCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) : \
+ (xmlSecParserCtxPtr)NULL)
+
+static int xmlSecParserInitialize (xmlSecTransformPtr transform);
+static void xmlSecParserFinalize (xmlSecTransformPtr transform);
+static int xmlSecParserPushBin (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ int final,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecParserPopXml (xmlSecTransformPtr transform,
+ xmlSecNodeSetPtr* nodes,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecParserKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecParserSize, /* xmlSecSize objSize */
+
+ BAD_CAST "xml-parser", /* const xmlChar* name; */
+ NULL, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecParserInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecParserFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecParserPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecParserPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ NULL, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXmlParserGetKlass:
+ *
+ * The XML parser transform.
+ *
+ * Returns: XML parser transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformXmlParserGetKlass(void) {
+ return(&xmlSecParserKlass);
+}
+
+static int
+xmlSecParserInitialize(xmlSecTransformPtr transform) {
+ xmlSecParserCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecParserSize), -1);
+
+ ctx = xmlSecParserGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecParserCtx));
+ return(0);
+}
+
+static void
+xmlSecParserFinalize(xmlSecTransformPtr transform) {
+ xmlSecParserCtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecParserSize));
+
+ ctx = xmlSecParserGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->parserCtx != NULL) {
+ xmlFreeParserCtxt(ctx->parserCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecParserCtx));
+}
+
+static int
+xmlSecParserPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
+ xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecParserCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecParserGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* check/update current transform status */
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlSecAssert2(ctx->parserCtx == NULL, -1);
+
+ ctx->parserCtx = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
+ if(ctx->parserCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlCreatePushParserCtxt",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* required for c14n! */
+ ctx->parserCtx->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ ctx->parserCtx->replaceEntities = 1;
+
+ transform->status = xmlSecTransformStatusWorking;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ return(0);
+ } else if(transform->status != xmlSecTransformStatusWorking) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
+ xmlSecAssert2(ctx->parserCtx != NULL, -1);
+
+ /* push data to the input buffer */
+ if((data != NULL) && (dataSize > 0)) {
+ ret = xmlParseChunk(ctx->parserCtx, (const char*)data, dataSize, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "size=%d", dataSize);
+ return(-1);
+ }
+ }
+
+ /* finish parsing and push to next in the chain */
+ if(final != 0) {
+ ret = xmlParseChunk(ctx->parserCtx, NULL, 0, 1);
+ if((ret != 0) || (ctx->parserCtx->myDoc == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* todo: check that document is well formed? */
+ transform->outNodes = xmlSecNodeSetCreate(ctx->parserCtx->myDoc,
+ NULL, xmlSecNodeSetTree);
+ if(transform->outNodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(ctx->parserCtx->myDoc);
+ ctx->parserCtx->myDoc = NULL;
+ return(-1);
+ }
+ xmlSecNodeSetDocDestroy(transform->outNodes); /* this node set "owns" the doc pointer */
+ ctx->parserCtx->myDoc = NULL;
+
+ /* push result to the next transform (if exist) */
+ if(transform->next != NULL) {
+ ret = xmlSecTransformPushXml(transform->next, transform->outNodes, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformPushXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecParserPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecParserCtxPtr ctx;
+ xmlParserInputBufferPtr buf;
+ xmlParserInputPtr input;
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXmlParserId), -1);
+ xmlSecAssert2(nodes != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecParserGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* check/update current transform status */
+ switch(transform->status) {
+ case xmlSecTransformStatusNone:
+ transform->status = xmlSecTransformStatusWorking;
+ break;
+ case xmlSecTransformStatusWorking:
+ /* just do nothing */
+ break;
+ case xmlSecTransformStatusFinished:
+ (*nodes) = NULL;
+ return(0);
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
+
+ /* prepare parser context */
+ if(transform->prev == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "prev transform is null");
+ return(-1);
+ }
+
+ buf = xmlSecTransformCreateInputBuffer(transform->prev, transformCtx);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformCreateInputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlNewParserCtxt",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeParserInputBuffer(buf);
+ return(-1);
+ }
+
+ input = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
+ if(input == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlNewParserCtxt",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeParserCtxt(ctxt);
+ xmlFreeParserInputBuffer(buf);
+ return(-1);
+ }
+
+ ret = inputPush(ctxt, input);
+ if(input == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "inputPush",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeInputStream(input);
+ xmlFreeParserCtxt(ctxt);
+ return(-1);
+ }
+
+ /* required for c14n! */
+ ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ ctxt->replaceEntities = 1;
+
+ /* finaly do the parsing */
+ ret = xmlParseDocument(ctxt);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlParseDocument",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ if(ctxt->myDoc != NULL) {
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ xmlFreeParserCtxt(ctxt);
+ return(-1);
+ }
+
+ /* remember the result and free parsing context */
+ doc = ctxt->myDoc;
+ ctxt->myDoc = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ /* return result to the caller */
+ (*nodes) = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetTree);
+ if((*nodes) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ xmlSecNodeSetDocDestroy((*nodes)); /* this node set "owns" the doc pointer */
+ transform->status = xmlSecTransformStatusFinished;
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * XML Parser functions
+ *
+ *************************************************************************/
+typedef struct _xmlSecExtMemoryParserCtx {
+ const xmlSecByte *prefix;
+ xmlSecSize prefixSize;
+ const xmlSecByte *buffer;
+ xmlSecSize bufferSize;
+ const xmlSecByte *postfix;
+ xmlSecSize postfixSize;
+} xmlSecExtMemoryParserCtx, *xmlSecExtMemoryParserCtxPtr;
+
+/**
+ * xmlSecParseFile:
+ * @filename: the filename.
+ *
+ * Loads XML Doc from file @filename. We need a special version because of
+ * c14n issue. The code is copied from xmlSAXParseFileWithData() function.
+ *
+ * Returns: pointer to the loaded XML document or NULL if an error occurs.
+ */
+xmlDocPtr
+xmlSecParseFile(const char *filename) {
+ xmlDocPtr ret;
+ xmlParserCtxtPtr ctxt;
+ char *directory = NULL;
+
+ xmlSecAssert2(filename != NULL, NULL);
+
+ xmlInitParser();
+ ctxt = xmlCreateFileParserCtxt(filename);
+ if (ctxt == NULL) {
+ return(NULL);
+ }
+
+ /* todo: set directories from current doc? */
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory(filename);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
+
+ /* required for c14n! */
+ ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ ctxt->replaceEntities = 1;
+
+ xmlParseDocument(ctxt);
+
+ if(ctxt->wellFormed) {
+ ret = ctxt->myDoc;
+ } else {
+ ret = NULL;
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ xmlFreeParserCtxt(ctxt);
+ return(ret);
+
+}
+
+/**
+ * xmlSecParseMemoryExt:
+ * @prefix: the first part of the input.
+ * @prefixSize: the size of the first part of the input.
+ * @buffer: the second part of the input.
+ * @bufferSize: the size of the second part of the input.
+ * @postfix: the third part of the input.
+ * @postfixSize: the size of the third part of the input.
+ *
+ * Loads XML Doc from 3 chunks of memory: @prefix, @buffer and @postfix.
+ *
+ * Returns: pointer to the loaded XML document or NULL if an error occurs.
+ */
+xmlDocPtr
+xmlSecParseMemoryExt(const xmlSecByte *prefix, xmlSecSize prefixSize,
+ const xmlSecByte *buffer, xmlSecSize bufferSize,
+ const xmlSecByte *postfix, xmlSecSize postfixSize) {
+ xmlParserCtxtPtr ctxt = NULL;
+ xmlDocPtr doc = NULL;
+ int ret;
+
+ /* create context */
+ ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
+ if(ctxt == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlCreatePushParserCtxt",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* required for c14n! */
+ ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ ctxt->replaceEntities = 1;
+
+ /* prefix */
+ if((prefix != NULL) && (prefixSize > 0)) {
+ ret = xmlParseChunk(ctxt, (const char*)prefix, prefixSize, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "prefixSize=%d", prefixSize);
+ goto done;
+ }
+ }
+
+ /* buffer */
+ if((buffer != NULL) && (bufferSize > 0)) {
+ ret = xmlParseChunk(ctxt, (const char*)buffer, bufferSize, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "bufferSize=%d", bufferSize);
+ goto done;
+ }
+ }
+
+ /* postfix */
+ if((postfix != NULL) && (postfixSize > 0)) {
+ ret = xmlParseChunk(ctxt, (const char*)postfix, postfixSize, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "postfixSize=%d", postfixSize);
+ goto done;
+ }
+ }
+
+ /* finishing */
+ ret = xmlParseChunk(ctxt, NULL, 0, 1);
+ if((ret != 0) || (ctxt->myDoc == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ doc = ctxt->myDoc;
+
+done:
+ if(ctxt != NULL) {
+ xmlFreeParserCtxt(ctxt);
+ }
+ return(doc);
+}
+
+
+/**
+ * xmlSecParseMemory:
+ * @buffer: the input buffer.
+ * @size: the input buffer size.
+ * @recovery: the flag.
+ *
+ * Loads XML Doc from memory. We need a special version because of
+ * c14n issue. The code is copied from xmlSAXParseMemory() function.
+ *
+ * Returns: pointer to the loaded XML document or NULL if an error occurs.
+ */
+xmlDocPtr
+xmlSecParseMemory(const xmlSecByte *buffer, xmlSecSize size, int recovery) {
+ xmlDocPtr ret;
+ xmlParserCtxtPtr ctxt;
+
+ xmlSecAssert2(buffer != NULL, NULL);
+
+ ctxt = xmlCreateMemoryParserCtxt((char*)buffer, size);
+ if (ctxt == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlCreateMemoryParserCtxt",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* required for c14n! */
+ ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ ctxt->replaceEntities = 1;
+
+ xmlParseDocument(ctxt);
+
+ if((ctxt->wellFormed) || recovery) {
+ ret = ctxt->myDoc;
+ } else {
+ ret = NULL;
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ xmlFreeParserCtxt(ctxt);
+ return(ret);
+}
+
diff --git a/src/skeleton/Makefile.am b/src/skeleton/Makefile.am
new file mode 100644
index 00000000..8e2e910b
--- /dev/null
+++ b/src/skeleton/Makefile.am
@@ -0,0 +1,45 @@
+NULL =
+
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-skeleton.la \
+ $(NULL)
+
+libxmlsec1_skeleton_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(XMLSEC_SKELETON_DEFINES) \
+ $(SKELETON_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_skeleton_la_SOURCES =\
+ app.c \
+ crypto.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_skeleton_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_skeleton_la_LIBADD = \
+ ../libxmlsec1.la \
+ $(SKELETON_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ $(NULL)
+
+libxmlsec1_skeleton_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_skeleton_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/skeleton/README b/src/skeleton/README
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/skeleton/README
diff --git a/src/skeleton/app.c b/src/skeleton/app.c
new file mode 100644
index 00000000..e229ab34
--- /dev/null
+++ b/src/skeleton/app.c
@@ -0,0 +1,499 @@
+/**
+ * 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>
+
+/* TODO: aadd Skeleton include files */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/skeleton/app.h>
+#include <xmlsec/skeleton/crypto.h>
+
+/**
+ * xmlSecSkeletonAppInit:
+ * @config: the path to Skeleton configuration (unused).
+ *
+ * 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
+xmlSecSkeletonAppInit(const char* config ATTRIBUTE_UNUSED) {
+ /* TODO: initialize Skeleton crypto engine */
+ return(0);
+}
+
+/**
+ * xmlSecSkeletonAppShutdown:
+ *
+ * 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
+xmlSecSkeletonAppShutdown(void) {
+ /* TODO: shutdown Skeleton crypto engine */
+
+ return(0);
+}
+
+/**
+ * xmlSecSkeletonAppKeyLoad:
+ * @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 (not implemented yet).
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecSkeletonAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd,
+ void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* TODO: load key */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppKeyLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecSkeletonAppKeyLoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the key data format.
+ * @pwd: the key data2 password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from a binary @data.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecSkeletonAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* TODO: load key */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppKeyLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+
+#ifndef XMLSEC_NO_X509
+/**
+ * xmlSecSkeletonAppKeyCertLoad:
+ * @key: the pointer to key.
+ * @filename: the certificate filename.
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from $@filename and adds it to key
+ * (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonAppKeyCertLoad(xmlSecKeyPtr key, const char* filename,
+ xmlSecKeyDataFormat format) {
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppKeyCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecSkeletonAppKeyCertLoadMemory:
+ * @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
+xmlSecSkeletonAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppKeyCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecSkeletonAppPkcs12Load:
+ * @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
+ * (not implemented yet).
+ * For uniformity, call xmlSecSkeletonAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecSkeletonAppPkcs12Load(const char *filename,
+ const char *pwd ATTRIBUTE_UNUSED,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(filename != NULL, NULL);
+
+ /* TODO: load pkcs12 file */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppPkcs12Load",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecSkeletonAppPkcs12LoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @pwd: the PKCS12 password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 binary data.
+ * For uniformity, call xmlSecSkeletonAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecSkeletonAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(data != NULL, NULL);
+
+ /* TODO: load pkcs12 file */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppPkcs12Load",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+
+
+/**
+ * xmlSecSkeletonAppKeysMngrCertLoad:
+ * @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 (not implemented yet).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO: load cert and add to keys manager */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppKeysMngrCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecSkeletonAppKeysMngrCertLoadMemory:
+ * @mngr: the pointer to keys manager.
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the certificate format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Reads cert from @data and adds to the list of trusted or known
+ * untrusted certs in @store
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO: load cert and add to keys manager */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonAppKeysMngrCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecSkeletonAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId
+ * and a default Skeleton crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* TODO: if Skeleton crypto engine has another default
+ * keys storage then use it!
+ */
+
+ /* 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 = xmlSecSkeletonKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSkeletonKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecSkeletonAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecSkeletonAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ /* TODO: if Skeleton crypto engine has another default
+ * keys storage then use it!
+ */
+
+ 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);
+}
+
+/**
+ * xmlSecSkeletonAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecSkeletonAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ /* TODO: if Skeleton crypto engine has another default
+ * keys storage then use it!
+ */
+
+ 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);
+}
+
+/**
+ * xmlSecSkeletonAppDefaultKeysMngrSave:
+ * @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
+xmlSecSkeletonAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename, xmlSecKeyDataType type) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+
+ /* TODO: if Skeleton crypto engine has another default
+ * keys storage then use it!
+ */
+
+ 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);
+}
+
+/**
+ * xmlSecSkeletonAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecSkeletonAppGetDefaultPwdCallback(void) {
+ /* TODO */
+ return(NULL);
+}
+
diff --git a/src/skeleton/crypto.c b/src/skeleton/crypto.c
new file mode 100644
index 00000000..aff0945a
--- /dev/null
+++ b/src/skeleton/crypto.c
@@ -0,0 +1,227 @@
+/**
+ * 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>
+
+/* TODO: add Skeleton include files */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/private.h>
+
+#include <xmlsec/skeleton/app.h>
+#include <xmlsec/skeleton/crypto.h>
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecSkeletonFunctions = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_skeleton:
+ *
+ * Gets the pointer to xmlsec-skeleton functions table.
+ *
+ * Returns: the xmlsec-skeleton functions table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_skeleton(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecSkeletonFunctions != NULL) {
+ return(gXmlSecSkeletonFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecSkeletonFunctions = &functions;
+
+ /**
+ * Crypto Init/shutdown
+ */
+ gXmlSecSkeletonFunctions->cryptoInit = xmlSecSkeletonInit;
+ gXmlSecSkeletonFunctions->cryptoShutdown = xmlSecSkeletonShutdown;
+ gXmlSecSkeletonFunctions->cryptoKeysMngrInit = xmlSecSkeletonKeysMngrInit;
+
+ /**
+ * Key data ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecSkeletonFunctions->keyDataAesGetKlass = xmlSecSkeletonKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecSkeletonFunctions->keyDataDesGetKlass = xmlSecSkeletonKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecSkeletonFunctions->keyDataDsaGetKlass = xmlSecSkeletonKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecSkeletonFunctions->keyDataGost2001GetKlass = xmlSecSkeletonKeyDataGost2001GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecSkeletonFunctions->keyDataHmacGetKlass = xmlSecSkeletonKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecSkeletonFunctions->keyDataRsaGetKlass = xmlSecSkeletonKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_X509
+ gXmlSecSkeletonFunctions->keyDataX509GetKlass = xmlSecSkeletonKeyDataX509GetKlass;
+ gXmlSecSkeletonFunctions->keyDataRawX509CertGetKlass = xmlSecSkeletonKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /**
+ * Key data store ids
+ */
+#ifndef XMLSEC_NO_X509
+ gXmlSecSkeletonFunctions->x509StoreGetKlass = xmlSecSkeletonX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /**
+ * Crypto transforms ids
+ */
+#ifndef XMLSEC_NO_AES
+ gXmlSecSkeletonFunctions->transformAes128CbcGetKlass = xmlSecSkeletonTransformAes128CbcGetKlass;
+ gXmlSecSkeletonFunctions->transformAes192CbcGetKlass = xmlSecSkeletonTransformAes192CbcGetKlass;
+ gXmlSecSkeletonFunctions->transformAes256CbcGetKlass = xmlSecSkeletonTransformAes256CbcGetKlass;
+ gXmlSecSkeletonFunctions->transformKWAes128GetKlass = xmlSecSkeletonTransformKWAes128GetKlass;
+ gXmlSecSkeletonFunctions->transformKWAes192GetKlass = xmlSecSkeletonTransformKWAes192GetKlass;
+ gXmlSecSkeletonFunctions->transformKWAes256GetKlass = xmlSecSkeletonTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecSkeletonFunctions->transformDes3CbcGetKlass = xmlSecSkeletonTransformDes3CbcGetKlass;
+ gXmlSecSkeletonFunctions->transformKWDes3GetKlass = xmlSecSkeletonTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecSkeletonFunctions->transformDsaSha1GetKlass = xmlSecSkeletonTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecSkeletonFunctions->transformGost2001GostR3411_94GetKlass = xmlSecSkeletonTransformGost2001GostR3411_94GetKlass;
+#endif /* XMLSEC_GOST */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecSkeletonFunctions->transformHmacSha1GetKlass = xmlSecSkeletonTransformHmacSha1GetKlass;
+ gXmlSecSkeletonFunctions->transformHmacRipemd160GetKlass = xmlSecSkeletonTransformHmacRipemd160GetKlass;
+ gXmlSecSkeletonFunctions->transformHmacMd5GetKlass = xmlSecSkeletonTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecSkeletonFunctions->transformRipemd160GetKlass = xmlSecSkeletonTransformRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecSkeletonFunctions->transformRsaSha1GetKlass = xmlSecSkeletonTransformRsaSha1GetKlass;
+ gXmlSecSkeletonFunctions->transformRsaPkcs1GetKlass = xmlSecSkeletonTransformRsaPkcs1GetKlass;
+ gXmlSecSkeletonFunctions->transformRsaOaepGetKlass = xmlSecSkeletonTransformRsaOaepGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecSkeletonFunctions->transformSha1GetKlass = xmlSecSkeletonTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecSkeletonFunctions->transformGostR3411_94GetKlass = xmlSecSkeletonTransformGostR3411_94GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+ /**
+ * High level routines form xmlsec command line utility
+ */
+ gXmlSecSkeletonFunctions->cryptoAppInit = xmlSecSkeletonAppInit;
+ gXmlSecSkeletonFunctions->cryptoAppShutdown = xmlSecSkeletonAppShutdown;
+ gXmlSecSkeletonFunctions->cryptoAppDefaultKeysMngrInit = xmlSecSkeletonAppDefaultKeysMngrInit;
+ gXmlSecSkeletonFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecSkeletonAppDefaultKeysMngrAdoptKey;
+ gXmlSecSkeletonFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecSkeletonAppDefaultKeysMngrLoad;
+ gXmlSecSkeletonFunctions->cryptoAppDefaultKeysMngrSave = xmlSecSkeletonAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecSkeletonFunctions->cryptoAppKeysMngrCertLoad = xmlSecSkeletonAppKeysMngrCertLoad;
+ gXmlSecSkeletonFunctions->cryptoAppKeysMngrCertLoadMemory = xmlSecSkeletonAppKeysMngrCertLoadMemory;
+ gXmlSecSkeletonFunctions->cryptoAppPkcs12Load = xmlSecSkeletonAppPkcs12Load;
+ gXmlSecSkeletonFunctions->cryptoAppPkcs12LoadMemory = xmlSecSkeletonAppPkcs12LoadMemory;
+ gXmlSecSkeletonFunctions->cryptoAppKeyCertLoad = xmlSecSkeletonAppKeyCertLoad;
+ gXmlSecSkeletonFunctions->cryptoAppKeyCertLoadMemory = xmlSecSkeletonAppKeyCertLoadMemory;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecSkeletonFunctions->cryptoAppKeyLoad = xmlSecSkeletonAppKeyLoad;
+ gXmlSecSkeletonFunctions->cryptoAppKeyLoadMemory = xmlSecSkeletonAppKeyLoadMemory;
+ gXmlSecSkeletonFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecSkeletonAppGetDefaultPwdCallback();
+
+ return(gXmlSecSkeletonFunctions);
+}
+
+
+/**
+ * xmlSecSkeletonInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonInit (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);
+ }
+
+ /* register our klasses */
+ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_skeleton()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+
+ /* TODO: if necessary do, additional initialization here */
+}
+
+/**
+ * xmlSecSkeletonShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonShutdown(void) {
+ /* TODO: if necessary, do additional shutdown here */
+ return(0);
+}
+
+/**
+ * xmlSecSkeletonKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds Skeleton specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecSkeletonKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* TODO: add key data stores */
+ return(0);
+}
+
+
diff --git a/src/skeleton/globals.h b/src/skeleton/globals.h
new file mode 100644
index 00000000..272a27b8
--- /dev/null
+++ b/src/skeleton/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/soap.c b/src/soap.c
new file mode 100644
index 00000000..84512b23
--- /dev/null
+++ b/src/soap.c
@@ -0,0 +1,1322 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Simple SOAP messages parsing/creation.
+ *
+ * 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_SOAP
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/soap.h>
+#include <xmlsec/errors.h>
+
+/***********************************************************************
+ *
+ * SOAP 1.1
+ *
+ **********************************************************************/
+/**
+ * xmlSecSoap11CreateEnvelope:
+ * @doc: the parent doc (might be NULL).
+ *
+ * Creates a new SOAP Envelope node. Caller is responsible for
+ * adding the returned node to the XML document.
+ *
+ * XML Schema (http://schemas.xmlsoap.org/soap/envelope/):
+ *
+ * <xs:element name="Envelope" type="tns:Envelope"/>
+ * <xs:complexType name="Envelope">
+ * <xs:sequence>
+ * <xs:element ref="tns:Header" minOccurs="0"/>
+ * <xs:element ref="tns:Body" minOccurs="1"/>
+ * <xs:any namespace="##other" minOccurs="0"
+ * maxOccurs="unbounded" processContents="lax"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##other" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to newly created <soap:Envelope> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11CreateEnvelope(xmlDocPtr doc) {
+ xmlNodePtr envNode;
+ xmlNodePtr bodyNode;
+ xmlNsPtr ns;
+
+ /* create Envelope node */
+ envNode = xmlNewDocNode(doc, NULL, xmlSecNodeEnvelope, NULL);
+ if(envNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDocNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEnvelope));
+ return(NULL);
+ }
+
+ ns = xmlNewNs(envNode, xmlSecSoap11Ns, NULL) ;
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(xmlSecSoap11Ns));
+ xmlFreeNode(envNode);
+ return(NULL);
+ }
+ xmlSetNs(envNode, ns);
+
+ /* add required Body node */
+ bodyNode = xmlSecAddChild(envNode, xmlSecNodeBody, xmlSecSoap11Ns);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeBody));
+ xmlFreeNode(envNode);
+ return(NULL);
+ }
+
+ return(envNode);
+}
+
+/**
+ * xmlSecSoap11EnsureHeader:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets the pointer to <soap:Header> node (if necessary, the node
+ * is created).
+ *
+ * XML Schema (http://schemas.xmlsoap.org/soap/envelope/):
+ *
+ * <xs:element name="Header" type="tns:Header"/>
+ * <xs:complexType name="Header">
+ * <xs:sequence>
+ * <xs:any namespace="##other" minOccurs="0"
+ * maxOccurs="unbounded" processContents="lax"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##other" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to <soap:Header> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11EnsureHeader(xmlNodePtr envNode) {
+ xmlNodePtr hdrNode;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* try to find Header node first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
+ return(cur);
+ }
+
+ /* if the first element child is not Header then it is Body */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* finally add Header node before body */
+ hdrNode = xmlSecAddPrevSibling(cur, xmlSecNodeHeader, xmlSecSoap11Ns);
+ if(hdrNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddPrevSibling",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(hdrNode);
+}
+
+/**
+ * xmlSecSoap11AddBodyEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ * @entryNode: the pointer to body entry node.
+ *
+ * Adds a new entry to <soap:Body> node.
+ *
+ * Returns: pointer to the added entry (@contentNode) or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11AddBodyEntry(xmlNodePtr envNode, xmlNodePtr entryNode) {
+ xmlNodePtr bodyNode;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+ xmlSecAssert2(entryNode != NULL, NULL);
+
+ bodyNode = xmlSecSoap11GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecAddChildNode(bodyNode, entryNode));
+}
+
+/**
+ * xmlSecSoap11AddFaultEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ * @faultCodeHref: the fault code QName href (must be known in th context of
+ * <soap:Body> node).
+ * @faultCodeLocalPart: the fault code QName LocalPart.
+ * @faultString: the human readable explanation of the fault.
+ * @faultActor: the information about who caused the fault (might be NULL).
+ *
+ * Adds <soap:Fault> entry to the @envNode. Note that only one <soap:Fault>
+ * entry is allowed.
+ *
+ * XML Schema (http://schemas.xmlsoap.org/soap/envelope/):
+ *
+ * <xs:element name="Fault" type="tns:Fault"/>
+ * <xs:complexType name="Fault" final="extension">
+ * <xs:sequence>
+ * <xs:element name="faultcode" type="xs:QName"/>
+ * <xs:element name="faultstring" type="xs:string"/>
+ * <xs:element name="faultactor" type="xs:anyURI" minOccurs="0"/>
+ * <xs:element name="detail" type="tns:detail" minOccurs="0"/>
+ * </xs:sequence>
+ * </xs:complexType>
+ * <xs:complexType name="detail">
+ * <xs:sequence>
+ * <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded"
+ * processContents="lax"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##any" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to the added entry or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11AddFaultEntry(xmlNodePtr envNode, const xmlChar* faultCodeHref,
+ const xmlChar* faultCodeLocalPart,
+ const xmlChar* faultString, const xmlChar* faultActor) {
+ xmlNodePtr bodyNode;
+ xmlNodePtr faultNode;
+ xmlNodePtr cur;
+ xmlChar* qname;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+ xmlSecAssert2(faultCodeLocalPart != NULL, NULL);
+ xmlSecAssert2(faultString != NULL, NULL);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap11GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* check that we don't have Fault node already */
+ faultNode = xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns);
+ if(faultNode != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* add Fault node */
+ faultNode = xmlSecAddChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns);
+ if(faultNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeFault));
+ return(NULL);
+ }
+
+ /* add faultcode node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeFaultCode, xmlSecSoap11Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeFaultCode));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* create qname for fault code */
+ qname = xmlSecGetQName(cur, faultCodeHref, faultCodeLocalPart);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGetQName",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(cur->name));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* set faultcode value */
+ xmlNodeSetContent(cur, qname);
+ xmlFree(qname);
+
+ /* add faultstring node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeFaultString, xmlSecSoap11Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeFaultString));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* set faultstring node */
+ xmlNodeSetContent(cur, faultString);
+
+ if(faultActor != NULL) {
+ /* add faultactor node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeFaultActor, xmlSecSoap11Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeFaultActor));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* set faultactor node */
+ xmlNodeSetContent(cur, faultActor);
+ }
+
+ return(faultNode);
+}
+
+/**
+ * xmlSecSoap11CheckEnvelope:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Validates <soap:Envelope> node structure.
+ *
+ * Returns: 1 if @envNode has a valid <soap:Envelope> element, 0 if it is
+ * not valid or a negative value if an error occurs.
+ */
+int
+xmlSecSoap11CheckEnvelope(xmlNodePtr envNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, -1);
+
+ /* verify envNode itself */
+ if(!xmlSecCheckNodeName(envNode, xmlSecNodeEnvelope, xmlSecSoap11Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeEnvelope),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+
+ /* optional Header node first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* required Body node is next */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+
+ return(1);
+}
+
+/**
+ * xmlSecSoap11GetHeader:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets pointer to the <soap:Header> node.
+ *
+ * Returns: pointer to <soap:Header> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11GetHeader(xmlNodePtr envNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* optional Header node is first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
+ return(cur);
+ }
+
+ return(NULL);
+}
+
+/**
+ * xmlSecSoap11GetBody:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets pointer to the <soap:Body> node.
+ *
+ * Returns: pointer to <soap:Body> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11GetBody(xmlNodePtr envNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* optional Header node first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* Body node is next */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(cur);
+}
+
+/**
+ * xmlSecSoap11GetBodyEntriesNumber:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets the number of body entries.
+ *
+ * Returns: the number of body entries.
+ */
+xmlSecSize
+xmlSecSoap11GetBodyEntriesNumber(xmlNodePtr envNode) {
+ xmlSecSize number = 0;
+ xmlNodePtr bodyNode;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, 0);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap11GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+
+ cur = xmlSecGetNextElementNode(bodyNode->children);
+ while(cur != NULL) {
+ number++;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ return(number);
+}
+
+/**
+ * xmlSecSoap11GetBodyEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ * @pos: the body entry number.
+ *
+ * Gets the body entry number @pos.
+ *
+ * Returns: pointer to body entry node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap11GetBodyEntry(xmlNodePtr envNode, xmlSecSize pos) {
+ xmlNodePtr bodyNode;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap11GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecGetNextElementNode(bodyNode->children);
+ while((cur != NULL) && (pos > 0)) {
+ pos--;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ return(cur);
+}
+
+/**
+ * xmlSecSoap11GetFaultEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets the Fault entry (if any).
+ *
+ * Returns: pointer to Fault entry or NULL if it does not exist.
+ */
+xmlNodePtr
+xmlSecSoap11GetFaultEntry(xmlNodePtr envNode) {
+ xmlNodePtr bodyNode;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap11GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns));
+}
+
+
+/***********************************************************************
+ *
+ * SOAP 1.2
+ *
+ **********************************************************************/
+static const xmlSecQName2IntegerInfo gXmlSecSoap12FaultCodeInfo[] =
+{
+ { xmlSecSoap12Ns, xmlSecSoapFaultCodeVersionMismatch,
+ xmlSecSoap12FaultCodeVersionMismatch },
+ { xmlSecSoap12Ns, xmlSecSoapFaultCodeMustUnderstand,
+ xmlSecSoap12FaultCodeMustUnderstand },
+ { xmlSecSoap12Ns, xmlSecSoapFaultDataEncodningUnknown,
+ xmlSecSoap12FaultCodeDataEncodingUnknown },
+ { xmlSecSoap12Ns, xmlSecSoapFaultCodeSender,
+ xmlSecSoap12FaultCodeSender },
+ { xmlSecSoap12Ns, xmlSecSoapFaultCodeReceiver,
+ xmlSecSoap12FaultCodeReceiver },
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+/**
+ * xmlSecSoap12CreateEnvelope:
+ * @doc: the parent doc (might be NULL).
+ *
+ * Creates a new SOAP 1.2 Envelope node. Caller is responsible for
+ * adding the returned node to the XML document.
+ *
+ * XML Schema (http://www.w3.org/2003/05/soap-envelope):
+ *
+ * <xs:element name="Envelope" type="tns:Envelope"/>
+ * <xs:complexType name="Envelope">
+ * <xs:sequence>
+ * <xs:element ref="tns:Header" minOccurs="0"/>
+ * <xs:element ref="tns:Body" minOccurs="1"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##other" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to newly created <soap:Envelope> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12CreateEnvelope(xmlDocPtr doc) {
+ xmlNodePtr envNode;
+ xmlNodePtr bodyNode;
+ xmlNsPtr ns;
+
+ /* create Envelope node */
+ envNode = xmlNewDocNode(doc, NULL, xmlSecNodeEnvelope, NULL);
+ if(envNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDocNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEnvelope));
+ return(NULL);
+ }
+
+ ns = xmlNewNs(envNode, xmlSecSoap12Ns, NULL) ;
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(xmlSecSoap12Ns));
+ xmlFreeNode(envNode);
+ return(NULL);
+ }
+ xmlSetNs(envNode, ns);
+
+ /* add required Body node */
+ bodyNode = xmlSecAddChild(envNode, xmlSecNodeBody, xmlSecSoap12Ns);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeBody));
+ xmlFreeNode(envNode);
+ return(NULL);
+ }
+
+ return(envNode);
+}
+
+/**
+ * xmlSecSoap12EnsureHeader:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets the pointer to <soap:Header> node (if necessary, the node
+ * is created).
+ *
+ * XML Schema (http://www.w3.org/2003/05/soap-envelope):
+ *
+ * <xs:element name="Header" type="tns:Header"/>
+ * <xs:complexType name="Header">
+ * <xs:sequence>
+ * <xs:any namespace="##any" processContents="lax"
+ * minOccurs="0" maxOccurs="unbounded"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##other" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to <soap:Header> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12EnsureHeader(xmlNodePtr envNode) {
+ xmlNodePtr hdrNode;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* try to find Header node first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
+ return(cur);
+ }
+
+ /* if the first element child is not Header then it is Body */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* finally add Header node before body */
+ hdrNode = xmlSecAddPrevSibling(cur, xmlSecNodeHeader, xmlSecSoap12Ns);
+ if(hdrNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddPrevSibling",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(hdrNode);
+}
+
+/**
+ * xmlSecSoap12AddBodyEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ * @entryNode: the pointer to body entry node.
+ *
+ * Adds a new entry to <soap:Body> node.
+ *
+ * XML Schema (http://www.w3.org/2003/05/soap-envelope):
+ *
+ * <xs:element name="Body" type="tns:Body"/>
+ * <xs:complexType name="Body">
+ * <xs:sequence>
+ * <xs:any namespace="##any" processContents="lax"
+ * minOccurs="0" maxOccurs="unbounded"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##other" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to the added entry (@contentNode) or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12AddBodyEntry(xmlNodePtr envNode, xmlNodePtr entryNode) {
+ xmlNodePtr bodyNode;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+ xmlSecAssert2(entryNode != NULL, NULL);
+
+ bodyNode = xmlSecSoap12GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecAddChildNode(bodyNode, entryNode));
+}
+
+/**
+ * xmlSecSoap12AddFaultEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ * @faultCode: the fault code.
+ * @faultReasonText: the human readable explanation of the fault.
+ * @faultReasonLang: the language (xml:lang) for @faultReason string.
+ * @faultNodeURI: the more preciese information about fault source
+ * (might be NULL).
+ * @faultRole: the role the node was operating in at the point
+ * the fault occurred (might be NULL).
+ *
+ * Adds <soap:Fault> entry to the @envNode. Note that only one <soap:Fault>
+ * entry is allowed.
+ *
+ * XML Schema (http://www.w3.org/2003/05/soap-envelope):
+ *
+ * <xs:element name="Fault" type="tns:Fault"/>
+ * <xs:complexType name="Fault" final="extension">
+ * <xs:sequence>
+ * <xs:element name="Code" type="tns:faultcode"/>
+ * <xs:element name="Reason" type="tns:faultreason"/>
+ * <xs:element name="Node" type="xs:anyURI" minOccurs="0"/>
+ * <xs:element name="Role" type="xs:anyURI" minOccurs="0"/>
+ * <xs:element name="Detail" type="tns:detail" minOccurs="0"/>
+ * </xs:sequence>
+ * </xs:complexType>
+ *
+ * <xs:complexType name="faultcode">
+ * <xs:sequence>
+ * <xs:element name="Value" type="tns:faultcodeEnum"/>
+ * <xs:element name="Subcode" type="tns:subcode" minOccurs="0"/>
+ * </xs:sequence>
+ * </xs:complexType>
+ *
+ * <xs:complexType name="faultreason">
+ * <xs:sequence>
+ * <xs:element name="Text" type="tns:reasontext"
+ * minOccurs="1" maxOccurs="unbounded"/>
+ * </xs:sequence>
+ * </xs:complexType>
+ *
+ * <xs:complexType name="reasontext">
+ * <xs:simpleContent>
+ * <xs:extension base="xs:string">
+ * <xs:attribute ref="xml:lang" use="required"/>
+ * </xs:extension>
+ * </xs:simpleContent>
+ * </xs:complexType>
+ *
+ * <xs:simpleType name="faultcodeEnum">
+ * <xs:restriction base="xs:QName">
+ * <xs:enumeration value="tns:DataEncodingUnknown"/>
+ * <xs:enumeration value="tns:MustUnderstand"/>
+ * <xs:enumeration value="tns:Receiver"/>
+ * <xs:enumeration value="tns:Sender"/>
+ * <xs:enumeration value="tns:VersionMismatch"/>
+ * </xs:restriction>
+ * </xs:simpleType>
+ *
+ * <xs:complexType name="subcode">
+ * <xs:sequence>
+ * <xs:element name="Value" type="xs:QName"/>
+ * <xs:element name="Subcode" type="tns:subcode" minOccurs="0"/>
+ * </xs:sequence>
+ * </xs:complexType>
+ *
+ * <xs:complexType name="detail">
+ * <xs:sequence>
+ * <xs:any namespace="##any" processContents="lax"
+ * minOccurs="0" maxOccurs="unbounded"/>
+ * </xs:sequence>
+ * <xs:anyAttribute namespace="##other" processContents="lax"/>
+ * </xs:complexType>
+ *
+ * Returns: pointer to the added entry or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12AddFaultEntry(xmlNodePtr envNode, xmlSecSoap12FaultCode faultCode,
+ const xmlChar* faultReasonText, const xmlChar* faultReasonLang,
+ const xmlChar* faultNodeURI, const xmlChar* faultRole) {
+ xmlNodePtr bodyNode;
+ xmlNodePtr faultNode;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+ xmlSecAssert2(faultCode != xmlSecSoap12FaultCodeUnknown, NULL);
+ xmlSecAssert2(faultReasonText != NULL, NULL);
+ xmlSecAssert2(faultReasonLang != NULL, NULL);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap12GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* check that we don't have Fault node already */
+ faultNode = xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns);
+ if(faultNode != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* add Fault node */
+ faultNode = xmlSecAddChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns);
+ if(faultNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeFault));
+ return(NULL);
+ }
+
+ /* add Code node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeCode, xmlSecSoap12Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCode));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* write the fault code in Value child */
+ ret = xmlSecQName2IntegerNodeWrite(gXmlSecSoap12FaultCodeInfo, cur,
+ xmlSecNodeValue, xmlSecSoap12Ns,
+ faultCode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "faultCode=%d",
+ faultCode);
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* add Reason node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeReason, xmlSecSoap12Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeReason));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ /* Add Reason/Text node */
+ if(xmlSecSoap12AddFaultReasonText(faultNode, faultReasonText, faultReasonLang) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12AddFaultReasonText",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "text=%s",
+ xmlSecErrorsSafeString(faultReasonText));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+
+ if(faultNodeURI != NULL) {
+ /* add Node node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeNode, xmlSecSoap12Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeNode));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+ xmlNodeSetContent(cur, faultNodeURI);
+ }
+
+ if(faultRole != NULL) {
+ /* add Role node */
+ cur = xmlSecAddChild(faultNode, xmlSecNodeRole, xmlSecSoap12Ns);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRole));
+ xmlUnlinkNode(faultNode);
+ xmlFreeNode(faultNode);
+ return(NULL);
+ }
+ xmlNodeSetContent(cur, faultRole);
+ }
+
+ return(faultNode);
+}
+
+/**
+ * xmlSecSoap12AddFaultSubcode:
+ * @faultNode: the pointer to <Fault> node.
+ * @subCodeHref: the subcode href.
+ * @subCodeName: the subcode name.
+ *
+ * Adds a new <Subcode> node to the <Code> node or the last <Subcode> node.
+ *
+ * Returns: a pointer to the newly created <Subcode> node or NULL if an error
+ * occurs.
+ */
+xmlNodePtr
+xmlSecSoap12AddFaultSubcode(xmlNodePtr faultNode, const xmlChar* subCodeHref, const xmlChar* subCodeName) {
+ xmlNodePtr cur, subcodeNode, valueNode;
+ xmlChar* qname;
+
+ xmlSecAssert2(faultNode != NULL, NULL);
+ xmlSecAssert2(subCodeHref != NULL, NULL);
+ xmlSecAssert2(subCodeName != NULL, NULL);
+
+ /* Code node is the first childern in Fault node */
+ cur = xmlSecGetNextElementNode(faultNode->children);
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeCode, xmlSecSoap12Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCode));
+ return(NULL);
+ }
+
+ /* find the Code or Subcode node that does not have Subcode child */
+ while(1) {
+ xmlNodePtr tmp;
+
+ tmp = xmlSecFindChild(cur, xmlSecNodeSubcode, xmlSecSoap12Ns);
+ if(tmp != NULL) {
+ cur = tmp;
+ } else {
+ break;
+ }
+ }
+ xmlSecAssert2(cur != NULL, NULL);
+
+ /* add Subcode node */
+ subcodeNode = xmlSecAddChild(cur, xmlSecNodeSubcode, xmlSecSoap12Ns);
+ if(subcodeNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSubcode));
+ return(NULL);
+ }
+
+ /* add Value node */
+ valueNode = xmlSecAddChild(subcodeNode, xmlSecNodeValue, xmlSecSoap12Ns);
+ if(valueNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeValue));
+ xmlUnlinkNode(subcodeNode);
+ xmlFreeNode(subcodeNode);
+ return(NULL);
+ }
+
+ /* create qname for fault code */
+ qname = xmlSecGetQName(cur, subCodeHref, subCodeName);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGetQName",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(cur->name));
+ xmlUnlinkNode(subcodeNode);
+ xmlFreeNode(subcodeNode);
+ return(NULL);
+ }
+
+ /* set result qname in Value node */
+ xmlNodeSetContent(cur, qname);
+ if(qname != subCodeName) {
+ xmlFree(qname);
+ }
+
+ return(subcodeNode);
+}
+
+/**
+ * xmlSecSoap12AddFaultReasonText:
+ * @faultNode: the pointer to <Fault> node.
+ * @faultReasonText: the new reason text.
+ * @faultReasonLang: the new reason xml:lang attribute.
+ *
+ * Adds a new Text node to the Fault/Reason node.
+ *
+ * Returns: a pointer to the newly created <Text> node or NULL if an error
+ * occurs.
+ */
+xmlNodePtr
+xmlSecSoap12AddFaultReasonText(xmlNodePtr faultNode, const xmlChar* faultReasonText,
+ const xmlChar* faultReasonLang) {
+ xmlNodePtr reasonNode;
+ xmlNodePtr textNode;
+
+ xmlSecAssert2(faultNode != NULL, NULL);
+ xmlSecAssert2(faultReasonText != NULL, NULL);
+ xmlSecAssert2(faultReasonLang != NULL, NULL);
+
+ /* find Reason node */
+ reasonNode = xmlSecFindChild(faultNode, xmlSecNodeReason, xmlSecSoap12Ns);
+ if(reasonNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecFindChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeReason));
+ return(NULL);
+ }
+
+ /* add Text node */
+ textNode = xmlSecAddChild(reasonNode, xmlSecNodeText, xmlSecSoap12Ns);
+ if(textNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeText));
+ return(NULL);
+ }
+ xmlNodeSetContent(textNode, faultReasonText);
+ xmlNodeSetLang(textNode, faultReasonLang);
+
+ return(textNode);
+}
+
+/**
+ * xmlSecSoap12AddFaultDetailEntry:
+ * @faultNode: the pointer to <Fault> node.
+ * @detailEntryNode: the pointer to detail entry node.
+ *
+ * Adds a new child to the Detail child element of @faultNode.
+ *
+ * Returns: pointer to the added child (@detailEntryNode) or NULL if an error
+ * occurs.
+ */
+xmlNodePtr
+xmlSecSoap12AddFaultDetailEntry(xmlNodePtr faultNode, xmlNodePtr detailEntryNode) {
+ xmlNodePtr detailNode;
+
+ xmlSecAssert2(faultNode != NULL, NULL);
+ xmlSecAssert2(detailEntryNode != NULL, NULL);
+
+ /* find Detail node and add it if needed */
+ detailNode = xmlSecFindChild(faultNode, xmlSecNodeDetail, xmlSecSoap12Ns);
+ if(detailNode == NULL) {
+ detailNode = xmlSecAddChild(faultNode, xmlSecNodeDetail, xmlSecSoap12Ns);
+ if(detailNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDetail));
+ return(NULL);
+ }
+ }
+
+ return(xmlSecAddChildNode(detailNode, detailEntryNode));
+}
+
+/**
+ * xmlSecSoap12CheckEnvelope:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Validates <soap:Envelope> node structure.
+ *
+ * Returns: 1 if @envNode has a valid <soap:Envelope> element, 0 if it is
+ * not valid or a negative value if an error occurs.
+ */
+int
+xmlSecSoap12CheckEnvelope(xmlNodePtr envNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, -1);
+
+ /* verify envNode itself */
+ if(!xmlSecCheckNodeName(envNode, xmlSecNodeEnvelope, xmlSecSoap12Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeEnvelope),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+
+ /* optional Header node first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* required Body node is next */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+
+ return(1);
+}
+
+/**
+ * xmlSecSoap12GetHeader:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets pointer to the <soap:Header> node.
+ *
+ * Returns: pointer to <soap:Header> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12GetHeader(xmlNodePtr envNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* optional Header node is first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
+ return(cur);
+ }
+
+ return(NULL);
+}
+
+/**
+ * xmlSecSoap12GetBody:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets pointer to the <soap:Body> node.
+ *
+ * Returns: pointer to <soap:Body> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12GetBody(xmlNodePtr envNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* optional Header node first */
+ cur = xmlSecGetNextElementNode(envNode->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* Body node is next */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeBody),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(cur);
+}
+
+/**
+ * xmlSecSoap12GetBodyEntriesNumber:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets the number of body entries.
+ *
+ * Returns: the number of body entries.
+ */
+xmlSecSize
+xmlSecSoap12GetBodyEntriesNumber(xmlNodePtr envNode) {
+ xmlSecSize number = 0;
+ xmlNodePtr bodyNode;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, 0);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap12GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+
+ cur = xmlSecGetNextElementNode(bodyNode->children);
+ while(cur != NULL) {
+ number++;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ return(number);
+}
+
+/**
+ * xmlSecSoap12GetBodyEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ * @pos: the body entry number.
+ *
+ * Gets the body entry number @pos.
+ *
+ * Returns: pointer to body entry node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecSoap12GetBodyEntry(xmlNodePtr envNode, xmlSecSize pos) {
+ xmlNodePtr bodyNode;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap12GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecGetNextElementNode(bodyNode->children);
+ while((cur != NULL) && (pos > 0)) {
+ pos--;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ return(cur);
+}
+
+/**
+ * xmlSecSoap12GetFaultEntry:
+ * @envNode: the pointer to <soap:Envelope> node.
+ *
+ * Gets the Fault entry (if any).
+ *
+ * Returns: pointer to Fault entry or NULL if it does not exist.
+ */
+xmlNodePtr
+xmlSecSoap12GetFaultEntry(xmlNodePtr envNode) {
+ xmlNodePtr bodyNode;
+
+ xmlSecAssert2(envNode != NULL, NULL);
+
+ /* get Body node */
+ bodyNode = xmlSecSoap12GetBody(envNode);
+ if(bodyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBody",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns));
+}
+
+#endif /* XMLSEC_NO_SOAP */
+
+
diff --git a/src/strings.c b/src/strings.c
new file mode 100644
index 00000000..98971986
--- /dev/null
+++ b/src/strings.c
@@ -0,0 +1,601 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * All the string constants.
+ *
+ * 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 <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+
+/*************************************************************************
+ *
+ * Global Namespaces
+ *
+ ************************************************************************/
+const xmlChar xmlSecNs[] = "http://www.aleksey.com/xmlsec/2002";
+const xmlChar xmlSecDSigNs[] = "http://www.w3.org/2000/09/xmldsig#";
+const xmlChar xmlSecEncNs[] = "http://www.w3.org/2001/04/xmlenc#";
+const xmlChar xmlSecXkmsNs[] = "http://www.w3.org/2002/03/xkms#";
+const xmlChar xmlSecXPathNs[] = "http://www.w3.org/TR/1999/REC-xpath-19991116";
+const xmlChar xmlSecXPath2Ns[] = "http://www.w3.org/2002/06/xmldsig-filter2";
+const xmlChar xmlSecXPointerNs[] = "http://www.w3.org/2001/04/xmldsig-more/xptr";
+const xmlChar xmlSecSoap11Ns[] = "http://schemas.xmlsoap.org/soap/envelope/";
+const xmlChar xmlSecSoap12Ns[] = "http://www.w3.org/2002/06/soap-envelope";
+
+/*************************************************************************
+ *
+ * DSig Nodes
+ *
+ ************************************************************************/
+const xmlChar xmlSecNodeSignature[] = "Signature";
+const xmlChar xmlSecNodeSignedInfo[] = "SignedInfo";
+const xmlChar xmlSecNodeCanonicalizationMethod[]= "CanonicalizationMethod";
+const xmlChar xmlSecNodeSignatureMethod[] = "SignatureMethod";
+const xmlChar xmlSecNodeSignatureValue[] = "SignatureValue";
+const xmlChar xmlSecNodeDigestMethod[] = "DigestMethod";
+const xmlChar xmlSecNodeDigestValue[] = "DigestValue";
+const xmlChar xmlSecNodeObject[] = "Object";
+const xmlChar xmlSecNodeManifest[] = "Manifest";
+const xmlChar xmlSecNodeSignatureProperties[] = "SignatureProperties";
+
+/*************************************************************************
+ *
+ * Encryption Nodes
+ *
+ ************************************************************************/
+const xmlChar xmlSecNodeEncryptedData[] = "EncryptedData";
+const xmlChar xmlSecNodeEncryptionMethod[] = "EncryptionMethod";
+const xmlChar xmlSecNodeEncryptionProperties[] = "EncryptionProperties";
+const xmlChar xmlSecNodeEncryptionProperty[] = "EncryptionProperty";
+const xmlChar xmlSecNodeCipherData[] = "CipherData";
+const xmlChar xmlSecNodeCipherValue[] = "CipherValue";
+const xmlChar xmlSecNodeCipherReference[] = "CipherReference";
+const xmlChar xmlSecNodeReferenceList[] = "ReferenceList";
+const xmlChar xmlSecNodeDataReference[] = "DataReference";
+const xmlChar xmlSecNodeKeyReference[] = "KeyReference";
+
+const xmlChar xmlSecNodeCarriedKeyName[] = "CarriedKeyName";
+
+const xmlChar xmlSecTypeEncContent[] = "http://www.w3.org/2001/04/xmlenc#Content";
+const xmlChar xmlSecTypeEncElement[] = "http://www.w3.org/2001/04/xmlenc#Element";
+
+/*************************************************************************
+ *
+ * XKMS Nodes
+ *
+ ************************************************************************/
+#ifndef XMLSEC_NO_XKMS
+const xmlChar xmlSecXkmsServerRequestResultName[] = "result-response";
+const xmlChar xmlSecXkmsServerRequestStatusName[] = "status-request";
+const xmlChar xmlSecXkmsServerRequestLocateName[] = "locate-request";
+const xmlChar xmlSecXkmsServerRequestValidateName[] = "validate-request";
+const xmlChar xmlSecXkmsServerRequestCompoundName[] = "compound-request";
+
+const xmlChar xmlSecNodeResult[] = "Result";
+const xmlChar xmlSecNodeStatusRequest[] = "StatusRequest";
+const xmlChar xmlSecNodeStatusResult[] = "StatusResult";
+const xmlChar xmlSecNodeLocateRequest[] = "LocateRequest";
+const xmlChar xmlSecNodeLocateResult[] = "LocateResult";
+const xmlChar xmlSecNodeValidateRequest[] = "ValidateRequest";
+const xmlChar xmlSecNodeValidateResult[] = "ValidateResult";
+const xmlChar xmlSecNodeCompoundRequest[] = "CompoundRequest";
+const xmlChar xmlSecNodeCompoundResult[] = "CompoundResult";
+
+const xmlChar xmlSecNodeMessageExtension[] = "MessageExtension";
+const xmlChar xmlSecNodeOpaqueClientData[] = "OpaqueClientData";
+const xmlChar xmlSecNodeResponseMechanism[] = "ResponseMechanism";
+const xmlChar xmlSecNodeRespondWith[] = "RespondWith";
+const xmlChar xmlSecNodePendingNotification[] = "PendingNotification";
+const xmlChar xmlSecNodeQueryKeyBinding[] = "QueryKeyBinding";
+const xmlChar xmlSecNodeKeyUsage[] = "KeyUsage";
+const xmlChar xmlSecNodeUseKeyWith[] = "UseKeyWith";
+const xmlChar xmlSecNodeTimeInstant[] = "TimeInstant";
+const xmlChar xmlSecNodeRequestSignatureValue[] = "RequestSignatureValue";
+const xmlChar xmlSecNodeUnverifiedKeyBinding[] = "UnverifiedKeyBinding";
+const xmlChar xmlSecNodeValidityInterval[] = "ValidityInterval";
+const xmlChar xmlSecNodeStatus[] = "Status";
+const xmlChar xmlSecNodeValidReason[] = "ValidReason";
+const xmlChar xmlSecNodeInvalidReason[] = "InvalidReason";
+const xmlChar xmlSecNodeIndeterminateReason[] = "IndeterminateReason";
+
+const xmlChar xmlSecAttrService[] = "Service";
+const xmlChar xmlSecAttrNonce[] = "Nonce";
+const xmlChar xmlSecAttrOriginalRequestId[] = "OriginalRequestId";
+const xmlChar xmlSecAttrResponseLimit[] = "ResponseLimit";
+const xmlChar xmlSecAttrMechanism[] = "Mechanism[";
+const xmlChar xmlSecAttrIdentifier[] = "Identifier";
+const xmlChar xmlSecAttrApplication[] = "Application";
+const xmlChar xmlSecAttrResultMajor[] = "ResultMajor";
+const xmlChar xmlSecAttrResultMinor[] = "ResultMinor";
+const xmlChar xmlSecAttrRequestId[] = "RequestId";
+const xmlChar xmlSecAttrNotBefore[] = "NotBefore";
+const xmlChar xmlSecAttrNotOnOrAfter[] = "NotOnOrAfter";
+const xmlChar xmlSecAttrTime[] = "Time";
+const xmlChar xmlSecAttrStatusValue[] = "StatusValue";
+
+const xmlChar xmlSecResponseMechanismPending[] = "Pending";
+const xmlChar xmlSecResponseMechanismRepresent[]= "Represent";
+const xmlChar xmlSecResponseMechanismRequestSignatureValue[] = "RequestSignatureValue";
+
+const xmlChar xmlSecRespondWithKeyName[] = "KeyName";
+const xmlChar xmlSecRespondWithKeyValue[] = "KeyValue";
+const xmlChar xmlSecRespondWithX509Cert[] = "X509Cert";
+const xmlChar xmlSecRespondWithX509Chain[] = "X509Chain";
+const xmlChar xmlSecRespondWithX509CRL[] = "X509CRL";
+const xmlChar xmlSecRespondWithOCSP[] = "OCSP";
+const xmlChar xmlSecRespondWithRetrievalMethod[]= "RetrievalMethod";
+const xmlChar xmlSecRespondWithPGP[] = "PGP";
+const xmlChar xmlSecRespondWithPGPWeb[] = "PGPWeb";
+const xmlChar xmlSecRespondWithSPKI[] = "SPKI";
+const xmlChar xmlSecRespondWithPrivateKey[] = "PrivateKey";
+
+const xmlChar xmlSecStatusResultSuccess[] = "Success";
+const xmlChar xmlSecStatusResultFailed[] = "Failed";
+const xmlChar xmlSecStatusResultPending[] = "Pending";
+
+const xmlChar xmlSecKeyUsageEncryption[] = "Encryption";
+const xmlChar xmlSecKeyUsageSignature[] = "Signature";
+const xmlChar xmlSecKeyUsageExchange[] = "Exchange";
+
+const xmlChar xmlSecKeyBindingStatusValid[] = "Valid";
+const xmlChar xmlSecKeyBindingStatusInvalid[] = "Invalid";
+const xmlChar xmlSecKeyBindingStatusIndeterminate[] = "Indeterminate";
+
+const xmlChar xmlSecKeyBindingReasonIssuerTrust[] = "IssuerTrust";
+const xmlChar xmlSecKeyBindingReasonRevocationStatus[] = "RevocationStatus";
+const xmlChar xmlSecKeyBindingReasonValidityInterval[] = "ValidityInterval";
+const xmlChar xmlSecKeyBindingReasonSignature[] = "Signature";
+
+const xmlChar xmlSecResultMajorCodeSuccess[] = "Success";
+const xmlChar xmlSecResultMajorCodeVersionMismatch[] = "VersionMismatch";
+const xmlChar xmlSecResultMajorCodeSender[] = "Sender";
+const xmlChar xmlSecResultMajorCodeReceiver[] = "Receiver";
+const xmlChar xmlSecResultMajorCodeRepresent[] = "Represent";
+const xmlChar xmlSecResultMajorCodePending[] = "Pending";
+
+const xmlChar xmlSecResultMinorCodeNoMatch[] = "NoMatch";
+const xmlChar xmlSecResultMinorCodeTooManyResponses[] = "TooManyResponses";
+const xmlChar xmlSecResultMinorCodeIncomplete[] = "Incomplete";
+const xmlChar xmlSecResultMinorCodeFailure[] = "Failure";
+const xmlChar xmlSecResultMinorCodeRefused[] = "Refused";
+const xmlChar xmlSecResultMinorCodeNoAuthentication[] = "NoAuthentication";
+const xmlChar xmlSecResultMinorCodeMessageNotSupported[]= "MessageNotSupported";
+const xmlChar xmlSecResultMinorCodeUnknownResponseId[] = "UnknownResponseId";
+const xmlChar xmlSecResultMinorCodeNotSynchronous[] = "NotSynchronous";
+
+const xmlChar xmlSecXkmsSoapSubcodeValueMessageNotSupported[] = "MessageNotSupported";
+const xmlChar xmlSecXkmsSoapSubcodeValueBadMessage[] = "BadMessage";
+
+const xmlChar xmlSecXkmsSoapFaultReasonLang[] = "en";
+const xmlChar xmlSecXkmsSoapFaultReasonUnsupportedVersion[] = "Unsupported SOAP version";
+const xmlChar xmlSecXkmsSoapFaultReasonUnableToProcess[] = "Unable to process %s";
+const xmlChar xmlSecXkmsSoapFaultReasonServiceUnavailable[] = "Service temporarily unable";
+const xmlChar xmlSecXkmsSoapFaultReasonMessageNotSupported[]= "%s message not supported";
+const xmlChar xmlSecXkmsSoapFaultReasonMessageInvalid[] = "%s message invalid";
+
+const xmlChar xmlSecXkmsFormatStrPlain[] = "plain";
+const xmlChar xmlSecXkmsFormatStrSoap11[] = "soap-1.1";
+const xmlChar xmlSecXkmsFormatStrSoap12[] = "soap-1.2";
+
+#endif /* XMLSEC_NO_XKMS */
+
+/*************************************************************************
+ *
+ * KeyInfo Nodes
+ *
+ ************************************************************************/
+const xmlChar xmlSecNodeKeyInfo[] = "KeyInfo";
+const xmlChar xmlSecNodeReference[] = "Reference";
+const xmlChar xmlSecNodeTransforms[] = "Transforms";
+const xmlChar xmlSecNodeTransform[] = "Transform";
+
+/*************************************************************************
+ *
+ * Attributes
+ *
+ ************************************************************************/
+const xmlChar xmlSecAttrId[] = "Id";
+const xmlChar xmlSecAttrURI[] = "URI";
+const xmlChar xmlSecAttrType[] = "Type";
+const xmlChar xmlSecAttrMimeType[] = "MimeType";
+const xmlChar xmlSecAttrEncoding[] = "Encoding";
+const xmlChar xmlSecAttrAlgorithm[] = "Algorithm";
+const xmlChar xmlSecAttrFilter[] = "Filter";
+const xmlChar xmlSecAttrRecipient[] = "Recipient";
+const xmlChar xmlSecAttrTarget[] = "Target";
+
+/*************************************************************************
+ *
+ * AES strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameAESKeyValue[] = "aes";
+const xmlChar xmlSecNodeAESKeyValue[] = "AESKeyValue";
+const xmlChar xmlSecHrefAESKeyValue[] = "http://www.aleksey.com/xmlsec/2002#AESKeyValue";
+
+const xmlChar xmlSecNameAes128Cbc[] = "aes128-cbc";
+const xmlChar xmlSecHrefAes128Cbc[] = "http://www.w3.org/2001/04/xmlenc#aes128-cbc";
+
+const xmlChar xmlSecNameAes192Cbc[] = "aes192-cbc";
+const xmlChar xmlSecHrefAes192Cbc[] = "http://www.w3.org/2001/04/xmlenc#aes192-cbc";
+
+const xmlChar xmlSecNameAes256Cbc[] = "aes256-cbc";
+const xmlChar xmlSecHrefAes256Cbc[] = "http://www.w3.org/2001/04/xmlenc#aes256-cbc";
+
+const xmlChar xmlSecNameKWAes128[] = "kw-aes128";
+const xmlChar xmlSecHrefKWAes128[] = "http://www.w3.org/2001/04/xmlenc#kw-aes128";
+
+const xmlChar xmlSecNameKWAes192[] = "kw-aes192";
+const xmlChar xmlSecHrefKWAes192[] = "http://www.w3.org/2001/04/xmlenc#kw-aes192";
+
+const xmlChar xmlSecNameKWAes256[] = "kw-aes256";
+const xmlChar xmlSecHrefKWAes256[] = "http://www.w3.org/2001/04/xmlenc#kw-aes256";
+
+/*************************************************************************
+ *
+ * BASE64 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameBase64[] = "base64";
+const xmlChar xmlSecHrefBase64[] = "http://www.w3.org/2000/09/xmldsig#base64";
+
+/*************************************************************************
+ *
+ * C14N strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameC14N[] = "c14n";
+const xmlChar xmlSecHrefC14N[] = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
+
+const xmlChar xmlSecNameC14NWithComments[] = "c14n-with-comments";
+const xmlChar xmlSecHrefC14NWithComments[] = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments";
+
+const xmlChar xmlSecNameC14N11[] = "c14n11";
+const xmlChar xmlSecHrefC14N11[] = "http://www.w3.org/2006/12/xml-c14n11";
+
+const xmlChar xmlSecNameC14N11WithComments[] = "c14n11-with-comments";
+const xmlChar xmlSecHrefC14N11WithComments[] = "http://www.w3.org/2006/12/xml-c14n11#WithComments";
+
+const xmlChar xmlSecNameExcC14N[] = "exc-c14n";
+const xmlChar xmlSecHrefExcC14N[] = "http://www.w3.org/2001/10/xml-exc-c14n#";
+
+const xmlChar xmlSecNameExcC14NWithComments[] = "exc-c14n-with-comments";
+const xmlChar xmlSecHrefExcC14NWithComments[] = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
+
+const xmlChar xmlSecNsExcC14N[] = "http://www.w3.org/2001/10/xml-exc-c14n#";
+const xmlChar xmlSecNsExcC14NWithComments[] = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
+
+const xmlChar xmlSecNodeInclusiveNamespaces[] = "InclusiveNamespaces";
+const xmlChar xmlSecAttrPrefixList[] = "PrefixList";
+
+/*************************************************************************
+ *
+ * DES strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameDESKeyValue[] = "des";
+const xmlChar xmlSecNodeDESKeyValue[] = "DESKeyValue";
+const xmlChar xmlSecHrefDESKeyValue[] = "http://www.aleksey.com/xmlsec/2002#DESKeyValue";
+
+const xmlChar xmlSecNameDes3Cbc[] = "tripledes-cbc";
+const xmlChar xmlSecHrefDes3Cbc[] = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc";
+
+const xmlChar xmlSecNameKWDes3[] = "kw-tripledes";
+const xmlChar xmlSecHrefKWDes3[] = "http://www.w3.org/2001/04/xmlenc#kw-tripledes";
+
+/*************************************************************************
+ *
+ * GOST2001 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameGOST2001KeyValue[] = "gost2001";
+const xmlChar xmlSecNodeGOST2001KeyValue[] = "gostr34102001-gostr3411";
+const xmlChar xmlSecHrefGOST2001KeyValue[] = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411";
+
+const xmlChar xmlSecNameGost2001GostR3411_94[] = "gostr34102001-gostr3411";
+const xmlChar xmlSecHrefGost2001GostR3411_94[] = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411";
+
+/*************************************************************************
+ *
+ * DSA strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameDSAKeyValue[] = "dsa";
+const xmlChar xmlSecNodeDSAKeyValue[] = "DSAKeyValue";
+const xmlChar xmlSecHrefDSAKeyValue[] = "http://www.w3.org/2000/09/xmldsig#DSAKeyValue";
+const xmlChar xmlSecNodeDSAP[] = "P";
+const xmlChar xmlSecNodeDSAQ[] = "Q";
+const xmlChar xmlSecNodeDSAG[] = "G";
+const xmlChar xmlSecNodeDSAJ[] = "J";
+const xmlChar xmlSecNodeDSAX[] = "X";
+const xmlChar xmlSecNodeDSAY[] = "Y";
+const xmlChar xmlSecNodeDSASeed[] = "Seed";
+const xmlChar xmlSecNodeDSAPgenCounter[] = "PgenCounter";
+
+const xmlChar xmlSecNameDsaSha1[] = "dsa-sha1";
+const xmlChar xmlSecHrefDsaSha1[] = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
+
+/*************************************************************************
+ *
+ * EncryptedKey
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameEncryptedKey[] = "enc-key";
+const xmlChar xmlSecNodeEncryptedKey[] = "EncryptedKey";
+const xmlChar xmlSecHrefEncryptedKey[] = "http://www.w3.org/2001/04/xmlenc#EncryptedKey";
+
+/*************************************************************************
+ *
+ * Enveloped transform strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameEnveloped[] = "enveloped-signature";
+const xmlChar xmlSecHrefEnveloped[] = "http://www.w3.org/2000/09/xmldsig#enveloped-signature";
+
+/*************************************************************************
+ *
+ * HMAC strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameHMACKeyValue[] = "hmac";
+const xmlChar xmlSecNodeHMACKeyValue[] = "HMACKeyValue";
+const xmlChar xmlSecHrefHMACKeyValue[] = "http://www.aleksey.com/xmlsec/2002#HMACKeyValue";
+
+const xmlChar xmlSecNodeHMACOutputLength[] = "HMACOutputLength";
+
+const xmlChar xmlSecNameHmacMd5[] = "hmac-md5";
+const xmlChar xmlSecHrefHmacMd5[] = "http://www.w3.org/2001/04/xmldsig-more#hmac-md5";
+
+const xmlChar xmlSecNameHmacRipemd160[] = "hmac-ripemd160";
+const xmlChar xmlSecHrefHmacRipemd160[] = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
+
+const xmlChar xmlSecNameHmacSha1[] = "hmac-sha1";
+const xmlChar xmlSecHrefHmacSha1[] = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
+
+const xmlChar xmlSecNameHmacSha224[] = "hmac-sha224";
+const xmlChar xmlSecHrefHmacSha224[] = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha224";
+
+const xmlChar xmlSecNameHmacSha256[] = "hmac-sha256";
+const xmlChar xmlSecHrefHmacSha256[] = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
+
+const xmlChar xmlSecNameHmacSha384[] = "hmac-sha384";
+const xmlChar xmlSecHrefHmacSha384[] = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
+
+const xmlChar xmlSecNameHmacSha512[] = "hmac-sha512";
+const xmlChar xmlSecHrefHmacSha512[] = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
+
+/*************************************************************************
+ *
+ * KeyName strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameKeyName[] = "key-name";
+const xmlChar xmlSecNodeKeyName[] = "KeyName";
+
+/*************************************************************************
+ *
+ * KeyValue strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameKeyValue[] = "key-value";
+const xmlChar xmlSecNodeKeyValue[] = "KeyValue";
+
+/*************************************************************************
+ *
+ * Memory Buffer strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameMemBuf[] = "membuf-transform";
+
+/*************************************************************************
+ *
+ * MD5 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameMd5[] = "md5";
+const xmlChar xmlSecHrefMd5[] = "http://www.w3.org/2001/04/xmldsig-more#md5";
+
+/*************************************************************************
+ *
+ * RetrievalMethod
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameRetrievalMethod[] = "retrieval-method";
+const xmlChar xmlSecNodeRetrievalMethod[] = "RetrievalMethod";
+
+/*************************************************************************
+ *
+ * RIPEMD160 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameRipemd160[] = "ripemd160";
+const xmlChar xmlSecHrefRipemd160[] = "http://www.w3.org/2001/04/xmlenc#ripemd160";
+
+/*************************************************************************
+ *
+ * RSA strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameRSAKeyValue[] = "rsa";
+const xmlChar xmlSecNodeRSAKeyValue[] = "RSAKeyValue";
+const xmlChar xmlSecHrefRSAKeyValue[] = "http://www.w3.org/2000/09/xmldsig#RSAKeyValue";
+const xmlChar xmlSecNodeRSAModulus[] = "Modulus";
+const xmlChar xmlSecNodeRSAExponent[] = "Exponent";
+const xmlChar xmlSecNodeRSAPrivateExponent[] = "PrivateExponent";
+
+const xmlChar xmlSecNameRsaMd5[] = "rsa-md5";
+const xmlChar xmlSecHrefRsaMd5[] = "http://www.w3.org/2001/04/xmldsig-more#rsa-md5";
+
+const xmlChar xmlSecNameRsaRipemd160[] = "rsa-ripemd160";
+const xmlChar xmlSecHrefRsaRipemd160[] = "http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160";
+
+const xmlChar xmlSecNameRsaSha1[] = "rsa-sha1";
+const xmlChar xmlSecHrefRsaSha1[] = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
+
+const xmlChar xmlSecNameRsaSha224[] = "rsa-sha224";
+const xmlChar xmlSecHrefRsaSha224[] = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha224";
+
+const xmlChar xmlSecNameRsaSha256[] = "rsa-sha256";
+const xmlChar xmlSecHrefRsaSha256[] = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+
+const xmlChar xmlSecNameRsaSha384[] = "rsa-sha384";
+const xmlChar xmlSecHrefRsaSha384[] = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384";
+
+const xmlChar xmlSecNameRsaSha512[] = "rsa-sha512";
+const xmlChar xmlSecHrefRsaSha512[] = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
+
+const xmlChar xmlSecNameRsaPkcs1[] = "rsa-1_5";
+const xmlChar xmlSecHrefRsaPkcs1[] = "http://www.w3.org/2001/04/xmlenc#rsa-1_5";
+
+const xmlChar xmlSecNameRsaOaep[] = "rsa-oaep-mgf1p";
+const xmlChar xmlSecHrefRsaOaep[] = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p";
+const xmlChar xmlSecNodeRsaOAEPparams[] = "OAEPparams";
+
+/*************************************************************************
+ *
+ * GOSTR3411_94 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameGostR3411_94[] = "gostr3411";
+const xmlChar xmlSecHrefGostR3411_94[] = "http://www.w3.org/2001/04/xmldsig-more#gostr3411";
+
+/*************************************************************************
+ *
+ * SHA1 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameSha1[] = "sha1";
+const xmlChar xmlSecHrefSha1[] = "http://www.w3.org/2000/09/xmldsig#sha1";
+
+const xmlChar xmlSecNameSha224[] = "sha224";
+const xmlChar xmlSecHrefSha224[] = "http://www.w3.org/2001/04/xmldsig-more#sha224";
+
+const xmlChar xmlSecNameSha256[] = "sha256";
+const xmlChar xmlSecHrefSha256[] = "http://www.w3.org/2001/04/xmlenc#sha256";
+
+const xmlChar xmlSecNameSha384[] = "sha384";
+const xmlChar xmlSecHrefSha384[] = "http://www.w3.org/2001/04/xmldsig-more#sha384";
+
+const xmlChar xmlSecNameSha512[] = "sha512";
+const xmlChar xmlSecHrefSha512[] = "http://www.w3.org/2001/04/xmlenc#sha512";
+
+/*************************************************************************
+ *
+ * X509 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameX509Data[] = "x509";
+const xmlChar xmlSecNodeX509Data[] = "X509Data";
+const xmlChar xmlSecHrefX509Data[] = "http://www.w3.org/2000/09/xmldsig#X509Data";
+
+const xmlChar xmlSecNodeX509Certificate[] = "X509Certificate";
+const xmlChar xmlSecNodeX509CRL[] = "X509CRL";
+const xmlChar xmlSecNodeX509SubjectName[] = "X509SubjectName";
+const xmlChar xmlSecNodeX509IssuerSerial[] = "X509IssuerSerial";
+const xmlChar xmlSecNodeX509IssuerName[] = "X509IssuerName";
+const xmlChar xmlSecNodeX509SerialNumber[] = "X509SerialNumber";
+const xmlChar xmlSecNodeX509SKI[] = "X509SKI";
+
+const xmlChar xmlSecNameRawX509Cert[] = "raw-x509-cert";
+const xmlChar xmlSecHrefRawX509Cert[] = "http://www.w3.org/2000/09/xmldsig#rawX509Certificate";
+
+const xmlChar xmlSecNameX509Store[] = "x509-store";
+
+/*************************************************************************
+ *
+ * PGP strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNamePGPData[] = "pgp";
+const xmlChar xmlSecNodePGPData[] = "PGPData";
+const xmlChar xmlSecHrefPGPData[] = "http://www.w3.org/2000/09/xmldsig#PGPData";
+
+/*************************************************************************
+ *
+ * SPKI strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameSPKIData[] = "spki";
+const xmlChar xmlSecNodeSPKIData[] = "SPKIData";
+const xmlChar xmlSecHrefSPKIData[] = "http://www.w3.org/2000/09/xmldsig#SPKIData";
+
+/*************************************************************************
+ *
+ * XPath/XPointer strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameXPath[] = "xpath";
+const xmlChar xmlSecNodeXPath[] = "XPath";
+
+const xmlChar xmlSecNameXPath2[] = "xpath2";
+const xmlChar xmlSecNodeXPath2[] = "XPath";
+const xmlChar xmlSecXPath2FilterIntersect[] = "intersect";
+const xmlChar xmlSecXPath2FilterSubtract[] = "subtract";
+const xmlChar xmlSecXPath2FilterUnion[] = "union";
+
+const xmlChar xmlSecNameXPointer[] = "xpointer";
+const xmlChar xmlSecNodeXPointer[] = "XPointer";
+
+/*************************************************************************
+ *
+ * Xslt strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNameXslt[] = "xslt";
+const xmlChar xmlSecHrefXslt[] = "http://www.w3.org/TR/1999/REC-xslt-19991116";
+
+#ifndef XMLSEC_NO_SOAP
+/*************************************************************************
+ *
+ * SOAP 1.1/1.2 strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecNodeEnvelope[] = "Envelope";
+const xmlChar xmlSecNodeHeader[] = "Header";
+const xmlChar xmlSecNodeBody[] = "Body";
+const xmlChar xmlSecNodeFault[] = "Fault";
+const xmlChar xmlSecNodeFaultCode[] = "faultcode";
+const xmlChar xmlSecNodeFaultString[] = "faultstring";
+const xmlChar xmlSecNodeFaultActor[] = "faultactor";
+const xmlChar xmlSecNodeFaultDetail[] = "detail";
+const xmlChar xmlSecNodeCode[] = "Code";
+const xmlChar xmlSecNodeReason[] = "Reason";
+const xmlChar xmlSecNodeNode[] = "Node";
+const xmlChar xmlSecNodeRole[] = "Role";
+const xmlChar xmlSecNodeDetail[] = "Detail";
+const xmlChar xmlSecNodeValue[] = "Value";
+const xmlChar xmlSecNodeSubcode[] = "Subcode";
+const xmlChar xmlSecNodeText[] = "Text";
+
+
+const xmlChar xmlSecSoapFaultCodeVersionMismatch[] = "VersionMismatch";
+const xmlChar xmlSecSoapFaultCodeMustUnderstand[] = "MustUnderstand";
+const xmlChar xmlSecSoapFaultCodeClient[] = "Client";
+const xmlChar xmlSecSoapFaultCodeServer[] = "Server";
+const xmlChar xmlSecSoapFaultCodeReceiver[] = "Receiver";
+const xmlChar xmlSecSoapFaultCodeSender[] = "Sender";
+const xmlChar xmlSecSoapFaultDataEncodningUnknown[] = "DataEncodingUnknown";
+
+
+#endif /* XMLSEC_NO_SOAP */
+
+/*************************************************************************
+ *
+ * Utility strings
+ *
+ ************************************************************************/
+const xmlChar xmlSecStringEmpty[] = "";
+const xmlChar xmlSecStringCR[] = "\n";
+
+
+
+
+
+
diff --git a/src/templates.c b/src/templates.c
new file mode 100644
index 00000000..67cadb14
--- /dev/null
+++ b/src/templates.c
@@ -0,0 +1,2091 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Creating signature and encryption templates.
+ *
+ * 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/xmltree.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/strings.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/templates.h>
+#include <xmlsec/errors.h>
+
+
+static xmlNodePtr xmlSecTmplAddReference (xmlNodePtr parentNode,
+ xmlSecTransformId digestMethodId,
+ const xmlChar *id,
+ const xmlChar *uri,
+ const xmlChar *type);
+static int xmlSecTmplPrepareEncData (xmlNodePtr parentNode,
+ xmlSecTransformId encMethodId);
+static int xmlSecTmplNodeWriteNsList (xmlNodePtr parentNode,
+ const xmlChar** namespaces);
+/**************************************************************************
+ *
+ * <dsig:Signature/> node
+ *
+ **************************************************************************/
+/**
+ * xmlSecTmplSignatureCreate:
+ * @doc: the pointer to signature document or NULL; in the
+ * second case, application must later call @xmlSetTreeDoc
+ * to ensure that all the children nodes have correct
+ * pointer to XML document.
+ * @c14nMethodId: the signature canonicalization method.
+ * @signMethodId: the signature method.
+ * @id: the node id (may be NULL).
+ *
+ * Creates new <dsig:Signature/> node with the mandatory <dsig:SignedInfo/>,
+ * <dsig:CanonicalizationMethod/>, <dsig:SignatureMethod/> and
+ * <dsig:SignatureValue/> children and sub-children.
+ * The application is responsible for inserting the returned node
+ * in the XML document.
+ *
+ * Returns: the pointer to newly created <dsig:Signature/> node or NULL if an
+ * error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureCreate(xmlDocPtr doc, xmlSecTransformId c14nMethodId,
+ xmlSecTransformId signMethodId, const xmlChar *id) {
+ return xmlSecTmplSignatureCreateNsPref(doc, c14nMethodId, signMethodId, id, NULL);
+}
+
+/**
+ * xmlSecTmplSignatureCreateNsPref:
+ * @doc: the pointer to signature document or NULL; in the
+ * second case, application must later call @xmlSetTreeDoc
+ * to ensure that all the children nodes have correct
+ * pointer to XML document.
+ * @c14nMethodId: the signature canonicalization method.
+ * @signMethodId: the signature method.
+ * @id: the node id (may be NULL).
+ * @nsPrefix: the namespace prefix for the signature element (e.g. "dsig"), or NULL
+ *
+ * Creates new <dsig:Signature/> node with the mandatory
+ * <dsig:SignedInfo/>, <dsig:CanonicalizationMethod/>,
+ * <dsig:SignatureMethod/> and <dsig:SignatureValue/> children and
+ * sub-children. This method differs from xmlSecTmplSignatureCreate in
+ * that it will define the http://www.w3.org/2000/09/xmldsig#
+ * namespace with the given prefix that will be used for all of the
+ * appropriate child nodes. The application is responsible for
+ * inserting the returned node in the XML document.
+ *
+ * Returns: the pointer to newly created <dsig:Signature/> node or NULL if an
+ * error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureCreateNsPref(xmlDocPtr doc, xmlSecTransformId c14nMethodId,
+ xmlSecTransformId signMethodId, const xmlChar *id,
+ const xmlChar* nsPrefix) {
+ xmlNodePtr signNode;
+ xmlNodePtr signedInfoNode;
+ xmlNodePtr cur;
+ xmlNsPtr ns;
+
+ xmlSecAssert2(c14nMethodId != NULL, NULL);
+ xmlSecAssert2(c14nMethodId->href != NULL, NULL);
+ xmlSecAssert2(signMethodId != NULL, NULL);
+ xmlSecAssert2(signMethodId->href != NULL, NULL);
+
+ /* create Signature node itself */
+ signNode = xmlNewDocNode(doc, NULL, xmlSecNodeSignature, NULL);
+ if(signNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDocNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignature));
+ return(NULL);
+ }
+
+ ns = xmlNewNs(signNode, xmlSecDSigNs, nsPrefix);
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(xmlSecDSigNs));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+ xmlSetNs(signNode, ns);
+
+ if(id != NULL) {
+ xmlSetProp(signNode, BAD_CAST "Id", id);
+ }
+
+ /* add SignedInfo node */
+ signedInfoNode = xmlSecAddChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
+ if(signedInfoNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+
+ /* add SignatureValue node */
+ cur = xmlSecAddChild(signNode, xmlSecNodeSignatureValue, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+
+ /* add CanonicaizationMethod node to SignedInfo */
+ cur = xmlSecAddChild(signedInfoNode, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+ if(xmlSetProp(cur, xmlSecAttrAlgorithm, c14nMethodId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(c14nMethodId->href));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+
+ /* add SignatureMethod node to SignedInfo */
+ cur = xmlSecAddChild(signedInfoNode, xmlSecNodeSignatureMethod, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+ if(xmlSetProp(cur, xmlSecAttrAlgorithm, signMethodId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(signMethodId->href));
+ xmlFreeNode(signNode);
+ return(NULL);
+ }
+
+ return(signNode);
+}
+
+/**
+ * xmlSecTmplSignatureEnsureKeyInfo:
+ * @signNode: the pointer to <dsig:Signature/> node.
+ * @id: the node id (may be NULL).
+ *
+ * Adds (if necessary) <dsig:KeyInfo/> node to the <dsig:Signature/>
+ * node @signNode.
+ *
+ * Returns: the pointer to newly created <dsig:KeyInfo/> node or NULL if an
+ * error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureEnsureKeyInfo(xmlNodePtr signNode, const xmlChar *id) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(signNode != NULL, NULL);
+
+ res = xmlSecFindChild(signNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlNodePtr signValueNode;
+
+ signValueNode = xmlSecFindChild(signNode, xmlSecNodeSignatureValue, xmlSecDSigNs);
+ if(signValueNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeSignatureValue),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecAddNextSibling(signValueNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddNextSibling",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ return(NULL);
+ }
+ }
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplSignatureAddReference:
+ * @signNode: the pointer to <dsig:Signature/> node.
+ * @digestMethodId: the reference digest method.
+ * @id: the node id (may be NULL).
+ * @uri: the reference node uri (may be NULL).
+ * @type: the reference node type (may be NULL).
+ *
+ * Adds <dsig:Reference/> node with given URI (@uri), Id (@id) and
+ * Type (@type) attributes and the required children <dsig:DigestMethod/> and
+ * <dsig:DigestValue/> to the <dsig:SignedInfo/> child of @signNode.
+ *
+ * Returns: the pointer to newly created <dsig:Reference/> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureAddReference(xmlNodePtr signNode, xmlSecTransformId digestMethodId,
+ const xmlChar *id, const xmlChar *uri, const xmlChar *type) {
+ xmlNodePtr signedInfoNode;
+
+ xmlSecAssert2(signNode != NULL, NULL);
+ xmlSecAssert2(digestMethodId != NULL, NULL);
+ xmlSecAssert2(digestMethodId->href != NULL, NULL);
+
+ signedInfoNode = xmlSecFindChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
+ if(signedInfoNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeSignedInfo),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecTmplAddReference(signedInfoNode, digestMethodId, id, uri, type));
+}
+
+static xmlNodePtr
+xmlSecTmplAddReference(xmlNodePtr parentNode, xmlSecTransformId digestMethodId,
+ const xmlChar *id, const xmlChar *uri, const xmlChar *type) {
+ xmlNodePtr res;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(parentNode != NULL, NULL);
+ xmlSecAssert2(digestMethodId != NULL, NULL);
+ xmlSecAssert2(digestMethodId->href != NULL, NULL);
+
+ /* add Reference node */
+ res = xmlSecAddChild(parentNode, xmlSecNodeReference, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeReference));
+ return(NULL);
+ }
+
+ /* set Reference node attributes */
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ if(type != NULL) {
+ xmlSetProp(res, xmlSecAttrType, type);
+ }
+ if(uri != NULL) {
+ xmlSetProp(res, xmlSecAttrURI, uri);
+ }
+
+ /* add DigestMethod node and set algorithm */
+ cur = xmlSecAddChild(res, xmlSecNodeDigestMethod, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+ if(xmlSetProp(cur, xmlSecAttrAlgorithm, digestMethodId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(digestMethodId->href));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+
+ /* add DigestValue node */
+ cur = xmlSecAddChild(res, xmlSecNodeDigestValue, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDigestValue));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplSignatureAddObject:
+ * @signNode: the pointer to <dsig:Signature/> node.
+ * @id: the node id (may be NULL).
+ * @mimeType: the object mime type (may be NULL).
+ * @encoding: the object encoding (may be NULL).
+ *
+ * Adds <dsig:Object/> node to the <dsig:Signature/> node @signNode.
+ *
+ * Returns: the pointer to newly created <dsig:Object/> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureAddObject(xmlNodePtr signNode, const xmlChar *id,
+ const xmlChar *mimeType, const xmlChar *encoding) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(signNode != NULL, NULL);
+
+ res = xmlSecAddChild(signNode, xmlSecNodeObject, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeObject));
+ return(NULL);
+ }
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ if(mimeType != NULL) {
+ xmlSetProp(res, xmlSecAttrMimeType, mimeType);
+ }
+ if(encoding != NULL) {
+ xmlSetProp(res, xmlSecAttrEncoding, encoding);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplSignatureGetSignMethodNode:
+ * @signNode: the pointer to <dsig:Signature /> node.
+ *
+ * Gets pointer to <dsig:SignatureMethod/> child of <dsig:KeyInfo/> node.
+ *
+ * Returns: pointer to <dsig:SignatureMethod /> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureGetSignMethodNode(xmlNodePtr signNode) {
+ xmlNodePtr signedInfoNode;
+
+ xmlSecAssert2(signNode != NULL, NULL);
+
+ signedInfoNode = xmlSecFindChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
+ if(signedInfoNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeSignedInfo),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ return(xmlSecFindChild(signedInfoNode, xmlSecNodeSignatureMethod, xmlSecDSigNs));
+}
+
+/**
+ * xmlSecTmplSignatureGetC14NMethodNode:
+ * @signNode: the pointer to <dsig:Signature /> node.
+ *
+ * Gets pointer to <dsig:CanonicalizationMethod/> child of <dsig:KeyInfo/> node.
+ *
+ * Returns: pointer to <dsig:CanonicalizationMethod /> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplSignatureGetC14NMethodNode(xmlNodePtr signNode) {
+ xmlNodePtr signedInfoNode;
+
+ xmlSecAssert2(signNode != NULL, NULL);
+
+ signedInfoNode = xmlSecFindChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
+ if(signedInfoNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeSignedInfo),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ return(xmlSecFindChild(signedInfoNode, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs));
+}
+
+/**
+ * xmlSecTmplReferenceAddTransform:
+ * @referenceNode: the pointer to <dsig:Reference/> node.
+ * @transformId: the transform method id.
+ *
+ * Adds <dsig:Transform/> node to the <dsig:Reference/> node @referenceNode.
+ *
+ * Returns: the pointer to newly created <dsig:Transform/> node or NULL if an
+ * error occurs.
+ */
+xmlNodePtr
+xmlSecTmplReferenceAddTransform(xmlNodePtr referenceNode, xmlSecTransformId transformId) {
+ xmlNodePtr transformsNode;
+ xmlNodePtr res;
+
+ xmlSecAssert2(referenceNode != NULL, NULL);
+ xmlSecAssert2(transformId != NULL, NULL);
+ xmlSecAssert2(transformId->href != NULL, NULL);
+
+ /* do we need to create Transforms node first */
+ transformsNode = xmlSecFindChild(referenceNode, xmlSecNodeTransforms, xmlSecDSigNs);
+ if(transformsNode == NULL) {
+ xmlNodePtr tmp;
+
+ tmp = xmlSecGetNextElementNode(referenceNode->children);
+ if(tmp == NULL) {
+ transformsNode = xmlSecAddChild(referenceNode, xmlSecNodeTransforms, xmlSecDSigNs);
+ } else {
+ transformsNode = xmlSecAddPrevSibling(tmp, xmlSecNodeTransforms, xmlSecDSigNs);
+ }
+ if(transformsNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild or xmlSecAddPrevSibling",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeTransforms));
+ return(NULL);
+ }
+ }
+
+ res = xmlSecAddChild(transformsNode, xmlSecNodeTransform, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeTransform));
+ return(NULL);
+ }
+
+ if(xmlSetProp(res, xmlSecAttrAlgorithm, transformId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(transformId->href));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplObjectAddSignProperties:
+ * @objectNode: the pointer to <dsig:Object/> node.
+ * @id: the node id (may be NULL).
+ * @target: the Target (may be NULL).
+ *
+ * Adds <dsig:SignatureProperties/> node to the <dsig:Object/> node @objectNode.
+ *
+ * Returns: the pointer to newly created <dsig:SignatureProperties/> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplObjectAddSignProperties(xmlNodePtr objectNode, const xmlChar *id, const xmlChar *target) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(objectNode != NULL, NULL);
+
+ res = xmlSecAddChild(objectNode, xmlSecNodeSignatureProperties, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureProperties));
+ return(NULL);
+ }
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ if(target != NULL) {
+ xmlSetProp(res, xmlSecAttrTarget, target);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplObjectAddManifest:
+ * @objectNode: the pointer to <dsig:Object/> node.
+ * @id: the node id (may be NULL).
+ *
+ * Adds <dsig:Manifest/> node to the <dsig:Object/> node @objectNode.
+ *
+ * Returns: the pointer to newly created <dsig:Manifest/> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplObjectAddManifest(xmlNodePtr objectNode, const xmlChar *id) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(objectNode != NULL, NULL);
+
+ res = xmlSecAddChild(objectNode, xmlSecNodeManifest, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeManifest));
+ return(NULL);
+ }
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplManifestAddReference:
+ * @manifestNode: the pointer to <dsig:Manifest/> node.
+ * @digestMethodId: the reference digest method.
+ * @id: the node id (may be NULL).
+ * @uri: the reference node uri (may be NULL).
+ * @type: the reference node type (may be NULL).
+ *
+ * Adds <dsig:Reference/> node with specified URI (@uri), Id (@id) and
+ * Type (@type) attributes and the required children <dsig:DigestMethod/> and
+ * <dsig:DigestValue/> to the <dsig:Manifest/> node @manifestNode.
+ *
+ * Returns: the pointer to newly created <dsig:Reference/> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplManifestAddReference(xmlNodePtr manifestNode, xmlSecTransformId digestMethodId,
+ const xmlChar *id, const xmlChar *uri, const xmlChar *type) {
+ return(xmlSecTmplAddReference(manifestNode, digestMethodId, id, uri, type));
+}
+
+/**************************************************************************
+ *
+ * <enc:EncryptedData/> node
+ *
+ **************************************************************************/
+/**
+ * xmlSecTmplEncDataCreate:
+ * @doc: the pointer to signature document or NULL; in the later
+ * case, application must later call @xmlSetTreeDoc to ensure
+ * that all the children nodes have correct pointer to XML document.
+ * @encMethodId: the encryption method (may be NULL).
+ * @id: the Id attribute (optional).
+ * @type: the Type attribute (optional)
+ * @mimeType: the MimeType attribute (optional)
+ * @encoding: the Encoding attribute (optional)
+ *
+ * Creates new <enc:EncryptedData /> node for encryption template.
+ *
+ * Returns: the pointer newly created <enc:EncryptedData/> node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataCreate(xmlDocPtr doc, xmlSecTransformId encMethodId,
+ const xmlChar *id, const xmlChar *type,
+ const xmlChar *mimeType, const xmlChar *encoding) {
+ xmlNodePtr encNode;
+ xmlNsPtr ns;
+
+ encNode = xmlNewDocNode(doc, NULL, xmlSecNodeEncryptedData, NULL);
+ if(encNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDocNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptedData));
+ return(NULL);
+ }
+
+ ns = xmlNewNs(encNode, xmlSecEncNs, NULL);
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(xmlSecEncNs));
+ return(NULL);
+ }
+ xmlSetNs(encNode, ns);
+
+ if(id != NULL) {
+ xmlSetProp(encNode, xmlSecAttrId, id);
+ }
+ if(type != NULL) {
+ xmlSetProp(encNode, xmlSecAttrType, type);
+ }
+ if(mimeType != NULL) {
+ xmlSetProp(encNode, xmlSecAttrMimeType, mimeType);
+ }
+ if(encoding != NULL) {
+ xmlSetProp(encNode, xmlSecAttrEncoding, encoding);
+ }
+
+ if(xmlSecTmplPrepareEncData(encNode, encMethodId) < 0) {
+ xmlFreeNode(encNode);
+ return(NULL);
+ }
+ return(encNode);
+}
+
+static int
+xmlSecTmplPrepareEncData(xmlNodePtr parentNode, xmlSecTransformId encMethodId) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(parentNode != NULL, -1);
+ xmlSecAssert2((encMethodId == NULL) || (encMethodId->href != NULL), -1);
+
+ /* add EncryptionMethod node if requested */
+ if(encMethodId != NULL) {
+ cur = xmlSecAddChild(parentNode, xmlSecNodeEncryptionMethod, xmlSecEncNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptionMethod));
+ return(-1);
+ }
+ if(xmlSetProp(cur, xmlSecAttrAlgorithm, encMethodId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(encMethodId->href));
+ return(-1);
+ }
+ }
+
+ /* and CipherData node */
+ cur = xmlSecAddChild(parentNode, xmlSecNodeCipherData, xmlSecEncNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCipherData));
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/**
+ * xmlSecTmplEncDataEnsureKeyInfo:
+ * @encNode: the pointer to <enc:EncryptedData/> node.
+ * @id: the Id attrbibute (optional).
+ *
+ * Adds <dsig:KeyInfo/> to the <enc:EncryptedData/> node @encNode.
+ *
+ * Returns: the pointer to newly created <dsig:KeyInfo/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataEnsureKeyInfo(xmlNodePtr encNode, const xmlChar* id) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ res = xmlSecFindChild(encNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlNodePtr cipherDataNode;
+
+ cipherDataNode = xmlSecFindChild(encNode, xmlSecNodeCipherData, xmlSecEncNs);
+ if(cipherDataNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeCipherData),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecAddPrevSibling(cipherDataNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddPrevSibling",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ return(NULL);
+ }
+ }
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplEncDataEnsureEncProperties:
+ * @encNode: the pointer to <enc:EncryptedData/> node.
+ * @id: the Id attribute (optional).
+ *
+ * Adds <enc:EncryptionProperties/> node to the <enc:EncryptedData/>
+ * node @encNode.
+ *
+ * Returns: the pointer to newly created <enc:EncryptionProperties/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataEnsureEncProperties(xmlNodePtr encNode, const xmlChar *id) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ res = xmlSecFindChild(encNode, xmlSecNodeEncryptionProperties, xmlSecEncNs);
+ if(res == NULL) {
+ res = xmlSecAddChild(encNode, xmlSecNodeEncryptionProperties, xmlSecEncNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptionProperties));
+ return(NULL);
+ }
+ }
+
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplEncDataAddEncProperty:
+ * @encNode: the pointer to <enc:EncryptedData/> node.
+ * @id: the Id attribute (optional).
+ * @target: the Target attribute (optional).
+ *
+ * Adds <enc:EncryptionProperty/> node (and the parent
+ * <enc:EncryptionProperties/> node if required) to the
+ * <enc:EncryptedData/> node @encNode.
+ *
+ * Returns: the pointer to newly created <enc:EncryptionProperty/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataAddEncProperty(xmlNodePtr encNode, const xmlChar *id, const xmlChar *target) {
+ xmlNodePtr encProps;
+ xmlNodePtr res;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ encProps = xmlSecTmplEncDataEnsureEncProperties(encNode, NULL);
+ if(encProps == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTmplEncDataEnsureEncProperties",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecAddChild(encProps, xmlSecNodeEncryptionProperty, xmlSecEncNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptionProperty));
+ return(NULL);
+ }
+ if(id != NULL) {
+ xmlSetProp(res, xmlSecAttrId, id);
+ }
+ if(target != NULL) {
+ xmlSetProp(res, xmlSecAttrTarget, target);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplEncDataEnsureCipherValue:
+ * @encNode: the pointer to <enc:EncryptedData/> node.
+ *
+ * Adds <enc:CipherValue/> to the <enc:EncryptedData/> node @encNode.
+ *
+ * Returns: the pointer to newly created <enc:CipherValue/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataEnsureCipherValue(xmlNodePtr encNode) {
+ xmlNodePtr cipherDataNode;
+ xmlNodePtr res, tmp;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ cipherDataNode = xmlSecFindChild(encNode, xmlSecNodeCipherData, xmlSecEncNs);
+ if(cipherDataNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeCipherData),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* check that we don;t have CipherReference node */
+ tmp = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherReference, xmlSecEncNs);
+ if(tmp != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeCipherReference),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherValue, xmlSecEncNs);
+ if(res == NULL) {
+ res = xmlSecAddChild(cipherDataNode, xmlSecNodeCipherValue, xmlSecEncNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCipherValue));
+ return(NULL);
+ }
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplEncDataEnsureCipherReference:
+ * @encNode: the pointer to <enc:EncryptedData/> node.
+ * @uri: the URI attribute (may be NULL).
+ *
+ * Adds <enc:CipherReference/> node with specified URI attribute @uri
+ * to the <enc:EncryptedData/> node @encNode.
+ *
+ * Returns: the pointer to newly created <enc:CipherReference/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataEnsureCipherReference(xmlNodePtr encNode, const xmlChar *uri) {
+ xmlNodePtr cipherDataNode;
+ xmlNodePtr res, tmp;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ cipherDataNode = xmlSecFindChild(encNode, xmlSecNodeCipherData, xmlSecEncNs);
+ if(cipherDataNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeCipherData),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* check that we don;t have CipherValue node */
+ tmp = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherValue, xmlSecEncNs);
+ if(tmp != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeCipherValue),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherReference, xmlSecEncNs);
+ if(res == NULL) {
+ res = xmlSecAddChild(cipherDataNode, xmlSecNodeCipherReference, xmlSecEncNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCipherReference));
+ return(NULL);
+ }
+ }
+
+ if(uri != NULL) {
+ xmlSetProp(res, xmlSecAttrURI, uri);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplEncDataGetEncMethodNode:
+ * @encNode: the pointer to <enc:EcnryptedData /> node.
+ *
+ * Gets pointer to <enc:EncrytpionMethod/> node.
+ *
+ * Returns: pointer to <enc:EncryptionMethod /> node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplEncDataGetEncMethodNode(xmlNodePtr encNode) {
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ return(xmlSecFindChild(encNode, xmlSecNodeEncryptionMethod, xmlSecEncNs));
+}
+
+/**
+ * xmlSecTmplCipherReferenceAddTransform:
+ * @cipherReferenceNode: the pointer to <enc:CipherReference/> node.
+ * @transformId: the transform id.
+ *
+ * Adds <dsig:Transform/> node (and the parent <dsig:Transforms/> node)
+ * with specified transform methods @transform to the <enc:CipherReference/>
+ * child node of the <enc:EncryptedData/> node @encNode.
+ *
+ * Returns: the pointer to newly created <dsig:Transform/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplCipherReferenceAddTransform(xmlNodePtr cipherReferenceNode,
+ xmlSecTransformId transformId) {
+ xmlNodePtr transformsNode;
+ xmlNodePtr res;
+
+ xmlSecAssert2(cipherReferenceNode != NULL, NULL);
+ xmlSecAssert2(transformId != NULL, NULL);
+ xmlSecAssert2(transformId->href != NULL, NULL);
+
+ transformsNode = xmlSecFindChild(cipherReferenceNode, xmlSecNodeTransforms, xmlSecEncNs);
+ if(transformsNode == NULL) {
+ transformsNode = xmlSecAddChild(cipherReferenceNode, xmlSecNodeTransforms, xmlSecEncNs);
+ if(transformsNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeTransforms));
+ return(NULL);
+ }
+ }
+
+ res = xmlSecAddChild(transformsNode, xmlSecNodeTransform, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeTransform));
+ return(NULL);
+ }
+
+ if(xmlSetProp(res, xmlSecAttrAlgorithm, transformId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(transformId->href));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+
+/***********************************************************************
+ *
+ * <enc:EncryptedKey> node
+ *
+ **********************************************************************/
+
+/**
+ * xmlSecTmplReferenceListAddDataReference:
+ * @encNode: the pointer to <enc:EncryptedKey/> node.
+ * @uri: uri to reference (optional)
+ *
+ * Adds <enc:DataReference/> and the parent <enc:ReferenceList/> node (if needed).
+ *
+ * Returns: the pointer to newly created <enc:DataReference/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplReferenceListAddDataReference(xmlNodePtr encNode, const xmlChar *uri) {
+ xmlNodePtr refListNode, res;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ refListNode = xmlSecFindChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
+ if(refListNode == NULL) {
+ refListNode = xmlSecAddChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
+ if(refListNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeReferenceList));
+ return(NULL);
+ }
+ }
+
+ res = xmlSecAddChild(refListNode, xmlSecNodeDataReference, xmlSecEncNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDataReference));
+ return(NULL);
+ }
+
+ if(uri != NULL) {
+ if(xmlSetProp(res, xmlSecAttrURI, uri) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrURI),
+ xmlSecErrorsSafeString(uri));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplReferenceListAddKeyReference:
+ * @encNode: the pointer to <enc:EncryptedKey/> node.
+ * @uri: uri to reference (optional)
+ *
+ * Adds <enc:KeyReference/> and the parent <enc:ReferenceList/> node (if needed).
+ *
+ * Returns: the pointer to newly created <enc:KeyReference/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplReferenceListAddKeyReference(xmlNodePtr encNode, const xmlChar *uri) {
+ xmlNodePtr refListNode, res;
+
+ xmlSecAssert2(encNode != NULL, NULL);
+
+ refListNode = xmlSecFindChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
+ if(refListNode == NULL) {
+ refListNode = xmlSecAddChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
+ if(refListNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeReferenceList));
+ return(NULL);
+ }
+ }
+
+ res = xmlSecAddChild(refListNode, xmlSecNodeKeyReference, xmlSecEncNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyReference));
+ return(NULL);
+ }
+
+ if(uri != NULL) {
+ if(xmlSetProp(res, xmlSecAttrURI, uri) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrURI),
+ xmlSecErrorsSafeString(uri));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+ }
+
+ return(res);
+}
+
+
+/**************************************************************************
+ *
+ * <dsig:KeyInfo/> node
+ *
+ **************************************************************************/
+
+/**
+ * xmlSecTmplKeyInfoAddKeyName:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ * @name: the key name (optional).
+ *
+ * Adds <dsig:KeyName/> node to the <dsig:KeyInfo/> node @keyInfoNode.
+ *
+ * Returns: the pointer to the newly created <dsig:KeyName/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplKeyInfoAddKeyName(xmlNodePtr keyInfoNode, const xmlChar* name) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(keyInfoNode != NULL, NULL);
+
+ res = xmlSecAddChild(keyInfoNode, xmlSecNodeKeyName, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyName));
+ return(NULL);
+ }
+ if(name != NULL) {
+ xmlSecNodeEncodeAndSetContent(res, name);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplKeyInfoAddKeyValue:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ *
+ * Adds <dsig:KeyValue/> node to the <dsig:KeyInfo/> node @keyInfoNode.
+ *
+ * Returns: the pointer to the newly created <dsig:KeyValue/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplKeyInfoAddKeyValue(xmlNodePtr keyInfoNode) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(keyInfoNode != NULL, NULL);
+
+ res = xmlSecAddChild(keyInfoNode, xmlSecNodeKeyValue, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyValue));
+ return(NULL);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplKeyInfoAddX509Data:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ *
+ * Adds <dsig:X509Data/> node to the <dsig:KeyInfo/> node @keyInfoNode.
+ *
+ * Returns: the pointer to the newly created <dsig:X509Data/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplKeyInfoAddX509Data(xmlNodePtr keyInfoNode) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(keyInfoNode != NULL, NULL);
+
+ res = xmlSecAddChild(keyInfoNode, xmlSecNodeX509Data, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509Data));
+ return(NULL);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecTmplKeyInfoAddRetrievalMethod:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ * @uri: the URI attribute (optional).
+ * @type: the Type attribute(optional).
+ *
+ * Adds <dsig:RetrievalMethod/> node to the <dsig:KeyInfo/> node @keyInfoNode.
+ *
+ * Returns: the pointer to the newly created <dsig:RetrievalMethod/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplKeyInfoAddRetrievalMethod(xmlNodePtr keyInfoNode, const xmlChar *uri,
+ const xmlChar *type) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(keyInfoNode != NULL, NULL);
+
+ res = xmlSecAddChild(keyInfoNode, xmlSecNodeRetrievalMethod, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRetrievalMethod));
+ return(NULL);
+ }
+
+ if(uri != NULL) {
+ xmlSetProp(res, xmlSecAttrURI, uri);
+ }
+ if(type != NULL) {
+ xmlSetProp(res, xmlSecAttrType, type);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplRetrievalMethodAddTransform:
+ * @retrMethodNode: the pointer to <dsig:RetrievalMethod/> node.
+ * @transformId: the transform id.
+ *
+ * Adds <dsig:Transform/> node (and the parent <dsig:Transforms/> node
+ * if required) to the <dsig:RetrievalMethod/> node @retrMethod.
+ *
+ * Returns: the pointer to the newly created <dsig:Transforms/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplRetrievalMethodAddTransform(xmlNodePtr retrMethodNode, xmlSecTransformId transformId) {
+ xmlNodePtr transformsNode;
+ xmlNodePtr res;
+
+ xmlSecAssert2(retrMethodNode != NULL, NULL);
+ xmlSecAssert2(transformId != NULL, NULL);
+ xmlSecAssert2(transformId->href != NULL, NULL);
+
+ transformsNode = xmlSecFindChild(retrMethodNode, xmlSecNodeTransforms, xmlSecDSigNs);
+ if(transformsNode == NULL) {
+ transformsNode = xmlSecAddChild(retrMethodNode, xmlSecNodeTransforms, xmlSecDSigNs);
+ if(transformsNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeTransforms));
+ return(NULL);
+ }
+ }
+
+ res = xmlSecAddChild(transformsNode, xmlSecNodeTransform, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeTransform));
+ return(NULL);
+ }
+
+ if(xmlSetProp(res, xmlSecAttrAlgorithm, transformId->href) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ xmlSecErrorsSafeString(transformId->href));
+ xmlUnlinkNode(res);
+ xmlFreeNode(res);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+
+/**
+ * xmlSecTmplKeyInfoAddEncryptedKey:
+ * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
+ * @encMethodId: the encryption method (optional).
+ * @id: the Id attribute (optional).
+ * @type: the Type attribute (optional).
+ * @recipient: the Recipient attribute (optional).
+ *
+ * Adds <enc:EncryptedKey/> node with given attributes to
+ * the <dsig:KeyInfo/> node @keyInfoNode.
+ *
+ * Returns: the pointer to the newly created <enc:EncryptedKey/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplKeyInfoAddEncryptedKey(xmlNodePtr keyInfoNode, xmlSecTransformId encMethodId,
+ const xmlChar* id, const xmlChar* type, const xmlChar* recipient) {
+ xmlNodePtr encKeyNode;
+
+ xmlSecAssert2(keyInfoNode != NULL, NULL);
+
+ /* we allow multiple encrypted key elements */
+ encKeyNode = xmlSecAddChild(keyInfoNode, xmlSecNodeEncryptedKey, xmlSecEncNs);
+ if(encKeyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptedKey));
+ return(NULL);
+ }
+
+ if(id != NULL) {
+ xmlSetProp(encKeyNode, xmlSecAttrId, id);
+ }
+ if(type != NULL) {
+ xmlSetProp(encKeyNode, xmlSecAttrType, type);
+ }
+ if(recipient != NULL) {
+ xmlSetProp(encKeyNode, xmlSecAttrRecipient, recipient);
+ }
+
+ if(xmlSecTmplPrepareEncData(encKeyNode, encMethodId) < 0) {
+ xmlUnlinkNode(encKeyNode);
+ xmlFreeNode(encKeyNode);
+ return(NULL);
+ }
+ return(encKeyNode);
+}
+
+/***********************************************************************
+ *
+ * <dsig:X509Data> node
+ *
+ **********************************************************************/
+/**
+ * xmlSecTmplX509DataAddIssuerSerial:
+ * @x509DataNode: the pointer to <dsig:X509Data/> node.
+ *
+ * Adds <dsig:X509IssuerSerial/> node to the given <dsig:X509Data/> node.
+ *
+ * Returns: the pointer to the newly created <dsig:X509IssuerSerial/> node or
+ * NULL if an error occurs.
+ */
+
+xmlNodePtr
+xmlSecTmplX509DataAddIssuerSerial(xmlNodePtr x509DataNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(x509DataNode != NULL, NULL);
+
+ cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial));
+ return(NULL);
+ }
+
+ return (cur);
+}
+
+/**
+ * xmlSecTmplX509IssuerSerialAddIssuerName:
+ * @x509IssuerSerialNode: the pointer to <dsig:X509IssuerSerial/> node.
+ * @issuerName: the issuer name (optional).
+ *
+ * Adds <dsig:X509IssuerName/> node to the <dsig:X509IssuerSerial/> node @x509IssuerSerialNode.
+ *
+ * Returns: the pointer to the newly created <dsig:X509IssuerName/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplX509IssuerSerialAddIssuerName(xmlNodePtr x509IssuerSerialNode, const xmlChar* issuerName) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(x509IssuerSerialNode != NULL, NULL);
+
+ if(xmlSecFindChild(x509IssuerSerialNode, xmlSecNodeX509IssuerName,
+ xmlSecDSigNs) != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecAddChild(x509IssuerSerialNode, xmlSecNodeX509IssuerName, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+ return(NULL);
+ }
+
+ if (issuerName != NULL) {
+ xmlSecNodeEncodeAndSetContent(res, issuerName);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplX509IssuerSerialAddSerialNumber:
+ * @x509IssuerSerialNode: the pointer to <dsig:X509IssuerSerial/> node.
+ * @serial: the serial number (optional).
+ *
+ * Adds <dsig:X509SerialNumber/> node to the <dsig:X509IssuerSerial/> node @x509IssuerSerialNode.
+ *
+ * Returns: the pointer to the newly created <dsig:X509SerialNumber/> node or
+ * NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecTmplX509IssuerSerialAddSerialNumber(xmlNodePtr x509IssuerSerialNode, const xmlChar* serial) {
+ xmlNodePtr res;
+
+ xmlSecAssert2(x509IssuerSerialNode != NULL, NULL);
+
+ if(xmlSecFindChild(x509IssuerSerialNode, xmlSecNodeX509SerialNumber,
+ xmlSecDSigNs) != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecAddChild(x509IssuerSerialNode, xmlSecNodeX509SerialNumber, xmlSecDSigNs);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+ return(NULL);
+ }
+
+ if (serial != NULL) {
+ xmlSecNodeEncodeAndSetContent(res, serial);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecTmplX509DataAddSubjectName:
+ * @x509DataNode: the pointer to <dsig:X509Data/> node.
+ *
+ * Adds <dsig:X509SubjectName/> node to the given <dsig:X509Data/> node.
+ *
+ * Returns: the pointer to the newly created <dsig:X509SubjectName/> node or
+ * NULL if an error occurs.
+ */
+
+xmlNodePtr
+xmlSecTmplX509DataAddSubjectName(xmlNodePtr x509DataNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(x509DataNode != NULL, NULL);
+
+ cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509SubjectName),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SubjectName));
+ return(NULL);
+ }
+
+ return (cur);
+}
+
+/**
+ * xmlSecTmplX509DataAddSKI:
+ * @x509DataNode: the pointer to <dsig:X509Data/> node.
+ *
+ * Adds <dsig:X509SKI/> node to the given <dsig:X509Data/> node.
+ *
+ * Returns: the pointer to the newly created <dsig:X509SKI/> node or
+ * NULL if an error occurs.
+ */
+
+xmlNodePtr
+xmlSecTmplX509DataAddSKI(xmlNodePtr x509DataNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(x509DataNode != NULL, NULL);
+
+ cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509SKI, xmlSecDSigNs);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509SKI, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+ return(NULL);
+ }
+
+ return (cur);
+}
+
+
+/**
+ * xmlSecTmplX509DataAddCertificate:
+ * @x509DataNode: the pointer to <dsig:X509Data/> node.
+ *
+ * Adds <dsig:X509Certificate/> node to the given <dsig:X509Data/> node.
+ *
+ * Returns: the pointer to the newly created <dsig:X509Certificate/> node or
+ * NULL if an error occurs.
+ */
+
+xmlNodePtr
+xmlSecTmplX509DataAddCertificate(xmlNodePtr x509DataNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(x509DataNode != NULL, NULL);
+
+ cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509Certificate, xmlSecDSigNs);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509Certificate),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509Certificate, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509Certificate));
+ return(NULL);
+ }
+
+ return (cur);
+}
+
+/**
+ * xmlSecTmplX509DataAddCRL:
+ * @x509DataNode: the pointer to <dsig:X509Data/> node.
+ *
+ * Adds <dsig:X509CRL/> node to the given <dsig:X509Data/> node.
+ *
+ * Returns: the pointer to the newly created <dsig:X509CRL/> node or
+ * NULL if an error occurs.
+ */
+
+xmlNodePtr
+xmlSecTmplX509DataAddCRL(xmlNodePtr x509DataNode) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(x509DataNode != NULL, NULL);
+
+ cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509CRL, xmlSecDSigNs);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeX509CRL),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509CRL, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509CRL));
+ return(NULL);
+ }
+
+ return (cur);
+}
+
+/*************************************************************************
+ *
+ * <dsig:Transform/> node
+ *
+ ************************************************************************/
+
+/**
+ * xmlSecTmplTransformAddHmacOutputLength:
+ * @transformNode: the pointer to <dsig:Transform/> node
+ * @bitsLen: the required length in bits
+ *
+ * Creates <dsig:HMACOutputLength/> child for the HMAC transform
+ * node @node.
+ *
+ * Returns: 0 on success and a negatie value otherwise.
+ */
+int
+xmlSecTmplTransformAddHmacOutputLength(xmlNodePtr transformNode, xmlSecSize bitsLen) {
+ xmlNodePtr cur;
+ char buf[32];
+
+ xmlSecAssert2(transformNode != NULL, -1);
+ xmlSecAssert2(bitsLen > 0, -1);
+
+ cur = xmlSecFindChild(transformNode, xmlSecNodeHMACOutputLength, xmlSecDSigNs);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeHMACOutputLength),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(transformNode, xmlSecNodeHMACOutputLength, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeHMACOutputLength));
+ return(-1);
+ }
+
+ sprintf(buf, "%u", bitsLen);
+ xmlNodeSetContent(cur, BAD_CAST buf);
+ return(0);
+}
+
+/**
+ * xmlSecTmplTransformAddRsaOaepParam:
+ * @transformNode: the pointer to <dsig:Transform/> node.
+ * @buf: the OAEP param buffer.
+ * @size: the OAEP param buffer size.
+ *
+ * Creates <enc:OAEPParam/> child node in the @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTmplTransformAddRsaOaepParam(xmlNodePtr transformNode,
+ const xmlSecByte *buf, xmlSecSize size) {
+ xmlNodePtr oaepParamNode;
+ xmlChar *base64;
+
+ xmlSecAssert2(transformNode != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(size > 0, -1);
+
+ oaepParamNode = xmlSecFindChild(transformNode, xmlSecNodeRsaOAEPparams, xmlSecEncNs);
+ if(oaepParamNode != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeRsaOAEPparams),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ oaepParamNode = xmlSecAddChild(transformNode, xmlSecNodeRsaOAEPparams, xmlSecEncNs);
+ if(oaepParamNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRsaOAEPparams));
+ return(-1);
+ }
+
+ base64 = xmlSecBase64Encode(buf, size, 0);
+ if(base64 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+
+ xmlNodeSetContent(oaepParamNode, base64);
+ xmlFree(base64);
+ return(0);
+}
+
+/**
+ * xmlSecTmplTransformAddXsltStylesheet:
+ * @transformNode: the pointer to <dsig:Transform/> node.
+ * @xslt: the XSLT transform exspression.
+ *
+ * Writes the XSLT transform expression to the @node.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTmplTransformAddXsltStylesheet(xmlNodePtr transformNode, const xmlChar *xslt) {
+ xmlDocPtr xsltDoc;
+ int ret;
+
+ xmlSecAssert2(transformNode != NULL, -1);
+ xmlSecAssert2(xslt != NULL, -1);
+
+ xsltDoc = xmlParseMemory((const char*)xslt, xmlStrlen(xslt));
+ if(xsltDoc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlParseMemory",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecReplaceContent(transformNode, xmlDocGetRootElement(xsltDoc));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(xsltDoc);
+ return(-1);
+ }
+
+ xmlFreeDoc(xsltDoc);
+ return(0);
+}
+
+/**
+ * xmlSecTmplTransformAddC14NInclNamespaces:
+ * @transformNode: the pointer to <dsig:Transform/> node.
+ * @prefixList: the white space delimited list of namespace prefixes,
+ * where "#default" indicates the default namespace
+ * (optional).
+ *
+ * Adds "inclusive" namespaces to the ExcC14N transform node @node.
+ *
+ * Returns: 0 if success or a negative value otherwise.
+ */
+int
+xmlSecTmplTransformAddC14NInclNamespaces(xmlNodePtr transformNode,
+ const xmlChar *prefixList) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(transformNode != NULL, -1);
+ xmlSecAssert2(prefixList != NULL, -1);
+
+ cur = xmlSecFindChild(transformNode, xmlSecNodeInclusiveNamespaces, xmlSecNsExcC14N);
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeInclusiveNamespaces),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(transformNode, xmlSecNodeInclusiveNamespaces, xmlSecNsExcC14N);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(transformNode)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeInclusiveNamespaces));
+ return(-1);
+ }
+
+ xmlSetProp(cur, xmlSecAttrPrefixList, prefixList);
+ return(0);
+}
+
+/**
+ * xmlSecTmplTransformAddXPath:
+ * @transformNode: the pointer to the <dsig:Transform/> node.
+ * @expression: the XPath expression.
+ * @nsList: the NULL terminated list of namespace prefix/href pairs
+ * (optional).
+ *
+ * Writes XPath transform infromation to the <dsig:Transform/> node
+ * @node.
+ *
+ * Returns: 0 for success or a negative value otherwise.
+ */
+int
+xmlSecTmplTransformAddXPath(xmlNodePtr transformNode, const xmlChar *expression,
+ const xmlChar **nsList) {
+ xmlNodePtr xpathNode;
+
+ xmlSecAssert2(transformNode != NULL, -1);
+ xmlSecAssert2(expression != NULL, -1);
+
+ xpathNode = xmlSecFindChild(transformNode, xmlSecNodeXPath, xmlSecDSigNs);
+ if(xpathNode != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeXPath),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ xpathNode = xmlSecAddChild(transformNode, xmlSecNodeXPath, xmlSecDSigNs);
+ if(xpathNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPath));
+ return(-1);
+ }
+
+ xmlSecNodeEncodeAndSetContent(xpathNode, expression);
+ return((nsList != NULL) ? xmlSecTmplNodeWriteNsList(xpathNode, nsList) : 0);
+}
+
+/**
+ * xmlSecTmplTransformAddXPath2:
+ * @transformNode: the pointer to the <dsig:Transform/> node.
+ * @type: the XPath2 transform type ("union", "intersect" or "subtract").
+ * @expression: the XPath expression.
+ * @nsList: the NULL terminated list of namespace prefix/href pairs.
+ * (optional).
+ *
+ * Writes XPath2 transform infromation to the <dsig:Transform/> node
+ * @node.
+ *
+ * Returns: 0 for success or a negative value otherwise.
+ */
+int
+xmlSecTmplTransformAddXPath2(xmlNodePtr transformNode, const xmlChar* type,
+ const xmlChar *expression, const xmlChar **nsList) {
+ xmlNodePtr xpathNode;
+
+ xmlSecAssert2(transformNode != NULL, -1);
+ xmlSecAssert2(type != NULL, -1);
+ xmlSecAssert2(expression != NULL, -1);
+
+ xpathNode = xmlSecAddChild(transformNode, xmlSecNodeXPath, xmlSecXPath2Ns);
+ if(xpathNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPath));
+ return(-1);
+ }
+ xmlSetProp(xpathNode, xmlSecAttrFilter, type);
+
+ xmlSecNodeEncodeAndSetContent(xpathNode, expression);
+ return((nsList != NULL) ? xmlSecTmplNodeWriteNsList(xpathNode, nsList) : 0);
+}
+
+/**
+ * xmlSecTmplTransformAddXPointer:
+ * @transformNode: the pointer to the <dsig:Transform/> node.
+ * @expression: the XPath expression.
+ * @nsList: the NULL terminated list of namespace prefix/href pairs.
+ * (optional).
+ *
+ * Writes XPoniter transform infromation to the <dsig:Transform/> node
+ * @node.
+ *
+ * Returns: 0 for success or a negative value otherwise.
+ */
+int
+xmlSecTmplTransformAddXPointer(xmlNodePtr transformNode, const xmlChar *expression,
+ const xmlChar **nsList) {
+ xmlNodePtr xpointerNode;
+
+ xmlSecAssert2(expression != NULL, -1);
+ xmlSecAssert2(transformNode != NULL, -1);
+
+ xpointerNode = xmlSecFindChild(transformNode, xmlSecNodeXPointer, xmlSecXPointerNs);
+ if(xpointerNode != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeXPointer),
+ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ xpointerNode = xmlSecAddChild(transformNode, xmlSecNodeXPointer, xmlSecXPointerNs);
+ if(xpointerNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPointer));
+ return(-1);
+ }
+
+
+ xmlSecNodeEncodeAndSetContent(xpointerNode, expression);
+ return((nsList != NULL) ? xmlSecTmplNodeWriteNsList(xpointerNode, nsList) : 0);
+}
+
+static int
+xmlSecTmplNodeWriteNsList(xmlNodePtr parentNode, const xmlChar** nsList) {
+ xmlNsPtr ns;
+ const xmlChar *prefix;
+ const xmlChar *href;
+ const xmlChar **ptr;
+
+ xmlSecAssert2(parentNode != NULL, -1);
+ xmlSecAssert2(nsList != NULL, -1);
+
+ ptr = nsList;
+ while((*ptr) != NULL) {
+ if(xmlStrEqual(BAD_CAST "#default", (*ptr))) {
+ prefix = NULL;
+ } else {
+ prefix = (*ptr);
+ }
+ if((++ptr) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "unexpected end of ns list");
+ return(-1);
+ }
+ href = *(ptr++);
+
+ ns = xmlNewNs(parentNode, href, prefix);
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "href=%s;prefix=%s",
+ xmlSecErrorsSafeString(href),
+ xmlSecErrorsSafeString(prefix));
+ return(-1);
+ }
+ }
+ return(0);
+}
diff --git a/src/transforms.c b/src/transforms.c
new file mode 100644
index 00000000..2ed3fe88
--- /dev/null
+++ b/src/transforms.c
@@ -0,0 +1,2892 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * The Transforms Element (http://www.w3.org/TR/xmldsig-core/#sec-Transforms)
+ *
+ * The optional Transforms element contains an ordered list of Transform
+ * elements; these describe how the signer obtained the data object that
+ * was digested.
+ *
+ * Schema Definition:
+ *
+ * <element name="Transforms" type="ds:TransformsType"/>
+ * <complexType name="TransformsType">
+ * <sequence>
+ * <element ref="ds:Transform" maxOccurs="unbounded"/>
+ * </sequence>
+ * </complexType>
+ *
+ * <element name="Transform" type="ds:TransformType"/>
+ * <complexType name="TransformType" mixed="true">
+ * <choice minOccurs="0" maxOccurs="unbounded">
+ * <any namespace="##other" processContents="lax"/>
+ * <!-- (1,1) elements from (0,unbounded) namespaces -->
+ * <element name="XPath" type="string"/>
+ * </choice>
+ * <attribute name="Algorithm" type="anyURI" use="required"/>
+ * </complexType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT Transforms (Transform+)>
+ * <!ELEMENT Transform (#PCDATA|XPath %Transform.ANY;)* >
+ * <!ATTLIST Transform Algorithm CDATA #REQUIRED >
+ * <!ELEMENT XPath (#PCDATA) >
+ *
+ * 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 <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpointer.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keysdata.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/io.h>
+#include <xmlsec/membuf.h>
+#include <xmlsec/parser.h>
+#include <xmlsec/errors.h>
+
+/**************************************************************************
+ *
+ * Global xmlSecTransformIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllTransformIds;
+
+
+/**
+ * xmlSecTransformIdsGet:
+ *
+ * Gets global registered transform klasses list.
+ *
+ * Returns: the pointer to list of all registered transform klasses.
+ */
+xmlSecPtrListPtr
+xmlSecTransformIdsGet(void) {
+ return(&xmlSecAllTransformIds);
+}
+
+/**
+ * xmlSecTransformIdsInit:
+ *
+ * Initializes the transform klasses. This function is called from the
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformIdsInit(void) {
+ int ret;
+
+ ret = xmlSecPtrListInitialize(xmlSecTransformIdsGet(), xmlSecTransformIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListPtrInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecTransformIdListId");
+ return(-1);
+ }
+
+ ret = xmlSecTransformIdsRegisterDefault();
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegisterDefault",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformIdsShutdown:
+ *
+ * Shuts down the keys data klasses. This function is called from the
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+void
+xmlSecTransformIdsShutdown(void) {
+ xmlSecPtrListFinalize(xmlSecTransformIdsGet());
+}
+
+/**
+ * xmlSecTransformIdsRegister:
+ * @id: the transform klass.
+ *
+ * Registers @id in the global list of transform klasses.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformIdsRegister(xmlSecTransformId id) {
+ int ret;
+
+ xmlSecAssert2(id != xmlSecTransformIdUnknown, -1);
+
+ ret = xmlSecPtrListAdd(xmlSecTransformIdsGet(), (xmlSecPtr)id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * transform klasses: XPath transform, Base64 transform, ...
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformIdsRegisterDefault(void) {
+ if(xmlSecTransformIdsRegister(xmlSecTransformBase64Id) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformBase64Id)));
+ return(-1);
+ }
+
+ if(xmlSecTransformIdsRegister(xmlSecTransformEnvelopedId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformEnvelopedId)));
+ return(-1);
+ }
+
+ /* c14n methods */
+ if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId)));
+ return(-1);
+ }
+ if(xmlSecTransformIdsRegister(xmlSecTransformInclC14NWithCommentsId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NWithCommentsId)));
+ return(-1);
+ }
+ if(xmlSecTransformIdsRegister(xmlSecTransformInclC14N11Id) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14N11Id)));
+ return(-1);
+ }
+ if(xmlSecTransformIdsRegister(xmlSecTransformInclC14N11WithCommentsId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14N11WithCommentsId)));
+ return(-1);
+ }
+ if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NId)));
+ return(-1);
+ }
+ if(xmlSecTransformIdsRegister(xmlSecTransformExclC14NWithCommentsId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformExclC14NWithCommentsId)));
+ return(-1);
+ }
+
+ if(xmlSecTransformIdsRegister(xmlSecTransformXPathId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPathId)));
+ return(-1);
+ }
+
+ if(xmlSecTransformIdsRegister(xmlSecTransformXPath2Id) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPath2Id)));
+ return(-1);
+ }
+
+ if(xmlSecTransformIdsRegister(xmlSecTransformXPointerId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId)));
+ return(-1);
+ }
+
+#ifndef XMLSEC_NO_XSLT
+ if(xmlSecTransformIdsRegister(xmlSecTransformXsltId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXsltId)));
+ return(-1);
+ }
+#endif /* XMLSEC_NO_XSLT */
+
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * utils
+ *
+ *************************************************************************/
+/**
+ * xmlSecTransformUriTypeCheck:
+ * @type: the expected URI type.
+ * @uri: the uri for checking.
+ *
+ * Checks if @uri matches expected type @type.
+ *
+ * Returns: 1 if @uri matches @type, 0 if not or a negative value
+ * if an error occurs.
+ */
+int
+xmlSecTransformUriTypeCheck(xmlSecTransformUriType type, const xmlChar* uri) {
+ xmlSecTransformUriType uriType = 0;
+
+ if((uri == NULL) || (xmlStrlen(uri) == 0)) {
+ uriType = xmlSecTransformUriTypeEmpty;
+ } else if(uri[0] == '#') {
+ uriType = xmlSecTransformUriTypeSameDocument;
+ } else if(xmlStrncmp(uri, BAD_CAST "file://", 7) == 0) {
+ uriType = xmlSecTransformUriTypeLocal;
+ } else {
+ uriType = xmlSecTransformUriTypeRemote;
+ }
+ return(((uriType & type) != 0) ? 1 : 0);
+}
+
+/**************************************************************************
+ *
+ * xmlSecTransformCtx
+ *
+ *************************************************************************/
+
+/**
+ * xmlSecTransformCtxCreate:
+ *
+ * Creates transforms chain processing context.
+ * The caller is responsible for destroying returend object by calling
+ * #xmlSecTransformCtxDestroy function.
+ *
+ * Returns: pointer to newly allocated context object or NULL if an error
+ * occurs.
+ */
+xmlSecTransformCtxPtr
+xmlSecTransformCtxCreate(void) {
+ xmlSecTransformCtxPtr ctx;
+ int ret;
+
+ /* Allocate a new xmlSecTransform and fill the fields. */
+ ctx = (xmlSecTransformCtxPtr)xmlMalloc(sizeof(xmlSecTransformCtx));
+ if(ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(xmlSecTransformCtx));
+ return(NULL);
+ }
+
+ ret = xmlSecTransformCtxInitialize(ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecTransformCtxDestroy(ctx);
+ return(NULL);
+ }
+
+ return(ctx);
+}
+
+/**
+ * xmlSecTransformCtxDestroy:
+ * @ctx: the pointer to transforms chain processing context.
+ *
+ * Destroy context object created with #xmlSecTransformCtxCreate function.
+ */
+void
+xmlSecTransformCtxDestroy(xmlSecTransformCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecTransformCtxFinalize(ctx);
+ xmlFree(ctx);
+}
+
+/**
+ * xmlSecTransformCtxInitialize:
+ * @ctx: the pointer to transforms chain processing context.
+ *
+ * Initializes transforms chain processing context.
+ * The caller is responsible for cleaing up returend object by calling
+ * #xmlSecTransformCtxFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformCtxInitialize(xmlSecTransformCtxPtr ctx) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecTransformCtx));
+
+ ret = xmlSecPtrListInitialize(&(ctx->enabledTransforms), xmlSecTransformIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->enabledUris = xmlSecTransformUriTypeAny;
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxFinalize:
+ * @ctx: the pointer to transforms chain processing context.
+ *
+ * Cleans up @ctx object initialized with #xmlSecTransformCtxInitialize function.
+ */
+void
+xmlSecTransformCtxFinalize(xmlSecTransformCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecTransformCtxReset(ctx);
+ xmlSecPtrListFinalize(&(ctx->enabledTransforms));
+ memset(ctx, 0, sizeof(xmlSecTransformCtx));
+}
+
+/**
+ * xmlSecTransformCtxReset:
+ * @ctx: the pointer to transforms chain processing context.
+ *
+ * Resets transfroms context for new processing.
+ */
+void
+xmlSecTransformCtxReset(xmlSecTransformCtxPtr ctx) {
+ xmlSecTransformPtr transform, tmp;
+
+ xmlSecAssert(ctx != NULL);
+
+ ctx->result = NULL;
+ ctx->status = xmlSecTransformStatusNone;
+
+ /* destroy uri */
+ if(ctx->uri != NULL) {
+ xmlFree(ctx->uri);
+ ctx->uri = NULL;
+ }
+ if(ctx->xptrExpr != NULL) {
+ xmlFree(ctx->xptrExpr);
+ ctx->xptrExpr = NULL;
+ }
+
+ /* destroy transforms chain */
+ for(transform = ctx->first; transform != NULL; transform = tmp) {
+ tmp = transform->next;
+ xmlSecTransformDestroy(transform);
+ }
+ ctx->first = ctx->last = NULL;
+}
+
+/**
+ * xmlSecTransformCtxCopyUserPref:
+ * @dst: the pointer to destination transforms chain processing context.
+ * @src: the pointer to source transforms chain processing context.
+ *
+ * Copies user settings from @src context to @dst.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxCopyUserPref(xmlSecTransformCtxPtr dst, xmlSecTransformCtxPtr src) {
+ int ret;
+
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(src != NULL, -1);
+
+ dst->userData = src->userData;
+ dst->flags = src->flags;
+ dst->flags2 = src->flags2;
+ dst->enabledUris = src->enabledUris;
+ dst->preExecCallback = src->preExecCallback;
+
+ ret = xmlSecPtrListCopy(&(dst->enabledTransforms), &(src->enabledTransforms));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxAppend:
+ * @ctx: the pointer to transforms chain processing context.
+ * @transform: the pointer to new transform.
+ *
+ * Connects the @transform to the end of the chain of transforms in the @ctx
+ * (see #xmlSecTransformConnect function for details).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+
+ if(ctx->last != NULL) {
+ ret = xmlSecTransformConnect(ctx->last, transform, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformConnect",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ return(-1);
+ }
+ } else {
+ xmlSecAssert2(ctx->first == NULL, -1);
+ ctx->first = transform;
+ }
+ ctx->last = transform;
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxPrepend:
+ * @ctx: the pointer to transforms chain processing context.
+ * @transform: the pointer to new transform.
+ *
+ * Connects the @transform to the beggining of the chain of transforms in the @ctx
+ * (see #xmlSecTransformConnect function for details).
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformPtr transform) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+
+ if(ctx->first != NULL) {
+ ret = xmlSecTransformConnect(transform, ctx->first, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformConnect",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ return(-1);
+ }
+ } else {
+ xmlSecAssert2(ctx->last == NULL, -1);
+ ctx->last = transform;
+ }
+ ctx->first = transform;
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxCreateAndAppend:
+ * @ctx: the pointer to transforms chain processing context.
+ * @id: the new transform klass.
+ *
+ * Creaeates new transform and connects it to the end of the chain of
+ * transforms in the @ctx (see #xmlSecTransformConnect function for details).
+ *
+ * Returns: pointer to newly created transform or NULL if an error occurs.
+ */
+xmlSecTransformPtr
+xmlSecTransformCtxCreateAndAppend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) {
+ xmlSecTransformPtr transform;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
+ xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL);
+
+ transform = xmlSecTransformCreate(id);
+ if(!xmlSecTransformIsValid(transform)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
+ return(NULL);
+ }
+
+ ret = xmlSecTransformCtxAppend(ctx, transform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ xmlSecTransformDestroy(transform);
+ return(NULL);
+ }
+
+ return(transform);
+}
+
+/**
+ * xmlSecTransformCtxCreateAndPrepend:
+ * @ctx: the pointer to transforms chain processing context.
+ * @id: the new transform klass.
+ *
+ * Creaeates new transform and connects it to the end of the chain of
+ * transforms in the @ctx (see #xmlSecTransformConnect function for details).
+ *
+ * Returns: pointer to newly created transform or NULL if an error occurs.
+ */
+xmlSecTransformPtr
+xmlSecTransformCtxCreateAndPrepend(xmlSecTransformCtxPtr ctx, xmlSecTransformId id) {
+ xmlSecTransformPtr transform;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
+ xmlSecAssert2(id != xmlSecTransformIdUnknown, NULL);
+
+ transform = xmlSecTransformCreate(id);
+ if(!xmlSecTransformIsValid(transform)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
+ return(NULL);
+ }
+
+ ret = xmlSecTransformCtxPrepend(ctx, transform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ xmlSecTransformDestroy(transform);
+ return(NULL);
+ }
+
+ return(transform);
+}
+
+/**
+ * xmlSecTransformCtxNodeRead:
+ * @ctx: the pointer to transforms chain processing context.
+ * @node: the pointer to transform's node.
+ * @usage: the transform's usage (signature, encryption, etc.).
+ *
+ * Reads the transform from the @node and appends it to the current chain
+ * of transforms in @ctx.
+ *
+ * Returns: pointer to newly created transform or NULL if an error occurs.
+ */
+xmlSecTransformPtr
+xmlSecTransformCtxNodeRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node,
+ xmlSecTransformUsage usage) {
+ xmlSecTransformPtr transform;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ transform = xmlSecTransformNodeRead(node, usage, ctx);
+ if(transform == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(NULL);
+ }
+
+ ret = xmlSecTransformCtxAppend(ctx, transform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ xmlSecTransformDestroy(transform);
+ return(NULL);
+ }
+
+ return(transform);
+}
+
+/**
+ * xmlSecTransformCtxNodesListRead:
+ * @ctx: the pointer to transforms chain processing context.
+ * @node: the pointer to <dsig:Transform/> nodes parent node.
+ * @usage: the transform's usage (signature, encryption, etc.).
+ *
+ * Reads transforms from the <dsig:Transform/> children of the @node and
+ * appends them to the current transforms chain in @ctx object.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxNodesListRead(xmlSecTransformCtxPtr ctx, xmlNodePtr node, xmlSecTransformUsage usage) {
+ xmlSecTransformPtr transform;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTransform, xmlSecDSigNs)) {
+ transform = xmlSecTransformNodeRead(cur, usage, ctx);
+ if(transform == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ ret = xmlSecTransformCtxAppend(ctx, transform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ xmlSecTransformDestroy(transform);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxSetUri:
+ * @ctx: the pointer to transforms chain processing context.
+ * @uri: the URI.
+ * @hereNode: the pointer to "here" node required by some
+ * XML transforms (may be NULL).
+ *
+ * Parses uri and adds xpointer transforms if required.
+ *
+ * The following examples demonstrate what the URI attribute identifies and
+ * how it is dereferenced
+ * (http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel):
+ *
+ * - URI="http://example.com/bar.xml"
+ * identifies the octets that represent the external resource
+ * 'http://example.com/bar.xml', that is probably an XML document given
+ * its file extension.
+ *
+ * - URI="http://example.com/bar.xml#chapter1"
+ * identifies the element with ID attribute value 'chapter1' of the
+ * external XML resource 'http://example.com/bar.xml', provided as an
+ * octet stream. Again, for the sake of interoperability, the element
+ * identified as 'chapter1' should be obtained using an XPath transform
+ * rather than a URI fragment (barename XPointer resolution in external
+ * resources is not REQUIRED in this specification).
+ *
+ * - URI=""
+ * identifies the node-set (minus any comment nodes) of the XML resource
+ * containing the signature
+ *
+ * - URI="#chapter1"
+ * identifies a node-set containing the element with ID attribute value
+ * 'chapter1' of the XML resource containing the signature. XML Signature
+ * (and its applications) modify this node-set to include the element plus
+ * all descendents including namespaces and attributes -- but not comments.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxSetUri(xmlSecTransformCtxPtr ctx, const xmlChar* uri, xmlNodePtr hereNode) {
+ xmlSecNodeSetType nodeSetType = xmlSecNodeSetTree;
+ const xmlChar* xptr;
+ xmlChar* buf = NULL;
+ int useVisa3DHack = 0;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->uri == NULL, -1);
+ xmlSecAssert2(ctx->xptrExpr == NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(hereNode != NULL, -1);
+
+ /* check uri */
+ if(xmlSecTransformUriTypeCheck(ctx->enabledUris, uri) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_URI_TYPE,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ /* is it an empty uri? */
+ if((uri == NULL) || (xmlStrlen(uri) == 0)) {
+ return(0);
+ }
+
+ /* do we have barename or full xpointer? */
+ xptr = xmlStrchr(uri, '#');
+ if(xptr == NULL){
+ ctx->uri = xmlStrdup(uri);
+ if(ctx->uri == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "size=%d", xmlStrlen(uri));
+ return(-1);
+ }
+ /* we are done */
+ return(0);
+ } else if(xmlStrcmp(uri, BAD_CAST "#xpointer(/)") == 0) {
+ ctx->xptrExpr = xmlStrdup(uri);
+ if(ctx->xptrExpr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "size=%d", xmlStrlen(uri));
+ return(-1);
+ }
+ /* we are done */
+ return(0);
+ }
+
+ ctx->uri = xmlStrndup(uri, xptr - uri);
+ if(ctx->uri == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "size=%d", xptr - uri);
+ return(-1);
+ }
+
+ ctx->xptrExpr = xmlStrdup(xptr);
+ if(ctx->xptrExpr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ "size=%d", xmlStrlen(xptr));
+ return(-1);
+ }
+
+ /* do we have barename or full xpointer? */
+ xmlSecAssert2(xptr != NULL, -1);
+ if((xmlStrncmp(xptr, BAD_CAST "#xpointer(", 10) == 0) || (xmlStrncmp(xptr, BAD_CAST "#xmlns(", 7) == 0)) {
+ ++xptr;
+ nodeSetType = xmlSecNodeSetTree;
+ } else if((ctx->flags & XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK) != 0) {
+ ++xptr;
+ nodeSetType = xmlSecNodeSetTreeWithoutComments;
+ useVisa3DHack = 1;
+ } else {
+ static const char tmpl[] = "xpointer(id(\'%s\'))";
+ xmlSecSize size;
+
+ /* we need to add "xpointer(id('..')) because otherwise we have
+ * problems with numeric ("111" and so on) and other "strange" ids */
+ size = xmlStrlen(BAD_CAST tmpl) + xmlStrlen(xptr) + 2;
+ buf = (xmlChar*)xmlMalloc(size * sizeof(xmlChar));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+ sprintf((char*)buf, tmpl, xptr + 1);
+ xptr = buf;
+ nodeSetType = xmlSecNodeSetTreeWithoutComments;
+ }
+
+ if(useVisa3DHack == 0) {
+ xmlSecTransformPtr transform;
+
+ /* we need to create XPonter transform to execute expr */
+ transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXPointerId);
+ if(!xmlSecTransformIsValid(transform)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXPointerId)));
+ return(-1);
+ }
+
+ ret = xmlSecTransformXPointerSetExpr(transform, xptr, nodeSetType, hereNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformXPointerSetExpr",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ if(buf != NULL) {
+ xmlFree(buf);
+ }
+ return(-1);
+ }
+ } else {
+ /* Visa3D protocol doesn't follow XML/XPointer/XMLDSig specs
+ * and allows invalid XPointer expressions (e.g. "#12345") in
+ * the URI attribute.
+ * Since we couldn't evaluate such expressions thru XPath/XPointer
+ * engine, we need to have this hack here
+ */
+ xmlSecTransformPtr transform;
+
+ transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformVisa3DHackId);
+ if(!xmlSecTransformIsValid(transform)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformVisa3DHackId)));
+ return(-1);
+ }
+
+ ret = xmlSecTransformVisa3DHackSetID(transform, xptr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformVisa3DHackSetID",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ if(buf != NULL) {
+ xmlFree(buf);
+ }
+ return(-1);
+ }
+ }
+ if(buf != NULL) {
+ xmlFree(buf);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxPrepare:
+ * @ctx: the pointer to transforms chain processing context.
+ * @inputDataType: the expected input type.
+ *
+ * Prepares the transform context for processing data of @inputDataType.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxPrepare(xmlSecTransformCtxPtr ctx, xmlSecTransformDataType inputDataType) {
+ xmlSecTransformDataType firstType;
+ xmlSecTransformPtr transform;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->result == NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+
+ /* add binary buffer to store result */
+ transform = xmlSecTransformCtxCreateAndAppend(ctx, xmlSecTransformMemBufId);
+ if(!xmlSecTransformIsValid(transform)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+ return(-1);
+ }
+ ctx->result = xmlSecTransformMemBufGetBuffer(transform);
+ if(ctx->result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformMemBufGetBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+ return(-1);
+ }
+
+ firstType = xmlSecTransformGetDataType(ctx->first, xmlSecTransformModePush, ctx);
+ if(((firstType & xmlSecTransformDataTypeBin) == 0) &&
+ ((inputDataType & xmlSecTransformDataTypeBin) != 0)) {
+
+ /* need to add parser transform */
+ transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformXmlParserId);
+ if(transform == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformXmlParserId)));
+ return(-1);
+ }
+ } else if(((firstType & xmlSecTransformDataTypeXml) == 0) &&
+ ((inputDataType & xmlSecTransformDataTypeXml) != 0)) {
+
+ /* need to add c14n transform */
+ transform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInclC14NId);
+ if(transform == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInclC14NId)));
+ return(-1);
+ }
+ }
+
+ /* finally let application a chance to verify that it's ok to execte
+ * this transforms chain */
+ if(ctx->preExecCallback != NULL) {
+ ret = (ctx->preExecCallback)(ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "ctx->preExecCallback",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ ctx->status = xmlSecTransformStatusWorking;
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxBinaryExecute:
+ * @ctx: the pointer to transforms chain processing context.
+ * @data: the input binary data buffer.
+ * @dataSize: the input data size.
+ *
+ * Processes binary data using transforms chain in the @ctx.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxBinaryExecute(xmlSecTransformCtxPtr ctx,
+ const xmlSecByte* data, xmlSecSize dataSize) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->result == NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+
+ /* we should not have uri stored in ctx */
+ xmlSecAssert2(ctx->uri == NULL, -1);
+
+ ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeBin);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxPrepare",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=bin");
+ return(-1);
+ }
+
+ ret = xmlSecTransformPushBin(ctx->first, data, dataSize, 1, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxPushBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "dataSize=%d", dataSize);
+ return(-1);
+ }
+
+ ctx->status = xmlSecTransformStatusFinished;
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxUriExecute:
+ * @ctx: the pointer to transforms chain processing context.
+ * @uri: the URI.
+ *
+ * Process binary data from the URI using transforms chain in @ctx.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxUriExecute(xmlSecTransformCtxPtr ctx, const xmlChar* uri) {
+ xmlSecTransformPtr uriTransform;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ /* we should not execute transform for a different uri */
+ xmlSecAssert2((ctx->uri == NULL) || (uri == ctx->uri) || xmlStrEqual(uri, ctx->uri), -1);
+
+ uriTransform = xmlSecTransformCtxCreateAndPrepend(ctx, xmlSecTransformInputURIId);
+ if(uriTransform == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformInputURIId)));
+ return(-1);
+ }
+
+ ret = xmlSecTransformInputURIOpen(uriTransform, uri);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformInputURIOpen",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ /* we do not need to do something special for this transform */
+ ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeUnknown);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxPrepare",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=bin");
+ return(-1);
+ }
+
+ /* Now we have a choice: we either can push from first transform or pop
+ * from last. Our C14N transforms prefers push, so push data!
+ */
+ ret = xmlSecTransformPump(uriTransform, uriTransform->next, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformPump",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ ctx->status = xmlSecTransformStatusFinished;
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxXmlExecute:
+ * @ctx: the pointer to transforms chain processing context.
+ * @nodes: the input node set.
+ *
+ * Process @nodes using transforms in the transforms chain in @ctx.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxXmlExecute(xmlSecTransformCtxPtr ctx, xmlSecNodeSetPtr nodes) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->result == NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(nodes != NULL, -1);
+
+ xmlSecAssert2((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0), -1);
+
+ ret = xmlSecTransformCtxPrepare(ctx, xmlSecTransformDataTypeXml);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxPrepare",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=xml");
+ return(-1);
+ }
+
+ /* it's better to do push than pop because all XML transform
+ * just don't care and c14n likes push more than pop */
+ ret = xmlSecTransformPushXml(ctx->first, nodes, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformPushXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(ctx->first)));
+ return(-1);
+ }
+
+ ctx->status = xmlSecTransformStatusFinished;
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxExecute:
+ * @ctx: the pointer to transforms chain processing context.
+ * @doc: the pointer to input document.
+ *
+ * Executes transforms chain in @ctx.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformCtxExecute(xmlSecTransformCtxPtr ctx, xmlDocPtr doc) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->result == NULL, -1);
+ xmlSecAssert2(ctx->status == xmlSecTransformStatusNone, -1);
+ xmlSecAssert2(doc != NULL, -1);
+
+ if((ctx->uri == NULL) || (xmlStrlen(ctx->uri) == 0)) {
+ xmlSecNodeSetPtr nodes;
+
+ if((ctx->xptrExpr != NULL) && (xmlStrlen(ctx->xptrExpr) > 0)){
+ /* our xpointer transform takes care of providing correct nodes set */
+ nodes = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetNormal);
+ if(nodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ } else {
+ /* we do not want to have comments for empty URI */
+ nodes = xmlSecNodeSetGetChildren(doc, NULL, 0, 0);
+ if(nodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetGetChildren",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ ret = xmlSecTransformCtxXmlExecute(ctx, nodes);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxXmlExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecNodeSetDestroy(nodes);
+ return(-1);
+ }
+ /* TODO: don't destroy nodes here */
+ xmlSecNodeSetDestroy(nodes);
+ } else {
+ ret = xmlSecTransformCtxUriExecute(ctx, ctx->uri);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxUriExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformCtxDebugDump:
+ * @ctx: the pointer to transforms chain processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints transforms context debug information to @output.
+ */
+void
+xmlSecTransformCtxDebugDump(xmlSecTransformCtxPtr ctx, FILE* output) {
+ xmlSecTransformPtr transform;
+
+ xmlSecAssert(ctx != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "== TRANSFORMS CTX (status=%d)\n", ctx->status);
+
+ fprintf(output, "== flags: 0x%08x\n", ctx->flags);
+ fprintf(output, "== flags2: 0x%08x\n", ctx->flags2);
+ if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) {
+ fprintf(output, "== enabled transforms: ");
+ xmlSecTransformIdListDebugDump(&(ctx->enabledTransforms), output);
+ } else {
+ fprintf(output, "== enabled transforms: all\n");
+ }
+
+ fprintf(output, "=== uri: %s\n",
+ (ctx->uri != NULL) ? ctx->uri : BAD_CAST "NULL");
+ fprintf(output, "=== uri xpointer expr: %s\n",
+ (ctx->xptrExpr != NULL) ? ctx->xptrExpr : BAD_CAST "NULL");
+ for(transform = ctx->first; transform != NULL; transform = transform->next) {
+ xmlSecTransformDebugDump(transform, output);
+ }
+}
+
+/**
+ * xmlSecTransformCtxDebugXmlDump:
+ * @ctx: the pointer to transforms chain processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints transforms context debug information to @output in XML format.
+ */
+void
+xmlSecTransformCtxDebugXmlDump(xmlSecTransformCtxPtr ctx, FILE* output) {
+ xmlSecTransformPtr transform;
+
+ xmlSecAssert(ctx != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<TransformCtx status=\"%d\">\n", ctx->status);
+
+ fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags);
+ fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2);
+ if(xmlSecPtrListGetSize(&(ctx->enabledTransforms)) > 0) {
+ fprintf(output, "<EnabledTransforms>\n");
+ xmlSecTransformIdListDebugXmlDump(&(ctx->enabledTransforms), output);
+ fprintf(output, "</EnabledTransforms>\n");
+ } else {
+ fprintf(output, "<EnabledTransforms>all</EnabledTransforms>\n");
+ }
+
+
+ fprintf(output, "<Uri>");
+ xmlSecPrintXmlString(output, ctx->uri);
+ fprintf(output, "</Uri>\n");
+
+ fprintf(output, "<UriXPointer>");
+ xmlSecPrintXmlString(output, ctx->xptrExpr);
+ fprintf(output, "</UriXPointer>\n");
+
+ for(transform = ctx->first; transform != NULL; transform = transform->next) {
+ xmlSecTransformDebugXmlDump(transform, output);
+ }
+ fprintf(output, "</TransformCtx>\n");
+}
+
+/**************************************************************************
+ *
+ * xmlSecTransform
+ *
+ *************************************************************************/
+/**
+ * xmlSecTransformCreate:
+ * @id: the transform id to create.
+ *
+ * Creates new transform of the @id klass. The caller is responsible for
+ * destroying returned tansform using #xmlSecTransformDestroy function.
+ *
+ * Returns: pointer to newly created transform or NULL if an error occurs.
+ */
+xmlSecTransformPtr
+xmlSecTransformCreate(xmlSecTransformId id) {
+ xmlSecTransformPtr transform;
+ int ret;
+
+ xmlSecAssert2(id != NULL, NULL);
+ xmlSecAssert2(id->klassSize >= sizeof(xmlSecTransformKlass), NULL);
+ xmlSecAssert2(id->objSize >= sizeof(xmlSecTransform), NULL);
+ xmlSecAssert2(id->name != NULL, NULL);
+
+ /* Allocate a new xmlSecTransform and fill the fields. */
+ transform = (xmlSecTransformPtr)xmlMalloc(id->objSize);
+ if(transform == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", id->objSize);
+ return(NULL);
+ }
+ memset(transform, 0, id->objSize);
+ transform->id = id;
+
+ if(id->initialize != NULL) {
+ ret = (id->initialize)(transform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "id->initialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecTransformDestroy(transform);
+ return(NULL);
+ }
+ }
+
+ ret = xmlSecBufferInitialize(&(transform->inBuf), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", 0);
+ xmlSecTransformDestroy(transform);
+ return(NULL);
+ }
+
+ ret = xmlSecBufferInitialize(&(transform->outBuf), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", 0);
+ xmlSecTransformDestroy(transform);
+ return(NULL);
+ }
+
+ return(transform);
+}
+
+/**
+ * xmlSecTransformDestroy:
+ * @transform: the pointer to transform.
+ *
+ * Destroys transform created with #xmlSecTransformCreate function.
+ */
+void
+xmlSecTransformDestroy(xmlSecTransformPtr transform) {
+ xmlSecAssert(xmlSecTransformIsValid(transform));
+ xmlSecAssert(transform->id->objSize > 0);
+
+ /* first need to remove ourselves from chain */
+ xmlSecTransformRemove(transform);
+
+ xmlSecBufferFinalize(&(transform->inBuf));
+ xmlSecBufferFinalize(&(transform->outBuf));
+
+ /* we never destroy input nodes, output nodes
+ * are destroyed if and only if they are different
+ * from input nodes
+ */
+ if((transform->outNodes != NULL) && (transform->outNodes != transform->inNodes)) {
+ xmlSecNodeSetDestroy(transform->outNodes);
+ }
+ if(transform->id->finalize != NULL) {
+ (transform->id->finalize)(transform);
+ }
+ memset(transform, 0, transform->id->objSize);
+ xmlFree(transform);
+}
+
+/**
+ * xmlSecTransformNodeRead:
+ * @node: the pointer to the transform's node.
+ * @usage: the transform usage (signature, encryption, ...).
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Reads transform from the @node as follows:
+ *
+ * 1) reads "Algorithm" attribute;
+ *
+ * 2) checks the lists of known and allowed transforms;
+ *
+ * 3) calls transform's create method;
+ *
+ * 4) calls transform's read transform node method.
+ *
+ * Returns: pointer to newly created transform or NULL if an error occurs.
+ */
+xmlSecTransformPtr
+xmlSecTransformNodeRead(xmlNodePtr node, xmlSecTransformUsage usage, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformPtr transform;
+ xmlSecTransformId id;
+ xmlChar *href;
+ int ret;
+
+ xmlSecAssert2(node != NULL, NULL);
+ xmlSecAssert2(transformCtx != NULL, NULL);
+
+ href = xmlGetProp(node, xmlSecAttrAlgorithm);
+ if(href == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(NULL);
+ }
+
+ id = xmlSecTransformIdListFindByHref(xmlSecTransformIdsGet(), href, usage);
+ if(id == xmlSecTransformIdUnknown) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdListFindByHref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "href=%s",
+ xmlSecErrorsSafeString(href));
+ xmlFree(href);
+ return(NULL);
+ }
+
+ /* check with enabled transforms list */
+ if((xmlSecPtrListGetSize(&(transformCtx->enabledTransforms)) > 0) &&
+ (xmlSecTransformIdListFind(&(transformCtx->enabledTransforms), id) != 1)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)),
+ XMLSEC_ERRORS_R_TRANSFORM_DISABLED,
+ "href=%s",
+ xmlSecErrorsSafeString(href));
+ xmlFree(href);
+ return(NULL);
+ }
+
+ transform = xmlSecTransformCreate(id);
+ if(!xmlSecTransformIsValid(transform)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(id)));
+ xmlFree(href);
+ return(NULL);
+ }
+
+ if(transform->id->readNode != NULL) {
+ ret = transform->id->readNode(transform, node, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "id->readNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)));
+ xmlSecTransformDestroy(transform);
+ xmlFree(href);
+ return(NULL);
+ }
+ }
+
+ /* finally remember the transform node */
+ transform->hereNode = node;
+ xmlFree(href);
+ return(transform);
+}
+
+/**
+ * xmlSecTransformPump:
+ * @left: the source pumping transform.
+ * @right: the destination pumping transform.
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Pops data from @left transform and pushes to @right transform until
+ * no more data is available.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformPump(xmlSecTransformPtr left, xmlSecTransformPtr right, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformDataType leftType;
+ xmlSecTransformDataType rightType;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(left), -1);
+ xmlSecAssert2(xmlSecTransformIsValid(right), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx);
+ rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx);
+
+ if(((leftType & xmlSecTransformDataTypeXml) != 0) &&
+ ((rightType & xmlSecTransformDataTypeXml) != 0)) {
+
+ xmlSecNodeSetPtr nodes = NULL;
+
+ ret = xmlSecTransformPopXml(left, &nodes, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
+ "xmlSecTransformPopXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecTransformPushXml(right, nodes, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
+ "xmlSecTransformPushXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else if(((leftType & xmlSecTransformDataTypeBin) != 0) &&
+ ((rightType & xmlSecTransformDataTypeBin) != 0)) {
+ xmlSecByte buf[XMLSEC_TRANSFORM_BINARY_CHUNK];
+ xmlSecSize bufSize;
+ int final;
+
+ do {
+ ret = xmlSecTransformPopBin(left, buf, sizeof(buf), &bufSize, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
+ "xmlSecTransformPopBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ final = (bufSize == 0) ? 1 : 0;
+ ret = xmlSecTransformPushBin(right, buf, bufSize, final, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
+ "xmlSecTransformPushBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } while(final == 0);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
+ xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "transforms input/output data formats do not match");
+ }
+ return(0);
+}
+
+
+/**
+ * xmlSecTransformSetKey:
+ * @transform: the pointer to transform.
+ * @key: the pointer to key.
+ *
+ * Sets the transform's key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ if(transform->id->setKey != NULL) {
+ return((transform->id->setKey)(transform, key));
+ }
+ return(0);
+}
+
+/**
+ * xmlSecTransformSetKeyReq:
+ * @transform: the pointer to transform.
+ * @keyReq: the pointer to keys requirements object.
+ *
+ * Sets the key requirements for @transform in the @keyReq.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecTransformSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecKeyDataIdUnknown;
+ keyReq->keyType = xmlSecKeyDataTypeUnknown;
+ keyReq->keyUsage = xmlSecKeyUsageAny;
+ keyReq->keyBitsSize = 0;
+
+ if(transform->id->setKeyReq != NULL) {
+ return((transform->id->setKeyReq)(transform, keyReq));
+ }
+ return(0);
+}
+
+/**
+ * xmlSecTransformVerify:
+ * @transform: the pointer to transform.
+ * @data: the binary data for verification.
+ * @dataSize: the data size.
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Verifies the data with transform's processing results
+ * (for digest, HMAC and signature transforms). The verification
+ * result is stored in the #status member of #xmlSecTransform object.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformVerify(xmlSecTransformPtr transform, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->id->verify != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ return((transform->id->verify)(transform, data, dataSize, transformCtx));
+}
+
+/**
+ * xmlSecTransformVerifyNodeContent:
+ * @transform: the pointer to transform.
+ * @node: the pointer to node.
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Gets the @node content, base64 decodes it and calls #xmlSecTransformVerify
+ * function to verify binary results.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformVerifyNodeContent(xmlSecTransformPtr transform, xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&buffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferBase64NodeContentRead(&buffer, node);
+ if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferBase64NodeContentRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ ret = xmlSecTransformVerify(transform, xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformVerify",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ xmlSecBufferFinalize(&buffer);
+ return(0);
+}
+
+/**
+ * xmlSecTransformGetDataType:
+ * @transform: the pointer to transform.
+ * @mode: the data mode (push or pop).
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Gets transform input (@mode is "push") or output (@mode is "pop") data
+ * type (binary or XML).
+ *
+ * Returns: the transform's data type for the @mode operation.
+ */
+xmlSecTransformDataType
+xmlSecTransformGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown);
+ xmlSecAssert2(transform->id->getDataType != NULL, xmlSecTransformDataTypeUnknown);
+
+ return((transform->id->getDataType)(transform, mode, transformCtx));
+}
+
+/**
+ * xmlSecTransformPushBin:
+ * @transform: the pointer to transform object.
+ * @data: the input binary data,
+ * @dataSize: the input data size.
+ * @final: the flag: if set to 1 then it's the last
+ * data chunk.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Process binary @data and pushes results to next transform.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
+ xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->id->pushBin != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ return((transform->id->pushBin)(transform, data, dataSize, final, transformCtx));
+}
+
+/**
+ * xmlSecTransformPopBin:
+ * @transform: the pointer to transform object.
+ * @data: the buffer to store result data.
+ * @maxDataSize: the size of the buffer #data.
+ * @dataSize: the pointer to returned data size.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Pops data from previous transform in the chain, processes data and
+ * returns result in the @data buffer. The size of returned data is
+ * placed in the @dataSize.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
+ xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->id->popBin != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ return((transform->id->popBin)(transform, data, maxDataSize, dataSize, transformCtx));
+}
+
+/**
+ * xmlSecTransformPushXml:
+ * @transform: the pointer to transform object.
+ * @nodes: the input nodes.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Processes @nodes and pushes result to the next transform in the chain.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->id->pushXml != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ return((transform->id->pushXml)(transform, nodes, transformCtx));
+}
+
+/**
+ * xmlSecTransformPopXml:
+ * @transform: the pointer to transform object.
+ * @nodes: the pointer to store popinter to result nodes.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Pops data from previous transform in the chain, processes the data and
+ * returns result in @nodes.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->id->popXml != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ return((transform->id->popXml)(transform, nodes, transformCtx));
+}
+
+/**
+ * xmlSecTransformExecute:
+ * @transform: the pointer to transform.
+ * @last: the flag: if set to 1 then it's the last data chunk.
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Executes transform (used by default popBin/pushBin/popXml/pushXml methods).
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->id->execute != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ return((transform->id->execute)(transform, last, transformCtx));
+}
+
+/**
+ * xmlSecTransformDebugDump:
+ * @transform: the pointer to transform.
+ * @output: the pointer to output FILE.
+ *
+ * Prints transform's debug information to @output.
+ */
+void
+xmlSecTransformDebugDump(xmlSecTransformPtr transform, FILE* output) {
+ xmlSecAssert(xmlSecTransformIsValid(transform));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== Transform: %s (href=%s)\n",
+ xmlSecErrorsSafeString(transform->id->name),
+ xmlSecErrorsSafeString(transform->id->href));
+}
+
+/**
+ * xmlSecTransformDebugXmlDump:
+ * @transform: the pointer to transform.
+ * @output: the pointer to output FILE.
+ *
+ * Prints transform's debug information to @output in XML format.
+ */
+void
+xmlSecTransformDebugXmlDump(xmlSecTransformPtr transform, FILE* output) {
+ xmlSecAssert(xmlSecTransformIsValid(transform));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<Transform name=\"");
+ xmlSecPrintXmlString(output,transform->id->name);
+ fprintf(output, "\" href=\"");
+ xmlSecPrintXmlString(output, transform->id->href);
+ fprintf(output, "\" />\n");
+}
+
+/************************************************************************
+ *
+ * Operations on transforms chain
+ *
+ ************************************************************************/
+/**
+ * xmlSecTransformConnect:
+ * @left: the pointer to left (prev) transform.
+ * @right: the pointer to right (next) transform.
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * If the data object is a node-set and the next transform requires octets,
+ * the signature application MUST attempt to convert the node-set to an octet
+ * stream using Canonical XML [XML-C14N].
+ *
+ * The story is different if the right transform is base64 decode
+ * (http://www.w3.org/TR/xmldsig-core/#sec-Base-64):
+ *
+ * This transform requires an octet stream for input. If an XPath node-set
+ * (or sufficiently functional alternative) is given as input, then it is
+ * converted to an octet stream by performing operations logically equivalent
+ * to 1) applying an XPath transform with expression self::text(), then 2)
+ * taking the string-value of the node-set. Thus, if an XML element is
+ * identified by a barename XPointer in the Reference URI, and its content
+ * consists solely of base64 encoded character data, then this transform
+ * automatically strips away the start and end tags of the identified element
+ * and any of its descendant elements as well as any descendant comments and
+ * processing instructions. The output of this transform is an octet stream.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformConnect(xmlSecTransformPtr left, xmlSecTransformPtr right,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformDataType leftType;
+ xmlSecTransformDataType rightType;
+ xmlSecTransformId middleId;
+ xmlSecTransformPtr middle;
+
+ xmlSecAssert2(xmlSecTransformIsValid(left), -1);
+ xmlSecAssert2(xmlSecTransformIsValid(right), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ leftType = xmlSecTransformGetDataType(left, xmlSecTransformModePop, transformCtx);
+ rightType = xmlSecTransformGetDataType(right, xmlSecTransformModePush, transformCtx);
+
+ /* happy case first: nothing need to be done */
+ if((((leftType & xmlSecTransformDataTypeBin) != 0) &&
+ ((rightType & xmlSecTransformDataTypeBin) != 0)) ||
+ (((leftType & xmlSecTransformDataTypeXml) != 0) &&
+ ((rightType & xmlSecTransformDataTypeXml) != 0))) {
+
+ left->next = right;
+ right->prev = left;
+ return(0);
+ }
+
+ if(((leftType & xmlSecTransformDataTypeBin) != 0) &&
+ ((rightType & xmlSecTransformDataTypeXml) != 0)) {
+
+ /* need to insert parser */
+ middleId = xmlSecTransformXmlParserId;
+ } else if(((leftType & xmlSecTransformDataTypeXml) != 0) &&
+ ((rightType & xmlSecTransformDataTypeBin) != 0)) {
+
+ /* need to insert c14n or special pre-base64 transform */
+ if(xmlSecTransformCheckId(right, xmlSecTransformBase64Id)) {
+ middleId = xmlSecTransformRemoveXmlTagsC14NId;
+ } else {
+ middleId = xmlSecTransformInclC14NId;
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
+ xmlSecErrorsSafeString(xmlSecTransformGetName(right)),
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "leftType=%d;rightType=%d",
+ leftType, rightType);
+ return(-1);
+ }
+
+ /* insert transform */
+ middle = xmlSecTransformCreate(middleId);
+ if(middle == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(left)),
+ "xmlSecTransformCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(middleId)));
+ return(-1);
+ }
+ left->next = middle;
+ middle->prev = left;
+ middle->next = right;
+ right->prev = middle;
+ return(0);
+}
+
+/**
+ * xmlSecTransformRemove:
+ * @transform: the pointer to #xmlSecTransform structure.
+ *
+ * Removes @transform from the chain.
+ */
+void
+xmlSecTransformRemove(xmlSecTransformPtr transform) {
+ xmlSecAssert(xmlSecTransformIsValid(transform));
+
+ if(transform->next != NULL) {
+ transform->next->prev = transform->prev;
+ }
+ if(transform->prev != NULL) {
+ transform->prev->next = transform->next;
+ }
+ transform->next = transform->prev = NULL;
+}
+
+
+/************************************************************************
+ *
+ * Default callbacks, most of the transforms can use them
+ *
+ ************************************************************************/
+/**
+ * xmlSecTransformDefaultGetDataType:
+ * @transform: the pointer to transform.
+ * @mode: the data mode (push or pop).
+ * @transformCtx: the transform's chaing processing context.
+ *
+ * Gets transform input (@mode is "push") or output (@mode is "pop") data
+ * type (binary or XML) by analyzing available pushBin/popBin/pushXml/popXml
+ * methods.
+ *
+ * Returns: the transform's data type for the @mode operation.
+ */
+xmlSecTransformDataType
+xmlSecTransformDefaultGetDataType(xmlSecTransformPtr transform, xmlSecTransformMode mode,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformDataType type = xmlSecTransformDataTypeUnknown;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), xmlSecTransformDataTypeUnknown);
+ xmlSecAssert2(transformCtx != NULL, xmlSecTransformDataTypeUnknown);
+
+ /* we'll try to guess the data type based on the handlers we have */
+ switch(mode) {
+ case xmlSecTransformModePush:
+ if(transform->id->pushBin != NULL) {
+ type |= xmlSecTransformDataTypeBin;
+ }
+ if(transform->id->pushXml != NULL) {
+ type |= xmlSecTransformDataTypeXml;
+ }
+ break;
+ case xmlSecTransformModePop:
+ if(transform->id->popBin != NULL) {
+ type |= xmlSecTransformDataTypeBin;
+ }
+ if(transform->id->popXml != NULL) {
+ type |= xmlSecTransformDataTypeXml;
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "mode=%d", mode);
+ return(xmlSecTransformDataTypeUnknown);
+ }
+
+ return(type);
+}
+
+/**
+ * xmlSecTransformDefaultPushBin:
+ * @transform: the pointer to transform object.
+ * @data: the input binary data,
+ * @dataSize: the input data size.
+ * @final: the flag: if set to 1 then it's the last
+ * data chunk.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Process binary @data by calling transform's execute method and pushes
+ * results to next transform.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformDefaultPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
+ xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize = 0;
+ xmlSecSize outSize = 0;
+ int finalData = 0;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ do {
+ /* append data to input buffer */
+ if(dataSize > 0) {
+ xmlSecSize chunkSize;
+
+ xmlSecAssert2(data != NULL, -1);
+
+ chunkSize = dataSize;
+ if(chunkSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
+ chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
+ }
+
+ ret = xmlSecBufferAppend(&(transform->inBuf), data, chunkSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", chunkSize);
+ return(-1);
+ }
+
+ dataSize -= chunkSize;
+ data += chunkSize;
+ }
+
+ /* process data */
+ inSize = xmlSecBufferGetSize(&(transform->inBuf));
+ outSize = xmlSecBufferGetSize(&(transform->outBuf));
+ finalData = (((dataSize == 0) && (final != 0)) ? 1 : 0);
+ ret = xmlSecTransformExecute(transform, finalData, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "final=%d", final);
+ return(-1);
+ }
+
+ /* push data to the next transform */
+ inSize = xmlSecBufferGetSize(&(transform->inBuf));
+ outSize = xmlSecBufferGetSize(&(transform->outBuf));
+ if(inSize > 0) {
+ finalData = 0;
+ }
+
+ /* we don't want to puch too much */
+ if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
+ outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
+ finalData = 0;
+ }
+ if((transform->next != NULL) && ((outSize > 0) || (finalData != 0))) {
+ ret = xmlSecTransformPushBin(transform->next,
+ xmlSecBufferGetData(&(transform->outBuf)),
+ outSize,
+ finalData,
+ transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform->next)),
+ "xmlSecTransformPushBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "final=%d;outSize=%d", final, outSize);
+ return(-1);
+ }
+ }
+
+ /* remove data anyway */
+ if(outSize > 0) {
+ ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+ }
+ } while((dataSize > 0) || (outSize > 0));
+
+ return(0);
+}
+
+/**
+ * xmlSecTransformDefaultPopBin:
+ * @transform: the pointer to transform object.
+ * @data: the buffer to store result data.
+ * @maxDataSize: the size of the buffer #data.
+ * @dataSize: the pointer to returned data size.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Pops data from previous transform in the chain, processes data by calling
+ * transform's execute method and returns result in the @data buffer. The
+ * size of returned data is placed in the @dataSize.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformDefaultPopBin(xmlSecTransformPtr transform, xmlSecByte* data,
+ xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize outSize;
+ int final = 0;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ while((xmlSecBufferGetSize(&(transform->outBuf)) == 0) && (final == 0)) {
+ /* read data from previous transform if exist */
+ if(transform->prev != NULL) {
+ xmlSecSize inSize, chunkSize;
+
+ inSize = xmlSecBufferGetSize(&(transform->inBuf));
+ chunkSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
+
+ /* ensure that we have space for at least one data chunk */
+ ret = xmlSecBufferSetMaxSize(&(transform->inBuf), inSize + chunkSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize + chunkSize);
+ return(-1);
+ }
+
+ /* get data from previous transform */
+ ret = xmlSecTransformPopBin(transform->prev,
+ xmlSecBufferGetData(&(transform->inBuf)) + inSize,
+ chunkSize, &chunkSize, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform->prev)),
+ "xmlSecTransformPopBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* adjust our size if needed */
+ if(chunkSize > 0) {
+ ret = xmlSecBufferSetSize(&(transform->inBuf), inSize + chunkSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize + chunkSize);
+ return(-1);
+ }
+ final = 0; /* the previous transform returned some data..*/
+ } else {
+ final = 1; /* no data returned from previous transform, we are done */
+ }
+ } else {
+ final = 1; /* no previous transform, we are "permanently final" */
+ }
+
+ /* execute our transform */
+ ret = xmlSecTransformExecute(transform, final, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* copy result (if any) */
+ outSize = xmlSecBufferGetSize(&(transform->outBuf));
+ if(outSize > maxDataSize) {
+ outSize = maxDataSize;
+ }
+
+ /* we don't want to put too much */
+ if(outSize > XMLSEC_TRANSFORM_BINARY_CHUNK) {
+ outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
+ }
+ if(outSize > 0) {
+ xmlSecAssert2(xmlSecBufferGetData(&(transform->outBuf)), -1);
+
+ memcpy(data, xmlSecBufferGetData(&(transform->outBuf)), outSize);
+
+ ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+ }
+
+ /* set the result size */
+ (*dataSize) = outSize;
+ return(0);
+}
+
+/**
+ * xmlSecTransformDefaultPushXml:
+ * @transform: the pointer to transform object.
+ * @nodes: the input nodes.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Processes @nodes by calling transform's execute method and pushes
+ * result to the next transform in the chain.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformDefaultPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes,
+ xmlSecTransformCtxPtr transformCtx) {
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->inNodes == NULL, -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ /* execute our transform */
+ transform->inNodes = nodes;
+ ret = xmlSecTransformExecute(transform, 1, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* push result to the next transform (if exist) */
+ if(transform->next != NULL) {
+ ret = xmlSecTransformPushXml(transform->next, transform->outNodes, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformPushXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecTransformDefaultPopXml:
+ * @transform: the pointer to transform object.
+ * @nodes: the pointer to store popinter to result nodes.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Pops data from previous transform in the chain, processes the data
+ * by calling transform's execute method and returns result in @nodes.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformDefaultPopXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr* nodes,
+ xmlSecTransformCtxPtr transformCtx) {
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->inNodes == NULL, -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ /* pop result from the prev transform (if exist) */
+ if(transform->prev != NULL) {
+ ret = xmlSecTransformPopXml(transform->prev, &(transform->inNodes), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformPopXml",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* execute our transform */
+ ret = xmlSecTransformExecute(transform, 1, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* return result if requested */
+ if(nodes != NULL) {
+ (*nodes) = transform->outNodes;
+ }
+
+ return(0);
+}
+
+/***********************************************************************
+ *
+ * Transform Ids list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecTransformIdListKlass = {
+ BAD_CAST "transform-ids-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecTransformIdListGetKlass:
+ *
+ * The transform id list klass.
+ *
+ * Returns: pointer to the transform id list klass.
+ */
+xmlSecPtrListId
+xmlSecTransformIdListGetKlass(void) {
+ return(&xmlSecTransformIdListKlass);
+}
+
+/**
+ * xmlSecTransformIdListFind:
+ * @list: the pointer to transform ids list.
+ * @transformId: the transform klass.
+ *
+ * Lookups @dataId in @list.
+ *
+ * Returns: 1 if @dataId is found in the @list, 0 if not and a negative
+ * value if an error occurs.
+ */
+int
+xmlSecTransformIdListFind(xmlSecPtrListPtr list, xmlSecTransformId transformId) {
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), -1);
+ xmlSecAssert2(transformId != NULL, -1);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ if((xmlSecTransformId)xmlSecPtrListGetItem(list, i) == transformId) {
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecTransformIdListFindByHref:
+ * @list: the pointer to transform ids list.
+ * @href: the desired transform klass href.
+ * @usage: the desired transform usage.
+ *
+ * Lookups data klass in the list with given @href and @usage in @list.
+ *
+ * Returns: transform klass is found and NULL otherwise.
+ */
+xmlSecTransformId
+xmlSecTransformIdListFindByHref(xmlSecPtrListPtr list, const xmlChar* href,
+ xmlSecTransformUsage usage) {
+ xmlSecTransformId transformId;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown);
+ xmlSecAssert2(href != NULL, xmlSecTransformIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown);
+
+ if(((usage & transformId->usage) != 0) && (transformId->href != NULL) &&
+ xmlStrEqual(href, transformId->href)) {
+ return(transformId);
+ }
+ }
+ return(xmlSecTransformIdUnknown);
+}
+
+/**
+ * xmlSecTransformIdListFindByName:
+ * @list: the pointer to transform ids list.
+ * @name: the desired transform klass name.
+ * @usage: the desired transform usage.
+ *
+ * Lookups data klass in the list with given @name and @usage in @list.
+ *
+ * Returns: transform klass is found and NULL otherwise.
+ */
+xmlSecTransformId
+xmlSecTransformIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name,
+ xmlSecTransformUsage usage) {
+ xmlSecTransformId transformId;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecTransformIdListId), xmlSecTransformIdUnknown);
+ xmlSecAssert2(name != NULL, xmlSecTransformIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert2(transformId != xmlSecTransformIdUnknown, xmlSecTransformIdUnknown);
+
+ if(((usage & transformId->usage) != 0) && (transformId->name != NULL) &&
+ xmlStrEqual(name, BAD_CAST transformId->name)) {
+
+ return(transformId);
+ }
+ }
+ return(xmlSecTransformIdUnknown);
+}
+
+/**
+ * xmlSecTransformIdListDebugDump:
+ * @list: the pointer to transform ids list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints binary transform debug information to @output.
+ */
+void
+xmlSecTransformIdListDebugDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecTransformId transformId;
+ xmlSecSize i, size;
+
+ xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId));
+ xmlSecAssert(output != NULL);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert(transformId != NULL);
+ xmlSecAssert(transformId->name != NULL);
+
+ if(i > 0) {
+ fprintf(output, ",\"%s\"", transformId->name);
+ } else {
+ fprintf(output, "\"%s\"", transformId->name);
+ }
+ }
+ fprintf(output, "\n");
+}
+
+/**
+ * xmlSecTransformIdListDebugXmlDump:
+ * @list: the pointer to transform ids list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints binary transform debug information to @output in XML format.
+ */
+void
+xmlSecTransformIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecTransformId transformId;
+ xmlSecSize i, size;
+
+ xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecTransformIdListId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<TransformIdsList>\n");
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ transformId = (xmlSecTransformId)xmlSecPtrListGetItem(list, i);
+ xmlSecAssert(transformId != NULL);
+ xmlSecAssert(transformId->name != NULL);
+
+ fprintf(output, "<TransformId name=\"");
+ xmlSecPrintXmlString(output, transformId->name);
+ fprintf(output, "\" />");
+ }
+ fprintf(output, "</TransformIdsList>\n");
+}
+
+/************************************************************************
+ *
+ * IO buffers for transforms
+ *
+ ************************************************************************/
+typedef struct _xmlSecTransformIOBuffer xmlSecTransformIOBuffer,
+ *xmlSecTransformIOBufferPtr;
+typedef enum {
+ xmlSecTransformIOBufferModeRead,
+ xmlSecTransformIOBufferModeWrite
+} xmlSecTransformIOBufferMode;
+
+struct _xmlSecTransformIOBuffer {
+ xmlSecTransformIOBufferMode mode;
+ xmlSecTransformPtr transform;
+ xmlSecTransformCtxPtr transformCtx;
+};
+
+static xmlSecTransformIOBufferPtr xmlSecTransformIOBufferCreate (xmlSecTransformIOBufferMode mode,
+ xmlSecTransformPtr transform,
+ xmlSecTransformCtxPtr transformCtx);
+static void xmlSecTransformIOBufferDestroy (xmlSecTransformIOBufferPtr buffer);
+static int xmlSecTransformIOBufferRead (xmlSecTransformIOBufferPtr buffer,
+ xmlSecByte *buf,
+ xmlSecSize size);
+static int xmlSecTransformIOBufferWrite (xmlSecTransformIOBufferPtr buffer,
+ const xmlSecByte *buf,
+ xmlSecSize size);
+static int xmlSecTransformIOBufferClose (xmlSecTransformIOBufferPtr buffer);
+
+
+/**
+ * xmlSecTransformCreateOutputBuffer:
+ * @transform: the pointer to transform.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Creates output buffer to write data to @transform.
+ *
+ * Returns: pointer to new output buffer or NULL if an error occurs.
+ */
+xmlOutputBufferPtr
+xmlSecTransformCreateOutputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformIOBufferPtr buffer;
+ xmlSecTransformDataType type;
+ xmlOutputBufferPtr output;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
+ xmlSecAssert2(transformCtx != NULL, NULL);
+
+ /* check that we have binary push method for this transform */
+ type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePush, transformCtx);
+ if((type & xmlSecTransformDataTypeBin) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "push binary data not supported");
+ return(NULL);
+ }
+
+ buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeWrite, transform, transformCtx);
+ if(buffer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformIOBufferCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ output = xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecTransformIOBufferWrite,
+ (xmlOutputCloseCallback)xmlSecTransformIOBufferClose,
+ buffer,
+ NULL);
+ if(output == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlOutputBufferCreateIO",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecTransformIOBufferDestroy(buffer);
+ return(NULL);
+ }
+
+ return(output);
+}
+
+/**
+ * xmlSecTransformCreateInputBuffer:
+ * @transform: the pointer to transform.
+ * @transformCtx: the pointer to transform context object.
+ *
+ * Creates input buffer to read data from @transform.
+ *
+ * Returns: pointer to new input buffer or NULL if an error occurs.
+ */
+xmlParserInputBufferPtr
+xmlSecTransformCreateInputBuffer(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformIOBufferPtr buffer;
+ xmlSecTransformDataType type;
+ xmlParserInputBufferPtr input;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
+ xmlSecAssert2(transformCtx != NULL, NULL);
+
+ /* check that we have binary pop method for this transform */
+ type = xmlSecTransformDefaultGetDataType(transform, xmlSecTransformModePop, transformCtx);
+ if((type & xmlSecTransformDataTypeBin) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "pop binary data not supported");
+ return(NULL);
+ }
+
+ buffer = xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferModeRead, transform, transformCtx);
+ if(buffer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformIOBufferCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ input = xmlParserInputBufferCreateIO((xmlInputReadCallback)xmlSecTransformIOBufferRead,
+ (xmlInputCloseCallback)xmlSecTransformIOBufferClose,
+ buffer,
+ XML_CHAR_ENCODING_NONE);
+ if(input == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlParserInputBufferCreateIO",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecTransformIOBufferDestroy(buffer);
+ return(NULL);
+ }
+
+ return(input);
+}
+
+static xmlSecTransformIOBufferPtr
+xmlSecTransformIOBufferCreate(xmlSecTransformIOBufferMode mode, xmlSecTransformPtr transform,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecTransformIOBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), NULL);
+ xmlSecAssert2(transformCtx != NULL, NULL);
+
+ buffer = (xmlSecTransformIOBufferPtr)xmlMalloc(sizeof(xmlSecTransformIOBuffer));
+ if(buffer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(xmlSecTransformIOBuffer));
+ return(NULL);
+ }
+ memset(buffer, 0, sizeof(xmlSecTransformIOBuffer));
+
+ buffer->mode = mode;
+ buffer->transform = transform;
+ buffer->transformCtx = transformCtx;
+
+ return(buffer);
+}
+
+static void
+xmlSecTransformIOBufferDestroy(xmlSecTransformIOBufferPtr buffer) {
+ xmlSecAssert(buffer != NULL);
+
+ memset(buffer, 0, sizeof(xmlSecTransformIOBuffer));
+ xmlFree(buffer);
+}
+
+static int
+xmlSecTransformIOBufferRead(xmlSecTransformIOBufferPtr buffer,
+ xmlSecByte *buf, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeRead, -1);
+ xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
+ xmlSecAssert2(buffer->transformCtx != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+
+ ret = xmlSecTransformPopBin(buffer->transform, buf, size, &size, buffer->transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
+ "xmlSecTransformPopBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(size);
+}
+
+static int
+xmlSecTransformIOBufferWrite(xmlSecTransformIOBufferPtr buffer,
+ const xmlSecByte *buf, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2(buffer->mode == xmlSecTransformIOBufferModeWrite, -1);
+ xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
+ xmlSecAssert2(buffer->transformCtx != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+
+ ret = xmlSecTransformPushBin(buffer->transform, buf, size, 0, buffer->transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
+ "xmlSecTransformPushBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(size);
+}
+
+static int
+xmlSecTransformIOBufferClose(xmlSecTransformIOBufferPtr buffer) {
+ int ret;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2(xmlSecTransformIsValid(buffer->transform), -1);
+ xmlSecAssert2(buffer->transformCtx != NULL, -1);
+
+ /* need to flush write buffer before destroing */
+ if(buffer->mode == xmlSecTransformIOBufferModeWrite) {
+ ret = xmlSecTransformPushBin(buffer->transform, NULL, 0, 1, buffer->transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(buffer->transform)),
+ "xmlSecTransformPushBin",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ xmlSecTransformIOBufferDestroy(buffer);
+ return(0);
+}
diff --git a/src/x509.c b/src/x509.c
new file mode 100644
index 00000000..22f5a196
--- /dev/null
+++ b/src/x509.c
@@ -0,0 +1,97 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * 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 <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/x509.h>
+#include <xmlsec/errors.h>
+
+/**
+ * xmlSecX509DataGetNodeContent:
+ * @node: the pointer to <dsig:X509Data/> node.
+ * @deleteChildren: the flag that indicates whether to remove node children after reading.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context.
+ *
+ * Reads the contents of <dsig:X509Data/> node and returns it as
+ * a bits mask.
+ *
+ * Returns: the bit mask representing the <dsig:X509Data/> node content
+ * or a negative value if an error occurs.
+ */
+int
+xmlSecX509DataGetNodeContent (xmlNodePtr node, int deleteChildren,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur, next;
+ int deleteCurNode;
+ int content = 0;
+
+ xmlSecAssert2(node != NULL, 0);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ /* determine the current node content */
+ cur = xmlSecGetNextElementNode(node->children);
+ while(cur != NULL) {
+ deleteCurNode = 0;
+ if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) {
+ if(xmlSecIsEmptyNode(cur) == 1) {
+ content |= XMLSEC_X509DATA_CERTIFICATE_NODE;
+ deleteCurNode = 1;
+ }
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+ if(xmlSecIsEmptyNode(cur) == 1) {
+ content |= XMLSEC_X509DATA_SUBJECTNAME_NODE;
+ deleteCurNode = 1;
+ }
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+ if(xmlSecIsEmptyNode(cur) == 1) {
+ content |= XMLSEC_X509DATA_ISSUERSERIAL_NODE;
+ deleteCurNode = 1;
+ }
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+ if(xmlSecIsEmptyNode(cur) == 1) {
+ content |= XMLSEC_X509DATA_SKI_NODE;
+ deleteCurNode = 1;
+ }
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+ if(xmlSecIsEmptyNode(cur) == 1) {
+ content |= XMLSEC_X509DATA_CRL_NODE;
+ deleteCurNode = 1;
+ }
+ } else {
+ /* todo: fail on unknown child node? */
+ }
+ next = xmlSecGetNextElementNode(cur->next);
+ if((deleteCurNode != 0) && (deleteChildren != 0)) {
+ /* remove "template" nodes */
+ xmlUnlinkNode(cur);
+ xmlFreeNode(cur);
+ }
+ cur = next;
+ }
+
+ return (content);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
diff --git a/src/xkms.c b/src/xkms.c
new file mode 100644
index 00000000..7b475301
--- /dev/null
+++ b/src/xkms.c
@@ -0,0 +1,4981 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * "XML Key Management Specification v 2.0" implementation
+ * http://www.w3.org/TR/xkms2/
+ *
+ * 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_XKMS
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/soap.h>
+#include <xmlsec/xkms.h>
+#include <xmlsec/private.h>
+#include <xmlsec/private/xkms.h>
+#include <xmlsec/errors.h>
+
+#define XMLSEC_XKMS_ID_ATTRIBUTE_LEN 32
+
+/* The ID attribute in XKMS is 'Id' */
+static const xmlChar* xmlSecXkmsServerIds[] = { BAD_CAST "Id", NULL };
+
+#ifndef XMLSEC_NO_SOAP
+static int xmlSecXkmsServerCtxWriteSoap11FatalError (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr envNode);
+static int xmlSecXkmsServerCtxWriteSoap12FatalError (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr envNode);
+#endif /* XMLSEC_NO_SOAP */
+
+static int xmlSecXkmsServerCtxRequestAbstractTypeNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr* node);
+static int xmlSecXkmsServerCtxSignatureNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxMessageExtensionNodesRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr* node);
+static int xmlSecXkmsServerCtxOpaqueClientDataNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxPendingNotificationNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxRespondWithNodesRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr* node);
+static int xmlSecXkmsServerCtxPendingRequestNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr* node);
+static int xmlSecXkmsServerCtxQueryKeyBindingNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr* node);
+static int xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+static int xmlSecXkmsServerCtxKeyInfoNodeWrite (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+static int xmlSecXkmsServerCtxUseKeyWithNodesRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr* node);
+static int xmlSecXkmsServerCtxUseKeyWithNodesWrite (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+static int xmlSecXkmsServerCtxTimeInstantNodeRead (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxResultTypeNodeWrite (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+static int xmlSecXkmsServerCtxKeyBindingNodeWrite (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+static int xmlSecXkmsServerCtxValidityIntervalNodeWrite (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+static int xmlSecXkmsServerCtxKeyBindingStatusNodeWrite (xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node,
+ xmlSecKeyPtr key);
+
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsResultMajorInfo[] =
+{
+ { xmlSecXkmsNs, xmlSecResultMajorCodeSuccess,
+ xmlSecXkmsResultMajorSuccess },
+ { xmlSecXkmsNs, xmlSecResultMajorCodeVersionMismatch,
+ xmlSecXkmsResultMajorVersionMismatch },
+ { xmlSecXkmsNs, xmlSecResultMajorCodeSender,
+ xmlSecXkmsResultMajorSender },
+ { xmlSecXkmsNs, xmlSecResultMajorCodeReceiver,
+ xmlSecXkmsResultMajorReceiver },
+ { xmlSecXkmsNs, xmlSecResultMajorCodeRepresent,
+ xmlSecXkmsResultMajorRepresent },
+ { xmlSecXkmsNs, xmlSecResultMajorCodePending,
+ xmlSecXkmsResultMajorPending, },
+ { NULL , NULL, 0 } /* MUST be last in the list */
+};
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsMinorErrorInfo[] =
+{
+ { xmlSecXkmsNs, xmlSecResultMinorCodeNoMatch,
+ xmlSecXkmsResultMinorNoMatch },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeTooManyResponses,
+ xmlSecXkmsResultMinorTooManyResponses },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeIncomplete,
+ xmlSecXkmsResultMinorIncomplete },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeFailure,
+ xmlSecXkmsResultMinorFailure },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeRefused,
+ xmlSecXkmsResultMinorRefused },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeNoAuthentication,
+ xmlSecXkmsResultMinorNoAuthentication },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeMessageNotSupported,
+ xmlSecXkmsResultMinorMessageNotSupported },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeUnknownResponseId,
+ xmlSecXkmsResultMinorUnknownResponseId },
+ { xmlSecXkmsNs, xmlSecResultMinorCodeNotSynchronous,
+ xmlSecXkmsResultMinorSynchronous },
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsKeyBindingStatusInfo[] =
+{
+ { xmlSecXkmsNs, xmlSecKeyBindingStatusValid,
+ xmlSecXkmsKeyBindingStatusValid },
+ { xmlSecXkmsNs, xmlSecKeyBindingStatusInvalid,
+ xmlSecXkmsKeyBindingStatusInvalid },
+ { xmlSecXkmsNs, xmlSecKeyBindingStatusIndeterminate,
+ xmlSecXkmsKeyBindingStatusIndeterminate },
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+static const xmlSecQName2BitMaskInfo gXmlSecXkmsKeyUsageInfo[] =
+{
+ { xmlSecXkmsNs, xmlSecKeyUsageEncryption,
+ xmlSecKeyUsageEncrypt | xmlSecKeyUsageDecrypt },
+ { xmlSecXkmsNs, xmlSecKeyUsageSignature,
+ xmlSecKeyUsageSign | xmlSecKeyUsageVerify },
+ { xmlSecXkmsNs, xmlSecKeyUsageExchange,
+ xmlSecKeyUsageKeyExchange},
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+static const xmlSecQName2BitMaskInfo gXmlSecXkmsKeyBindingReasonInfo[] =
+{
+ { xmlSecXkmsNs, xmlSecKeyBindingReasonIssuerTrust,
+ XMLSEC_XKMS_KEY_BINDING_REASON_MASK_ISSUER_TRAST },
+ { xmlSecXkmsNs, xmlSecKeyBindingReasonRevocationStatus,
+ XMLSEC_XKMS_KEY_BINDING_REASON_MASK_REVOCATION_STATUS },
+ { xmlSecXkmsNs, xmlSecKeyBindingReasonValidityInterval,
+ XMLSEC_XKMS_KEY_BINDING_REASON_MASK_VALIDITY_INTERVAL },
+ { xmlSecXkmsNs, xmlSecKeyBindingReasonSignature,
+ XMLSEC_XKMS_KEY_BINDING_REASON_MASK_SIGNATURE },
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+static const xmlSecQName2BitMaskInfo gXmlSecXkmsResponseMechanismInfo[] =
+{
+ { xmlSecXkmsNs, xmlSecResponseMechanismRepresent,
+ XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REPRESENT },
+ { xmlSecXkmsNs, xmlSecResponseMechanismPending,
+ XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_PENDING },
+ { xmlSecXkmsNs, xmlSecResponseMechanismRequestSignatureValue,
+ XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REQUEST_SIGNATURE_VALUE },
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsFormatInfo[] =
+{
+ { NULL, xmlSecXkmsFormatStrPlain,
+ xmlSecXkmsServerFormatPlain },
+#ifndef XMLSEC_NO_SOAP
+ { NULL, xmlSecXkmsFormatStrSoap11,
+ xmlSecXkmsServerFormatSoap11 },
+ { NULL, xmlSecXkmsFormatStrSoap12,
+ xmlSecXkmsServerFormatSoap12 },
+#endif /* XMLSEC_NO_SOAP */
+ { NULL, NULL, 0 } /* MUST be last in the list */
+};
+
+/**
+ * xmlSecXkmsServerFormatFromString:
+ * @str the string.
+ *
+ * Gets xmlSecXkmsServerFormat from string @str.
+ *
+ * Returns: corresponding format or xmlSecXkmsServerFormatUnknown
+ * if format could not be recognized.
+ */
+xmlSecXkmsServerFormat
+xmlSecXkmsServerFormatFromString(const xmlChar* str) {
+ int res;
+ int ret;
+
+ xmlSecAssert2(str != NULL, xmlSecXkmsServerFormatUnknown);
+
+ ret = xmlSecQName2IntegerGetInteger(gXmlSecXkmsFormatInfo, NULL, str, &res);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetInteger",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(xmlSecXkmsServerFormatUnknown);
+ }
+
+ return((xmlSecXkmsServerFormat)res);
+}
+
+/**
+ * xmlSecXkmsServerFormatToString:
+ * @format: the format.
+ *
+ * Gets string from @format.
+ *
+ * Returns: string corresponding to @format or NULL if an error occurs.
+ */
+const xmlChar*
+xmlSecXkmsServerFormatToString (xmlSecXkmsServerFormat format) {
+ xmlSecQName2IntegerInfoConstPtr info;
+
+ xmlSecAssert2(format != xmlSecXkmsServerFormatUnknown, NULL);
+
+ info = xmlSecQName2IntegerGetInfo(gXmlSecXkmsFormatInfo, format);
+ if(info == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetInfo",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ return(info->qnameLocalPart);
+}
+
+/**
+ * xmlSecXkmsServerCtxCreate:
+ * @keysMngr: the pointer to keys manager.
+ *
+ * Creates XKMS request server side processing context.
+ * The caller is responsible for destroying returend object by calling
+ * #xmlSecXkmsServerCtxDestroy function.
+ *
+ * Returns: pointer to newly allocated context object or NULL if an error
+ * occurs.
+ */
+xmlSecXkmsServerCtxPtr
+xmlSecXkmsServerCtxCreate(xmlSecKeysMngrPtr keysMngr) {
+ xmlSecXkmsServerCtxPtr ctx;
+ int ret;
+
+ ctx = (xmlSecXkmsServerCtxPtr) xmlMalloc(sizeof(xmlSecXkmsServerCtx));
+ if(ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecXkmsServerCtx)=%d",
+ sizeof(xmlSecXkmsServerCtx));
+ return(NULL);
+ }
+
+ ret = xmlSecXkmsServerCtxInitialize(ctx, keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxDestroy(ctx);
+ return(NULL);
+ }
+ return(ctx);
+}
+
+/**
+ * xmlSecXkmsServerCtxDestroy:
+ * @ctx: the pointer to XKMS processing context.
+ *
+ * Destroy context object created with #xmlSecXkmsServerCtxCreate function.
+ */
+void
+xmlSecXkmsServerCtxDestroy(xmlSecXkmsServerCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecXkmsServerCtxFinalize(ctx);
+ xmlFree(ctx);
+}
+
+/**
+ * xmlSecXkmsServerCtxInitialize:
+ * @ctx: the pointer to XKMS processing context.
+ * @keysMngr: the pointer to keys manager.
+ *
+ * Initializes XKMS element processing context.
+ * The caller is responsible for cleaing up returend object by calling
+ * #xmlSecXkmsServerCtxFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerCtxInitialize(xmlSecXkmsServerCtxPtr ctx, xmlSecKeysMngrPtr keysMngr) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecXkmsServerCtx));
+
+ ctx->resultMajor = xmlSecXkmsResultMajorSuccess;
+ ctx->resultMinor = xmlSecXkmsResultMinorNone;
+ ctx->responseLimit = XMLSEC_XKMS_NO_RESPONSE_LIMIT;
+ ctx->idLen = XMLSEC_XKMS_ID_ATTRIBUTE_LEN;
+
+ /* initialize key info */
+ ret = xmlSecKeyInfoCtxInitialize(&(ctx->keyInfoReadCtx), keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ctx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
+
+ ret = xmlSecKeyInfoCtxInitialize(&(ctx->keyInfoWriteCtx), keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ctx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
+
+ /* enabled RespondWith */
+ ret = xmlSecPtrListInitialize(&(ctx->enabledRespondWithIds), xmlSecXkmsRespondWithIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* enabled ServerRequest */
+ ret = xmlSecPtrListInitialize(&(ctx->enabledServerRequestIds), xmlSecXkmsServerRequestIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+
+
+ /* initialize keys list */
+ ret = xmlSecPtrListInitialize(&(ctx->keys), xmlSecKeyPtrListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* initialize RespondWith list */
+ ret = xmlSecPtrListInitialize(&(ctx->respWithList), xmlSecXkmsRespondWithIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsServerCtxFinalize:
+ * @ctx: the pointer to XKMS processing context.
+ *
+ * Cleans up @ctx object.
+ */
+void
+xmlSecXkmsServerCtxFinalize(xmlSecXkmsServerCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecXkmsServerCtxReset(ctx);
+
+ if(ctx->expectedService != NULL) {
+ xmlFree(ctx->expectedService);
+ }
+ if(ctx->idPrefix != NULL) {
+ xmlFree(ctx->idPrefix);
+ }
+
+ xmlSecKeyInfoCtxFinalize(&(ctx->keyInfoReadCtx));
+ xmlSecKeyInfoCtxFinalize(&(ctx->keyInfoWriteCtx));
+ xmlSecPtrListFinalize(&(ctx->enabledRespondWithIds));
+ xmlSecPtrListFinalize(&(ctx->enabledServerRequestIds));
+ xmlSecPtrListFinalize(&(ctx->keys));
+ xmlSecPtrListFinalize(&(ctx->respWithList));
+ memset(ctx, 0, sizeof(xmlSecXkmsServerCtx));
+}
+
+/**
+ * xmlSecXkmsServerCtxReset:
+ * @ctx: the pointer to XKMS processing context.
+ *
+ * Resets @ctx object, user settings are not touched.
+ */
+void
+xmlSecXkmsServerCtxReset(xmlSecXkmsServerCtxPtr ctx) {
+ xmlSecAssert(ctx != NULL);
+
+ ctx->resultMajor = xmlSecXkmsResultMajorSuccess;
+ ctx->resultMinor = xmlSecXkmsResultMinorNone;
+ xmlSecKeyInfoCtxReset(&(ctx->keyInfoReadCtx));
+ xmlSecKeyInfoCtxReset(&(ctx->keyInfoWriteCtx));
+ xmlSecPtrListEmpty(&(ctx->keys));
+ xmlSecPtrListEmpty(&(ctx->respWithList));
+
+ ctx->requestNode = NULL;
+ ctx->opaqueClientDataNode = NULL;
+ ctx->firtsMsgExtNode = NULL;
+ ctx->keyInfoNode = NULL;
+ ctx->requestId = xmlSecXkmsServerRequestIdUnknown;
+
+ if(ctx->id != NULL) {
+ xmlFree(ctx->id); ctx->id = NULL;
+ }
+ if(ctx->service != NULL) {
+ xmlFree(ctx->service); ctx->service = NULL;
+ }
+ if(ctx->nonce != NULL) {
+ xmlFree(ctx->nonce); ctx->nonce = NULL;
+ }
+ if(ctx->originalRequestId != NULL) {
+ xmlFree(ctx->originalRequestId); ctx->originalRequestId = NULL;
+ }
+ if(ctx->pendingNotificationMechanism != NULL) {
+ xmlFree(ctx->pendingNotificationMechanism);
+ ctx->pendingNotificationMechanism = NULL;
+ }
+ if(ctx->pendingNotificationIdentifier != NULL) {
+ xmlFree(ctx->pendingNotificationIdentifier);
+ ctx->pendingNotificationIdentifier = NULL;
+ }
+ if(ctx->compoundRequestContexts != NULL) {
+ xmlSecPtrListDestroy(ctx->compoundRequestContexts);
+ ctx->compoundRequestContexts = NULL;
+ }
+
+ ctx->responseLimit = XMLSEC_XKMS_NO_RESPONSE_LIMIT;
+ ctx->responseMechanismMask = 0;
+}
+
+/**
+ * xmlSecXkmsServerCtxCopyUserPref:
+ * @dst: the pointer to destination context.
+ * @src: the pointer to source context.
+ *
+ * Copies user preference from @src context to @dst.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerCtxCopyUserPref(xmlSecXkmsServerCtxPtr dst, xmlSecXkmsServerCtxPtr src) {
+ int ret;
+
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(src != NULL, -1);
+
+ dst->userData = src->userData;
+ dst->flags = src->flags;
+ dst->flags2 = src->flags2;
+
+ ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(src->expectedService != NULL) {
+ dst->expectedService = xmlStrdup(src->expectedService);
+ if(dst->expectedService == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(src->idPrefix != NULL) {
+ dst->idPrefix = xmlStrdup(src->idPrefix);
+ if(dst->idPrefix == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ src->idLen = dst->idLen;
+
+
+ ret = xmlSecPtrListCopy(&(dst->enabledRespondWithIds), &(src->enabledRespondWithIds));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecPtrListCopy(&(dst->enabledServerRequestIds), &(src->enabledServerRequestIds));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsServerCtxProcess:
+ * @ctx: the pointer to XKMS processing context.
+ * @node: the pointer to request node.
+ * @format: the request/response format.
+ * @doc: the pointer to response parent XML document (might be NULL).
+ *
+ * Reads XKMS request from @node and creates response to a newly created node.
+ * Caller is responsible for adding the returned node to the XML document.
+ *
+ * Returns: pointer to newly created XKMS response node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecXkmsServerCtxProcess(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node,
+ xmlSecXkmsServerFormat format, xmlDocPtr doc) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->requestId == NULL, NULL);
+ xmlSecAssert2(ctx->requestNode == NULL, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ ctx->requestNode = xmlSecXkmsServerCtxRequestUnwrap(ctx, node, format);
+ if(ctx->requestNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRequestUnwrap",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ goto done;
+ }
+
+ ret = xmlSecXkmsServerCtxRequestRead(ctx, ctx->requestNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdListFindByNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ctx->requestNode=%s",
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ goto done;
+ }
+
+ ret = xmlSecXkmsServerRequestExecute(ctx->requestId, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ctx->requestNode=%s",
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ goto done;
+ }
+
+done:
+ /* always try to write response back */
+ if(ctx->requestId != NULL) {
+ xmlNodePtr respNode;
+ xmlNodePtr wrappedRespNode;
+
+ respNode = xmlSecXkmsServerCtxResponseWrite(ctx, doc);
+ if(respNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResponseWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ctx->requestNode=%s",
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ goto error;
+ }
+
+
+ wrappedRespNode = xmlSecXkmsServerCtxResponseWrap(ctx, respNode, format, doc);
+ if(wrappedRespNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResponseWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ctx->requestNode=%s",
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ xmlFreeNode(respNode);
+ goto error;
+ }
+
+ return(wrappedRespNode);
+ }
+
+error:
+ /* last attempt: create fatatl error response */
+ return(xmlSecXkmsServerCtxFatalErrorResponseCreate(ctx, format, doc));
+}
+
+/**
+ * xmlSecXkmsServerCtxRequestRead:
+ * @ctx: the pointer to XKMS processing context.
+ * @node: the pointer to request node.
+ *
+ * Reads XKMS request from @node and stores data in @ctx.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerCtxRequestRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->requestId == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* find out what the request is */
+ if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+ ctx->requestId = xmlSecXkmsServerRequestIdListFindByNode(&(ctx->enabledServerRequestIds), node);
+ } else {
+ ctx->requestId = xmlSecXkmsServerRequestIdListFindByNode(xmlSecXkmsServerRequestIdsGet(), node);
+ }
+ if(ctx->requestId == xmlSecXkmsServerRequestIdUnknown) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdListFindByNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorMessageNotSupported);
+ return(-1);
+ }
+
+ xmlSecAddIDs(node->doc, node, xmlSecXkmsServerIds);
+ ret = xmlSecXkmsServerRequestNodeRead(ctx->requestId, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "request=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctx->requestId)));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsServerCtxResponseWrite:
+ * @ctx: the pointer to XKMS processing context.
+ * @doc: the pointer to response parent XML document (might be NULL).
+ *
+ * Writes XKMS response from context to a newly created node. Caller is
+ * responsible for adding the returned node to the XML document.
+ *
+ * Returns: pointer to newly created XKMS response node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecXkmsServerCtxResponseWrite(xmlSecXkmsServerCtxPtr ctx, xmlDocPtr doc) {
+ xmlNodePtr respNode;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->requestId != NULL, NULL);
+
+ /* now write results */
+ respNode = xmlSecXkmsServerRequestNodeWrite(ctx->requestId, ctx, doc, NULL);
+ if(respNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "request=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctx->requestId)));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ return(respNode);
+}
+
+/**
+ * xmlSecXkmsServerCtxRequestUnwrap:
+ * @ctx: the pointer to XKMS processing context.
+ * @node: the pointer to request node.
+ * @format: the request/response format.
+ *
+ * Removes SOAP or other envelope from XKMS request.
+ *
+ * Returns: pointer to "real" XKMS request node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecXkmsServerCtxRequestUnwrap(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecXkmsServerFormat format) {
+ xmlNodePtr result = NULL;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ switch(format) {
+ case xmlSecXkmsServerFormatPlain:
+ result = node;
+ break;
+#ifndef XMLSEC_NO_SOAP
+ case xmlSecXkmsServerFormatSoap11:
+ /* verify that it is actually soap Envelope node */
+ if(xmlSecSoap11CheckEnvelope(node) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11CheckEnvelope",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ /* check that Body has exactly one entry */
+ if(xmlSecSoap11GetBodyEntriesNumber(node) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBodyEntriesNumber",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ /* this one enntry is our xkms request */
+ result = xmlSecSoap11GetBodyEntry(node, 0);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11GetBodyEntry",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ break;
+ case xmlSecXkmsServerFormatSoap12:
+ /* verify that it is actually soap Envelope node */
+ if(xmlSecSoap12CheckEnvelope(node) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12CheckEnvelope",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ /* check that Body has exactly one entry */
+ if(xmlSecSoap12GetBodyEntriesNumber(node) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBodyEntriesNumber",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ /* this one enntry is our xkms request */
+ result = xmlSecSoap12GetBodyEntry(node, 0);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12GetBodyEntry",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ break;
+#endif /* XMLSEC_NO_SOAP */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ "format=%d",
+ format);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ return(result);
+}
+
+/**
+ * xmlSecXkmsServerCtxResponseWrap:
+ * @ctx: the pointer to XKMS processing context.
+ * @node: the pointer to response node.
+ * @format: the request/response format.
+ * @doc: the pointer to response parent XML document (might be NULL).
+ *
+ * Creates SOAP or other envelope around XKMS response.
+ * Caller is responsible for adding the returned node to the XML document.
+ *
+ * Returns: pointer to newly created response envelope node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecXkmsServerCtxResponseWrap(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecXkmsServerFormat format, xmlDocPtr doc) {
+ xmlNodePtr result = NULL;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ switch(format) {
+ case xmlSecXkmsServerFormatPlain:
+ result = node; /* do nothing */
+ break;
+#ifndef XMLSEC_NO_SOAP
+ case xmlSecXkmsServerFormatSoap11:
+ result = xmlSecSoap11CreateEnvelope(doc);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11CreateEnvelope",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ if(xmlSecSoap11AddBodyEntry(result, node) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11AddBodyEntry",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+ break;
+ case xmlSecXkmsServerFormatSoap12:
+ result = xmlSecSoap12CreateEnvelope(doc);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12CreateEnvelope",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ if(xmlSecSoap12AddBodyEntry(result, node) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12AddBodyEntry",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_SOAP */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ "format=%d",
+ format);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ return(result);
+}
+
+/**
+ * xmlSecXkmsServerCtxFatalErrorResponseCreate:
+ * @ctx: the pointer to XKMS processing context.
+ * @format: the request/response format.
+ * @doc: the pointer to response parent XML document (might be NULL).
+ *
+ * Creates a "fatal error" SOAP or other envelope respons. Caller is
+ * responsible for adding the returned node to the XML document.
+ *
+ * Returns: pointer to newly created fatal error response (it might be NULL).
+ */
+xmlNodePtr
+xmlSecXkmsServerCtxFatalErrorResponseCreate(xmlSecXkmsServerCtxPtr ctx, xmlSecXkmsServerFormat format, xmlDocPtr doc) {
+ xmlNodePtr result = NULL;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ /* make sure that we have an error */
+ if(ctx->resultMajor == xmlSecXkmsResultMajorSuccess) {
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ }
+
+ switch(format) {
+ case xmlSecXkmsServerFormatPlain:
+ /* try to create fatal error response with XKMS Status request */
+ result = xmlSecXkmsServerRequestNodeWrite(xmlSecXkmsServerRequestResultId, ctx, doc, NULL);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+#ifndef XMLSEC_NO_SOAP
+ case xmlSecXkmsServerFormatSoap11:
+ result = xmlSecSoap11CreateEnvelope(doc);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11CreateEnvelope",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ ret = xmlSecXkmsServerCtxWriteSoap11FatalError(ctx, result);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxWriteSoap11FatalError",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ xmlFreeNode(result);
+ return(NULL);
+ }
+
+ break;
+ case xmlSecXkmsServerFormatSoap12:
+ result = xmlSecSoap12CreateEnvelope(doc);
+ if(result == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12CreateEnvelope",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ ret = xmlSecXkmsServerCtxWriteSoap12FatalError(ctx, result);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxWriteSoap12FatalError",
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ xmlFreeNode(result);
+ return(NULL);
+ }
+
+ break;
+#endif /* XMLSEC_NO_SOAP */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ "format=%d",
+ format);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(NULL);
+ }
+
+ return(result);
+}
+
+#ifndef XMLSEC_NO_SOAP
+static int
+xmlSecXkmsServerCtxWriteSoap11FatalError(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr envNode) {
+ const xmlChar* faultCodeHref = NULL;
+ const xmlChar* faultCodeLocalPart = NULL;
+ xmlChar* faultString = NULL;
+ int len;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(envNode != NULL, -1);
+
+ if((ctx->resultMajor == xmlSecXkmsResultMajorVersionMismatch) ||
+ (ctx->requestNode == NULL)) {
+ /* we were not able to parse the envelope or its general version mismatch error */
+ faultCodeHref = xmlSecSoap11Ns;
+ faultCodeLocalPart = xmlSecSoapFaultCodeVersionMismatch;
+ faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonUnsupportedVersion);
+ if(faultString == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ } else if((ctx->resultMajor == xmlSecXkmsResultMajorSender) &&
+ (ctx->requestId == NULL)) {
+ /* we understood the request but were not able to parse input message */
+ faultCodeHref = xmlSecSoap11Ns;
+ faultCodeLocalPart = xmlSecSoapFaultCodeClient;
+
+ len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) +
+ xmlStrlen(xmlSecXkmsSoapFaultReasonMessageInvalid) + 1;
+ faultString = xmlMalloc(len + 1);
+ if(faultString == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ xmlSecStrPrintf(faultString, len , xmlSecXkmsSoapFaultReasonMessageInvalid,
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ } else if((ctx->resultMajor == xmlSecXkmsResultMajorReceiver) &&
+ (ctx->requestId == NULL)) {
+ /* we understood the request but were not able to process it */
+ faultCodeHref = xmlSecSoap11Ns;
+ faultCodeLocalPart = xmlSecSoapFaultCodeServer;
+ faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+ if(faultString == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ } else if((ctx->requestId == NULL) && (ctx->requestNode != NULL)) {
+ /* we parsed the envelope but were not able to understand this request */
+ faultCodeHref = xmlSecSoap11Ns;
+ faultCodeLocalPart = xmlSecSoapFaultCodeClient;
+
+ len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) +
+ xmlStrlen(xmlSecXkmsSoapFaultReasonMessageNotSupported) + 1;
+ faultString = xmlMalloc(len + 1);
+ if(faultString == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ xmlSecStrPrintf(faultString, len , xmlSecXkmsSoapFaultReasonMessageNotSupported,
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ } else {
+ /* just some error */
+ faultCodeHref = xmlSecSoap11Ns;
+ faultCodeLocalPart = xmlSecSoapFaultCodeServer;
+ faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+ if(faultString == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ }
+
+ if(xmlSecSoap11AddFaultEntry(envNode, faultCodeHref, faultCodeLocalPart, faultString, NULL) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap11AddFaultEntry",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ xmlFree(faultString);
+ return(-1);
+ }
+
+ xmlFree(faultString);
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxWriteSoap12FatalError(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr envNode) {
+ xmlSecSoap12FaultCode faultCode = xmlSecSoap12FaultCodeUnknown;
+ const xmlChar* faultSubCodeHref = NULL;
+ const xmlChar* faultSubCodeLocalPart = NULL;
+ xmlChar* faultReason = NULL;
+ int len;
+ xmlNodePtr faultNode;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(envNode != NULL, -1);
+
+ if((ctx->resultMajor == xmlSecXkmsResultMajorVersionMismatch) ||
+ (ctx->requestNode == NULL)) {
+ /* we were not able to parse the envelope or its general version mismatch error */
+ faultCode = xmlSecSoap12FaultCodeVersionMismatch;
+ faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonUnsupportedVersion);
+ if(faultReason == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ } else if((ctx->resultMajor == xmlSecXkmsResultMajorSender) &&
+ (ctx->requestId == NULL)) {
+ /* we understood the request but were not able to parse input message */
+ faultCode = xmlSecSoap12FaultCodeSender;
+ faultSubCodeHref = xmlSecXkmsNs;
+ faultSubCodeLocalPart = xmlSecXkmsSoapSubcodeValueMessageNotSupported;
+
+ len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) +
+ xmlStrlen(xmlSecXkmsSoapFaultReasonMessageInvalid) + 1;
+ faultReason = xmlMalloc(len + 1);
+ if(faultReason == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ xmlSecStrPrintf(faultReason, len , xmlSecXkmsSoapFaultReasonMessageInvalid,
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ } else if((ctx->resultMajor == xmlSecXkmsResultMajorReceiver) &&
+ (ctx->requestId == NULL)) {
+ /* we understood the request but were not able to process it */
+ faultCode = xmlSecSoap12FaultCodeReceiver;
+ faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+ if(faultReason == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ } else if((ctx->requestId == NULL) && (ctx->requestNode != NULL)) {
+ /* we parsed the envelope but were not able to understand this request */
+ faultCode = xmlSecSoap12FaultCodeSender;
+ faultSubCodeHref = xmlSecXkmsNs;
+ faultSubCodeLocalPart = xmlSecXkmsSoapSubcodeValueBadMessage;
+
+ len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) +
+ xmlStrlen(xmlSecXkmsSoapFaultReasonMessageNotSupported) + 1;
+ faultReason = xmlMalloc(len + 1);
+ if(faultReason == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ xmlSecStrPrintf(faultReason, len , xmlSecXkmsSoapFaultReasonMessageNotSupported,
+ xmlSecErrorsSafeString(ctx->requestNode->name));
+ } else {
+ /* just some error */
+ faultCode = xmlSecSoap12FaultCodeReceiver;
+ faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+ if(faultReason == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ }
+ xmlSecAssert2(faultCode != xmlSecSoap12FaultCodeUnknown, -1);
+ xmlSecAssert2(faultReason != NULL, -1);
+
+ faultNode = xmlSecSoap12AddFaultEntry(envNode, faultCode, faultReason,
+ xmlSecXkmsSoapFaultReasonLang, NULL, NULL);
+ if(faultNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12AddFaultEntry",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ xmlFree(faultReason);
+ return(-1);
+ }
+ xmlFree(faultReason);
+
+ if((faultSubCodeHref != NULL) && (faultSubCodeLocalPart != NULL)) {
+ /* make sure that we have subcode (xkms) namespace declared */
+ if(xmlNewNs(faultNode, faultSubCodeHref, BAD_CAST "xkms") == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(faultSubCodeHref));
+ return(-1);
+ }
+ if(xmlSecSoap12AddFaultSubcode(faultNode, faultSubCodeHref, faultSubCodeLocalPart) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSoap12AddFaultSubcode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "href=%s,value=%s",
+ xmlSecErrorsSafeString(faultSubCodeHref),
+ xmlSecErrorsSafeString(faultSubCodeLocalPart));
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_NO_SOAP */
+
+
+/**
+ * xmlSecXkmsServerCtxSetResult:
+ * @ctx: the pointer to XKMS processing context.
+ * @resultMajor: the major result code.
+ * @resultMinor: the minor result code.
+ *
+ * Sets the major/minor result code in the context if no other result is already
+ * reported.
+ */
+void
+xmlSecXkmsServerCtxSetResult(xmlSecXkmsServerCtxPtr ctx, xmlSecXkmsResultMajor resultMajor,
+ xmlSecXkmsResultMinor resultMinor) {
+ xmlSecAssert(ctx != NULL);
+
+ if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) &&
+ (resultMinor != xmlSecXkmsResultMajorSuccess)) {
+ ctx->resultMajor = resultMajor;
+ ctx->resultMinor = resultMinor;
+ } else if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) &&
+ (ctx->resultMinor == xmlSecXkmsResultMinorNone)) {
+ xmlSecAssert(resultMajor == xmlSecXkmsResultMajorSuccess);
+
+ ctx->resultMinor = resultMinor;
+ }
+}
+
+
+/**
+ * xmlSecXkmsServerCtxDebugDump:
+ * @ctx: the pointer to XKMS processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the debug information about @ctx to @output.
+ */
+void
+xmlSecXkmsServerCtxDebugDump(xmlSecXkmsServerCtxPtr ctx, FILE* output) {
+ xmlSecAssert(ctx != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "= XKMS SERVER CONTEXT: %s\n",
+ (ctx->requestId != xmlSecXkmsServerRequestIdUnknown &&
+ xmlSecXkmsServerRequestKlassGetName(ctx->requestId)) ?
+ xmlSecXkmsServerRequestKlassGetName(ctx->requestId) :
+ BAD_CAST "NULL");
+
+ xmlSecQName2IntegerDebugDump(gXmlSecXkmsResultMajorInfo,
+ ctx->resultMajor, BAD_CAST "resultMajor", output);
+ xmlSecQName2IntegerDebugDump(gXmlSecXkmsMinorErrorInfo,
+ ctx->resultMinor, BAD_CAST "resultMinor", output);
+
+ fprintf(output, "== id: %s\n",
+ (ctx->id) ? ctx->id : BAD_CAST "");
+ fprintf(output, "== service: %s\n",
+ (ctx->service) ? ctx->service : BAD_CAST "");
+ fprintf(output, "== nonce: %s\n",
+ (ctx->nonce) ? ctx->nonce : BAD_CAST "");
+ fprintf(output, "== originalRequestId: %s\n",
+ (ctx->originalRequestId) ? ctx->originalRequestId : BAD_CAST "");
+ fprintf(output, "== pendingNotificationMechanism: %s\n",
+ (ctx->pendingNotificationMechanism) ?
+ ctx->pendingNotificationMechanism :
+ BAD_CAST "");
+ fprintf(output, "== pendingNotificationIdentifier: %s\n",
+ (ctx->pendingNotificationIdentifier) ?
+ ctx->pendingNotificationIdentifier :
+ BAD_CAST "");
+ if(ctx->responseLimit != XMLSEC_XKMS_NO_RESPONSE_LIMIT) {
+ fprintf(output, "== ResponseLimit: %d\n", ctx->responseLimit);
+ }
+ xmlSecQName2BitMaskDebugDump(gXmlSecXkmsResponseMechanismInfo,
+ ctx->responseMechanismMask, BAD_CAST "responseMechanism", output);
+
+ if(ctx->expectedService != NULL) {
+ fprintf(output, "== expected service: %s\n", ctx->expectedService);
+ }
+ fprintf(output, "== flags: 0x%08x\n", ctx->flags);
+ fprintf(output, "== flags2: 0x%08x\n", ctx->flags2);
+
+ fprintf(output, "== Key Info Read Ctx:\n");
+ xmlSecKeyInfoCtxDebugDump(&(ctx->keyInfoReadCtx), output);
+
+ fprintf(output, "== Key Info Write Ctx:\n");
+ xmlSecKeyInfoCtxDebugDump(&(ctx->keyInfoWriteCtx), output);
+
+ if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) {
+ fprintf(output, "== Enabled RespondWith: ");
+ xmlSecTransformIdListDebugDump(&(ctx->enabledRespondWithIds), output);
+ } else {
+ fprintf(output, "== Enabled RespondWith: all\n");
+ }
+
+ if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+ fprintf(output, "== Enabled ServerRequest: ");
+ xmlSecTransformIdListDebugDump(&(ctx->enabledServerRequestIds), output);
+ } else {
+ fprintf(output, "== Enabled ServerRequest: all\n");
+ }
+
+ fprintf(output, "== RespondWith List:\n");
+ xmlSecPtrListDebugDump(&(ctx->respWithList), output);
+
+ fprintf(output, "== Keys:\n");
+ xmlSecPtrListDebugDump(&(ctx->keys), output);
+
+ if(ctx->compoundRequestContexts != NULL) {
+ fprintf(output, "== Compound Request:\n");
+ xmlSecPtrListDebugDump(ctx->compoundRequestContexts, output);
+ }
+}
+
+/**
+ * xmlSecXkmsServerCtxDebugXmlDump:
+ * @ctx: the pointer to XKMS processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the debug information about @ctx to @output in XML format.
+ */
+void
+xmlSecXkmsServerCtxDebugXmlDump(xmlSecXkmsServerCtxPtr ctx, FILE* output) {
+ xmlSecAssert(ctx != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<XkmsServerRequestContext name=\"");
+ xmlSecPrintXmlString(output,
+ (ctx->requestId != xmlSecXkmsServerRequestIdUnknown) ?
+ xmlSecXkmsServerRequestKlassGetName(ctx->requestId) :
+ BAD_CAST "NULL"
+ );
+ fprintf(output, "\">\n");
+
+ xmlSecQName2IntegerDebugXmlDump(gXmlSecXkmsResultMajorInfo,
+ ctx->resultMajor, BAD_CAST "MajorError", output);
+ xmlSecQName2IntegerDebugXmlDump(gXmlSecXkmsMinorErrorInfo,
+ ctx->resultMinor, BAD_CAST "MinorError", output);
+
+ fprintf(output, "<Id>");
+ xmlSecPrintXmlString(output, ctx->id);
+ fprintf(output, "</Id>\n");
+
+ fprintf(output, "<Service>");
+ xmlSecPrintXmlString(output, ctx->service);
+ fprintf(output, "</Service>\n");
+
+ fprintf(output, "<Nonce>");
+ xmlSecPrintXmlString(output, ctx->nonce);
+ fprintf(output, "</Nonce>\n");
+
+ fprintf(output, "<OriginalRequestId>");
+ xmlSecPrintXmlString(output, ctx->originalRequestId);
+ fprintf(output, "</OriginalRequestId>\n");
+
+ fprintf(output, "<PendingNotificationMechanism>");
+ xmlSecPrintXmlString(output, ctx->pendingNotificationMechanism);
+ fprintf(output, "</PendingNotificationMechanism>\n");
+
+ fprintf(output, "<PendingNotificationIdentifier>");
+ xmlSecPrintXmlString(output, ctx->pendingNotificationIdentifier);
+ fprintf(output, "</PendingNotificationIdentifier>\n");
+
+ if(ctx->responseLimit != XMLSEC_XKMS_NO_RESPONSE_LIMIT) {
+ fprintf(output, "<ResponseLimit>%d</ResponseLimit>\n", ctx->responseLimit);
+ }
+ xmlSecQName2BitMaskDebugXmlDump(gXmlSecXkmsResponseMechanismInfo,
+ ctx->responseMechanismMask, BAD_CAST "ResponseMechanism", output);
+
+
+ fprintf(output, "<ExpectedService>");
+ xmlSecPrintXmlString(output, ctx->expectedService);
+ fprintf(output, "</ExpectedService>\n");
+
+ fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags);
+ fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2);
+
+ fprintf(output, "<KeyInfoReadCtx>\n");
+ xmlSecKeyInfoCtxDebugXmlDump(&(ctx->keyInfoReadCtx), output);
+ fprintf(output, "</KeyInfoReadCtx>\n");
+
+ fprintf(output, "<KeyInfoWriteCtx>\n");
+ xmlSecKeyInfoCtxDebugXmlDump(&(ctx->keyInfoWriteCtx), output);
+ fprintf(output, "</KeyInfoWriteCtx>\n");
+
+ if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) {
+ fprintf(output, "<EnabledRespondWith>\n");
+ xmlSecTransformIdListDebugXmlDump(&(ctx->enabledRespondWithIds), output);
+ fprintf(output, "</EnabledRespondWith>\n");
+ } else {
+ fprintf(output, "<EnabledRespondWith>all</EnabledRespondWith>\n");
+ }
+
+ if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+ fprintf(output, "<EnabledServerRequest>\n");
+ xmlSecTransformIdListDebugXmlDump(&(ctx->enabledServerRequestIds), output);
+ fprintf(output, "</EnabledServerRequest>\n");
+ } else {
+ fprintf(output, "<EnabledServerRequest>all</EnabledServerRequest>\n");
+ }
+
+
+ fprintf(output, "<RespondWithList>\n");
+ xmlSecPtrListDebugXmlDump(&(ctx->respWithList), output);
+ fprintf(output, "</RespondWithList>\n");
+
+ fprintf(output, "<Keys>\n");
+ xmlSecPtrListDebugXmlDump(&(ctx->keys), output);
+ fprintf(output, "</Keys>\n");
+
+ if(ctx->compoundRequestContexts != NULL) {
+ fprintf(output, "<CompoundRequest>\n");
+ xmlSecPtrListDebugXmlDump(ctx->compoundRequestContexts, output);
+ fprintf(output, "</CompoundRequest>\n");
+ }
+
+ fprintf(output, "</XkmsServerRequestContext>\n");
+}
+
+/**
+ * <xkms:MessageAbstractType Id Service Nonce?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ *
+ * <xkms:RequestAbstractType Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:ResponseMechanism>*
+ * <xkms:RespondWith>*
+ * <xkms:PendingNotification Mechanism Identifier>?
+ *
+ * XML Schema:
+ *
+ * <!-- RequestAbstractType -->
+ * <complexType name="RequestAbstractType" abstract="true">
+ * <complexContent>
+ * <extension base="xkms:MessageAbstractType">
+ * <sequence>
+ * <element ref="xkms:ResponseMechanism" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * <element ref="xkms:RespondWith" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * <element ref="xkms:PendingNotification" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="OriginalRequestId" type="anyURI"
+ * use="optional"/>
+ * <attribute name="ResponseLimit" type="integer" use="optional"/>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /RequestAbstractType -->
+ *
+ * <!-- MessageAbstractType -->
+ * <complexType name="MessageAbstractType" abstract="true">
+ * <sequence>
+ * <element ref="ds:Signature" minOccurs="0"/>
+ * <element ref="xkms:MessageExtension" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * <element ref="xkms:OpaqueClientData" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Id" type="ID" use="required"/>
+ * <attribute name="Service" type="anyURI" use="required"/>
+ * <attribute name="Nonce" type="base64Binary" use="optional"/>
+ * </complexType>
+ * <!-- /MessageAbstractType -->
+ */
+static int
+xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+ xmlNodePtr cur;
+ xmlChar* tmp;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2((*node) != NULL, -1);
+
+ cur = (*node);
+ xmlSecAssert2(cur != NULL, -1);
+
+ /* required Id attribute */
+ xmlSecAssert2(ctx->id == NULL, -1);
+ ctx->id = xmlGetProp(cur, xmlSecAttrId);
+ if(ctx->id == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s;node=%s",
+ xmlSecErrorsSafeString(xmlSecAttrId),
+ xmlSecErrorsSafeString(cur->name));
+ return(-1);
+ }
+
+ /* required Service attribute */
+ xmlSecAssert2(ctx->service == NULL, -1);
+ ctx->service = xmlGetProp(cur, xmlSecAttrService);
+ if(ctx->service == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s;node=%s",
+ xmlSecErrorsSafeString(xmlSecAttrService),
+ xmlSecErrorsSafeString(cur->name));
+ return(-1);
+ }
+
+ /* check service */
+ if((ctx->expectedService != NULL) && (!xmlStrEqual(ctx->expectedService, ctx->service))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "expectedService=%s;actualService=%s",
+ xmlSecErrorsSafeString(ctx->expectedService),
+ xmlSecErrorsSafeString(ctx->service));
+ return(-1);
+ }
+
+ /* optional Nonce attribute */
+ xmlSecAssert2(ctx->nonce == NULL, -1);
+ ctx->nonce = xmlGetProp(cur, xmlSecAttrNonce);
+
+ /* optional OriginalRequestId attribute */
+ xmlSecAssert2(ctx->originalRequestId == NULL, -1);
+ ctx->originalRequestId = xmlGetProp(cur, xmlSecAttrOriginalRequestId);
+
+ /* optional ResponseLimit attribute */
+ xmlSecAssert2(ctx->responseLimit == XMLSEC_XKMS_NO_RESPONSE_LIMIT, -1);
+ tmp = xmlGetProp(cur, xmlSecAttrResponseLimit);
+ if(tmp != NULL) {
+ ctx->responseLimit = atoi((char*)tmp);
+ xmlFree(tmp);
+ }
+
+ /* now read children */
+ cur = xmlSecGetNextElementNode(cur->children);
+
+ /* first node is optional <dsig:Signature/> node */
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeSignature, xmlSecDSigNs)) {
+ ret = xmlSecXkmsServerCtxSignatureNodeRead(ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxSignatureNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is zero or more <xkms:MessageExtension/> nodes */
+ ret = xmlSecXkmsServerCtxMessageExtensionNodesRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxMessageExtensionNodesRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* next is optional <xkms:OpaqueClientData/> node */
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeOpaqueClientData, xmlSecXkmsNs)) {
+ ret = xmlSecXkmsServerCtxOpaqueClientDataNodeRead(ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxOpaqueClientDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is zero or more <xkms:ResponseMechanism/> nodes */
+ ret = xmlSecQName2BitMaskNodesRead(gXmlSecXkmsResponseMechanismInfo, &cur,
+ xmlSecNodeResponseMechanism, xmlSecXkmsNs,
+ ((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_RESPONSE_MECHANISM) != 0) ? 1 : 0,
+ &ctx->responseMechanismMask);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskNodesRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecNodeResponseMechanism));
+ return(-1);
+ }
+
+ /* next is zero or more <xkms:RespondWith/> nodes */
+ ret = xmlSecXkmsServerCtxRespondWithNodesRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRespondWithNodesRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* next is optional <xkms:PendingNotification/> node */
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodePendingNotification, xmlSecXkmsNs)) {
+ ret = xmlSecXkmsServerCtxPendingNotificationNodeRead(ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxPendingNotificationNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ (*node) = cur;
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxSignatureNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* todo: verify signature and make sure that correct data was signed */
+ return(0);
+}
+
+/**
+ * <!-- MessageExtension -->
+ * <element name="MessageExtension" type="xkms:MessageExtensionAbstractType"
+ * abstract="true"/>
+ * <complexType name="MessageExtensionAbstractType" abstract="true"/>
+ * <!-- /MessageExtension -->
+ */
+static int
+xmlSecXkmsServerCtxMessageExtensionNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->firtsMsgExtNode == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = (*node);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeMessageExtension, xmlSecXkmsNs)) {
+ if(ctx->firtsMsgExtNode == NULL) {
+ ctx->firtsMsgExtNode = cur;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ (*node) = cur;
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxOpaqueClientDataNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->opaqueClientDataNode == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* remember that node, will copy it in the response later */
+ ctx->opaqueClientDataNode = node;
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxRespondWithNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = (*node);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeRespondWith, xmlSecXkmsNs)) {
+ xmlSecXkmsRespondWithId id = xmlSecXkmsRespondWithIdUnknown;
+
+ if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) {
+ id = xmlSecXkmsRespondWithIdListFindByNodeValue(&(ctx->enabledRespondWithIds), cur);
+ } else {
+ id = xmlSecXkmsRespondWithIdListFindByNodeValue(xmlSecXkmsRespondWithIdsGet(), cur);
+ }
+
+ if(id != xmlSecXkmsRespondWithIdUnknown) {
+ ret = xmlSecXkmsRespondWithNodeRead(id, ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCreateTree",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else if((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_RESPOND_WITH) != 0) {
+ xmlChar* content ;
+
+ content = xmlNodeGetContent(cur);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(cur->name),
+ xmlSecErrorsSafeString(content));
+ if(content != NULL) {
+ xmlFree(content);
+ }
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ (*node) = cur;
+ return(0);
+}
+
+/**
+ * XML Schema:
+ * <!-- PendingNotification -->
+ * <element name="PendingNotification" type="xkms:PendingNotificationType"/>
+ * <complexType name="PendingNotificationType">
+ * <attribute name="Mechanism" type="anyURI" use="required"/>
+ * <attribute name="Identifier" type="anyURI" use="required"/>
+ * </complexType>
+ * <!-- /PendingNotification -->
+ */
+static int
+xmlSecXkmsServerCtxPendingNotificationNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ xmlSecAssert2(ctx->pendingNotificationMechanism == NULL, -1);
+ ctx->pendingNotificationMechanism = xmlGetProp(node, xmlSecAttrMechanism);
+ if(ctx->pendingNotificationMechanism == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s;node=%s",
+ xmlSecErrorsSafeString(xmlSecAttrMechanism),
+ xmlSecErrorsSafeString(node->name));
+ return(-1);
+ }
+
+ xmlSecAssert2(ctx->pendingNotificationIdentifier == NULL, -1);
+ ctx->pendingNotificationIdentifier = xmlGetProp(node, xmlSecAttrIdentifier);
+ if(ctx->pendingNotificationIdentifier == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s;node=%s",
+ xmlSecErrorsSafeString(xmlSecAttrIdentifier),
+ xmlSecErrorsSafeString(node->name));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * <xkms:PendingRequestType Id Service Nonce? OriginalRequestId? ResponseLimit? ResponseId?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:ResponseMechanism>*
+ * <xkms:RespondWith>*
+ * <xkms:PendingNotification Mechanism Identifier>?
+ *
+ * XML Schema:
+ *
+ * <!-- PendingRequest -->
+ * <element name="PendingRequest" type="xkms:PendingRequestType"/>
+ * <complexType name="PendingRequestType">
+ * <complexContent>
+ * <extension base="xkms:RequestAbstractType">
+ * <attribute name="ResponseId" type="anyURI" use="optional"/>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /PendingRequest --> *
+ */
+static int
+xmlSecXkmsServerCtxPendingRequestNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first read "parent" type */
+ ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* todo: read responseId */
+ return(0);
+}
+
+/**
+ * <xkms:QueryKeyBinding Id?
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:TimeInstant Time>?
+ *
+ * XML Schema:
+ * <!-- QueryKeyBinding -->
+ * <element name="QueryKeyBinding" type="xkms:QueryKeyBindingType"/>
+ * <complexType name="QueryKeyBindingType">
+ * <complexContent>
+ * <extension base="xkms:KeyBindingAbstractType">
+ * <sequence>
+ * <element ref="xkms:TimeInstant" minOccurs="0"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /QueryKeyBinding -->
+ */
+static int
+xmlSecXkmsServerCtxQueryKeyBindingNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first read "parent" type */
+ cur = node;
+ ret = xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* next is optional <xkms:TimeInstant/> node */
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTimeInstant, xmlSecXkmsNs)) {
+ ret = xmlSecXkmsServerCtxTimeInstantNodeRead(ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxTimeInstantNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that there is nothing after the last node */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * <xkms:KeyBindingAbstractType Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ *
+ * XML Schema:
+ * <!-- KeyBindingAbstractType-->
+ * <complexType name="KeyBindingAbstractType" abstract="true">
+ * <sequence>
+ * <element ref="ds:KeyInfo" minOccurs="0"/>
+ * <element ref="xkms:KeyUsage" minOccurs="0" maxOccurs="3"/>
+ * <element ref="xkms:UseKeyWith" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="ID" use="optional"/>
+ * </complexType>
+ * <!-- /KeyBindingAbstractType-->
+ */
+static int
+xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2((*node) != NULL, -1);
+
+ cur = (*node);
+ xmlSecAssert2(cur != NULL, -1);
+
+ /* we don't care about Id attribute in this node */
+ cur = xmlSecGetNextElementNode(cur->children);
+
+ /* first node is optional <dsig:KeyInfo/> node. for now we only remember pointer */
+ xmlSecAssert2(ctx->keyInfoNode == NULL, -1);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
+ ctx->keyInfoNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is zero or more <xkms:KeyUsage/> nodes */
+ ret = xmlSecQName2BitMaskNodesRead(gXmlSecXkmsKeyUsageInfo, &cur,
+ xmlSecNodeKeyUsage, xmlSecXkmsNs,
+ ((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_KEY_USAGE) != 0) ? 1 : 0,
+ &(ctx->keyInfoReadCtx.keyReq.keyUsage));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskNodesRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyUsage));
+ return(-1);
+ }
+
+ /* next is zero or more <xkms:UseKeyWith/> nodes */
+ ret = xmlSecXkmsServerCtxUseKeyWithNodesRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxUseKeyWithNodesRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ (*node) = cur;
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ /* generate and add Id attribute */
+ ret = xmlSecGenerateAndAddID(node, xmlSecAttrId, ctx->idPrefix, ctx->idLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGenerateAndAddID",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* <dsig:KeyInfo/> node */
+ cur = xmlSecAddChild(node, xmlSecNodeKeyInfo, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ return(-1);
+ }
+
+ ret = xmlSecXkmsServerCtxKeyInfoNodeWrite(ctx, cur, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxKeyInfoNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* next is <xkms:KeyUsage/> node */
+ ret = xmlSecQName2BitMaskNodesWrite(gXmlSecXkmsKeyUsageInfo, node,
+ xmlSecNodeKeyUsage, xmlSecXkmsNs,
+ key->usage);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskNodesWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyUsage));
+ return(-1);
+ }
+
+ /* and the last node is <xkms:UseKeyWith/> */
+ ret = xmlSecXkmsServerCtxUseKeyWithNodesWrite(ctx, node, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxUseKeyWithNodesWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxKeyInfoNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* add child nodes as requested in <xkms:RespondWith/> nodes */
+ ret = xmlSecXkmsRespondWithIdListWrite(&(ctx->respWithList), ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdListWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoNodeWrite(node, key, &(ctx->keyInfoWriteCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/**
+ * XML Schema:
+ * <!-- UseKeyWith -->
+ * <element name="UseKeyWith" type="xkms:UseKeyWithType"/>
+ * <complexType name="UseKeyWithType">
+ * <attribute name="Application" type="anyURI" use="required"/>
+ * <attribute name="Identifier" type="string" use="required"/>
+ * </complexType>
+ * <!-- /UseKeyWith -->
+ */
+static int
+xmlSecXkmsServerCtxUseKeyWithNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+ xmlSecPtrListPtr list;
+ xmlNodePtr cur;
+ xmlSecKeyUseWithPtr keyUseWith;
+ xmlChar* application;
+ xmlChar* identifier;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ list = &(ctx->keyInfoReadCtx.keyReq.keyUseWithList);
+ xmlSecAssert2(xmlSecPtrListGetSize(list) == 0, -1);
+
+ cur = (*node);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeUseKeyWith, xmlSecXkmsNs)) {
+ application = xmlGetProp(cur, xmlSecAttrApplication);
+ if(application == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s;node=%s",
+ xmlSecErrorsSafeString(xmlSecAttrApplication),
+ xmlSecErrorsSafeString(cur->name));
+ return(-1);
+ }
+
+ identifier = xmlGetProp(cur, xmlSecAttrIdentifier);
+ if(identifier == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s;node=%s",
+ xmlSecErrorsSafeString(xmlSecAttrIdentifier),
+ xmlSecErrorsSafeString(cur->name));
+ xmlFree(application);
+ return(-1);
+ }
+
+ keyUseWith = xmlSecKeyUseWithCreate(application, identifier);
+ if(keyUseWith == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyUseWithCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(application);
+ xmlFree(identifier);
+ return(-1);
+ }
+ xmlFree(application);
+ xmlFree(identifier);
+
+ ret = xmlSecPtrListAdd(list, keyUseWith);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyUseWithDestroy(keyUseWith);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ (*node) = cur;
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxUseKeyWithNodesWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ /* todo: write UseKeyWith */
+ return(0);
+}
+
+
+static int
+xmlSecXkmsServerCtxTimeInstantNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* todo: parse xml schema dataTime or use libxml? */
+ return(0);
+}
+
+/**
+ * <xkms:ResultType Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:RequestSignatureValue>*
+ *
+ * XML Schema:
+ * <!-- ResultType -->
+ * <element name="Result" type="xkms:ResultType"/>
+ * <complexType name="ResultType">
+ * <complexContent>
+ * <extension base="xkms:MessageAbstractType">
+ * <sequence>
+ * <element ref="xkms:RequestSignatureValue" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="ResultMajor" type="QName" use="required"/>
+ * <attribute name="ResultMinor" type="QName" use="optional"/>
+ * <attribute name="RequestId" type="anyURI" use="optional"/>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /ResultType -->
+ */
+static int
+xmlSecXkmsServerCtxResultTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* generate and add Id attribute */
+ ret = xmlSecGenerateAndAddID(node, xmlSecAttrId, ctx->idPrefix, ctx->idLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGenerateAndAddID",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* todo: generate nonce? */
+
+ /* set Service atribute (required) */
+ if((ctx->service == NULL) || (xmlSetProp(node, xmlSecAttrService, ctx->service) == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrService),
+ xmlSecErrorsSafeString(ctx->service));
+ return(-1);
+ }
+
+
+ /* set RequestId atribute (optional) */
+ if((ctx->id != NULL) && (xmlSetProp(node, xmlSecAttrRequestId, ctx->id) == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s,value=%s",
+ xmlSecErrorsSafeString(xmlSecAttrRequestId),
+ xmlSecErrorsSafeString(ctx->id));
+ return(-1);
+ }
+
+
+ /* set major code (required) */
+ ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsResultMajorInfo, node,
+ xmlSecAttrResultMajor, ctx->resultMajor);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerAttributeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s,value=%d",
+ xmlSecErrorsSafeString(xmlSecAttrResultMajor),
+ ctx->resultMajor);
+ return(-1);
+ }
+
+ /* set minor code (optional) */
+ if(ctx->resultMinor != xmlSecXkmsResultMinorNone) {
+ ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsMinorErrorInfo, node,
+ xmlSecAttrResultMinor, ctx->resultMinor);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerAttributeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s,value=%d",
+ xmlSecErrorsSafeString(xmlSecAttrResultMinor),
+ ctx->resultMinor);
+ return(-1);
+ }
+ }
+
+ /* todo: create signature template */
+
+ /* todo: create message extension nodes? */
+
+ /* <xkms:OpaqueClientData/>: An XKMS service SHOULD return the value of
+ * the <OpaqueClientData> element unmodified in a request in a response
+ * with status code Succes */
+ if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && (ctx->opaqueClientDataNode != NULL)) {
+ xmlNodePtr copyNode;
+
+ copyNode = xmlDocCopyNode(ctx->opaqueClientDataNode, node->doc, 1);
+ if(copyNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(ctx->opaqueClientDataNode->name));
+ return(-1);
+ }
+
+ if(xmlSecAddChildNode(node, copyNode) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChildNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(copyNode->name));
+ return(-1);
+ }
+ }
+
+ ret = xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRequestSignatureValueNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * A service SHOULD include the <RequestSignatureValue> element in a response
+ * if the following conditions are satisfied and MUST NOT include the value
+ * otherwise:
+ *
+ *
+ * - The <ds:Signature> element was present in the corresponding request
+ * - The service successfully verified the <ds:Signature> element in the
+ * corresponding request, and
+ * - The ResponseMechanism RequestSignatureValue was specified.
+ *
+ */
+static int
+xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* todo: check all conditions for RequestSignatureValue */
+ if((ctx->responseMechanismMask & XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REQUEST_SIGNATURE_VALUE) == 0) {
+ /* The ResponseMechanism RequestSignatureValue was not specified. */
+ return(0);
+ }
+
+ /* todo: write RequestSignatureValue */
+ return(0);
+}
+
+
+/**
+ *
+ * <xkms:UnverifiedKeyBindingType Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ *
+ * XML Schema:
+ *
+ * <!-- UnverifiedKeyBinding -->
+ * <element name="UnverifiedKeyBinding" type="xkms:UnverifiedKeyBindingType"/>
+ * <complexType name="UnverifiedKeyBindingType">
+ * <complexContent>
+ * <extension base="xkms:KeyBindingAbstractType">
+ * <sequence>
+ * <element ref="xkms:ValidityInterval" minOccurs="0"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /UnverifiedKeyBinding -->
+ */
+static int
+xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first write "parent" type */
+ ret = xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(ctx, node, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* <xkms:ValidityInterval/> node */
+ ret = xmlSecXkmsServerCtxValidityIntervalNodeWrite(ctx, node, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxValidityIntervalNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXkmsServerCtxValidityIntervalNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* todo: write key validity interval */
+ return(0);
+}
+
+/**
+ * <xkms:KeyBinding Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ * <xkms:Status StatusValue>
+ * (<xkms:ValidReason>?
+ * <xkms:IndeterminateReason>?
+ * <xkms:InvalidReason>?
+ * )*
+ *
+ * XML Schema:
+ *
+ * <!-- KeyBinding -->
+ * <element name="KeyBinding" type="xkms:KeyBindingType"/>
+ * <complexType name="KeyBindingType">
+ * <complexContent>
+ * <extension base="xkms:UnverifiedKeyBindingType">
+ * <sequence>
+ * <element ref="xkms:Status"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /KeyBinding -->
+ */
+static int
+xmlSecXkmsServerCtxKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first write "parent" type */
+ ret = xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(ctx, node, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* <xkms:Status/> node */
+ ret = xmlSecXkmsServerCtxKeyBindingStatusNodeWrite(ctx, node, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxKeyBindingStatusNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * <xkms:Status StatusValue>
+ * (<xkms:ValidReason>?
+ * <xkms:IndeterminateReason>?
+ * <xkms:InvalidReason>?
+ * )*
+ *
+ * XML Schema:
+ *
+ * <!-- Status -->
+ * <element name="Status" type="xkms:StatusType"/>
+ * <complexType name="StatusType">
+ * <sequence>
+ * <element ref="xkms:ValidReason" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * <element ref="xkms:IndeterminateReason" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * <element ref="xkms:InvalidReason" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="StatusValue" type="xkms:KeyBindingStatus"
+ * use="required"/>
+ * </complexType>
+ * <simpleType name="KeyBindingStatus">
+ * <restriction base="QName">
+ * <enumeration value="xkms:Valid"/>
+ * <enumeration value="xkms:Invalid"/>
+ * <enumeration value="xkms:Indeterminate"/>
+ * </restriction>
+ * </simpleType>
+ * <!-- /Status -->
+ */
+static int
+xmlSecXkmsServerCtxKeyBindingStatusNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = xmlSecAddChild(node, xmlSecNodeStatus, xmlSecXkmsNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeStatus));
+ return(-1);
+ }
+
+ /* if we are here then the key was validated */
+ ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsKeyBindingStatusInfo, cur,
+ xmlSecAttrStatusValue, xmlSecXkmsKeyBindingStatusValid);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerAttributeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecAttrStatusValue));
+ return(-1);
+ }
+
+ /* todo: write the reasons */
+ return(0);
+}
+
+/************************************************************************
+ *
+ * xmlSecXkmsServerCtx list
+ *
+ ************************************************************************/
+static xmlSecPtrListKlass xmlSecXkmsServerCtxPtrListKlass = {
+ BAD_CAST "xkms-server-ctx-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecXkmsServerCtxDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerCtxDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerCtxDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+xmlSecPtrListId
+xmlSecXkmsServerCtxPtrListGetKlass(void) {
+ return(&xmlSecXkmsServerCtxPtrListKlass);
+}
+
+
+/**************************************************************************
+ *
+ * Global xmlSecXkmsRespondWithIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllXkmsRespondWithIds;
+
+
+/**
+ * xmlSecXkmsRespondWithIdsGet:
+ *
+ * Gets global registered RespondWith klasses list.
+ *
+ * Returns: the pointer to list of all registered RespondWith klasses.
+ */
+xmlSecPtrListPtr
+xmlSecXkmsRespondWithIdsGet(void) {
+ return(&xmlSecAllXkmsRespondWithIds);
+}
+
+/**
+ * xmlSecXkmsRespondWithIdsInit:
+ *
+ * Initializes the RespondWith klasses. This function is called from the
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsRespondWithIdsInit(void) {
+ int ret;
+
+ ret = xmlSecPtrListInitialize(xmlSecXkmsRespondWithIdsGet(), xmlSecXkmsRespondWithIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListPtrInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecXkmsRespondWithIdListId");
+ return(-1);
+ }
+
+ ret = xmlSecXkmsRespondWithIdsRegisterDefault();
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegisterDefault",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithIdsShutdown:
+ *
+ * Shuts down the keys data klasses. This function is called from the
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+void
+xmlSecXkmsRespondWithIdsShutdown(void) {
+ xmlSecPtrListFinalize(xmlSecXkmsRespondWithIdsGet());
+}
+
+/**
+ * xmlSecXkmsRespondWithIdsRegister:
+ * @id: the RespondWith klass.
+ *
+ * Registers @id in the global list of RespondWith klasses.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithId id) {
+ int ret;
+
+ xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+
+ ret = xmlSecPtrListAdd(xmlSecXkmsRespondWithIdsGet(), (xmlSecPtr)id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "RespondWith=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * RespondWith klasses: KeyName, KeyValue,...
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsRespondWithIdsRegisterDefault(void) {
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithKeyNameId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithKeyNameId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithKeyValueId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithKeyValueId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithPrivateKeyId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithPrivateKeyId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithRetrievalMethodId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithRetrievalMethodId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509CertId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509CertId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509ChainId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509ChainId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509CRLId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509CRLId)));
+ return(-1);
+ }
+
+ /* TODO: OCSP, PGP, PGPWeb, SPKI */
+ /*
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithPGPId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithPGPId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithSPKIId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithSPKIId)));
+ return(-1);
+ }
+ */
+ return(0);
+}
+
+
+/************************************************************************
+ *
+ * XKMS RespondWith Klass
+ *
+ ************************************************************************/
+/**
+ * xmlSecXkmsRespondWithNodeRead:
+ * @id: the RespondWith class.
+ * @ctx: the XKMS request processing context.
+ * @node: the pointer to <xkms:RespondWith/> node.
+ *
+ * Reads the content of the <xkms:RespondWith/> @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsRespondWithNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ if(id->readNode != NULL) {
+ return((id->readNode)(id, ctx, node));
+ }
+ return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithNodeWrite:
+ * @id: the RespondWith class.
+ * @ctx: the XKMS request processing context.
+ * @node: the pointer to <xkms:RespondWith/> node.
+ *
+ * Writes the content of the <xkms:RespondWith/> @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsRespondWithNodeWrite(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ if(id->writeNode != NULL) {
+ return((id->writeNode)(id, ctx, node));
+ }
+ return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithDebugDump:
+ * @id: the RespondWith class.
+ * @output: the output file.
+ *
+ * Writes debug information about @id into the @output.
+ */
+void
+xmlSecXkmsRespondWithDebugDump(xmlSecXkmsRespondWithId id, FILE* output) {
+ xmlSecAssert(id != xmlSecXkmsRespondWithIdUnknown);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== RespondWith: \"%s\" (href=\"%s\")\n",
+ xmlSecErrorsSafeString(id->valueName),
+ xmlSecErrorsSafeString(id->valueNs));
+}
+
+/**
+ * xmlSecXkmsRespondWithDebugXmlDump:
+ * @id: the RespondWith class.
+ * @output: the output file.
+ *
+ * Writes debug information about @id into the @output in XML format.
+ */
+void
+xmlSecXkmsRespondWithDebugXmlDump(xmlSecXkmsRespondWithId id, FILE* output) {
+ xmlSecAssert(id != xmlSecXkmsRespondWithIdUnknown);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<RespondWith href=\"");
+ xmlSecPrintXmlString(output, id->valueNs);
+ fprintf(output, "\">");
+ xmlSecPrintXmlString(output, id->valueName);
+ fprintf(output, "</RespondWith>\n");
+}
+
+int
+xmlSecXkmsRespondWithDefaultNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ ret = xmlSecXkmsRespondWithIdListFind(&(ctx->respWithList), id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithIdListFind",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ } else if(ret > 0) {
+ /* do nothing, we already have it in the list */
+ return(0);
+ }
+
+ ret = xmlSecPtrListAdd(&(ctx->respWithList), id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+int
+xmlSecXkmsRespondWithDefaultNodeWrite(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+ xmlSecAssert2(id->nodeName != NULL, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = xmlSecAddChild(node, id->nodeName, id->nodeNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(id->nodeName));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/************************************************************************
+ *
+ * XKMS RespondWith Klass List
+ *
+ ************************************************************************/
+static xmlSecPtrListKlass xmlSecXkmsRespondWithIdListKlass = {
+ BAD_CAST "respond-with-ids-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsRespondWithDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsRespondWithDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+xmlSecPtrListId
+xmlSecXkmsRespondWithIdListGetKlass(void) {
+ return(&xmlSecXkmsRespondWithIdListKlass);
+}
+
+int
+xmlSecXkmsRespondWithIdListFind(xmlSecPtrListPtr list, xmlSecXkmsRespondWithId id) {
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), -1);
+ xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ if((xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i) == id) {
+ return(1);
+ }
+ }
+ return(0);
+}
+
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithIdListFindByNodeValue(xmlSecPtrListPtr list, xmlNodePtr node) {
+ xmlSecXkmsRespondWithId result = xmlSecXkmsRespondWithIdUnknown;
+ xmlSecXkmsRespondWithId id;
+ xmlChar* content;
+ xmlChar* qnameLocalPart = NULL;
+ xmlChar* qnamePrefix = NULL;
+ const xmlChar* qnameHref;
+ xmlNsPtr ns;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), xmlSecXkmsRespondWithIdUnknown);
+ xmlSecAssert2(node != NULL, xmlSecXkmsRespondWithIdUnknown);
+
+ content = xmlNodeGetContent(node);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNodeGetContent",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ return(xmlSecXkmsRespondWithIdUnknown);
+ }
+
+ qnameLocalPart = (xmlChar*)xmlStrchr(content, ':');
+ if(qnameLocalPart != NULL) {
+ qnamePrefix = content;
+ *(qnameLocalPart++) = '\0';
+ } else {
+ qnamePrefix = NULL;
+ qnameLocalPart = content;
+ }
+
+ /* search namespace href */
+ ns = xmlSearchNs(node->doc, node, qnamePrefix);
+ if((ns == NULL) && (qnamePrefix != NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSearchNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s,qnamePrefix=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnamePrefix));
+ xmlFree(content);
+ return(xmlSecXkmsRespondWithIdUnknown);
+ }
+ qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ id = (xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i);
+ if((id != xmlSecXkmsRespondWithIdUnknown) &&
+ xmlStrEqual(id->valueName, qnameLocalPart) &&
+ xmlStrEqual(id->valueNs, qnameHref)) {
+ result = id;
+ break;
+ }
+ }
+
+ xmlFree(content);
+ return(result);
+}
+
+int
+xmlSecXkmsRespondWithIdListWrite(xmlSecPtrListPtr list, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecXkmsRespondWithId id;
+ xmlSecSize i, size;
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ id = (xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i);
+ if(id != xmlSecXkmsRespondWithIdUnknown) {
+ ret = xmlSecXkmsRespondWithNodeWrite(id, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+/********************************************************************
+ *
+ * XML Sec Library RespondWith Ids
+ *
+ *******************************************************************/
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithKeyNameKlass = {
+ xmlSecRespondWithKeyName, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeKeyName, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithKeyNameGetKlass:
+ *
+ * The respond with KeyName klass.
+ *
+ * Returns: respond with KeyName klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithKeyNameGetKlass(void) {
+ return(&xmlSecXkmsRespondWithKeyNameKlass);
+}
+
+
+
+static int xmlSecXkmsRespondWithKeyValueNodeRead (xmlSecXkmsRespondWithId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithKeyValueKlass = {
+ xmlSecRespondWithKeyValue, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeKeyValue, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithKeyValueNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithKeyValueGetKlass:
+ *
+ * The respond with KeyValue klass.
+ *
+ * Returns: respond with KeyValue klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithKeyValueGetKlass(void) {
+ return(&xmlSecXkmsRespondWithKeyValueKlass);
+}
+
+static int
+xmlSecXkmsRespondWithKeyValueNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsRespondWithKeyValueId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* do usual stuff */
+ ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithDefaultNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* and now set some parameters in the ctx to look for a public or private
+ * key and to write a public key
+ */
+ ctx->keyInfoReadCtx.keyReq.keyType |= (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
+ ctx->keyInfoWriteCtx.keyReq.keyType |= xmlSecKeyDataTypePublic;
+
+ return(0);
+}
+
+static int xmlSecXkmsRespondWithPrivateKeyNodeRead (xmlSecXkmsRespondWithId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithPrivateKeyKlass = {
+ xmlSecRespondWithPrivateKey, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeKeyValue, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithPrivateKeyNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithPrivateKeyGetKlass:
+ *
+ * The respond with PrivateKey klass.
+ *
+ * Returns: respond with PrivateKey klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithPrivateKeyGetKlass(void) {
+ return(&xmlSecXkmsRespondWithPrivateKeyKlass);
+}
+
+static int
+xmlSecXkmsRespondWithPrivateKeyNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsRespondWithPrivateKeyId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* do usual stuff */
+ ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithDefaultNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* and now set some parameters in the ctx to look for a private
+ * key and to write a private key
+ */
+ ctx->keyInfoReadCtx.keyReq.keyType |= xmlSecKeyDataTypePrivate;
+ ctx->keyInfoWriteCtx.keyReq.keyType |= xmlSecKeyDataTypePrivate;
+
+ return(0);
+}
+
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithRetrievalMethodKlass = {
+ xmlSecRespondWithRetrievalMethod, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeRetrievalMethod, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithRetrievalMethodGetKlass:
+ *
+ * The respond with RetrievalMethod klass.
+ *
+ * Returns: respond with RetrievalMethod klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithRetrievalMethodGetKlass(void) {
+ return(&xmlSecXkmsRespondWithRetrievalMethodKlass);
+}
+
+
+
+static int xmlSecXkmsRespondWithX509CertNodeRead (xmlSecXkmsRespondWithId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509CertKlass = {
+ xmlSecRespondWithX509Cert, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeX509Data, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithX509CertNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithX509CertGetKlass:
+ *
+ * The respond with X509Cert klass.
+ *
+ * Returns: respond with X509Cert klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithX509CertGetKlass(void) {
+ return(&xmlSecXkmsRespondWithX509CertKlass);
+}
+
+static int
+xmlSecXkmsRespondWithX509CertNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsRespondWithX509CertId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* do usual stuff */
+ ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithDefaultNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int xmlSecXkmsRespondWithX509ChainNodeRead (xmlSecXkmsRespondWithId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509ChainKlass = {
+ xmlSecRespondWithX509Chain, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeX509Data, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithX509ChainNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithX509ChainGetKlass:
+ *
+ * The respond with X509Chain klass.
+ *
+ * Returns: respond with X509Chain klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithX509ChainGetKlass(void) {
+ return(&xmlSecXkmsRespondWithX509ChainKlass);
+}
+
+static int
+xmlSecXkmsRespondWithX509ChainNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsRespondWithX509ChainId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* do usual stuff */
+ ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithDefaultNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int xmlSecXkmsRespondWithX509CRLNodeRead (xmlSecXkmsRespondWithId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509CRLKlass = {
+ xmlSecRespondWithX509CRL, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeX509Data, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithX509CRLNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithX509CRLGetKlass:
+ *
+ * The respond with X509CRL klass.
+ *
+ * Returns: respond with X509CRL klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithX509CRLGetKlass(void) {
+ return(&xmlSecXkmsRespondWithX509CRLKlass);
+}
+
+static int
+xmlSecXkmsRespondWithX509CRLNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsRespondWithX509CRLId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* do usual stuff */
+ ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+ "xmlSecXkmsRespondWithDefaultNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithPGPKlass = {
+ xmlSecRespondWithPGP, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodePGPData, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithPGPGetKlass:
+ *
+ * The respond with PGP klass.
+ *
+ * Returns: respond with PGP klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithPGPGetKlass(void) {
+ return(&xmlSecXkmsRespondWithPGPKlass);
+}
+
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithSPKIKlass = {
+ xmlSecRespondWithSPKI, /* const xmlChar* valueName; */
+ xmlSecXkmsNs, /* const xmlChar* valueNs; */
+ xmlSecNodeSPKIData, /* const xmlChar* nodeName; */
+ xmlSecDSigNs, /* const xmlChar* nodeNs; */
+ xmlSecXkmsRespondWithDefaultNodeRead, /* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+ xmlSecXkmsRespondWithDefaultNodeWrite, /* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithSPKIGetKlass:
+ *
+ * The respond with SPKI klass.
+ *
+ * Returns: respond with SPKI klass.
+ */
+xmlSecXkmsRespondWithId
+xmlSecXkmsRespondWithSPKIGetKlass(void) {
+ return(&xmlSecXkmsRespondWithSPKIKlass);
+}
+
+/**************************************************************************
+ *
+ * Global xmlSecXkmsServerRequestIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllXkmsServerRequestIds;
+
+
+/**
+ * xmlSecXkmsServerRequestIdsGet:
+ *
+ * Gets global registered ServerRequest klasses list.
+ *
+ * Returns: the pointer to list of all registered ServerRequest klasses.
+ */
+xmlSecPtrListPtr
+xmlSecXkmsServerRequestIdsGet(void) {
+ return(&xmlSecAllXkmsServerRequestIds);
+}
+
+/**
+ * xmlSecXkmsServerRequestIdsInit:
+ *
+ * Initializes the ServerRequest klasses. This function is called from the
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerRequestIdsInit(void) {
+ int ret;
+
+ ret = xmlSecPtrListInitialize(xmlSecXkmsServerRequestIdsGet(), xmlSecXkmsServerRequestIdListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListPtrInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecXkmsServerRequestIdListId");
+ return(-1);
+ }
+
+ ret = xmlSecXkmsServerRequestIdsRegisterDefault();
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsRegisterDefault",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsServerRequestIdsShutdown:
+ *
+ * Shuts down the keys data klasses. This function is called from the
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+void
+xmlSecXkmsServerRequestIdsShutdown(void) {
+ xmlSecPtrListFinalize(xmlSecXkmsServerRequestIdsGet());
+}
+
+/**
+ * xmlSecXkmsServerRequestIdsRegister:
+ * @id: the ServerRequest klass.
+ *
+ * Registers @id in the global list of ServerRequest klasses.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestId id) {
+ int ret;
+
+ xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+
+ ret = xmlSecPtrListAdd(xmlSecXkmsServerRequestIdsGet(), (xmlSecPtr)id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ServerRequest=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(id)));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecXkmsServerRequestIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * ServerRequest klasses: KeyName, KeyValue,...
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerRequestIdsRegisterDefault(void) {
+ if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestResultId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestResultId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestStatusId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestStatusId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestCompoundId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestCompoundId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestLocateId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestLocateId)));
+ return(-1);
+ }
+
+ if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestValidateId) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsRegister",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestValidateId)));
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/************************************************************************
+ *
+ * XKMS ServerRequest Klass
+ *
+ ************************************************************************/
+/**
+ * xmlSecXkmsServerRequestNodeRead:
+ * @id: the ServerRequest class.
+ * @ctx: the XKMS request processing context.
+ * @node: the pointer to <xkms:ServerRequest/> node.
+ *
+ * Reads the content of the <xkms:ServerRequest/> @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerRequestNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node) {
+ xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ if(id->readNode != NULL) {
+ return((id->readNode)(id, ctx, node));
+ }
+ return(0);
+}
+
+/**
+ * xmlSecXkmsServerExecute:
+ * @id: the ServerRequest class.
+ * @ctx: the XKMS request processing context.
+ *
+ * Executes XKMS server request.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecXkmsServerRequestExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+ xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(id->execute != NULL) {
+ return((id->execute)(id, ctx));
+ }
+ return(0);
+}
+
+
+/**
+ * xmlSecXkmsServerResponseNodeWrite:
+ * @id: the ServerRequest class.
+ * @ctx: the XKMS request processing context.
+ * @doc: the pointer to response parent XML document (might be NULL).
+ * @node: the pointer to response parent XML node (might be NULL).
+ *
+ * Writes XKMS response from context to a newly created node. Caller is
+ * responsible for adding the returned node to the XML document.
+ *
+ * Returns: pointer to newly created XKMS response node or NULL
+ * if an error occurs.
+ */
+xmlNodePtr
+xmlSecXkmsServerRequestNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx,
+ xmlDocPtr doc, xmlNodePtr node) {
+ xmlNodePtr respNode;
+ int ret;
+
+ xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, NULL);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ /* create the response root node */
+ if(node == NULL) {
+ xmlNsPtr ns;
+
+ respNode = xmlNewDocNode(doc, NULL, id->resultNodeName, NULL);
+ if(respNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDocNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(id->resultNodeName));
+ return(NULL);
+ }
+ ns = xmlNewNs(respNode, id->resultNodeNs, NULL);
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(id->resultNodeNs));
+ xmlFreeNode(respNode);
+ return(NULL);
+ }
+ xmlSetNs(respNode, ns);
+ } else {
+ respNode = xmlSecAddChild(node, id->resultNodeName, id->resultNodeNs);
+ if(respNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(id->resultNodeName));
+ return(NULL);
+ }
+ }
+
+ if(id->writeNode != NULL) {
+ ret = (id->writeNode)(id, ctx, respNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "writeNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(id->resultNodeName));
+ xmlFreeNode(respNode);
+ return(NULL);
+ }
+ }
+
+ return(respNode);
+}
+
+/**
+ * xmlSecXkmsServerRequestDebugDump:
+ * @id: the ServerRequest class.
+ * @output: the output file.
+ *
+ * Writes debug information about @id into the @output.
+ */
+void
+xmlSecXkmsServerRequestDebugDump(xmlSecXkmsServerRequestId id, FILE* output) {
+ xmlSecAssert(id != xmlSecXkmsServerRequestIdUnknown);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== ServerRequest: %s\n", xmlSecErrorsSafeString(id->name));
+}
+
+/**
+ * xmlSecXkmsServerRequestDebugXmlDump:
+ * @id: the ServerRequest class.
+ * @output: the output file.
+ *
+ * Writes debug information about @id into the @output in XML format.
+ */
+void
+xmlSecXkmsServerRequestDebugXmlDump(xmlSecXkmsServerRequestId id, FILE* output) {
+ xmlSecAssert(id != xmlSecXkmsServerRequestIdUnknown);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<ServerRequest>");
+ xmlSecPrintXmlString(output, id->name);
+ fprintf(output, "</ServerRequest>\n");
+}
+
+/************************************************************************
+ *
+ * XKMS ServerRequest Klass List
+ *
+ ************************************************************************/
+static xmlSecPtrListKlass xmlSecXkmsServerRequestIdListKlass = {
+ BAD_CAST "xkms-server-request-ids-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ NULL, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerRequestDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerRequestDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+xmlSecPtrListId
+xmlSecXkmsServerRequestIdListGetKlass(void) {
+ return(&xmlSecXkmsServerRequestIdListKlass);
+}
+
+int
+xmlSecXkmsServerRequestIdListFind(xmlSecPtrListPtr list, xmlSecXkmsServerRequestId id) {
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), -1);
+ xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ if((xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i) == id) {
+ return(1);
+ }
+ }
+ return(0);
+}
+
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name) {
+ xmlSecXkmsServerRequestId id;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), xmlSecXkmsServerRequestIdUnknown);
+ xmlSecAssert2(name != NULL, xmlSecXkmsServerRequestIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ id = (xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i);
+ if((id != xmlSecXkmsServerRequestIdUnknown) && xmlStrEqual(id->name, name)) {
+ return(id);
+ }
+ }
+ return(xmlSecXkmsServerRequestIdUnknown);
+}
+
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestIdListFindByNode(xmlSecPtrListPtr list, xmlNodePtr node) {
+ xmlSecXkmsServerRequestId id;
+ xmlSecSize i, size;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), xmlSecXkmsServerRequestIdUnknown);
+ xmlSecAssert2(node != NULL, xmlSecXkmsServerRequestIdUnknown);
+
+ size = xmlSecPtrListGetSize(list);
+ for(i = 0; i < size; ++i) {
+ id = (xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i);
+ if((id != xmlSecXkmsServerRequestIdUnknown) &&
+ xmlSecCheckNodeName(node, id->requestNodeName, id->requestNodeNs)) {
+
+ return(id);
+ }
+ }
+ return(xmlSecXkmsServerRequestIdUnknown);
+}
+
+/********************************************************************
+ *
+ * XML Sec Library ServerRequest Ids
+ *
+ *******************************************************************/
+
+
+/********************************************************************
+ *
+ * Result response
+ *
+ *******************************************************************/
+static int xmlSecXkmsServerRequestResultNodeWrite (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestResultKlass = {
+ xmlSecXkmsServerRequestResultName, /* const xmlChar* name; */
+ NULL, /* const xmlChar* requestNodeName; */
+ NULL, /* const xmlChar* requestNodeNs; */
+ xmlSecNodeResult, /* const xmlChar* responseNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */
+ 0, /* xmlSecBitMask flags; */
+ NULL, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+ xmlSecXkmsServerRequestResultNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+ NULL, /* xmlSecXkmsServerRequestExecuteMethod execute; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestResultGetKlass:
+ *
+ * The Result response klass.
+ *
+ * Returns: Result response klass.
+ */
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestResultGetKlass(void) {
+ return(&xmlSecXkmsServerRequestResultKlass);
+}
+
+static int
+xmlSecXkmsServerRequestResultNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestResultId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* set missing parameters (if any) */
+ if(ctx->service == NULL) {
+ ctx->service = xmlStrdup((ctx->expectedService != NULL) ? ctx->expectedService : BAD_CAST "");
+ if(ctx->service == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* first write the "parent" type */
+ ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResultTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/********************************************************************
+ *
+ * StatusRequest/StatusResponse
+ *
+ *******************************************************************/
+static int xmlSecXkmsServerRequestStatusNodeRead (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestStatusNodeWrite (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestStatusKlass = {
+ xmlSecXkmsServerRequestStatusName, /* const xmlChar* name; */
+ xmlSecNodeStatusRequest, /* const xmlChar* requestNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */
+ xmlSecNodeStatusResult, /* const xmlChar* responseNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */
+ 0, /* xmlSecBitMask flags; */
+ xmlSecXkmsServerRequestStatusNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+ xmlSecXkmsServerRequestStatusNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+ NULL, /* xmlSecXkmsServerRequestExecuteMethod execute; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestStatusGetKlass:
+ *
+ * The StatusRequest klass.
+ *
+ * Returns: StatusRequest klass.
+ */
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestStatusGetKlass(void) {
+ return(&xmlSecXkmsServerRequestStatusKlass);
+}
+
+/**
+ *
+ * <xkms:StatusRequest Id Service Nonce? OriginalRequestId? ResponseLimit? ResponseId?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:ResponseMechanism>*
+ * <xkms:RespondWith>*
+ * <xkms:PendingNotification Mechanism Identifier>?
+ *
+ * XML Schema:
+ * <!-- StatusRequest -->
+ * <element name="StatusRequest" type="xkms:StatusRequestType"/>
+ * <complexType name="StatusRequestType">
+ * <complexContent>
+ * <extension base="xkms:PendingRequestType"/>
+ * </complexContent>
+ * </complexType>
+ * <!-- /StatusRequest -->
+ */
+static int
+xmlSecXkmsServerRequestStatusNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestStatusId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = node;
+
+ /* first read "parent" type */
+ ret = xmlSecXkmsServerCtxPendingRequestNodeRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxPendingRequestNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* check that there is nothing after the last node */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ *
+ * <xkms:StatusResult Id Service Nonce? ResultMajor ResultMinor? RequestId? Success? Failure? Pending?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:RequestSignatureValue>*
+ *
+ * XML Schema:
+ *
+ * <!-- StatusResult -->
+ * <element name="StatusResult" type="xkms:StatusResultType"/>
+ * <complexType name="StatusResultType">
+ * <complexContent>
+ * <extension base="xkms:ResultType">
+ * <attribute name="Success" type="integer" use="optional"/>
+ * <attribute name="Failure" type="integer" use="optional"/>
+ * <attribute name="Pending" type="integer" use="optional"/>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /StatusResult --> *
+ */
+static int
+xmlSecXkmsServerRequestStatusNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestStatusId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first write the "parent" type */
+ ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResultTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* todo: add optional StatusResult attributes */
+ return(0);
+}
+
+/********************************************************************
+ *
+ * CompoundRequest/CompoundResponse
+ *
+ *******************************************************************/
+static int xmlSecXkmsServerRequestCompoundNodeRead (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestCompoundNodeWrite(xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestCompoundExecute (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestCompoundKlass = {
+ xmlSecXkmsServerRequestCompoundName, /* const xmlChar* name; */
+ xmlSecNodeCompoundRequest, /* const xmlChar* requestNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */
+ xmlSecNodeCompoundResult, /* const xmlChar* responseNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */
+ 0, /* xmlSecBitMask flags; */
+ xmlSecXkmsServerRequestCompoundNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+ xmlSecXkmsServerRequestCompoundNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+ xmlSecXkmsServerRequestCompoundExecute, /* xmlSecXkmsServerRequestExecuteMethod execute; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestCompoundGetKlass:
+ *
+ * The CompoundRequest klass.
+ *
+ * Returns: CompoundRequest klass.
+ */
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestCompoundGetKlass(void) {
+ return(&xmlSecXkmsServerRequestCompoundKlass);
+}
+
+/**
+ * <xkms:CompoundRequest Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:ResponseMechanism>*
+ * <xkms:RespondWith>*
+ * <xkms:PendingNotification Mechanism Identifier>?
+ * (
+ * <xkms:LocateRequest>?
+ * <xkms:ValidateRequest>?
+ * <xkms:RegisterRequest>?
+ * <xkms:ReissueRequest>?
+ * <xkms:RecoverRequest>?
+ * <xkms:RevokeRequest>?
+ * )*
+ *
+ * XML Schema:
+ *
+ * <!-- CompoundRequest -->
+ * <element name="CompoundRequest" type="xkms:CompoundRequestType"/>
+ * <complexType name="CompoundRequestType">
+ * <complexContent>
+ * <extension base="xkms:RequestAbstractType">
+ * <choice maxOccurs="unbounded">
+ * <element ref="xkms:LocateRequest"/>
+ * <element ref="xkms:ValidateRequest"/>
+ * <element ref="xkms:RegisterRequest"/>
+ * <element ref="xkms:ReissueRequest"/>
+ * <element ref="xkms:RecoverRequest"/>
+ * <element ref="xkms:RevokeRequest"/>
+ * </choice>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /CompoundRequest -->
+ */
+static int
+xmlSecXkmsServerRequestCompoundNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecPtrListPtr serverRequestIdsList;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = node;
+
+ /* first read "parent" type */
+ ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* create list for compound requests */
+ xmlSecAssert2(ctx->compoundRequestContexts == NULL, -1);
+ ctx->compoundRequestContexts = xmlSecPtrListCreate(xmlSecXkmsServerCtxPtrListId);
+ if(ctx->compoundRequestContexts == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* get the list of enabled or all request klasses */
+ if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+ serverRequestIdsList = &(ctx->enabledServerRequestIds);
+ } else {
+ serverRequestIdsList = xmlSecXkmsServerRequestIdsGet();
+ }
+ xmlSecAssert2(serverRequestIdsList != NULL, -1);
+
+ while(cur != NULL) {
+ xmlSecXkmsServerCtxPtr ctxChild;
+
+ /* create a new context */
+ ctxChild = xmlSecXkmsServerCtxCreate(ctx->keyInfoReadCtx.keysMngr);
+ if(ctxChild == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* copy all settings from us */
+ ret = xmlSecXkmsServerCtxCopyUserPref(ctxChild, ctx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxDestroy(ctxChild);
+ return(-1);
+ }
+
+ /* add it to the list */
+ ret = xmlSecPtrListAdd(ctx->compoundRequestContexts, ctxChild);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxDestroy(ctxChild);
+ return(-1);
+ }
+
+ /* and now process request from current node */
+ ctxChild->requestId = xmlSecXkmsServerRequestIdListFindByNode(serverRequestIdsList, cur);
+ if((ctxChild->requestId == xmlSecXkmsServerRequestIdUnknown) ||
+ ((ctxChild->requestId->flags & XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND) == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdListFindByNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorMessageNotSupported);
+ return(-1);
+ }
+
+ ret = xmlSecXkmsServerRequestNodeRead(ctxChild->requestId, ctxChild, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "request=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId)));
+ xmlSecXkmsServerCtxSetResult(ctxChild, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that there is nothing after the last node */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * <xkms:CompoundResult Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:RequestSignatureValue>*
+ * (
+ * <xkms:LocateResult>?
+ * <xkms:ValidateResult>?
+ * <xkms:RegisterResult>?
+ * <xkms:ReissueResult>?
+ * <xkms:RecoverResult>?
+ * <xkms:RevokeResult>?
+ * )*
+ *
+ *
+ * XML Schema:
+ *
+ * <!-- CompoundResponse -->
+ * <element name="CompoundResult" type="xkms:CompoundResultType"/>
+ * <complexType name="CompoundResultType">
+ * <complexContent>
+ * <extension base="xkms:ResultType">
+ * <choice maxOccurs="unbounded">
+ * <element ref="xkms:LocateResult"/>
+ * <element ref="xkms:ValidateResult"/>
+ * <element ref="xkms:RegisterResult"/>
+ * <element ref="xkms:ReissueResult"/>
+ * <element ref="xkms:RecoverResult"/>
+ * <element ref="xkms:RevokeResult"/>
+ * </choice>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /CompoundResponse -->
+ */
+static int
+xmlSecXkmsServerRequestCompoundNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* walk thru the list of chilren and pickup first error */
+ if(ctx->compoundRequestContexts != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) {
+ xmlSecXkmsServerCtxPtr ctxChild;
+
+ ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos);
+ if(ctxChild == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(ctxChild->resultMajor != xmlSecXkmsResultMajorSuccess) {
+ xmlSecXkmsServerCtxSetResult(ctx, ctxChild->resultMajor, ctxChild->resultMinor);
+ break;
+ }
+ }
+ }
+
+ /* first write the "parent" type */
+ ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResultTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* write compound result */
+ if(ctx->compoundRequestContexts != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) {
+ xmlSecXkmsServerCtxPtr ctxChild;
+ xmlNodePtr cur;
+
+ ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos);
+ if(ctxChild == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecXkmsServerRequestNodeWrite(ctxChild->requestId, ctxChild, node->doc, node);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "request=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId)));
+ return(-1);
+ }
+
+ if(xmlSecAddChildNode(node, cur) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChildNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeNode(cur);
+ return(-1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXkmsServerRequestCompoundExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->compoundRequestContexts != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) {
+ xmlSecXkmsServerCtxPtr ctxChild;
+
+ ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos);
+ if(ctxChild == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+ continue;
+ }
+
+ ret = xmlSecXkmsServerRequestExecute(ctxChild->requestId, ctxChild);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "request=%s",
+ xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId)));
+ xmlSecXkmsServerCtxSetResult(ctxChild, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+ continue;
+ }
+ }
+ }
+
+ return(0);
+}
+
+
+/********************************************************************
+ *
+ * LocateRequest/LocateResponse
+ *
+ *******************************************************************/
+static int xmlSecXkmsServerRequestLocateNodeRead (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestLocateNodeWrite (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestLocateExecute (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestLocateKlass = {
+ xmlSecXkmsServerRequestLocateName, /* const xmlChar* name; */
+ xmlSecNodeLocateRequest, /* const xmlChar* requestNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */
+ xmlSecNodeLocateResult, /* const xmlChar* responseNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */
+ XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND, /* xmlSecBitMask flags; */
+ xmlSecXkmsServerRequestLocateNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+ xmlSecXkmsServerRequestLocateNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+ xmlSecXkmsServerRequestLocateExecute, /* xmlSecXkmsServerRequestExecuteMethod execute; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestLocateGetKlass:
+ *
+ * The LocateRequest klass.
+ *
+ * Returns: LocateRequest klass.
+ */
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestLocateGetKlass(void) {
+ return(&xmlSecXkmsServerRequestLocateKlass);
+}
+
+/**
+ * <xkms:LocateRequest Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:ResponseMechanism>*
+ * <xkms:RespondWith>*
+ * <xkms:PendingNotification Mechanism Identifier>?
+ * <xkms:QueryKeyBinding Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:TimeInstant Time>?
+ *
+ * XML Schema:
+ *
+ * <!-- LocateRequest -->
+ * <element name="LocateRequest" type="xkms:LocateRequestType"/>
+ * <complexType name="LocateRequestType">
+ * <complexContent>
+ * <extension base="xkms:RequestAbstractType">
+ * <sequence>
+ * <element ref="xkms:QueryKeyBinding"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /LocateRequest -->
+ */
+static int
+xmlSecXkmsServerRequestLocateNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = node;
+
+ /* first read "parent" type */
+ ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* now read required <xkms:QueryKeyBinding/> node */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeQueryKeyBinding, xmlSecXkmsNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeQueryKeyBinding));
+ return(-1);
+ }
+
+ /* read <xkms:QueryKeyBinding/> node */
+ ret = xmlSecXkmsServerCtxQueryKeyBindingNodeRead(ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxQueryKeyBindingNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* check that there is nothing after the last node */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * <xkms:LocateResult Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:RequestSignatureValue>*
+ * (<xkms:UnverifiedKeyBinding Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ * )*
+ *
+ * XML Schema:
+ * <!-- LocateResult -->
+ * <element name="LocateResult" type="xkms:LocateResultType"/>
+ * <complexType name="LocateResultType">
+ * <complexContent>
+ * <extension base="xkms:ResultType">
+ * <sequence>
+ * <element ref="xkms:UnverifiedKeyBinding" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /LocateResult -->
+ */
+static int
+xmlSecXkmsServerRequestLocateNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecSize pos, size;
+ xmlSecKeyPtr key;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first write the "parent" type */
+ ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResultTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* write keys in <xkms:UnverifiedKeyBinding> nodes */
+ size = xmlSecPtrListGetSize(&(ctx->keys));
+ for(pos = 0; pos < size; ++pos) {
+ key = (xmlSecKeyPtr)xmlSecPtrListGetItem(&(ctx->keys), pos);
+ if(key == NULL) {
+ continue;
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeUnverifiedKeyBinding, xmlSecXkmsNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeUnverifiedKeyBinding));
+ return(-1);
+ }
+
+ ret = xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(ctx, cur, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXkmsServerRequestLocateExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+ xmlSecKeyPtr key = NULL;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* now we are ready to search for key */
+ if((ctx->keyInfoReadCtx.keysMngr != NULL) && (ctx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
+ /* todo: set parameters to locate but not validate the key */
+ key = (ctx->keyInfoReadCtx.keysMngr->getKey)(ctx->keyInfoNode, &(ctx->keyInfoReadCtx));
+ }
+
+ /* check that we got what we needed */
+ if((key == NULL) || (!xmlSecKeyMatch(key, NULL, &(ctx->keyInfoReadCtx.keyReq)))) {
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorNoMatch);
+ return(-1);
+ }
+
+ xmlSecAssert2(key != NULL, -1);
+ ret = xmlSecPtrListAdd(&(ctx->keys), key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/********************************************************************
+ *
+ * ValidateRequest/ValidateResponse
+ *
+ *******************************************************************/
+static int xmlSecXkmsServerRequestValidateNodeRead (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestValidateNodeWrite(xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx,
+ xmlNodePtr node);
+static int xmlSecXkmsServerRequestValidateExecute (xmlSecXkmsServerRequestId id,
+ xmlSecXkmsServerCtxPtr ctx);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestValidateKlass = {
+ xmlSecXkmsServerRequestValidateName, /* const xmlChar* name; */
+ xmlSecNodeValidateRequest, /* const xmlChar* requestNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* requestNodeNs; */
+ xmlSecNodeValidateResult, /* const xmlChar* responseNodeName; */
+ xmlSecXkmsNs, /* const xmlChar* responseNodeNs; */
+ XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND, /* xmlSecBitMask flags; */
+ xmlSecXkmsServerRequestValidateNodeRead, /* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+ xmlSecXkmsServerRequestValidateNodeWrite, /* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+ xmlSecXkmsServerRequestValidateExecute, /* xmlSecXkmsServerRequestExecuteMethod execute; */
+ NULL, /* void* reserved1; */
+ NULL /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestValidateGetKlass:
+ *
+ * The ValidateRequest klass.
+ *
+ * Returns: ValidateRequest klass.
+ */
+xmlSecXkmsServerRequestId
+xmlSecXkmsServerRequestValidateGetKlass(void) {
+ return(&xmlSecXkmsServerRequestValidateKlass);
+}
+
+/**
+ * <xkms:ValidateRequest Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:ResponseMechanism>*
+ * <xkms:RespondWith>*
+ * <xkms:PendingNotification Mechanism Identifier>?
+ * <xkms:QueryKeyBinding Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:TimeInstant Time>?
+ *
+ * XML Schema:
+ *
+ * <!-- ValidateRequest -->
+ * <element name="ValidateRequest" type="xkms:ValidateRequestType"/>
+ * <complexType name="ValidateRequestType">
+ * <complexContent>
+ * <extension base="xkms:RequestAbstractType">
+ * <sequence>
+ * <element ref="xkms:QueryKeyBinding"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /ValidateRequest -->
+ */
+static int
+xmlSecXkmsServerRequestValidateNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = node;
+
+ /* first read "parent" type */
+ ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* now read required <xkms:QueryKeyBinding/> node */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeQueryKeyBinding, xmlSecXkmsNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeQueryKeyBinding));
+ return(-1);
+ }
+
+ /* read <xkms:QueryKeyBinding/> node */
+ ret = xmlSecXkmsServerCtxQueryKeyBindingNodeRead(ctx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxQueryKeyBindingNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* check that there is nothing after the last node */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * <xkms:ValidateResult Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ * <ds:Signature>?
+ * <xkms:MessageExtension>*
+ * (<xkms:OpaqueClientData>
+ * <xkms:OpaqueData>?
+ * )?
+ * <xkms:RequestSignatureValue>*
+ * (<xkms:KeyBinding Id?>
+ * <ds:KeyInfo>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:KeyUsage>?
+ * <xkms:UseKeyWith Application Identifier>*
+ * <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ * <xkms:Status StatusValue>
+ * (<xkms:ValidReason>?
+ * <xkms:IndeterminateReason>?
+ * <xkms:InvalidReason>?
+ * )*
+ * )*
+ *
+ * XML Schema:
+ *
+ * <!-- ValidateResult -->
+ * <element name="ValidateResult" type="xkms:ValidateResultType"/>
+ * <complexType name="ValidateResultType">
+ * <complexContent>
+ * <extension base="xkms:ResultType">
+ * <sequence>
+ * <element ref="xkms:KeyBinding" minOccurs="0"
+ * maxOccurs="unbounded"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * <!-- /ValidateResult -->
+ */
+static int
+xmlSecXkmsServerRequestValidateNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+ xmlSecSize pos, size;
+ xmlSecKeyPtr key;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first write the "parent" type */
+ ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxResultTypeNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* write keys in <xkms:UnverifiedKeyBinding> nodes */
+ size = xmlSecPtrListGetSize(&(ctx->keys));
+ for(pos = 0; pos < size; ++pos) {
+ key = (xmlSecKeyPtr)xmlSecPtrListGetItem(&(ctx->keys), pos);
+ if(key == NULL) {
+ continue;
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeUnverifiedKeyBinding, xmlSecXkmsNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeUnverifiedKeyBinding));
+ return(-1);
+ }
+
+ ret = xmlSecXkmsServerCtxKeyBindingNodeWrite(ctx, cur, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerCtxKeyBindingNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXkmsServerRequestValidateExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+ xmlSecKeyPtr key = NULL;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* now we are ready to search for key */
+ if((ctx->keyInfoReadCtx.keysMngr != NULL) && (ctx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
+ key = (ctx->keyInfoReadCtx.keysMngr->getKey)(ctx->keyInfoNode, &(ctx->keyInfoReadCtx));
+ }
+
+ /* check that we got what we needed */
+ if((key == NULL) || (!xmlSecKeyMatch(key, NULL, &(ctx->keyInfoReadCtx.keyReq)))) {
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorNoMatch);
+ return(-1);
+ }
+
+ xmlSecAssert2(key != NULL, -1);
+ ret = xmlSecPtrListAdd(&(ctx->keys), key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_NO_XKMS */
+
diff --git a/src/xmldsig.c b/src/xmldsig.c
new file mode 100644
index 00000000..cbd825e5
--- /dev/null
+++ b/src/xmldsig.c
@@ -0,0 +1,1795 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * "XML Digital Signature" implementation
+ * http://www.w3.org/TR/xmldsig-core/
+ * http://www.w3.org/Signature/Overview.html
+ *
+ * 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_XMLDSIG
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/membuf.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/errors.h>
+
+/**************************************************************************
+ *
+ * xmlSecDSigCtx
+ *
+ *************************************************************************/
+static int xmlSecDSigCtxProcessSignatureNode (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node);
+static int xmlSecDSigCtxProcessSignedInfoNode (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node);
+static int xmlSecDSigCtxProcessKeyInfoNode (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node);
+static int xmlSecDSigCtxProcessObjectNode (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node);
+static int xmlSecDSigCtxProcessManifestNode (xmlSecDSigCtxPtr dsigCtx,
+ xmlNodePtr node);
+
+/* The ID attribute in XMLDSig is 'Id' */
+static const xmlChar* xmlSecDSigIds[] = { xmlSecAttrId, NULL };
+
+/**
+ * xmlSecDSigCtxCreate:
+ * @keysMngr: the pointer to keys manager.
+ *
+ * Creates <dsig:Signature/> element processing context.
+ * The caller is responsible for destroying returend object by calling
+ * #xmlSecDSigCtxDestroy function.
+ *
+ * Returns: pointer to newly allocated context object or NULL if an error
+ * occurs.
+ */
+xmlSecDSigCtxPtr
+xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) {
+ xmlSecDSigCtxPtr dsigCtx;
+ int ret;
+
+ dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx));
+ if(dsigCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecDSigCtx)=%d",
+ sizeof(xmlSecDSigCtx));
+ return(NULL);
+ }
+
+ ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecDSigCtxDestroy(dsigCtx);
+ return(NULL);
+ }
+ return(dsigCtx);
+}
+
+/**
+ * xmlSecDSigCtxDestroy:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ *
+ * Destroy context object created with #xmlSecDSigCtxCreate function.
+ */
+void
+xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) {
+ xmlSecAssert(dsigCtx != NULL);
+
+ xmlSecDSigCtxFinalize(dsigCtx);
+ xmlFree(dsigCtx);
+}
+
+/**
+ * xmlSecDSigCtxInitialize:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @keysMngr: the pointer to keys manager.
+ *
+ * Initializes <dsig:Signature/> element processing context.
+ * The caller is responsible for cleaing up returend object by calling
+ * #xmlSecDSigCtxFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) {
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+
+ memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
+
+ /* initialize key info */
+ ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ dsigCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
+
+ ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
+ /* it's not wise to write private key :) */
+ dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
+
+ /* initializes transforms dsigCtx */
+ ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* references lists from SignedInfo and Manifest elements */
+ xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences),
+ xmlSecDSigReferenceCtxListId);
+ xmlSecPtrListInitialize(&(dsigCtx->manifestReferences),
+ xmlSecDSigReferenceCtxListId);
+
+ dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny;
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxFinalize:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ *
+ * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function.
+ */
+void
+xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) {
+ xmlSecAssert(dsigCtx != NULL);
+
+ xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx));
+ xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx));
+ xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx));
+ xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences));
+ xmlSecPtrListFinalize(&(dsigCtx->manifestReferences));
+
+ if(dsigCtx->enabledReferenceTransforms != NULL) {
+ xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms);
+ }
+ if(dsigCtx->signKey != NULL) {
+ xmlSecKeyDestroy(dsigCtx->signKey);
+ }
+ if(dsigCtx->id != NULL) {
+ xmlFree(dsigCtx->id);
+ }
+ memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
+}
+
+/**
+ * xmlSecDSigCtxEnableReferenceTransform:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @transformId: the transform klass.
+ *
+ * Enables @transformId for <dsig:Reference/> elements processing.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->result == NULL, -1);
+ xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
+
+ if(dsigCtx->enabledReferenceTransforms == NULL) {
+ dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListId);
+ if(dsigCtx->enabledReferenceTransforms == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxEnableSignatureTransform:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @transformId: the transform klass.
+ *
+ * Enables @transformId for <dsig:SignedInfo/> element processing.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->result == NULL, -1);
+ xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
+
+ return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId));
+}
+
+/**
+ * xmlSecDSigCtxGetPreSignBuffer:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ *
+ * Gets pointer to the buffer with serialized <dsig:SignedInfo/> element
+ * just before signature claculation (valid if and only if
+ * #XMLSEC_DSIG_FLAGS_STORE_SIGNATURE context flag is set.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+xmlSecBufferPtr
+xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) {
+ xmlSecAssert2(dsigCtx != NULL, NULL);
+
+ return((dsigCtx->preSignMemBufMethod != NULL) ?
+ xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL);
+}
+
+/**
+ * xmlSecDSigCtxSign:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @tmpl: the pointer to <dsig:Signature/> node with signature template.
+ *
+ * Signs the data as described in @tmpl node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) {
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->result == NULL, -1);
+ xmlSecAssert2(tmpl != NULL, -1);
+ xmlSecAssert2(tmpl->doc != NULL, -1);
+
+ /* add ids for Signature nodes */
+ dsigCtx->operation = xmlSecTransformOperationSign;
+ dsigCtx->status = xmlSecDSigStatusUnknown;
+ xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds);
+
+ /* read signature template */
+ ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxSigantureProcessNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+ xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
+
+ /* references processing might change the status */
+ if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+ return(0);
+ }
+
+ /* check what we've got */
+ dsigCtx->result = dsigCtx->transformCtx.result;
+ if((dsigCtx->result == NULL) || (xmlSecBufferGetData(dsigCtx->result) == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_RESULT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* write signed data to xml */
+ xmlNodeSetContentLen(dsigCtx->signValueNode,
+ xmlSecBufferGetData(dsigCtx->result),
+ xmlSecBufferGetSize(dsigCtx->result));
+
+ /* set success status and we are done */
+ dsigCtx->status = xmlSecDSigStatusSucceeded;
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxVerify:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @node: the pointer with <dsig:Signature/> node.
+ *
+ * Vaidates signature in the @node. The verification result is returned
+ * in #status member of the @dsigCtx object.
+ *
+ * Returns: 0 on success (check #status member of @dsigCtx to get
+ * signature verification result) or a negative value if an error occurs.
+ */
+int
+xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+
+ /* add ids for Signature nodes */
+ dsigCtx->operation = xmlSecTransformOperationVerify;
+ dsigCtx->status = xmlSecDSigStatusUnknown;
+ xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
+
+ /* read siganture info */
+ ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxSigantureProcessNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+ xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
+
+ /* references processing might change the status */
+ if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+ return(0);
+ }
+
+ /* verify SignatureValue node content */
+ ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
+ &(dsigCtx->transformCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformVerifyNodeContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set status and we are done */
+ if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
+ dsigCtx->status = xmlSecDSigStatusSucceeded;
+ } else {
+ dsigCtx->status = xmlSecDSigStatusInvalid;
+ }
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessSignatureNode:
+ *
+ * The Signature element (http://www.w3.org/TR/xmldsig-core/#sec-Signature)
+ *
+ * The Signature element is the root element of an XML Signature.
+ * Implementation MUST generate laxly schema valid [XML-schema] Signature
+ * elements as specified by the following schema:
+ * The way in which the SignedInfo element is presented to the
+ * canonicalization method is dependent on that method. The following
+ * applies to algorithms which process XML as nodes or characters:
+ *
+ * - XML based canonicalization implementations MUST be provided with
+ * a [XPath] node-set originally formed from the document containing
+ * the SignedInfo and currently indicating the SignedInfo, its descendants,
+ * and the attribute and namespace nodes of SignedInfo and its descendant
+ * elements.
+ *
+ * - Text based canonicalization algorithms (such as CRLF and charset
+ * normalization) should be provided with the UTF-8 octets that represent
+ * the well-formed SignedInfo element, from the first character to the
+ * last character of the XML representation, inclusive. This includes
+ * the entire text of the start and end tags of the SignedInfo element
+ * as well as all descendant markup and character data (i.e., the text)
+ * between those tags. Use of text based canonicalization of SignedInfo
+ * is NOT RECOMMENDED.
+ *
+ * =================================
+ * we do not support any non XML based C14N
+ *
+ * Schema Definition:
+ *
+ * <element name="Signature" type="ds:SignatureType"/>
+ * <complexType name="SignatureType">
+ * <sequence>
+ * <element ref="ds:SignedInfo"/>
+ * <element ref="ds:SignatureValue"/>
+ * <element ref="ds:KeyInfo" minOccurs="0"/>
+ * <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
+ * </sequence> <attribute name="Id" type="ID" use="optional"/>
+ * </complexType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*) >
+ * <!ATTLIST Signature
+ * xmlns CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#'
+ * Id ID #IMPLIED >
+ *
+ */
+static int
+xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+ xmlSecTransformDataType firstType;
+ xmlNodePtr signedInfoNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+ xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
+ xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
+ xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignature));
+ return(-1);
+ }
+
+ /* read node data */
+ xmlSecAssert2(dsigCtx->id == NULL, -1);
+ dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
+
+ /* first node is required SignedInfo */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
+ return(-1);
+ }
+ signedInfoNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next node is required SignatureValue */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
+ return(-1);
+ }
+ dsigCtx->signValueNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next node is optional KeyInfo */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
+ keyInfoNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else {
+ keyInfoNode = NULL;
+ }
+
+ /* next nodes are optional Object nodes */
+ while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
+ /* read manifests from objects */
+ if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
+ ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessObjectNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* if there is something left than it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* now validated all the references and prepare transform */
+ ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessSignedInfoNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ /* references processing might change the status */
+ if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+ return(0);
+ }
+
+ /* as the result, we should have sign and c14n methods set */
+ xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+ xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
+
+ ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessKeyInfoNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ /* as the result, we should have a key */
+ xmlSecAssert2(dsigCtx->signKey != NULL, -1);
+
+ /* if we need to write result to xml node then we need base64 encode result */
+ if(dsigCtx->operation == xmlSecTransformOperationSign) {
+ xmlSecTransformPtr base64Encode;
+
+ /* we need to add base64 encode transform */
+ base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ xmlSecTransformBase64Id);
+ if(base64Encode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ base64Encode->operation = xmlSecTransformOperationEncode;
+ }
+
+ firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
+ xmlSecTransformModePush,
+ &(dsigCtx->transformCtx));
+ if((firstType & xmlSecTransformDataTypeXml) != 0) {
+ xmlSecNodeSetPtr nodeset = NULL;
+
+ xmlSecAssert2(signedInfoNode != NULL, -1);
+ nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
+ if(nodeset == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetGetChildren",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
+ return(-1);
+ }
+
+ /* calculate the signature */
+ ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxXmlExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecNodeSetDestroy(nodeset);
+ return(-1);
+ }
+ xmlSecNodeSetDestroy(nodeset);
+ } else {
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "the binary c14n transforms are not supported yet",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessSignedInfoNode:
+ *
+ * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo)
+ *
+ * The structure of SignedInfo includes the canonicalization algorithm,
+ * a result algorithm, and one or more references. The SignedInfo element
+ * may contain an optional ID attribute that will allow it to be referenced by
+ * other signatures and objects.
+ *
+ * SignedInfo does not include explicit result or digest properties (such as
+ * calculation time, cryptographic device serial number, etc.). If an
+ * application needs to associate properties with the result or digest,
+ * it may include such information in a SignatureProperties element within
+ * an Object element.
+ *
+ * Schema Definition:
+ *
+ * <element name="SignedInfo" type="ds:SignedInfoType"/>
+ * <complexType name="SignedInfoType">
+ * <sequence>
+ * <element ref="ds:CanonicalizationMethod"/>
+ * <element ref="ds:SignatureMethod"/>
+ * <element ref="ds:Reference" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="ID" use="optional"/>
+ * </complexType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod, Reference+) >
+ * <!ATTLIST SignedInfo Id ID #IMPLIED>
+ *
+ */
+static int
+xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+ xmlSecDSigReferenceCtxPtr dsigRefCtx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+ xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
+ xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
+ xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first node is required CanonicalizationMethod. */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
+ dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
+ cur, xmlSecTransformUsageC14NMethod);
+ if(dsigCtx->c14nMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
+ /* the dsig spec does require CanonicalizationMethod node
+ * to be present but in some case it application might decide to
+ * minimize traffic */
+ dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ dsigCtx->defC14NMethodId);
+ if(dsigCtx->c14nMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CanonicalizationMethod",
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
+ return(-1);
+ }
+
+ /* insert membuf if requested */
+ if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
+ xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
+ dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ xmlSecTransformMemBufId);
+ if(dsigCtx->preSignMemBufMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+ }
+ }
+
+ /* next node is required SignatureMethod. */
+ cur = xmlSecGetNextElementNode( ((cur != NULL) ? cur->next : node->children) );
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
+ dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
+ cur, xmlSecTransformUsageSignatureMethod);
+ if(dsigCtx->signMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
+ /* the dsig spec does require SignatureMethod node
+ * to be present but in some case it application might decide to
+ * minimize traffic */
+ dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
+ dsigCtx->defSignMethodId);
+ if(dsigCtx->signMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
+ return(-1);
+ }
+ dsigCtx->signMethod->operation = dsigCtx->operation;
+
+ /* calculate references */
+ cur = xmlSecGetNextElementNode(cur->next);
+ while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
+ /* create reference */
+ dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
+ if(dsigRefCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* add to the list */
+ ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+ return(-1);
+ }
+
+ /* process */
+ ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxProcessNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ /* bail out if next Reference processing failed */
+ if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
+ dsigCtx->status = xmlSecDSigStatusInvalid;
+ return(0);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that we have at least one Reference */
+ if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* if there is something left than it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+
+ /* set key requirements */
+ ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformSetKeyReq",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
+ return(-1);
+ }
+
+ /* ignore <dsig:KeyInfo /> if there is the key is already set */
+ /* todo: throw an error if key is set and node != NULL? */
+ if((dsigCtx->signKey == NULL) && (dsigCtx->keyInfoReadCtx.keysMngr != NULL)
+ && (dsigCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
+ dsigCtx->signKey = (dsigCtx->keyInfoReadCtx.keysMngr->getKey)(node, &(dsigCtx->keyInfoReadCtx));
+ }
+
+ /* check that we have exactly what we want */
+ if((dsigCtx->signKey == NULL) || (!xmlSecKeyMatch(dsigCtx->signKey, NULL, &(dsigCtx->keyInfoReadCtx.keyReq)))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_KEY_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set the key to the transform */
+ ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformSetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
+ return(-1);
+ }
+
+ /* if we are signing document, update <dsig:KeyInfo/> node */
+ if((node != NULL) && (dsigCtx->operation == xmlSecTransformOperationSign)) {
+ ret = xmlSecKeyInfoNodeWrite(node, dsigCtx->signKey, &(dsigCtx->keyInfoWriteCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessObjectNode:
+ *
+ * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object)
+ *
+ * Object is an optional element that may occur one or more times. When
+ * present, this element may contain any data. The Object element may include
+ * optional MIME type, ID, and encoding attributes.
+ *
+ * Schema Definition:
+ *
+ * <element name="Object" type="ds:ObjectType"/>
+ * <complexType name="ObjectType" mixed="true">
+ * <sequence minOccurs="0" maxOccurs="unbounded">
+ * <any namespace="##any" processContents="lax"/>
+ * </sequence>
+ * <attribute name="Id" type="ID" use="optional"/>
+ * <attribute name="MimeType" type="string" use="optional"/>
+ * <attribute name="Encoding" type="anyURI" use="optional"/>
+ * </complexType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* >
+ * <!ATTLIST Object Id ID #IMPLIED
+ * MimeType CDATA #IMPLIED
+ * Encoding CDATA #IMPLIED >
+ */
+static int
+xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* we care about Manifest nodes only; ignore everything else */
+ cur = xmlSecGetNextElementNode(node->children);
+ while(cur != NULL) {
+ if(xmlSecCheckNodeName(cur, xmlSecNodeManifest, xmlSecDSigNs)) {
+ ret = xmlSecDSigCtxProcessManifestNode(dsigCtx, cur);
+ if(ret < 0){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigCtxProcessManifestNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessManifestNode:
+ *
+ * The Manifest Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest)
+ *
+ * The Manifest element provides a list of References. The difference from
+ * the list in SignedInfo is that it is application defined which, if any, of
+ * the digests are actually checked against the objects referenced and what to
+ * do if the object is inaccessible or the digest compare fails. If a Manifest
+ * is pointed to from SignedInfo, the digest over the Manifest itself will be
+ * checked by the core result validation behavior. The digests within such
+ * a Manifest are checked at the application's discretion. If a Manifest is
+ * referenced from another Manifest, even the overall digest of this two level
+ * deep Manifest might not be checked.
+ *
+ * Schema Definition:
+ *
+ * <element name="Manifest" type="ds:ManifestType"/>
+ * <complexType name="ManifestType">
+ * <sequence>
+ * <element ref="ds:Reference" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="ID" use="optional"/>
+ * </complexType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT Manifest (Reference+) >
+ * <!ATTLIST Manifest Id ID #IMPLIED >
+ */
+static int
+xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+ xmlSecDSigReferenceCtxPtr dsigRefCtx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* calculate references */
+ cur = xmlSecGetNextElementNode(node->children);
+ while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
+ /* create reference */
+ dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest);
+ if(dsigRefCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* add to the list */
+ ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+ return(-1);
+ }
+
+ /* process */
+ ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxProcessNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ /* we don;t care if Reference processing failed because
+ * it's Manifest node */
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* we should have nothing else here */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecDSigCtxDebugDump:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the debug information about @dsigCtx to @output.
+ */
+void
+xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
+ xmlSecAssert(dsigCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ if(dsigCtx->operation == xmlSecTransformOperationSign) {
+ fprintf(output, "= SIGNATURE CONTEXT\n");
+ } else {
+ fprintf(output, "= VERIFICATION CONTEXT\n");
+ }
+ switch(dsigCtx->status) {
+ case xmlSecDSigStatusUnknown:
+ fprintf(output, "== Status: unknown\n");
+ break;
+ case xmlSecDSigStatusSucceeded:
+ fprintf(output, "== Status: succeeded\n");
+ break;
+ case xmlSecDSigStatusInvalid:
+ fprintf(output, "== Status: invalid\n");
+ break;
+ }
+ fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags);
+ fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2);
+
+ if(dsigCtx->id != NULL) {
+ fprintf(output, "== Id: \"%s\"\n", dsigCtx->id);
+ }
+
+ fprintf(output, "== Key Info Read Ctx:\n");
+ xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoReadCtx), output);
+ fprintf(output, "== Key Info Write Ctx:\n");
+ xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoWriteCtx), output);
+
+ fprintf(output, "== Signature Transform Ctx:\n");
+ xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output);
+
+ if(dsigCtx->signMethod != NULL) {
+ fprintf(output, "== Signature Method:\n");
+ xmlSecTransformDebugDump(dsigCtx->signMethod, output);
+ }
+
+ if(dsigCtx->signKey != NULL) {
+ fprintf(output, "== Signature Key:\n");
+ xmlSecKeyDebugDump(dsigCtx->signKey, output);
+ }
+
+ fprintf(output, "== SignedInfo References List:\n");
+ xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output);
+
+ fprintf(output, "== Manifest References List:\n");
+ xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output);
+
+ if((dsigCtx->result != NULL) &&
+ (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
+
+ fprintf(output, "== Result - start buffer:\n");
+ fwrite(xmlSecBufferGetData(dsigCtx->result),
+ xmlSecBufferGetSize(dsigCtx->result),
+ 1, output);
+ fprintf(output, "\n== Result - end buffer\n");
+ }
+ if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
+ (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
+ (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
+
+ fprintf(output, "== PreSigned data - start buffer:\n");
+ fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
+ xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
+ 1, output);
+ fprintf(output, "\n== PreSigned data - end buffer\n");
+ }
+}
+
+/**
+ * xmlSecDSigCtxDebugXmlDump:
+ * @dsigCtx: the pointer to <dsig:Signature/> processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the debug information about @dsigCtx to @output in XML format.
+ */
+void
+xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
+ xmlSecAssert(dsigCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ if(dsigCtx->operation == xmlSecTransformOperationSign) {
+ fprintf(output, "<SignatureContext \n");
+ } else {
+ fprintf(output, "<VerificationContext \n");
+ }
+ switch(dsigCtx->status) {
+ case xmlSecDSigStatusUnknown:
+ fprintf(output, "status=\"unknown\" >\n");
+ break;
+ case xmlSecDSigStatusSucceeded:
+ fprintf(output, "status=\"succeeded\" >\n");
+ break;
+ case xmlSecDSigStatusInvalid:
+ fprintf(output, "status=\"invalid\" >\n");
+ break;
+ }
+
+ fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags);
+ fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2);
+
+ fprintf(output, "<Id>");
+ xmlSecPrintXmlString(output, dsigCtx->id);
+ fprintf(output, "</Id>\n");
+
+ fprintf(output, "<KeyInfoReadCtx>\n");
+ xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output);
+ fprintf(output, "</KeyInfoReadCtx>\n");
+
+ fprintf(output, "<KeyInfoWriteCtx>\n");
+ xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output);
+ fprintf(output, "</KeyInfoWriteCtx>\n");
+
+ fprintf(output, "<SignatureTransformCtx>\n");
+ xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output);
+ fprintf(output, "</SignatureTransformCtx>\n");
+
+ if(dsigCtx->signMethod != NULL) {
+ fprintf(output, "<SignatureMethod>\n");
+ xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output);
+ fprintf(output, "</SignatureMethod>\n");
+ }
+
+ if(dsigCtx->signKey != NULL) {
+ fprintf(output, "<SignatureKey>\n");
+ xmlSecKeyDebugXmlDump(dsigCtx->signKey, output);
+ fprintf(output, "</SignatureKey>\n");
+ }
+
+ fprintf(output, "<SignedInfoReferences>\n");
+ xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output);
+ fprintf(output, "</SignedInfoReferences>\n");
+
+ fprintf(output, "<ManifestReferences>\n");
+ xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output);
+ fprintf(output, "</ManifestReferences>\n");
+
+ if((dsigCtx->result != NULL) &&
+ (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
+
+ fprintf(output, "<Result>");
+ fwrite(xmlSecBufferGetData(dsigCtx->result),
+ xmlSecBufferGetSize(dsigCtx->result),
+ 1, output);
+ fprintf(output, "</Result>\n");
+ }
+ if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
+ (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
+ (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
+
+ fprintf(output, "<PreSignedData>");
+ fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
+ xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
+ 1, output);
+ fprintf(output, "</PreSignedData>\n");
+ }
+
+ if(dsigCtx->operation == xmlSecTransformOperationSign) {
+ fprintf(output, "</SignatureContext>\n");
+ } else {
+ fprintf(output, "</VerificationContext>\n");
+ }
+}
+
+/**************************************************************************
+ *
+ * xmlSecDSigReferenceCtx
+ *
+ *************************************************************************/
+/**
+ * xmlSecDSigReferenceCtxCreate:
+ * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context.
+ * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
+ *
+ * Creates new <dsig:Reference/> element processing context. Caller is responsible
+ * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy
+ * function.
+ *
+ * Returns: pointer to newly created context or NULL if an error occurs.
+ */
+xmlSecDSigReferenceCtxPtr
+xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) {
+ xmlSecDSigReferenceCtxPtr dsigRefCtx;
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, NULL);
+
+ dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx));
+ if(dsigRefCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecDSigReferenceCtx)=%d",
+ sizeof(xmlSecDSigReferenceCtx));
+ return(NULL);
+ }
+
+ ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecDSigReferenceCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+ return(NULL);
+ }
+ return(dsigRefCtx);
+}
+
+/**
+ * xmlSecDSigReferenceCtxDestroy:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ *
+ * Destroy context object created with #xmlSecDSigReferenceCtxCreate function.
+ */
+void
+xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
+ xmlSecAssert(dsigRefCtx != NULL);
+
+ xmlSecDSigReferenceCtxFinalize(dsigRefCtx);
+ xmlFree(dsigRefCtx);
+}
+
+/**
+ * xmlSecDSigReferenceCtxInitialize:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context.
+ * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
+ *
+ * Initializes new <dsig:Reference/> element processing context. Caller is responsible
+ * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize
+ * function.
+ *
+ * Returns: 0 on succes or aa negative value otherwise.
+ */
+int
+xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx,
+ xmlSecDSigReferenceOrigin origin) {
+ int ret;
+
+ xmlSecAssert2(dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigRefCtx != NULL, -1);
+
+ memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
+
+ dsigRefCtx->dsigCtx = dsigCtx;
+ dsigRefCtx->origin = origin;
+
+ /* initializes transforms dsigRefCtx */
+ ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* copy enabled transforms */
+ if(dsigCtx->enabledReferenceTransforms != NULL) {
+ ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms),
+ dsigCtx->enabledReferenceTransforms);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;
+ dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris;
+
+ if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK) != 0) {
+ dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK;
+ }
+ return(0);
+}
+
+/**
+ * xmlSecDSigReferenceCtxFinalize:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ *
+ * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function.
+ */
+void
+xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
+ xmlSecAssert(dsigRefCtx != NULL);
+
+ xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx));
+ if(dsigRefCtx->id != NULL) {
+ xmlFree(dsigRefCtx->id);
+ }
+ if(dsigRefCtx->uri != NULL) {
+ xmlFree(dsigRefCtx->uri);
+ }
+ if(dsigRefCtx->type != NULL) {
+ xmlFree(dsigRefCtx->type);
+ }
+ memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
+}
+
+/**
+ * xmlSecDSigReferenceCtxGetPreDigestBuffer:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ *
+ * Gets the results of <dsig:Reference/> node processing just before digesting
+ * (valid only if #XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES or
+ * #XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES flas of signature context
+ * is set).
+ *
+ * Returns: pointer to the buffer or NULL if an error occurs.
+ */
+xmlSecBufferPtr
+xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
+ xmlSecAssert2(dsigRefCtx != NULL, NULL);
+
+ return((dsigRefCtx->preDigestMemBufMethod != NULL) ?
+ xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL);
+}
+
+/**
+ * xmlSecDSigReferenceCtxProcessNode:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ * @node: the pointer to <dsig:Reference/> node.
+
+ * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference)
+ *
+ * Reference is an element that may occur one or more times. It specifies
+ * a digest algorithm and digest value, and optionally an identifier of the
+ * object being signed, the type of the object, and/or a list of transforms
+ * to be applied prior to digesting. The identification (URI) and transforms
+ * describe how the digested content (i.e., the input to the digest method)
+ * was created. The Type attribute facilitates the processing of referenced
+ * data. For example, while this specification makes no requirements over
+ * external data, an application may wish to signal that the referent is a
+ * Manifest. An optional ID attribute permits a Reference to be referenced
+ * from elsewhere.
+ *
+ * Returns: 0 on succes or aa negative value otherwise.
+ */
+int
+xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) {
+ xmlSecTransformCtxPtr transformCtx;
+ xmlNodePtr digestValueNode;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(dsigRefCtx != NULL, -1);
+ xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
+ xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
+ xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
+ xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+
+ transformCtx = &(dsigRefCtx->transformCtx);
+
+ /* read attributes first */
+ dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
+ dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId);
+ dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
+
+ /* set start URI (and check that it is enabled!) */
+ ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxSetUri",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(dsigRefCtx->uri));
+ return(-1);
+ }
+
+ /* first is optional Transforms node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
+ ret = xmlSecTransformCtxNodesListRead(transformCtx,
+ cur, xmlSecTransformUsageDSigTransform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodesListRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* insert membuf if requested */
+ if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
+ ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
+ ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
+ ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
+
+ xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
+ dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
+ transformCtx,
+ xmlSecTransformMemBufId);
+ if(dsigRefCtx->preDigestMemBufMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+ return(-1);
+ }
+ }
+
+ /* next node is required DigestMethod. */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
+ dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx),
+ cur, xmlSecTransformUsageDigestMethod);
+ if(dsigRefCtx->digestMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
+ /* the dsig spec does require DigestMethod node
+ * to be present but in some case it application might decide to
+ * minimize traffic */
+ dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx),
+ dsigRefCtx->dsigCtx->defSignMethodId);
+ if(dsigRefCtx->digestMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
+ return(-1);
+ }
+ dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
+
+ /* last node is required DigestValue */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
+ digestValueNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDigestValue));
+ return(-1);
+ }
+
+ /* if we have something else then it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* if we need to write result to xml node then we need base64 encode result */
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ xmlSecTransformPtr base64Encode;
+
+ /* we need to add base64 encode transform */
+ base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
+ if(base64Encode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ base64Encode->operation = xmlSecTransformOperationEncode;
+ }
+
+ /* finally get transforms results */
+ ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ dsigRefCtx->result = transformCtx->result;
+
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* write signed data to xml */
+ xmlNodeSetContentLen(digestValueNode,
+ xmlSecBufferGetData(dsigRefCtx->result),
+ xmlSecBufferGetSize(dsigRefCtx->result));
+
+ /* set success status and we are done */
+ dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+ } else {
+ /* verify SignatureValue node content */
+ ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
+ digestValueNode, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformVerifyNodeContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set status and we are done */
+ if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
+ dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+ } else {
+ dsigRefCtx->status = xmlSecDSigStatusInvalid;
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecDSigReferenceCtxDebugDump:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @dsigRefCtx to @output.
+ */
+void
+xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
+ xmlSecAssert(dsigRefCtx != NULL);
+ xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ fprintf(output, "= REFERENCE CALCULATION CONTEXT\n");
+ } else {
+ fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n");
+ }
+ switch(dsigRefCtx->status) {
+ case xmlSecDSigStatusUnknown:
+ fprintf(output, "== Status: unknown\n");
+ break;
+ case xmlSecDSigStatusSucceeded:
+ fprintf(output, "== Status: succeeded\n");
+ break;
+ case xmlSecDSigStatusInvalid:
+ fprintf(output, "== Status: invalid\n");
+ break;
+ }
+ if(dsigRefCtx->id != NULL) {
+ fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id);
+ }
+ if(dsigRefCtx->uri != NULL) {
+ fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri);
+ }
+ if(dsigRefCtx->type != NULL) {
+ fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type);
+ }
+
+ fprintf(output, "== Reference Transform Ctx:\n");
+ xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output);
+
+ if(dsigRefCtx->digestMethod != NULL) {
+ fprintf(output, "== Digest Method:\n");
+ xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output);
+ }
+
+ if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
+ (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
+
+ fprintf(output, "== PreDigest data - start buffer:\n");
+ fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
+ xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
+ 1, output);
+ fprintf(output, "\n== PreDigest data - end buffer\n");
+ }
+
+ if((dsigRefCtx->result != NULL) &&
+ (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
+
+ fprintf(output, "== Result - start buffer:\n");
+ fwrite(xmlSecBufferGetData(dsigRefCtx->result),
+ xmlSecBufferGetSize(dsigRefCtx->result), 1,
+ output);
+ fprintf(output, "\n== Result - end buffer\n");
+ }
+}
+
+/**
+ * xmlSecDSigReferenceCtxDebugXmlDump:
+ * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @dsigRefCtx to @output in output format.
+ */
+void
+xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
+ xmlSecAssert(dsigRefCtx != NULL);
+ xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ fprintf(output, "<ReferenceCalculationContext ");
+ } else {
+ fprintf(output, "<ReferenceVerificationContext ");
+ }
+ switch(dsigRefCtx->status) {
+ case xmlSecDSigStatusUnknown:
+ fprintf(output, "status=\"unknown\" >\n");
+ break;
+ case xmlSecDSigStatusSucceeded:
+ fprintf(output, "status=\"succeeded\" >\n");
+ break;
+ case xmlSecDSigStatusInvalid:
+ fprintf(output, "status=\"invalid\" >\n");
+ break;
+ }
+
+ fprintf(output, "<Id>");
+ xmlSecPrintXmlString(output, dsigRefCtx->id);
+ fprintf(output, "</Id>\n");
+
+ fprintf(output, "<URI>");
+ xmlSecPrintXmlString(output, dsigRefCtx->uri);
+ fprintf(output, "</URI>\n");
+
+ fprintf(output, "<Type>");
+ xmlSecPrintXmlString(output, dsigRefCtx->type);
+ fprintf(output, "</Type>\n");
+
+ fprintf(output, "<ReferenceTransformCtx>\n");
+ xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output);
+ fprintf(output, "</ReferenceTransformCtx>\n");
+
+ if(dsigRefCtx->digestMethod != NULL) {
+ fprintf(output, "<DigestMethod>\n");
+ xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output);
+ fprintf(output, "</DigestMethod>\n");
+ }
+
+ if((dsigRefCtx->result != NULL) &&
+ (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
+
+ fprintf(output, "<Result>");
+ fwrite(xmlSecBufferGetData(dsigRefCtx->result),
+ xmlSecBufferGetSize(dsigRefCtx->result), 1,
+ output);
+ fprintf(output, "</Result>\n");
+ }
+
+ if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
+ (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
+
+ fprintf(output, "<PreDigestData>");
+ fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
+ xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
+ 1, output);
+ fprintf(output, "</PreDigestData>\n");
+ }
+ if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
+ fprintf(output, "</ReferenceCalculationContext>\n");
+ } else {
+ fprintf(output, "</ReferenceVerificationContext>\n");
+ }
+}
+
+
+/**************************************************************************
+ *
+ * xmlSecDSigReferenceCtxListKlass
+ *
+ *************************************************************************/
+static xmlSecPtrListKlass xmlSecDSigReferenceCtxListKlass = {
+ BAD_CAST "dsig-reference-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecDSigReferenceCtxDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecDSigReferenceCtxListGetKlass:
+ *
+ * The <dsig:Reference/> element processing contexts list klass.
+ *
+ * Returns: <dsig:Reference/> element processing context list klass.
+ */
+xmlSecPtrListId
+xmlSecDSigReferenceCtxListGetKlass(void) {
+ return(&xmlSecDSigReferenceCtxListKlass);
+}
+
+#endif /* XMLSEC_NO_XMLDSIG */
+
+
diff --git a/src/xmlenc.c b/src/xmlenc.c
new file mode 100644
index 00000000..cd226a5a
--- /dev/null
+++ b/src/xmlenc.c
@@ -0,0 +1,1339 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * "XML Encryption" implementation
+ * http://www.w3.org/TR/xmlenc-core
+ *
+ * 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_XMLENC
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/errors.h>
+
+static int xmlSecEncCtxEncDataNodeRead (xmlSecEncCtxPtr encCtx,
+ xmlNodePtr node);
+static int xmlSecEncCtxEncDataNodeWrite (xmlSecEncCtxPtr encCtx);
+static int xmlSecEncCtxCipherDataNodeRead (xmlSecEncCtxPtr encCtx,
+ xmlNodePtr node);
+static int xmlSecEncCtxCipherReferenceNodeRead (xmlSecEncCtxPtr encCtx,
+ xmlNodePtr node);
+
+/* The ID attribute in XMLEnc is 'Id' */
+static const xmlChar* xmlSecEncIds[] = { BAD_CAST "Id", NULL };
+
+
+/**
+ * xmlSecEncCtxCreate:
+ * @keysMngr: the pointer to keys manager.
+ *
+ * Creates <enc:EncryptedData/> element processing context.
+ * The caller is responsible for destroying returend object by calling
+ * #xmlSecEncCtxDestroy function.
+ *
+ * Returns: pointer to newly allocated context object or NULL if an error
+ * occurs.
+ */
+xmlSecEncCtxPtr
+xmlSecEncCtxCreate(xmlSecKeysMngrPtr keysMngr) {
+ xmlSecEncCtxPtr encCtx;
+ int ret;
+
+ encCtx = (xmlSecEncCtxPtr) xmlMalloc(sizeof(xmlSecEncCtx));
+ if(encCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecEncCtx)=%d",
+ sizeof(xmlSecEncCtx));
+ return(NULL);
+ }
+
+ ret = xmlSecEncCtxInitialize(encCtx, keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecEncCtxDestroy(encCtx);
+ return(NULL);
+ }
+ return(encCtx);
+}
+
+/**
+ * xmlSecEncCtxDestroy:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ *
+ * Destroy context object created with #xmlSecEncCtxCreate function.
+ */
+void
+xmlSecEncCtxDestroy(xmlSecEncCtxPtr encCtx) {
+ xmlSecAssert(encCtx != NULL);
+
+ xmlSecEncCtxFinalize(encCtx);
+ xmlFree(encCtx);
+}
+
+/**
+ * xmlSecEncCtxInitialize:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @keysMngr: the pointer to keys manager.
+ *
+ * Initializes <enc:EncryptedData/> element processing context.
+ * The caller is responsible for cleaing up returend object by calling
+ * #xmlSecEncCtxFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecEncCtxInitialize(xmlSecEncCtxPtr encCtx, xmlSecKeysMngrPtr keysMngr) {
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+
+ memset(encCtx, 0, sizeof(xmlSecEncCtx));
+
+ /* initialize key info */
+ ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoReadCtx), keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ encCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
+
+ ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoWriteCtx), keysMngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ encCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
+ /* it's not wise to write private key :) */
+ encCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
+
+ /* initializes transforms encCtx */
+ ret = xmlSecTransformCtxInitialize(&(encCtx->transformCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxFinalize:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ *
+ * Cleans up @encCtx object.
+ */
+void
+xmlSecEncCtxFinalize(xmlSecEncCtxPtr encCtx) {
+ xmlSecAssert(encCtx != NULL);
+
+ xmlSecEncCtxReset(encCtx);
+
+ xmlSecTransformCtxFinalize(&(encCtx->transformCtx));
+ xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoReadCtx));
+ xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoWriteCtx));
+
+ memset(encCtx, 0, sizeof(xmlSecEncCtx));
+}
+
+/**
+ * xmlSecEncCtxReset:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ *
+ * Resets @encCtx object, user settings are not touched.
+ */
+void
+xmlSecEncCtxReset(xmlSecEncCtxPtr encCtx) {
+ xmlSecAssert(encCtx != NULL);
+
+ xmlSecTransformCtxReset(&(encCtx->transformCtx));
+ xmlSecKeyInfoCtxReset(&(encCtx->keyInfoReadCtx));
+ xmlSecKeyInfoCtxReset(&(encCtx->keyInfoWriteCtx));
+
+ encCtx->operation = xmlSecTransformOperationNone;
+ encCtx->result = NULL;
+ encCtx->resultBase64Encoded = 0;
+ encCtx->resultReplaced = 0;
+ encCtx->encMethod = NULL;
+
+ if (encCtx->replacedNodeList != NULL) {
+ xmlFreeNodeList(encCtx->replacedNodeList);
+ encCtx->replacedNodeList = NULL;
+ }
+
+ if(encCtx->encKey != NULL) {
+ xmlSecKeyDestroy(encCtx->encKey);
+ encCtx->encKey = NULL;
+ }
+
+ if(encCtx->id != NULL) {
+ xmlFree(encCtx->id);
+ encCtx->id = NULL;
+ }
+
+ if(encCtx->type != NULL) {
+ xmlFree(encCtx->type);
+ encCtx->type = NULL;
+ }
+
+ if(encCtx->mimeType != NULL) {
+ xmlFree(encCtx->mimeType);
+ encCtx->mimeType = NULL;
+ }
+
+ if(encCtx->encoding != NULL) {
+ xmlFree(encCtx->encoding);
+ encCtx->encoding = NULL;
+ }
+
+ if(encCtx->recipient != NULL) {
+ xmlFree(encCtx->recipient);
+ encCtx->recipient = NULL;
+ }
+
+ if(encCtx->carriedKeyName != NULL) {
+ xmlFree(encCtx->carriedKeyName);
+ encCtx->carriedKeyName = NULL;
+ }
+
+ encCtx->encDataNode = encCtx->encMethodNode =
+ encCtx->keyInfoNode = encCtx->cipherValueNode = NULL;
+}
+
+/**
+ * xmlSecEncCtxCopyUserPref:
+ * @dst: the pointer to destination context.
+ * @src: the pointer to source context.
+ *
+ * Copies user preference from @src context to @dst.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecEncCtxCopyUserPref(xmlSecEncCtxPtr dst, xmlSecEncCtxPtr src) {
+ int ret;
+
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(src != NULL, -1);
+
+ dst->userData = src->userData;
+ dst->flags = src->flags;
+ dst->flags2 = src->flags2;
+ dst->defEncMethodId = src->defEncMethodId;
+ dst->mode = src->mode;
+
+ ret = xmlSecTransformCtxCopyUserPref(&(dst->transformCtx), &(src->transformCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoCtxCopyUserPref",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxBinaryEncrypt:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @tmpl: the pointer to <enc:EncryptedData/> template node.
+ * @data: the pointer for binary buffer.
+ * @dataSize: the @data buffer size.
+ *
+ * Encrypts @data according to template @tmpl.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecEncCtxBinaryEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl,
+ const xmlSecByte* data, xmlSecSize dataSize) {
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(encCtx->result == NULL, -1);
+ xmlSecAssert2(tmpl != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+
+ /* initialize context and add ID atributes to the list of known ids */
+ encCtx->operation = xmlSecTransformOperationEncrypt;
+ xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
+
+ /* read the template and set encryption method, key, etc. */
+ ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxBinaryExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "dataSize=%d",
+ dataSize);
+ return(-1);
+ }
+
+ encCtx->result = encCtx->transformCtx.result;
+ xmlSecAssert2(encCtx->result != NULL, -1);
+
+ ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxXmlEncrypt:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @tmpl: the pointer to <enc:EncryptedData/> template node.
+ * @node: the pointer to node for encryption.
+ *
+ * Encrypts @node according to template @tmpl. If requested, @node is replaced
+ * with result <enc:EncryptedData/> node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecEncCtxXmlEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, xmlNodePtr node) {
+ xmlOutputBufferPtr output;
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(encCtx->result == NULL, -1);
+ xmlSecAssert2(tmpl != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+
+ /* initialize context and add ID atributes to the list of known ids */
+ encCtx->operation = xmlSecTransformOperationEncrypt;
+ xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
+
+ /* read the template and set encryption method, key, etc. */
+ ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecTransformCtxPrepare(&(encCtx->transformCtx), xmlSecTransformDataTypeBin);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxPrepare",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=bin");
+ return(-1);
+ }
+
+ xmlSecAssert2(encCtx->transformCtx.first != NULL, -1);
+ output = xmlSecTransformCreateOutputBuffer(encCtx->transformCtx.first,
+ &(encCtx->transformCtx));
+ if(output == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->transformCtx.first)),
+ "xmlSecTransformCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* push data thru */
+ if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
+ /* get the content of the node */
+ xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
+ } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
+ xmlNodePtr cur;
+
+ /* get the content of the nodes childs */
+ for(cur = node->children; cur != NULL; cur = cur->next) {
+ xmlNodeDumpOutput(output, node->doc, cur, 0, 0, NULL);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "type=%s",
+ xmlSecErrorsSafeString(encCtx->type));
+ xmlOutputBufferClose(output);
+ return(-1);
+ }
+
+ /* close the buffer and flush everything */
+ ret = xmlOutputBufferClose(output);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlOutputBufferClose",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ encCtx->result = encCtx->transformCtx.result;
+ xmlSecAssert2(encCtx->result != NULL, -1);
+
+ ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* now we need to update our original document */
+ if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
+ /* check if we need to return the replaced node */
+ if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+ ret = xmlSecReplaceNodeAndReturn(node, tmpl, &(encCtx->replacedNodeList));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ } else {
+ ret = xmlSecReplaceNode(node, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ }
+
+ encCtx->resultReplaced = 1;
+ } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
+ /* check if we need to return the replaced node */
+ if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+ ret = xmlSecReplaceContentAndReturn(node, tmpl, &(encCtx->replacedNodeList));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceContentAndReturn",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ } else {
+ ret = xmlSecReplaceContent(node, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ }
+
+ encCtx->resultReplaced = 1;
+ } else {
+ /* we should've catached this error before */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "type=%s",
+ xmlSecErrorsSafeString(encCtx->type));
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxUriEncrypt:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @tmpl: the pointer to <enc:EncryptedData/> template node.
+ * @uri: the URI.
+ *
+ * Encrypts data from @uri according to template @tmpl.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecEncCtxUriEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, const xmlChar *uri) {
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(encCtx->result == NULL, -1);
+ xmlSecAssert2(tmpl != NULL, -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ /* initialize context and add ID atributes to the list of known ids */
+ encCtx->operation = xmlSecTransformOperationEncrypt;
+ xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
+
+ /* we need to add input uri transform first */
+ ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxSetUri",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ /* read the template and set encryption method, key, etc. */
+ ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* encrypt the data */
+ ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), tmpl->doc);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ encCtx->result = encCtx->transformCtx.result;
+ xmlSecAssert2(encCtx->result != NULL, -1);
+
+ ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxDecrypt:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @node: the pointer to <enc:EncryptedData/> node.
+ *
+ * Decrypts @node and if necessary replaces @node with decrypted data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecEncCtxDecrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
+ xmlSecBufferPtr buffer;
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* decrypt */
+ buffer = xmlSecEncCtxDecryptToBuffer(encCtx, node);
+ if(buffer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxDecryptToBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* replace original node if requested */
+ if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
+ /* check if we need to return the replaced node */
+ if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+ ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceNodeBufferAndReturn",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ } else {
+ ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceNodeBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ }
+
+ encCtx->resultReplaced = 1;
+ } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
+ /* replace the node with the buffer */
+
+ /* check if we need to return the replaced node */
+ if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+ ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceNodeBufferAndReturn",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ } else {
+ ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecReplaceNodeBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+ return(-1);
+ }
+ }
+ encCtx->resultReplaced = 1;
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxDecryptToBuffer:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @node: the pointer to <enc:EncryptedData/> node.
+ *
+ * Decrypts @node data to the @encCtx buffer.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+xmlSecBufferPtr
+xmlSecEncCtxDecryptToBuffer(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, NULL);
+ xmlSecAssert2(encCtx->result == NULL, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ /* initialize context and add ID atributes to the list of known ids */
+ encCtx->operation = xmlSecTransformOperationDecrypt;
+ xmlSecAddIDs(node->doc, node, xmlSecEncIds);
+
+ ret = xmlSecEncCtxEncDataNodeRead(encCtx, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxEncDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* decrypt the data */
+ if(encCtx->cipherValueNode != NULL) {
+ xmlChar* data = NULL;
+ xmlSecSize dataSize = 0;
+
+ data = xmlNodeGetContent(encCtx->cipherValueNode);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(encCtx->cipherValueNode)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ dataSize = xmlStrlen(data);
+
+ ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxBinaryExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ if(data != NULL) {
+ xmlFree(data);
+ }
+ return(NULL);
+ }
+ if(data != NULL) {
+ xmlFree(data);
+ }
+ } else {
+ ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), node->doc);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxBinaryExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ }
+
+ encCtx->result = encCtx->transformCtx.result;
+ xmlSecAssert2(encCtx->result != NULL, NULL);
+
+ return(encCtx->result);
+}
+
+static int
+xmlSecEncCtxEncDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2((encCtx->operation == xmlSecTransformOperationEncrypt) || (encCtx->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ switch(encCtx->mode) {
+ case xmlEncCtxModeEncryptedData:
+ if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedData, xmlSecEncNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptedData));
+ return(-1);
+ }
+ break;
+ case xmlEncCtxModeEncryptedKey:
+ if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedKey, xmlSecEncNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeEncryptedKey));
+ return(-1);
+ }
+ break;
+ }
+
+ /* first read node data */
+ xmlSecAssert2(encCtx->id == NULL, -1);
+ xmlSecAssert2(encCtx->type == NULL, -1);
+ xmlSecAssert2(encCtx->mimeType == NULL, -1);
+ xmlSecAssert2(encCtx->encoding == NULL, -1);
+ xmlSecAssert2(encCtx->recipient == NULL, -1);
+ xmlSecAssert2(encCtx->carriedKeyName == NULL, -1);
+
+ encCtx->id = xmlGetProp(node, xmlSecAttrId);
+ encCtx->type = xmlGetProp(node, xmlSecAttrType);
+ encCtx->mimeType = xmlGetProp(node, xmlSecAttrMimeType);
+ encCtx->encoding = xmlGetProp(node, xmlSecAttrEncoding);
+ if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
+ encCtx->recipient = xmlGetProp(node, xmlSecAttrRecipient);
+ /* todo: check recipient? */
+ }
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* first node is optional EncryptionMethod, we'll read it later */
+ xmlSecAssert2(encCtx->encMethodNode == NULL, -1);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionMethod, xmlSecEncNs))) {
+ encCtx->encMethodNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next node is optional KeyInfo, we'll process it later */
+ xmlSecAssert2(encCtx->keyInfoNode == NULL, -1);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
+ encCtx->keyInfoNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is required CipherData node */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeCipherData, xmlSecEncNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCipherData));
+ return(-1);
+ }
+
+ ret = xmlSecEncCtxCipherDataNodeRead(encCtx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxCipherDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is optional EncryptionProperties node (we simply ignore it) */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionProperties, xmlSecEncNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* there are more possible nodes for the <EncryptedKey> node */
+ if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
+ /* next is optional ReferenceList node (we simply ignore it) */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReferenceList, xmlSecEncNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is optional CarriedKeyName node (we simply ignore it) */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCarriedKeyName, xmlSecEncNs))) {
+ encCtx->carriedKeyName = xmlNodeGetContent(cur);
+ if(encCtx->carriedKeyName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeCipherData));
+ return(-1);
+ }
+ /* TODO: decode the name? */
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+ }
+
+ /* if there is something left than it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* now read the encryption method node */
+ xmlSecAssert2(encCtx->encMethod == NULL, -1);
+ if(encCtx->encMethodNode != NULL) {
+ encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), encCtx->encMethodNode,
+ xmlSecTransformUsageEncryptionMethod);
+ if(encCtx->encMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(encCtx->encMethodNode)));
+ return(-1);
+ }
+ } else if(encCtx->defEncMethodId != xmlSecTransformIdUnknown) {
+ encCtx->encMethod = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx),
+ encCtx->defEncMethodId);
+ if(encCtx->encMethod == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "encryption method not specified");
+ return(-1);
+ }
+ encCtx->encMethod->operation = encCtx->operation;
+
+ /* we have encryption method, find key */
+ ret = xmlSecTransformSetKeyReq(encCtx->encMethod, &(encCtx->keyInfoReadCtx.keyReq));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformSetKeyReq",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
+ return(-1);
+ }
+
+ /* TODO: KeyInfo node != NULL and encKey != NULL */
+ if((encCtx->encKey == NULL) && (encCtx->keyInfoReadCtx.keysMngr != NULL)
+ && (encCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
+ encCtx->encKey = (encCtx->keyInfoReadCtx.keysMngr->getKey)(encCtx->keyInfoNode,
+ &(encCtx->keyInfoReadCtx));
+ }
+
+ /* check that we have exactly what we want */
+ if((encCtx->encKey == NULL) ||
+ (!xmlSecKeyMatch(encCtx->encKey, NULL, &(encCtx->keyInfoReadCtx.keyReq)))) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_KEY_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set the key to the transform */
+ ret = xmlSecTransformSetKey(encCtx->encMethod, encCtx->encKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformSetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
+ return(-1);
+ }
+
+ /* if we need to write result to xml node then we need base64 encode it */
+ if((encCtx->operation == xmlSecTransformOperationEncrypt) && (encCtx->cipherValueNode != NULL)) {
+ xmlSecTransformPtr base64Encode;
+
+ /* we need to add base64 encode transform */
+ base64Encode = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
+ if(base64Encode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ base64Encode->operation = xmlSecTransformOperationEncode;
+ encCtx->resultBase64Encoded = 1;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecEncCtxEncDataNodeWrite(xmlSecEncCtxPtr encCtx) {
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(encCtx->result != NULL, -1);
+ xmlSecAssert2(encCtx->encKey != NULL, -1);
+
+ /* write encrypted data to xml (if requested) */
+ if(encCtx->cipherValueNode != NULL) {
+ xmlSecAssert2(xmlSecBufferGetData(encCtx->result) != NULL, -1);
+
+ xmlNodeSetContentLen(encCtx->cipherValueNode,
+ xmlSecBufferGetData(encCtx->result),
+ xmlSecBufferGetSize(encCtx->result));
+ encCtx->resultReplaced = 1;
+ }
+
+ /* update <enc:KeyInfo/> node */
+ if(encCtx->keyInfoNode != NULL) {
+ ret = xmlSecKeyInfoNodeWrite(encCtx->keyInfoNode, encCtx->encKey, &(encCtx->keyInfoWriteCtx));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyInfoNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecEncCtxCipherDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* we either have CipherValue or CipherReference node */
+ xmlSecAssert2(encCtx->cipherValueNode == NULL, -1);
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherValue, xmlSecEncNs))) {
+ /* don't need data from CipherData node when we are encrypting */
+ if(encCtx->operation == xmlSecTransformOperationDecrypt) {
+ xmlSecTransformPtr base64Decode;
+
+ /* we need to add base64 decode transform */
+ base64Decode = xmlSecTransformCtxCreateAndPrepend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
+ if(base64Decode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxCreateAndPrepend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ encCtx->cipherValueNode = cur;
+ cur = xmlSecGetNextElementNode(cur->next);
+ } else if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherReference, xmlSecEncNs))) {
+ /* don't need data from CipherReference node when we are encrypting */
+ if(encCtx->operation == xmlSecTransformOperationDecrypt) {
+ ret = xmlSecEncCtxCipherReferenceNodeRead(encCtx, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecEncCtxCipherReferenceNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecEncCtxCipherReferenceNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
+ xmlNodePtr cur;
+ xmlChar* uri;
+ int ret;
+
+ xmlSecAssert2(encCtx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* first read the optional uri attr and check that we can process it */
+ uri = xmlGetProp(node, xmlSecAttrURI);
+ ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxSetUri",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ xmlFree(uri);
+ return(-1);
+ }
+ xmlFree(uri);
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* the only one node is optional Transforms node */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecEncNs))) {
+ ret = xmlSecTransformCtxNodesListRead(&(encCtx->transformCtx), cur,
+ xmlSecTransformUsageDSigTransform);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformCtxNodesListRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(encCtx->encMethodNode)));
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* if there is something left than it's an error */
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecEncCtxDebugDump:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the debug information about @encCtx to @output.
+ */
+void
+xmlSecEncCtxDebugDump(xmlSecEncCtxPtr encCtx, FILE* output) {
+ xmlSecAssert(encCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ switch(encCtx->mode) {
+ case xmlEncCtxModeEncryptedData:
+ if(encCtx->operation == xmlSecTransformOperationEncrypt) {
+ fprintf(output, "= DATA ENCRYPTION CONTEXT\n");
+ } else {
+ fprintf(output, "= DATA DECRYPTION CONTEXT\n");
+ }
+ break;
+ case xmlEncCtxModeEncryptedKey:
+ if(encCtx->operation == xmlSecTransformOperationEncrypt) {
+ fprintf(output, "= KEY ENCRYPTION CONTEXT\n");
+ } else {
+ fprintf(output, "= KEY DECRYPTION CONTEXT\n");
+ }
+ break;
+ }
+ fprintf(output, "== Status: %s\n",
+ (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
+
+ fprintf(output, "== flags: 0x%08x\n", encCtx->flags);
+ fprintf(output, "== flags2: 0x%08x\n", encCtx->flags2);
+
+ if(encCtx->id != NULL) {
+ fprintf(output, "== Id: \"%s\"\n", encCtx->id);
+ }
+ if(encCtx->type != NULL) {
+ fprintf(output, "== Type: \"%s\"\n", encCtx->type);
+ }
+ if(encCtx->mimeType != NULL) {
+ fprintf(output, "== MimeType: \"%s\"\n", encCtx->mimeType);
+ }
+ if(encCtx->encoding != NULL) {
+ fprintf(output, "== Encoding: \"%s\"\n", encCtx->encoding);
+ }
+ if(encCtx->recipient != NULL) {
+ fprintf(output, "== Recipient: \"%s\"\n", encCtx->recipient);
+ }
+ if(encCtx->carriedKeyName != NULL) {
+ fprintf(output, "== CarriedKeyName: \"%s\"\n", encCtx->carriedKeyName);
+ }
+
+ fprintf(output, "== Key Info Read Ctx:\n");
+ xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoReadCtx), output);
+
+ fprintf(output, "== Key Info Write Ctx:\n");
+ xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoWriteCtx), output);
+
+ fprintf(output, "== Encryption Transform Ctx:\n");
+ xmlSecTransformCtxDebugDump(&(encCtx->transformCtx), output);
+
+ if(encCtx->encMethod != NULL) {
+ fprintf(output, "== Encryption Method:\n");
+ xmlSecTransformDebugDump(encCtx->encMethod, output);
+ }
+
+ if(encCtx->encKey != NULL) {
+ fprintf(output, "== Encryption Key:\n");
+ xmlSecKeyDebugDump(encCtx->encKey, output);
+ }
+
+ if((encCtx->result != NULL) &&
+ (xmlSecBufferGetData(encCtx->result) != NULL) &&
+ (encCtx->resultBase64Encoded != 0)) {
+
+ fprintf(output, "== Result - start buffer:\n");
+ fwrite(xmlSecBufferGetData(encCtx->result),
+ xmlSecBufferGetSize(encCtx->result), 1,
+ output);
+ fprintf(output, "\n== Result - end buffer\n");
+ }
+}
+
+/**
+ * xmlSecEncCtxDebugXmlDump:
+ * @encCtx: the pointer to <enc:EncryptedData/> processing context.
+ * @output: the pointer to output FILE.
+ *
+ * Prints the debug information about @encCtx to @output in XML format.
+ */
+void
+xmlSecEncCtxDebugXmlDump(xmlSecEncCtxPtr encCtx, FILE* output) {
+ xmlSecAssert(encCtx != NULL);
+ xmlSecAssert(output != NULL);
+
+ switch(encCtx->mode) {
+ case xmlEncCtxModeEncryptedData:
+ if(encCtx->operation == xmlSecTransformOperationEncrypt) {
+ fprintf(output, "<DataEncryptionContext ");
+ } else {
+ fprintf(output, "<DataDecryptionContext ");
+ }
+ break;
+ case xmlEncCtxModeEncryptedKey:
+ if(encCtx->operation == xmlSecTransformOperationEncrypt) {
+ fprintf(output, "<KeyEncryptionContext ");
+ } else {
+ fprintf(output, "<KeyDecryptionContext ");
+ }
+ break;
+ }
+ fprintf(output, "status=\"%s\" >\n", (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
+
+ fprintf(output, "<Flags>%08x</Flags>\n", encCtx->flags);
+ fprintf(output, "<Flags2>%08x</Flags2>\n", encCtx->flags2);
+
+ fprintf(output, "<Id>");
+ xmlSecPrintXmlString(output, encCtx->id);
+ fprintf(output, "</Id>");
+
+ fprintf(output, "<Type>");
+ xmlSecPrintXmlString(output, encCtx->type);
+ fprintf(output, "</Type>");
+
+ fprintf(output, "<MimeType>");
+ xmlSecPrintXmlString(output, encCtx->mimeType);
+ fprintf(output, "</MimeType>");
+
+ fprintf(output, "<Encoding>");
+ xmlSecPrintXmlString(output, encCtx->encoding);
+ fprintf(output, "</Encoding>");
+
+ fprintf(output, "<Recipient>");
+ xmlSecPrintXmlString(output, encCtx->recipient);
+ fprintf(output, "</Recipient>");
+
+ fprintf(output, "<CarriedKeyName>");
+ xmlSecPrintXmlString(output, encCtx->carriedKeyName);
+ fprintf(output, "</CarriedKeyName>");
+
+ fprintf(output, "<KeyInfoReadCtx>\n");
+ xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoReadCtx), output);
+ fprintf(output, "</KeyInfoReadCtx>\n");
+
+ fprintf(output, "<KeyInfoWriteCtx>\n");
+ xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoWriteCtx), output);
+ fprintf(output, "</KeyInfoWriteCtx>\n");
+
+ fprintf(output, "<EncryptionTransformCtx>\n");
+ xmlSecTransformCtxDebugXmlDump(&(encCtx->transformCtx), output);
+ fprintf(output, "</EncryptionTransformCtx>\n");
+
+ if(encCtx->encMethod != NULL) {
+ fprintf(output, "<EncryptionMethod>\n");
+ xmlSecTransformDebugXmlDump(encCtx->encMethod, output);
+ fprintf(output, "</EncryptionMethod>\n");
+ }
+
+ if(encCtx->encKey != NULL) {
+ fprintf(output, "<EncryptionKey>\n");
+ xmlSecKeyDebugXmlDump(encCtx->encKey, output);
+ fprintf(output, "</EncryptionKey>\n");
+ }
+
+ if((encCtx->result != NULL) &&
+ (xmlSecBufferGetData(encCtx->result) != NULL) &&
+ (encCtx->resultBase64Encoded != 0)) {
+
+ fprintf(output, "<Result>");
+ fwrite(xmlSecBufferGetData(encCtx->result),
+ xmlSecBufferGetSize(encCtx->result), 1,
+ output);
+ fprintf(output, "</Result>\n");
+ }
+
+ switch(encCtx->mode) {
+ case xmlEncCtxModeEncryptedData:
+ if(encCtx->operation == xmlSecTransformOperationEncrypt) {
+ fprintf(output, "</DataEncryptionContext>\n");
+ } else {
+ fprintf(output, "</DataDecryptionContext>\n");
+ }
+ break;
+ case xmlEncCtxModeEncryptedKey:
+ if(encCtx->operation == xmlSecTransformOperationEncrypt) {
+ fprintf(output, "</KeyEncryptionContext>\n");
+ } else {
+ fprintf(output, "</KeyDecryptionContext>\n");
+ }
+ break;
+ }
+}
+
+#endif /* XMLSEC_NO_XMLENC */
+
diff --git a/src/xmlsec.c b/src/xmlsec.c
new file mode 100644
index 00000000..3baa81a0
--- /dev/null
+++ b/src/xmlsec.c
@@ -0,0 +1,185 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * General functions.
+ *
+ * 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 <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/app.h>
+#include <xmlsec/io.h>
+#include <xmlsec/xkms.h>
+#include <xmlsec/errors.h>
+
+/**
+ * xmlSecInit:
+ *
+ * Initializes XML Security Library. The depended libraries
+ * (LibXML and LibXSLT) must be initialized before.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecInit(void) {
+ xmlSecErrorsInit();
+ xmlSecIOInit();
+
+#ifndef XMLSEC_NO_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLInit() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#endif /* XMLSEC_NO_CRYPTO_DYNAMIC_LOADING */
+
+ if(xmlSecKeyDataIdsInit() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataIdsInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(xmlSecTransformIdsInit() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecTransformIdsInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_NO_XKMS
+ if(xmlSecXkmsRespondWithIdsInit() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsRespondWithIdsInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(xmlSecXkmsServerRequestIdsInit() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXkmsServerRequestIdsInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#endif /* XMLSEC_NO_XKMS */
+
+ /* we use rand() function to generate id attributes */
+ srand(time(NULL));
+ return(0);
+}
+
+/**
+ * xmlSecShutdown:
+ *
+ * Clean ups the XML Security Library.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecShutdown(void) {
+ int res = 0;
+
+#ifndef XMLSEC_NO_XKMS
+ xmlSecXkmsServerRequestIdsShutdown();
+ xmlSecXkmsRespondWithIdsShutdown();
+#endif /* XMLSEC_NO_XKMS */
+
+ xmlSecTransformIdsShutdown();
+ xmlSecKeyDataIdsShutdown();
+
+#ifndef XMLSEC_NO_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLShutdown() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLShutdown",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ res = -1;
+ }
+#endif /* XMLSEC_NO_CRYPTO_DYNAMIC_LOADING */
+
+ xmlSecIOShutdown();
+ xmlSecErrorsShutdown();
+ return(res);
+}
+
+/**
+ * xmlSecCheckVersionExt:
+ * @major: the major version number.
+ * @minor: the minor version number.
+ * @subminor: the subminor version number.
+ * @mode: the version check mode.
+ *
+ * Checks if the loaded version of xmlsec library could be used.
+ *
+ * Returns: 1 if the loaded xmlsec library version is OK to use
+ * 0 if it is not or a negative value if an error occurs.
+ */
+int
+xmlSecCheckVersionExt(int major, int minor, int subminor, xmlSecCheckVersionMode mode) {
+ /* we always want to have a match for major version number */
+ if(major != XMLSEC_VERSION_MAJOR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected major version=%d;real major version=%d",
+ XMLSEC_VERSION_MAJOR, major);
+ return(0);
+ }
+
+ switch(mode) {
+ case xmlSecCheckVersionExactMatch:
+ if((minor != XMLSEC_VERSION_MINOR) || (subminor != XMLSEC_VERSION_SUBMINOR)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "mode=exact;expected minor version=%d;real minor version=%d;expected subminor version=%d;real subminor version=%d",
+ XMLSEC_VERSION_MINOR, minor,
+ XMLSEC_VERSION_SUBMINOR, subminor);
+ return(0);
+ }
+ break;
+ case xmlSecCheckVersionABICompatible:
+ if((minor < XMLSEC_VERSION_MINOR) ||
+ ((minor == XMLSEC_VERSION_MINOR) &&
+ (subminor < XMLSEC_VERSION_SUBMINOR))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "mode=abi compatible;expected minor version=%d;real minor version=%d;expected subminor version=%d;real subminor version=%d",
+ XMLSEC_VERSION_MINOR, minor,
+ XMLSEC_VERSION_SUBMINOR, subminor);
+ return(0);
+ }
+ break;
+ }
+
+ return(1);
+}
+
+
diff --git a/src/xmltree.c b/src/xmltree.c
new file mode 100644
index 00000000..96ea53c1
--- /dev/null
+++ b/src/xmltree.c
@@ -0,0 +1,1908 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Common XML Doc utility functions
+ *
+ * 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 <ctype.h>
+#include <errno.h>
+
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/parser.h>
+#include <xmlsec/private.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+/**
+ * xmlSecFindChild:
+ * @parent: the pointer to XML node.
+ * @name: the name.
+ * @ns: the namespace href (may be NULL).
+ *
+ * Searches a direct child of the @parent node having given name and
+ * namespace href.
+ *
+ * Returns: the pointer to the found node or NULL if an error occurs or
+ * node is not found.
+ */
+xmlNodePtr
+xmlSecFindChild(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr cur;
+
+ xmlSecAssert2(parent != NULL, NULL);
+ xmlSecAssert2(name != NULL, NULL);
+
+ cur = parent->children;
+ while(cur != NULL) {
+ if(cur->type == XML_ELEMENT_NODE) {
+ if(xmlSecCheckNodeName(cur, name, ns)) {
+ return(cur);
+ }
+ }
+ cur = cur->next;
+ }
+ return(NULL);
+}
+
+/**
+ * xmlSecFindParent:
+ * @cur: the pointer to an XML node.
+ * @name: the name.
+ * @ns: the namespace href (may be NULL).
+ *
+ * Searches the ancestors axis of the @cur node for a node having given name
+ * and namespace href.
+ *
+ * Returns: the pointer to the found node or NULL if an error occurs or
+ * node is not found.
+ */
+xmlNodePtr
+xmlSecFindParent(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
+ xmlSecAssert2(cur != NULL, NULL);
+ xmlSecAssert2(name != NULL, NULL);
+
+ if(xmlSecCheckNodeName(cur, name, ns)) {
+ return(cur);
+ } else if(cur->parent != NULL) {
+ return(xmlSecFindParent(cur->parent, name, ns));
+ }
+ return(NULL);
+}
+
+/**
+ * xmlSecFindNode:
+ * @parent: the pointer to XML node.
+ * @name: the name.
+ * @ns: the namespace href (may be NULL).
+ *
+ * Searches all children of the @parent node having given name and
+ * namespace href.
+ *
+ * Returns: the pointer to the found node or NULL if an error occurs or
+ * node is not found.
+ */
+xmlNodePtr
+xmlSecFindNode(const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr cur;
+ xmlNodePtr ret;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ cur = parent;
+ while(cur != NULL) {
+ if((cur->type == XML_ELEMENT_NODE) && xmlSecCheckNodeName(cur, name, ns)) {
+ return(cur);
+ }
+ if(cur->children != NULL) {
+ ret = xmlSecFindNode(cur->children, name, ns);
+ if(ret != NULL) {
+ return(ret);
+ }
+ }
+ cur = cur->next;
+ }
+ return(NULL);
+}
+
+/**
+ * xmlSecGetNodeNsHref:
+ * @cur: the pointer to node.
+ *
+ * Get's node's namespace href.
+ *
+ * Returns: node's namespace href.
+ */
+const xmlChar*
+xmlSecGetNodeNsHref(const xmlNodePtr cur) {
+ xmlNsPtr ns;
+
+ xmlSecAssert2(cur != NULL, NULL);
+
+ /* do we have a namespace in the node? */
+ if(cur->ns != NULL) {
+ return(cur->ns->href);
+ }
+
+ /* search for default namespace */
+ ns = xmlSearchNs(cur->doc, cur, NULL);
+ if(ns != NULL) {
+ return(ns->href);
+ }
+
+ return(NULL);
+}
+
+/**
+ * xmlSecCheckNodeName:
+ * @cur: the pointer to an XML node.
+ * @name: the name,
+ * @ns: the namespace href.
+ *
+ * Checks that the node has a given name and a given namespace href.
+ *
+ * Returns: 1 if the node matches or 0 otherwise.
+ */
+int
+xmlSecCheckNodeName(const xmlNodePtr cur, const xmlChar *name, const xmlChar *ns) {
+ xmlSecAssert2(cur != NULL, 0);
+
+ return(xmlStrEqual(cur->name, name) &&
+ xmlStrEqual(xmlSecGetNodeNsHref(cur), ns));
+}
+
+/**
+ * xmlSecAddChild:
+ * @parent: the pointer to an XML node.
+ * @name: the new node name.
+ * @ns: the new node namespace.
+ *
+ * Adds a child to the node @parent with given @name and namespace @ns.
+ *
+ * Returns: pointer to the new node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecAddChild(xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr cur;
+ xmlNodePtr text;
+
+ xmlSecAssert2(parent != NULL, NULL);
+ xmlSecAssert2(name != NULL, NULL);
+
+ if(parent->children == NULL) {
+ /* TODO: add indents */
+ text = xmlNewText(xmlSecStringCR);
+ if(text == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewText",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddChild(parent, text);
+ }
+
+ cur = xmlNewChild(parent, NULL, name, NULL);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewChild",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* namespaces support */
+ if(ns != NULL) {
+ xmlNsPtr nsPtr;
+
+ /* find namespace by href and check that its prefix is not overwritten */
+ nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
+ if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) {
+ nsPtr = xmlNewNs(cur, ns, NULL);
+ }
+ xmlSetNs(cur, nsPtr);
+ }
+
+ /* TODO: add indents */
+ text = xmlNewText(xmlSecStringCR);
+ if(text == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewText",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddChild(parent, text);
+
+ return(cur);
+}
+
+/**
+ * xmlSecAddChildNode:
+ * @parent: the pointer to an XML node.
+ * @child: the new node.
+ *
+ * Adds @child node to the @parent node.
+ *
+ * Returns: pointer to the new node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecAddChildNode(xmlNodePtr parent, xmlNodePtr child) {
+ xmlNodePtr text;
+
+ xmlSecAssert2(parent != NULL, NULL);
+ xmlSecAssert2(child != NULL, NULL);
+
+ if(parent->children == NULL) {
+ /* TODO: add indents */
+ text = xmlNewText(xmlSecStringCR);
+ if(text == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewText",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddChild(parent, text);
+ }
+
+ xmlAddChild(parent, child);
+
+ /* TODO: add indents */
+ text = xmlNewText(xmlSecStringCR);
+ if(text == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewText",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddChild(parent, text);
+
+ return(child);
+}
+
+/**
+ * xmlSecAddNextSibling
+ * @node: the pointer to an XML node.
+ * @name: the new node name.
+ * @ns: the new node namespace.
+ *
+ * Adds next sibling to the node @node with given @name and namespace @ns.
+ *
+ * Returns: pointer to the new node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecAddNextSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr cur;
+ xmlNodePtr text;
+
+ xmlSecAssert2(node != NULL, NULL);
+ xmlSecAssert2(name != NULL, NULL);
+
+ cur = xmlNewNode(NULL, name);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddNextSibling(node, cur);
+
+ /* namespaces support */
+ if(ns != NULL) {
+ xmlNsPtr nsPtr;
+
+ /* find namespace by href and check that its prefix is not overwritten */
+ nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
+ if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) {
+ nsPtr = xmlNewNs(cur, ns, NULL);
+ }
+ xmlSetNs(cur, nsPtr);
+ }
+
+ /* TODO: add indents */
+ text = xmlNewText(xmlSecStringCR);
+ if(text == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewText",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddNextSibling(node, text);
+
+ return(cur);
+}
+
+/**
+ * xmlSecAddPrevSibling
+ * @node: the pointer to an XML node.
+ * @name: the new node name.
+ * @ns: the new node namespace.
+ *
+ * Adds prev sibling to the node @node with given @name and namespace @ns.
+ *
+ * Returns: pointer to the new node or NULL if an error occurs.
+ */
+xmlNodePtr
+xmlSecAddPrevSibling(xmlNodePtr node, const xmlChar *name, const xmlChar *ns) {
+ xmlNodePtr cur;
+ xmlNodePtr text;
+
+ xmlSecAssert2(node != NULL, NULL);
+ xmlSecAssert2(name != NULL, NULL);
+
+ cur = xmlNewNode(NULL, name);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddPrevSibling(node, cur);
+
+ /* namespaces support */
+ if(ns != NULL) {
+ xmlNsPtr nsPtr;
+
+ /* find namespace by href and check that its prefix is not overwritten */
+ nsPtr = xmlSearchNsByHref(cur->doc, cur, ns);
+ if((nsPtr == NULL) || (xmlSearchNs(cur->doc, cur, nsPtr->prefix) != nsPtr)) {
+ nsPtr = xmlNewNs(cur, ns, NULL);
+ }
+ xmlSetNs(cur, nsPtr);
+ }
+
+ /* TODO: add indents */
+ text = xmlNewText(xmlSecStringCR);
+ if(text == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewText",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlAddPrevSibling(node, text);
+
+ return(cur);
+}
+
+/**
+ * xmlSecGetNextElementNode:
+ * @cur: the pointer to an XML node.
+ *
+ * Seraches for the next element node.
+ *
+ * Returns: the pointer to next element node or NULL if it is not found.
+ */
+xmlNodePtr
+xmlSecGetNextElementNode(xmlNodePtr cur) {
+
+ while((cur != NULL) && (cur->type != XML_ELEMENT_NODE)) {
+ cur = cur->next;
+ }
+ return(cur);
+}
+
+/**
+ * xmlSecReplaceNode:
+ * @node: the current node.
+ * @newNode: the new node.
+ *
+ * Swaps the @node and @newNode in the XML tree.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode) {
+ return xmlSecReplaceNodeAndReturn(node, newNode, NULL);
+}
+
+/**
+ * xmlSecReplaceNodeAndReturn:
+ * @node: the current node.
+ * @newNode: the new node.
+ * @replaced: the replaced node, or release it if NULL is given
+ *
+ * Swaps the @node and @newNode in the XML tree.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceNodeAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr* replaced) {
+ xmlNodePtr oldNode;
+ int restoreRoot = 0;
+
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(newNode != NULL, -1);
+
+ /* fix documents children if necessary first */
+ if((node->doc != NULL) && (node->doc->children == node)) {
+ node->doc->children = node->next;
+ restoreRoot = 1;
+ }
+ if((newNode->doc != NULL) && (newNode->doc->children == newNode)) {
+ newNode->doc->children = newNode->next;
+ }
+
+ oldNode = xmlReplaceNode(node, newNode);
+ if(oldNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlReplaceNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(restoreRoot != 0) {
+ xmlDocSetRootElement(oldNode->doc, newNode);
+ }
+
+ /* return the old node if requested */
+ if(replaced != NULL) {
+ (*replaced) = oldNode;
+ } else {
+ xmlFreeNode(oldNode);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecReplaceContent
+ * @node: the current node.
+ * @newNode: the new node.
+ *
+ * Swaps the content of @node and @newNode.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode) {
+ return xmlSecReplaceContentAndReturn(node, newNode, NULL);
+}
+
+/**
+ * xmlSecReplaceContentAndReturn
+ * @node: the current node.
+ * @newNode: the new node.
+ * @replaced: the replaced nodes, or release them if NULL is given
+ *
+ * Swaps the content of @node and @newNode.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceContentAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr *replaced) {
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(newNode != NULL, -1);
+
+ xmlUnlinkNode(newNode);
+ xmlSetTreeDoc(newNode, node->doc);
+
+ /* return the old nodes if requested */
+ if(replaced != NULL) {
+ xmlNodePtr cur, next, tail;
+
+ (*replaced) = tail = NULL;
+ for(cur = node->children; (cur != NULL); cur = next) {
+ next = cur->next;
+ if((*replaced) != NULL) {
+ /* n is unlinked in this function */
+ xmlAddNextSibling(tail, cur);
+ tail = cur;
+ } else {
+ /* this is the first node, (*replaced) is the head */
+ xmlUnlinkNode(cur);
+ (*replaced) = tail = cur;
+ }
+ }
+ } else {
+ /* just delete the content */
+ xmlNodeSetContent(node, NULL);
+ }
+
+ xmlAddChild(node, newNode);
+ xmlSetTreeDoc(newNode, node->doc);
+
+ return(0);
+}
+
+/**
+ * xmlSecReplaceNodeBuffer:
+ * @node: the current node.
+ * @buffer: the XML data.
+ * @size: the XML data size.
+ *
+ * Swaps the @node and the parsed XML data from the @buffer in the XML tree.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceNodeBuffer(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size) {
+ return xmlSecReplaceNodeBufferAndReturn(node, buffer, size, NULL);
+}
+
+/**
+ * xmlSecReplaceNodeBufferAndReturn:
+ * @node: the current node.
+ * @buffer: the XML data.
+ * @size: the XML data size.
+ * @replaced: the replaced nodes, or release them if NULL is given
+ *
+ * Swaps the @node and the parsed XML data from the @buffer in the XML tree.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceNodeBufferAndReturn(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size, xmlNodePtr *replaced) {
+ xmlNodePtr results = NULL;
+ xmlNodePtr next = NULL;
+
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->parent != NULL, -1);
+
+ /* parse buffer in the context of node's parent */
+ if(xmlParseInNodeContext(node->parent, (const char*)buffer, size, XML_PARSE_NODICT, &results) != XML_ERR_OK) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlParseInNodeContext",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "Failed to parse content");
+ return(-1);
+ }
+
+ /* add new nodes */
+ while (results != NULL) {
+ next = results->next;
+ xmlAddPrevSibling(node, results);
+ results = next;
+ }
+
+ /* remove old node */
+ xmlUnlinkNode(node);
+
+ /* return the old node if requested */
+ if(replaced != NULL) {
+ (*replaced) = node;
+ } else {
+ xmlFreeNode(node);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNodeEncodeAndSetContent:
+ * @node: the pointer to an XML node.
+ * @buffer: the pointer to the node content.
+ *
+ * Encodes "special" characters in the @buffer and sets the result
+ * as the node content.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNodeEncodeAndSetContent(xmlNodePtr node, const xmlChar * buffer) {
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(node->doc != NULL, -1);
+
+ if(buffer != NULL) {
+ xmlChar * tmp;
+
+ tmp = xmlEncodeSpecialChars(node->doc, buffer);
+ if (tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlEncodeSpecialChars",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "Failed to encode special characters");
+ return(-1);
+ }
+
+ xmlNodeSetContent(node, tmp);
+ xmlFree(tmp);
+ } else {
+ xmlNodeSetContent(node, NULL);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecAddIDs:
+ * @doc: the pointer to an XML document.
+ * @cur: the pointer to an XML node.
+ * @ids: the pointer to a NULL terminated list of ID attributes.
+ *
+ * Walks thru all children of the @cur node and adds all attributes
+ * from the @ids list to the @doc document IDs attributes hash.
+ */
+void
+xmlSecAddIDs(xmlDocPtr doc, xmlNodePtr cur, const xmlChar** ids) {
+ xmlNodePtr children = NULL;
+
+ xmlSecAssert(doc != NULL);
+ xmlSecAssert(ids != NULL);
+
+ if((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
+ xmlAttrPtr attr;
+ xmlAttrPtr tmp;
+ int i;
+ xmlChar* name;
+
+ for(attr = cur->properties; attr != NULL; attr = attr->next) {
+ for(i = 0; ids[i] != NULL; ++i) {
+ if(xmlStrEqual(attr->name, ids[i])) {
+ name = xmlNodeListGetString(doc, attr->children, 1);
+ if(name != NULL) {
+ tmp = xmlGetID(doc, name);
+ if(tmp == NULL) {
+ xmlAddID(NULL, doc, name, attr);
+ } else if(tmp != attr) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "id=%s already defined",
+ xmlSecErrorsSafeString(name));
+ }
+ xmlFree(name);
+ }
+ }
+ }
+ }
+
+ children = cur->children;
+ } else if(cur == NULL) {
+ children = doc->children;
+ }
+
+ while(children != NULL) {
+ if(children->type == XML_ELEMENT_NODE) {
+ xmlSecAddIDs(doc, children, ids);
+ }
+ children = children->next;
+ }
+}
+
+/**
+ * xmlSecGenerateAndAddID:
+ * @node: the node to ID attr to.
+ * @attrName: the ID attr name.
+ * @prefix: the prefix to add to the generated ID (can be NULL).
+ * @len: the length of ID.
+ *
+ * Generates a unique ID in the format <@prefix>base64-encoded(@len random bytes)
+ * and puts it in the attribute @attrName.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGenerateAndAddID(xmlNodePtr node, const xmlChar* attrName, const xmlChar* prefix, xmlSecSize len) {
+ xmlChar* id;
+ int count;
+
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(attrName != NULL, -1);
+
+ /* we will try 5 times before giving up */
+ for(count = 0; count < 5; count++) {
+ id = xmlSecGenerateID(prefix, len);
+ if(id == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGenerateID",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((node->doc == NULL) || (xmlGetID(node->doc, id) == NULL)) {
+ /* this is a unique ID in the document and we can use it */
+ if(xmlSetProp(node, attrName, id) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(id);
+ return(-1);
+ }
+
+ xmlFree(id);
+ return(0);
+ }
+ xmlFree(id);
+ }
+
+ return(-1);
+}
+
+/**
+ * xmlSecGenerateID:
+ * @prefix: the prefix to add to the generated ID (can be NULL).
+ * @len: the length of ID.
+ *
+ * Generates a unique ID in the format <@prefix>base64-encoded(@len random bytes).
+ * The caller is responsible for freeing returned string using @xmlFree function.
+ *
+ * Returns: pointer to generated ID string or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecGenerateID(const xmlChar* prefix, xmlSecSize len) {
+ xmlSecBuffer buffer;
+ xmlSecSize i, binLen;
+ xmlChar* res;
+ xmlChar* p;
+ int ret;
+
+ xmlSecAssert2(len > 0, NULL);
+
+ /* we will do base64 decoding later */
+ binLen = (3 * len + 1) / 4;
+
+ ret = xmlSecBufferInitialize(&buffer, binLen + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ xmlSecAssert2(xmlSecBufferGetData(&buffer) != NULL, NULL);
+ xmlSecAssert2(xmlSecBufferGetMaxSize(&buffer) >= binLen, NULL);
+
+ ret = xmlSecBufferSetSize(&buffer, binLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+ xmlSecAssert2(xmlSecBufferGetSize(&buffer) == binLen, NULL);
+
+ /* create random bytes */
+ for(i = 0; i < binLen; i++) {
+ (xmlSecBufferGetData(&buffer)) [i] = (xmlSecByte) (256.0 * rand() / (RAND_MAX + 1.0));
+ }
+
+ /* base64 encode random bytes */
+ res = xmlSecBase64Encode(xmlSecBufferGetData(&buffer), xmlSecBufferGetSize(&buffer), 0);
+ if((res == NULL) || (xmlStrlen(res) == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+ xmlSecBufferFinalize(&buffer);
+
+ /* truncate the generated id attribute if needed */
+ if(xmlStrlen(res) > (int)len) {
+ res[len] = '\0';
+ }
+
+ /* we need to cleanup base64 encoded id because ID attr can't have '+' or '/' characters */
+ for(p = res; (*p) != '\0'; p++) {
+ if(((*p) == '+') || ((*p) == '/')) {
+ (*p) = '_';
+ }
+ }
+
+ /* add prefix if exist */
+ if(prefix) {
+ xmlChar* tmp;
+ xmlSecSize tmpLen;
+
+ tmpLen = xmlStrlen(prefix) + xmlStrlen(res) + 1;
+ tmp = xmlMalloc(tmpLen + 1);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(res);
+ return(NULL);
+ }
+
+ xmlSecStrPrintf(tmp, tmpLen, BAD_CAST "%s%s", prefix, res);
+ xmlFree(res);
+ res = tmp;
+ } else {
+ /* no prefix: check that ID attribute starts from a letter */
+ if(!(((res[0] >= 'A') && (res[0] <= 'Z')) ||
+ ((res[0] >= 'a') && (res[0] <= 'z')))) {
+ res[0] = 'A';
+ }
+ }
+
+ return(res);
+}
+
+
+/**
+ * xmlSecCreateTree:
+ * @rootNodeName: the root node name.
+ * @rootNodeNs: the root node namespace (otpional).
+ *
+ * Creates a new XML tree with one root node @rootNodeName.
+ *
+ * Returns: pointer to the newly created tree or NULL if an error occurs.
+ */
+xmlDocPtr
+xmlSecCreateTree(const xmlChar* rootNodeName, const xmlChar* rootNodeNs) {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNsPtr ns;
+
+ xmlSecAssert2(rootNodeName != NULL, NULL);
+
+ /* create doc */
+ doc = xmlNewDoc(BAD_CAST "1.0");
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDoc",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* create root node */
+ root = xmlNewDocNode(doc, NULL, rootNodeName, NULL);
+ if(root == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewDocNode",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=Keys");
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+ xmlDocSetRootElement(doc, root);
+
+ /* and set root node namespace */
+ ns = xmlNewNs(root, rootNodeNs, NULL);
+ if(ns == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNewNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "ns=%s",
+ xmlSecErrorsSafeString(rootNodeNs));
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+ xmlSetNs(root, ns);
+
+ return(doc);
+}
+
+/**
+ * xmlSecIsEmptyNode:
+ * @node: the node to check
+ *
+ * Checks whethere the @node is empty (i.e. has only whitespaces children).
+ *
+ * Returns: 1 if @node is empty, 0 otherwise or a negative value if an error occurs.
+ */
+int
+xmlSecIsEmptyNode(xmlNodePtr node) {
+ xmlChar* content;
+ int res;
+
+ xmlSecAssert2(node != NULL, -1);
+
+ if(xmlSecGetNextElementNode(node->children) != NULL) {
+ return(0);
+ }
+
+ content = xmlNodeGetContent(node);
+ if(content == NULL) {
+ return(1);
+ }
+
+ res = xmlSecIsEmptyString(content);
+ xmlFree(content);
+ return(res);
+}
+
+/**
+ * xmlSecIsEmptyString:
+ * @str: the string to check
+ *
+ * Checks whethere the @str is empty (i.e. has only whitespaces children).
+ *
+ * Returns: 1 if @str is empty, 0 otherwise or a negative value if an error occurs.
+ */
+int
+xmlSecIsEmptyString(const xmlChar* str) {
+ xmlSecAssert2(str != NULL, -1);
+
+ for( ;*str != '\0'; ++str) {
+ if(!isspace((int)(*str))) {
+ return(0);
+ }
+ }
+ return(1);
+}
+
+/**
+ * xmlSecPrintXmlString:
+ * @fd: the file descriptor to write the XML string to
+ * @str: the string
+ *
+ * Encodes the @str (e.g. replaces '&' with '&amp;') and writes it to @fd.
+ *
+ * Returns: he number of bytes transmitted or a negative value if an error occurs.
+ */
+int
+xmlSecPrintXmlString(FILE * fd, const xmlChar * str) {
+ int res;
+
+ if(str != NULL) {
+ xmlChar * encoded_str = NULL;
+ encoded_str = xmlEncodeSpecialChars(NULL, str);
+ if(encoded_str == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlEncodeSpecialChars",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "string=%s",
+ xmlSecErrorsSafeString(str));
+ return(-1);
+ }
+
+ res = fprintf(fd, "%s", (const char*)encoded_str);
+ xmlFree(encoded_str);
+ } else {
+ res = fprintf(fd, "NULL");
+ }
+
+ if(res < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "fprintf",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "res=%d,errno=%d",
+ res, errno);
+ return(-1);
+ }
+ return(res);
+}
+
+
+/**
+ * xmlSecGetQName:
+ * @node: the context node.
+ * @href: the QName href (can be NULL).
+ * @local: the QName local part.
+ *
+ * Creates QName (prefix:local) from @href and @local in the context of the @node.
+ * Caller is responsible for freeing returned string with xmlFree.
+ *
+ * Returns: qname or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecGetQName(xmlNodePtr node, const xmlChar* href, const xmlChar* local) {
+ xmlChar* qname;
+ xmlNsPtr ns;
+
+ xmlSecAssert2(node != NULL, NULL);
+ xmlSecAssert2(local != NULL, NULL);
+
+ /* we don't want to create namespace node ourselves because
+ * it might cause collisions */
+ ns = xmlSearchNsByHref(node->doc, node, href);
+ if((ns == NULL) && (href != NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSearchNsByHref",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s,href=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(href));
+ return(NULL);
+ }
+
+ if((ns != NULL) && (ns->prefix != NULL)) {
+ xmlSecSize len;
+
+ len = xmlStrlen(local) + xmlStrlen(ns->prefix) + 4;
+ qname = xmlMalloc(len);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ return(NULL);
+ }
+ xmlSecStrPrintf(qname, len, BAD_CAST "%s:%s", ns->prefix, local);
+ } else {
+ qname = xmlStrdup(local);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ return(NULL);
+ }
+ }
+
+
+ return(qname);
+}
+
+
+/*************************************************************************
+ *
+ * QName <-> Integer mapping
+ *
+ ************************************************************************/
+/**
+ * xmlSecQName2IntegerGetInfo:
+ * @info: the qname<->integer mapping information.
+ * @intValue: the integer value.
+ *
+ * Maps integer @intValue to a QName prefix.
+ *
+ * Returns: the QName info that is mapped to @intValue or NULL if such value
+ * is not found.
+ */
+xmlSecQName2IntegerInfoConstPtr
+xmlSecQName2IntegerGetInfo(xmlSecQName2IntegerInfoConstPtr info, int intValue) {
+ unsigned int ii;
+
+ xmlSecAssert2(info != NULL, NULL);
+
+ for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
+ if(info[ii].intValue == intValue) {
+ return(&info[ii]);
+ }
+ }
+
+ return(NULL);
+}
+
+/**
+ * xmlSecQName2IntegerGetInteger:
+ * @info: the qname<->integer mapping information.
+ * @qnameHref: the qname href value.
+ * @qnameLocalPart: the qname local part value.
+ * @intValue: the pointer to result integer value.
+ *
+ * Maps qname qname to an integer and returns it in @intValue.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2IntegerGetInteger(xmlSecQName2IntegerInfoConstPtr info,
+ const xmlChar* qnameHref, const xmlChar* qnameLocalPart,
+ int* intValue) {
+ unsigned int ii;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(qnameLocalPart != NULL, -1);
+ xmlSecAssert2(intValue != NULL, -1);
+
+ for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
+ if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) &&
+ xmlStrEqual(info[ii].qnameHref, qnameHref)) {
+ (*intValue) = info[ii].intValue;
+ return(0);
+ }
+ }
+
+ return(-1);
+}
+
+/**
+ * xmlSecQName2IntegerGetIntegerFromString:
+ * @info: the qname<->integer mapping information.
+ * @node: the pointer to node.
+ * @qname: the qname string.
+ * @intValue: the pointer to result integer value.
+ *
+ * Converts @qname into integer in context of @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2IntegerGetIntegerFromString(xmlSecQName2IntegerInfoConstPtr info,
+ xmlNodePtr node, const xmlChar* qname,
+ int* intValue) {
+ const xmlChar* qnameLocalPart = NULL;
+ xmlChar* qnamePrefix = NULL;
+ const xmlChar* qnameHref;
+ xmlNsPtr ns;
+ int ret;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(qname != NULL, -1);
+ xmlSecAssert2(intValue != NULL, -1);
+
+ qnameLocalPart = xmlStrchr(qname, ':');
+ if(qnameLocalPart != NULL) {
+ qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
+ if(qnamePrefix == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrndup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "node=%s,value=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qname));
+ return(-1);
+ }
+ qnameLocalPart++;
+ } else {
+ qnamePrefix = NULL;
+ qnameLocalPart = qname;
+ }
+
+ /* search namespace href */
+ ns = xmlSearchNs(node->doc, node, qnamePrefix);
+ if((ns == NULL) && (qnamePrefix != NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSearchNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s,qnamePrefix=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnamePrefix));
+ if(qnamePrefix != NULL) {
+ xmlFree(qnamePrefix);
+ }
+ return(-1);
+ }
+ qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
+
+ /* and finally search for integer */
+ ret = xmlSecQName2IntegerGetInteger(info, qnameHref, qnameLocalPart, intValue);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetInteger",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,qnameLocalPart=%s,qnameHref=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnameLocalPart),
+ xmlSecErrorsSafeString(qnameHref));
+ if(qnamePrefix != NULL) {
+ xmlFree(qnamePrefix);
+ }
+ return(-1);
+ }
+
+ if(qnamePrefix != NULL) {
+ xmlFree(qnamePrefix);
+ }
+ return(0);
+}
+
+
+/**
+ * xmlSecQName2IntegerGetStringFromInteger:
+ * @info: the qname<->integer mapping information.
+ * @node: the pointer to node.
+ * @intValue: the integer value.
+ *
+ * Creates qname string for @intValue in context of given @node. Caller
+ * is responsible for freeing returned string with @xmlFree.
+ *
+ * Returns: pointer to newly allocated string on success or NULL if an error occurs,
+ */
+xmlChar*
+xmlSecQName2IntegerGetStringFromInteger(xmlSecQName2IntegerInfoConstPtr info,
+ xmlNodePtr node, int intValue) {
+ xmlSecQName2IntegerInfoConstPtr qnameInfo;
+
+ xmlSecAssert2(info != NULL, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
+ if(qnameInfo == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetInfo",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,intValue=%d",
+ xmlSecErrorsSafeString(node->name),
+ intValue);
+ return(NULL);
+ }
+
+ return (xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart));
+}
+
+/**
+ * xmlSecQName2IntegerNodeRead:
+ * @info: the qname<->integer mapping information.
+ * @node: the pointer to node.
+ * @intValue: the pointer to result integer value.
+ *
+ * Reads the content of @node and converts it to an integer using mapping
+ * from @info.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2IntegerNodeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node, int* intValue) {
+ xmlChar* content = NULL;
+ int ret;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(intValue != NULL, -1);
+
+ content = xmlNodeGetContent(node);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNodeGetContent",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(node->name));
+ return(-1);
+ }
+ /* todo: trim content? */
+
+ ret = xmlSecQName2IntegerGetIntegerFromString(info, node, content, intValue);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetIntegerFromString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,value=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(content));
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+/**
+ * xmlSecQName2IntegerNodeWrite:
+ * @info: the qname<->integer mapping information.
+ * @node: the parent node.
+ * @nodeName: the child node name.
+ * @nodeNs: the child node namespace.
+ * @intValue: the integer value.
+ *
+ * Creates new child node in @node and sets its value to @intValue.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2IntegerNodeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
+ const xmlChar* nodeName, const xmlChar* nodeNs, int intValue) {
+ xmlNodePtr cur;
+ xmlChar* qname = NULL;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(nodeName != NULL, -1);
+
+ /* find and build qname */
+ qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetStringFromInteger",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,intValue=%d",
+ xmlSecErrorsSafeString(node->name),
+ intValue);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, nodeName, nodeNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,intValue=%d",
+ xmlSecErrorsSafeString(nodeName),
+ intValue);
+ xmlFree(qname);
+ return(-1);
+ }
+
+ xmlNodeSetContent(cur, qname);
+ xmlFree(qname);
+ return(0);
+}
+
+/**
+ * xmlSecQName2IntegerAttributeRead:
+ * @info: the qname<->integer mapping information.
+ * @node: the element node.
+ * @attrName: the attribute name.
+ * @intValue: the pointer to result integer value.
+ *
+ * Gets the value of @attrName atrtibute from @node and converts it to integer
+ * according to @info.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2IntegerAttributeRead(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
+ const xmlChar* attrName, int* intValue) {
+ xmlChar* attrValue;
+ int ret;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(attrName != NULL, -1);
+ xmlSecAssert2(intValue != NULL, -1);
+
+ attrValue = xmlGetProp(node, attrName);
+ if(attrValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlGetProp",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s,attrValue=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(attrName));
+ return(-1);
+ }
+ /* todo: trim value? */
+
+ ret = xmlSecQName2IntegerGetIntegerFromString(info, node, attrValue, intValue);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetIntegerFromString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,attrName=%s,attrValue=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(attrName),
+ xmlSecErrorsSafeString(attrValue));
+ xmlFree(attrValue);
+ return(-1);
+ }
+
+ xmlFree(attrValue);
+ return(0);
+}
+
+/**
+ * xmlSecQName2IntegerAttributeWrite:
+ * @info: the qname<->integer mapping information.
+ * @node: the parent node.
+ * @attrName: the name of attribute.
+ * @intValue: the integer value.
+ *
+ * Converts @intValue to a qname and sets it to the value of
+ * attribute @attrName in @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2IntegerAttributeWrite(xmlSecQName2IntegerInfoConstPtr info, xmlNodePtr node,
+ const xmlChar* attrName, int intValue) {
+ xmlChar* qname;
+ xmlAttrPtr attr;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(attrName != NULL, -1);
+
+ /* find and build qname */
+ qname = xmlSecQName2IntegerGetStringFromInteger(info, node, intValue);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2IntegerGetStringFromInteger",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,attrName=%s,intValue=%d",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(attrName),
+ intValue);
+ return(-1);
+ }
+
+ attr = xmlSetProp(node, attrName, qname);
+ if(attr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChildNode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,attrName=%s,intValue=%d",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(attrName),
+ intValue);
+ xmlFree(qname);
+ return(-1);
+ }
+
+ xmlFree(qname);
+ return(0);
+}
+
+/**
+ * xmlSecQName2IntegerDebugDump:
+ * @info: the qname<->integer mapping information.
+ * @intValue: the integer value.
+ * @name: the value name to print.
+ * @output: the pointer to output FILE.
+ *
+ * Prints @intValue into @output.
+ */
+void
+xmlSecQName2IntegerDebugDump(xmlSecQName2IntegerInfoConstPtr info, int intValue,
+ const xmlChar* name, FILE* output) {
+ xmlSecQName2IntegerInfoConstPtr qnameInfo;
+
+ xmlSecAssert(info != NULL);
+ xmlSecAssert(name != NULL);
+ xmlSecAssert(output != NULL);
+
+ qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
+ if(qnameInfo != NULL) {
+ fprintf(output, "== %s: %d (name=\"%s\", href=\"%s\")\n", name, intValue,
+ (qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL,
+ (qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL);
+ }
+}
+
+/**
+ * xmlSecQName2IntegerDebugXmlDump:
+ * @info: the qname<->integer mapping information.
+ * @intValue: the integer value.
+ * @name: the value name to print.
+ * @output: the pointer to output FILE.
+ *
+ * Prints @intValue into @output in XML format.
+ */
+void
+xmlSecQName2IntegerDebugXmlDump(xmlSecQName2IntegerInfoConstPtr info, int intValue,
+ const xmlChar* name, FILE* output) {
+ xmlSecQName2IntegerInfoConstPtr qnameInfo;
+
+ xmlSecAssert(info != NULL);
+ xmlSecAssert(name != NULL);
+ xmlSecAssert(output != NULL);
+
+ qnameInfo = xmlSecQName2IntegerGetInfo(info, intValue);
+ if(qnameInfo != NULL) {
+ fprintf(output, "<%s value=\"%d\" href=\"%s\">%s<%s>\n", name, intValue,
+ (qnameInfo->qnameHref) ? qnameInfo->qnameHref : BAD_CAST NULL,
+ (qnameInfo->qnameLocalPart) ? qnameInfo->qnameLocalPart : BAD_CAST NULL,
+ name);
+ }
+}
+
+
+/*************************************************************************
+ *
+ * QName <-> Bits mask mapping
+ *
+ ************************************************************************/
+/**
+ * xmlSecQName2BitMaskGetInfo:
+ * @info: the qname<->bit mask mapping information.
+ * @mask: the bit mask.
+ *
+ * Converts @mask to qname.
+ *
+ * Returns: pointer to the qname info for @mask or NULL if mask is unknown.
+ */
+xmlSecQName2BitMaskInfoConstPtr
+xmlSecQName2BitMaskGetInfo(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask) {
+ unsigned int ii;
+
+ xmlSecAssert2(info != NULL, NULL);
+
+ for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
+ xmlSecAssert2(info[ii].mask != 0, NULL);
+ if(info[ii].mask == mask) {
+ return(&info[ii]);
+ }
+ }
+
+ return(NULL);
+}
+
+/**
+ * xmlSecQName2BitMaskGetBitMask:
+ * @info: the qname<->bit mask mapping information.
+ * @qnameHref: the qname Href value.
+ * @qnameLocalPart: the qname LocalPart value.
+ * @mask: the pointer to result mask.
+ *
+ * Converts @qnameLocalPart to @mask.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2BitMaskGetBitMask(xmlSecQName2BitMaskInfoConstPtr info,
+ const xmlChar* qnameHref, const xmlChar* qnameLocalPart,
+ xmlSecBitMask* mask) {
+ unsigned int ii;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(qnameLocalPart != NULL, -1);
+ xmlSecAssert2(mask != NULL, -1);
+
+ for(ii = 0; info[ii].qnameLocalPart != NULL; ii++) {
+ xmlSecAssert2(info[ii].mask != 0, -1);
+ if(xmlStrEqual(info[ii].qnameLocalPart, qnameLocalPart) &&
+ xmlStrEqual(info[ii].qnameHref, qnameHref)) {
+
+ (*mask) = info[ii].mask;
+ return(0);
+ }
+ }
+
+ return(-1);
+}
+
+/**
+ * xmlSecQName2BitMaskGetBitMaskFromString:
+ * @info: the qname<->integer mapping information.
+ * @node: the pointer to node.
+ * @qname: the qname string.
+ * @mask: the pointer to result msk value.
+ *
+ * Converts @qname into integer in context of @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2BitMaskGetBitMaskFromString(xmlSecQName2BitMaskInfoConstPtr info,
+ xmlNodePtr node, const xmlChar* qname,
+ xmlSecBitMask* mask) {
+ const xmlChar* qnameLocalPart = NULL;
+ xmlChar* qnamePrefix = NULL;
+ const xmlChar* qnameHref;
+ xmlNsPtr ns;
+ int ret;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(qname != NULL, -1);
+ xmlSecAssert2(mask != NULL, -1);
+
+ qnameLocalPart = xmlStrchr(qname, ':');
+ if(qnameLocalPart != NULL) {
+ qnamePrefix = xmlStrndup(qname, qnameLocalPart - qname);
+ if(qnamePrefix == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrndup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "node=%s,value=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qname));
+ return(-1);
+ }
+ qnameLocalPart++;
+ } else {
+ qnamePrefix = NULL;
+ qnameLocalPart = qname;
+ }
+
+ /* search namespace href */
+ ns = xmlSearchNs(node->doc, node, qnamePrefix);
+ if((ns == NULL) && (qnamePrefix != NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSearchNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s,qnamePrefix=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnamePrefix));
+ if(qnamePrefix != NULL) {
+ xmlFree(qnamePrefix);
+ }
+ return(-1);
+ }
+ qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
+
+ /* and finally search for integer */
+ ret = xmlSecQName2BitMaskGetBitMask(info, qnameHref, qnameLocalPart, mask);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskGetBitMask",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,qnameLocalPart=%s,qnameHref=%s",
+ xmlSecErrorsSafeString(node->name),
+ xmlSecErrorsSafeString(qnameLocalPart),
+ xmlSecErrorsSafeString(qnameHref));
+ if(qnamePrefix != NULL) {
+ xmlFree(qnamePrefix);
+ }
+ return(-1);
+ }
+
+ if(qnamePrefix != NULL) {
+ xmlFree(qnamePrefix);
+ }
+ return(0);
+}
+
+
+/**
+ * xmlSecQName2BitMaskGetStringFromBitMask:
+ * @info: the qname<->integer mapping information.
+ * @node: the pointer to node.
+ * @mask: the mask.
+ *
+ * Creates qname string for @mask in context of given @node. Caller
+ * is responsible for freeing returned string with @xmlFree.
+ *
+ * Returns: pointer to newly allocated string on success or NULL if an error occurs,
+ */
+xmlChar*
+xmlSecQName2BitMaskGetStringFromBitMask(xmlSecQName2BitMaskInfoConstPtr info,
+ xmlNodePtr node, xmlSecBitMask mask) {
+ xmlSecQName2BitMaskInfoConstPtr qnameInfo;
+
+ xmlSecAssert2(info != NULL, NULL);
+ xmlSecAssert2(node != NULL, NULL);
+
+ qnameInfo = xmlSecQName2BitMaskGetInfo(info, mask);
+ if(qnameInfo == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskGetInfo",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s,mask=%d",
+ xmlSecErrorsSafeString(node->name),
+ mask);
+ return(NULL);
+ }
+
+ return(xmlSecGetQName(node, qnameInfo->qnameHref, qnameInfo->qnameLocalPart));
+}
+
+/**
+ * xmlSecQName2BitMaskNodesRead:
+ * @info: the qname<->bit mask mapping information.
+ * @node: the start.
+ * @nodeName: the mask nodes name.
+ * @nodeNs: the mask nodes namespace.
+ * @stopOnUnknown: if this flag is set then function exits if unknown
+ * value was found.
+ * @mask: the pointer to result mask.
+ *
+ * Reads <@nodeNs:@nodeName> elements and puts the result bit mask
+ * into @mask. When function exits, @node points to the first element node
+ * after all the <@nodeNs:@nodeName> elements.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2BitMaskNodesRead(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr* node,
+ const xmlChar* nodeName, const xmlChar* nodeNs,
+ int stopOnUnknown, xmlSecBitMask* mask) {
+ xmlNodePtr cur;
+ xmlChar* content;
+ xmlSecBitMask tmp;
+ int ret;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(mask != NULL, -1);
+
+ (*mask) = 0;
+ cur = (*node);
+ while((cur != NULL) && (xmlSecCheckNodeName(cur, nodeName, nodeNs))) {
+ content = xmlNodeGetContent(cur);
+ if(content == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlNodeGetContent",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(cur->name));
+ return(-1);
+ }
+
+ ret = xmlSecQName2BitMaskGetBitMaskFromString(info, cur, content, &tmp);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskGetBitMaskFromString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "value=%s",
+ xmlSecErrorsSafeString(content));
+ xmlFree(content);
+ return(-1);
+ }
+ xmlFree(content);
+
+ if((stopOnUnknown != 0) && (tmp == 0)) {
+ /* todo: better error */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecQName2BitMaskGetBitMaskFromString",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "value=%s",
+ xmlSecErrorsSafeString(content));
+ return(-1);
+ }
+
+ (*mask) |= tmp;
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ (*node) = cur;
+ return(0);
+}
+
+/**
+ * xmlSecQName2BitMaskNodesWrite:
+ * @info: the qname<->bit mask mapping information.
+ * @node: the parent element for mask nodes.
+ * @nodeName: the mask nodes name.
+ * @nodeNs: the mask nodes namespace.
+ * @mask: the bit mask.
+ *
+ * Writes <@nodeNs:@nodeName> elemnts with values from @mask to @node.
+ *
+ * Returns: 0 on success or a negative value if an error occurs,
+ */
+int
+xmlSecQName2BitMaskNodesWrite(xmlSecQName2BitMaskInfoConstPtr info, xmlNodePtr node,
+ const xmlChar* nodeName, const xmlChar* nodeNs,
+ xmlSecBitMask mask) {
+ unsigned int ii;
+
+ xmlSecAssert2(info != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(nodeName != NULL, -1);
+
+ for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
+ xmlSecAssert2(info[ii].mask != 0, -1);
+
+ if((mask & info[ii].mask) != 0) {
+ xmlNodePtr cur;
+ xmlChar* qname;
+
+ qname = xmlSecGetQName(node, info[ii].qnameHref, info[ii].qnameLocalPart);
+ if(qname == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGetQName",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(nodeName));
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, nodeName, nodeNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(nodeName));
+ xmlFree(qname);
+ return(-1);
+ }
+
+ xmlNodeSetContent(cur, qname);
+ xmlFree(qname);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecQName2BitMaskDebugDump:
+ * @info: the qname<->bit mask mapping information.
+ * @mask: the bit mask.
+ * @name: the value name to print.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @mask to @output.
+ */
+void
+xmlSecQName2BitMaskDebugDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask,
+ const xmlChar* name, FILE* output) {
+ unsigned int ii;
+
+ xmlSecAssert(info != NULL);
+ xmlSecAssert(name != NULL);
+ xmlSecAssert(output != NULL);
+
+ if(mask == 0) {
+ return;
+ }
+
+ fprintf(output, "== %s (0x%08x): ", name, mask);
+ for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
+ xmlSecAssert(info[ii].mask != 0);
+
+ if((mask & info[ii].mask) != 0) {
+ fprintf(output, "name=\"%s\" (href=\"%s\"),", info[ii].qnameLocalPart, info[ii].qnameHref);
+ }
+ }
+ fprintf(output, "\n");
+}
+
+/**
+ * xmlSecQName2BitMaskDebugXmlDump:
+ * @info: the qname<->bit mask mapping information.
+ * @mask: the bit mask.
+ * @name: the value name to print.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @mask to @output in XML format.
+ */
+void
+xmlSecQName2BitMaskDebugXmlDump(xmlSecQName2BitMaskInfoConstPtr info, xmlSecBitMask mask,
+ const xmlChar* name, FILE* output) {
+ unsigned int ii;
+
+ xmlSecAssert(info != NULL);
+ xmlSecAssert(name != NULL);
+ xmlSecAssert(output != NULL);
+
+ if(mask == 0) {
+ return;
+ }
+
+ fprintf(output, "<%sList>\n", name);
+ for(ii = 0; (mask != 0) && (info[ii].qnameLocalPart != NULL); ii++) {
+ xmlSecAssert(info[ii].mask != 0);
+
+ if((mask & info[ii].mask) != 0) {
+ fprintf(output, "<%s href=\"%s\">%s</%s>\n", name,
+ info[ii].qnameHref, info[ii].qnameLocalPart, name);
+ }
+ }
+ fprintf(output, "</%sList>\n", name);
+}
+
+
+
+
diff --git a/src/xpath.c b/src/xpath.c
new file mode 100644
index 00000000..8b0b4f8e
--- /dev/null
+++ b/src/xpath.c
@@ -0,0 +1,1148 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * XPath transform
+ *
+ * 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 <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xpointer.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/list.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+
+/**************************************************************************
+ *
+ * xmlSecXPathHereFunction:
+ * @ctxt: the ponter to XPath context.
+ * @nargs: the arguments nubmer.
+ *
+ * The implementation of XPath "here()" function.
+ * See xmlXPtrHereFunction() in xpointer.c. the only change is that
+ * we return NodeSet instead of NodeInterval.
+ *
+ *****************************************************************************/
+static void
+xmlSecXPathHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ CHECK_ARITY(0);
+
+ if((ctxt == NULL) || (ctxt->context == NULL) || (ctxt->context->here == NULL)) {
+ XP_ERROR(XPTR_SYNTAX_ERROR);
+ }
+ valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->here));
+}
+
+/**************************************************************************
+ *
+ * XPath/XPointer data
+ *
+ *****************************************************************************/
+typedef struct _xmlSecXPathData xmlSecXPathData,
+ *xmlSecXPathDataPtr;
+typedef enum {
+ xmlSecXPathDataTypeXPath,
+ xmlSecXPathDataTypeXPath2,
+ xmlSecXPathDataTypeXPointer
+} xmlSecXPathDataType;
+
+struct _xmlSecXPathData {
+ xmlSecXPathDataType type;
+ xmlXPathContextPtr ctx;
+ xmlChar* expr;
+ xmlSecNodeSetOp nodeSetOp;
+ xmlSecNodeSetType nodeSetType;
+};
+
+static xmlSecXPathDataPtr xmlSecXPathDataCreate (xmlSecXPathDataType type);
+static void xmlSecXPathDataDestroy (xmlSecXPathDataPtr data);
+static int xmlSecXPathDataSetExpr (xmlSecXPathDataPtr data,
+ const xmlChar* expr);
+static int xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data,
+ xmlNodePtr node);
+static int xmlSecXPathDataNodeRead (xmlSecXPathDataPtr data,
+ xmlNodePtr node);
+static xmlSecNodeSetPtr xmlSecXPathDataExecute (xmlSecXPathDataPtr data,
+ xmlDocPtr doc,
+ xmlNodePtr hereNode);
+
+static xmlSecXPathDataPtr
+xmlSecXPathDataCreate(xmlSecXPathDataType type) {
+ xmlSecXPathDataPtr data;
+
+ data = (xmlSecXPathDataPtr) xmlMalloc(sizeof(xmlSecXPathData));
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecXPathData)=%d",
+ sizeof(xmlSecXPathData));
+ return(NULL);
+ }
+ memset(data, 0, sizeof(xmlSecXPathData));
+
+ data->type = type;
+ data->nodeSetType = xmlSecNodeSetTree;
+
+ /* create xpath or xpointer context */
+ switch(data->type) {
+ case xmlSecXPathDataTypeXPath:
+ case xmlSecXPathDataTypeXPath2:
+ data->ctx = xmlXPathNewContext(NULL); /* we'll set doc in the context later */
+ if(data->ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathNewContext",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(NULL);
+ }
+ break;
+ case xmlSecXPathDataTypeXPointer:
+ data->ctx = xmlXPtrNewContext(NULL, NULL, NULL); /* we'll set doc in the context later */
+ if(data->ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPtrNewContext",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(NULL);
+ }
+ break;
+ }
+
+ return(data);
+}
+
+static void
+xmlSecXPathDataDestroy(xmlSecXPathDataPtr data) {
+ xmlSecAssert(data != NULL);
+
+ if(data->expr != NULL) {
+ xmlFree(data->expr);
+ }
+ if(data->ctx != NULL) {
+ xmlXPathFreeContext(data->ctx);
+ }
+ memset(data, 0, sizeof(xmlSecXPathData));
+ xmlFree(data);
+}
+
+static int
+xmlSecXPathDataSetExpr(xmlSecXPathDataPtr data, const xmlChar* expr) {
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(data->expr == NULL, -1);
+ xmlSecAssert2(data->ctx != NULL, -1);
+ xmlSecAssert2(expr != NULL, -1);
+
+ data->expr = xmlStrdup(expr);
+ if(data->expr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_STRDUP_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecXPathDataRegisterNamespaces(xmlSecXPathDataPtr data, xmlNodePtr node) {
+ xmlNodePtr cur;
+ xmlNsPtr ns;
+ int ret;
+
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(data->ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* register namespaces */
+ for(cur = node; cur != NULL; cur = cur->parent) {
+ for(ns = cur->nsDef; ns != NULL; ns = ns->next) {
+ /* check that we have no other namespace with same prefix already */
+ if((ns->prefix != NULL) && (xmlXPathNsLookup(data->ctx, ns->prefix) == NULL)){
+ ret = xmlXPathRegisterNs(data->ctx, ns->prefix, ns->href);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathRegisterNs",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "href=%s;prefix=%s",
+ xmlSecErrorsSafeString(ns->href),
+ xmlSecErrorsSafeString(ns->prefix));
+ return(-1);
+ }
+ }
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXPathDataNodeRead(xmlSecXPathDataPtr data, xmlNodePtr node) {
+ int ret;
+
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(data->expr == NULL, -1);
+ xmlSecAssert2(data->ctx != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ ret = xmlSecXPathDataRegisterNamespaces (data, node);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXPathDataRegisterNamespaces",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* read node content and set expr */
+ data->expr = xmlNodeGetContent(node);
+ if(data->expr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static xmlSecNodeSetPtr
+xmlSecXPathDataExecute(xmlSecXPathDataPtr data, xmlDocPtr doc, xmlNodePtr hereNode) {
+ xmlXPathObjectPtr xpathObj = NULL;
+ xmlSecNodeSetPtr nodes;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(data->expr != NULL, NULL);
+ xmlSecAssert2(data->ctx != NULL, NULL);
+ xmlSecAssert2(doc != NULL, NULL);
+ xmlSecAssert2(hereNode != NULL, NULL);
+
+ /* do not forget to set the doc */
+ data->ctx->doc = doc;
+
+ /* here function works only on the same document */
+ if(hereNode->doc == doc) {
+ xmlXPathRegisterFunc(data->ctx, (xmlChar *)"here", xmlSecXPathHereFunction);
+ data->ctx->here = hereNode;
+ data->ctx->xptr = 1;
+ }
+
+ /* execute xpath or xpointer expression */
+ switch(data->type) {
+ case xmlSecXPathDataTypeXPath:
+ case xmlSecXPathDataTypeXPath2:
+ xpathObj = xmlXPathEvalExpression(data->expr, data->ctx);
+ if(xpathObj == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPathEvalExpression",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "expr=%s",
+ xmlSecErrorsSafeString(data->expr));
+ return(NULL);
+ }
+ break;
+ case xmlSecXPathDataTypeXPointer:
+ xpathObj = xmlXPtrEval(data->expr, data->ctx);
+ if(xpathObj == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlXPtrEval",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "expr=%s",
+ xmlSecErrorsSafeString(data->expr));
+ return(NULL);
+ }
+ break;
+ }
+
+ nodes = xmlSecNodeSetCreate(doc, xpathObj->nodesetval, data->nodeSetType);
+ if(nodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=%d", data->nodeSetType);
+ xmlXPathFreeObject(xpathObj);
+ return(NULL);
+ }
+ xpathObj->nodesetval = NULL;
+ xmlXPathFreeObject(xpathObj);
+
+ return(nodes);
+}
+
+
+/**************************************************************************
+ *
+ * XPath data list
+ *
+ *****************************************************************************/
+#define xmlSecXPathDataListId \
+ xmlSecXPathDataListGetKlass()
+static xmlSecPtrListId xmlSecXPathDataListGetKlass (void);
+static xmlSecNodeSetPtr xmlSecXPathDataListExecute (xmlSecPtrListPtr dataList,
+ xmlDocPtr doc,
+ xmlNodePtr hereNode,
+ xmlSecNodeSetPtr nodes);
+
+static xmlSecPtrListKlass xmlSecXPathDataListKlass = {
+ BAD_CAST "xpath-data-list",
+ NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ (xmlSecPtrDestroyItemMethod)xmlSecXPathDataDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+static xmlSecPtrListId
+xmlSecXPathDataListGetKlass(void) {
+ return(&xmlSecXPathDataListKlass);
+}
+
+static xmlSecNodeSetPtr
+xmlSecXPathDataListExecute(xmlSecPtrListPtr dataList, xmlDocPtr doc,
+ xmlNodePtr hereNode, xmlSecNodeSetPtr nodes) {
+ xmlSecXPathDataPtr data;
+ xmlSecNodeSetPtr res, tmp, tmp2;
+ xmlSecSize pos;
+
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), NULL);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, NULL);
+ xmlSecAssert2(doc != NULL, NULL);
+ xmlSecAssert2(hereNode != NULL, NULL);
+
+ res = nodes;
+ for(pos = 0; pos < xmlSecPtrListGetSize(dataList); ++pos) {
+ data = (xmlSecXPathDataPtr)xmlSecPtrListGetItem(dataList, pos);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ if((res != NULL) && (res != nodes)) {
+ xmlSecNodeSetDestroy(res);
+ }
+ return(NULL);
+ }
+
+ tmp = xmlSecXPathDataExecute(data, doc, hereNode);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXPathDataExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ if((res != NULL) && (res != nodes)) {
+ xmlSecNodeSetDestroy(res);
+ }
+ return(NULL);
+ }
+
+ tmp2 = xmlSecNodeSetAdd(res, tmp, data->nodeSetOp);
+ if(tmp2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNodeSetAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNodeSetIntersection");
+ if((res != NULL) && (res != nodes)) {
+ xmlSecNodeSetDestroy(res);
+ }
+ xmlSecNodeSetDestroy(tmp);
+ return(NULL);
+ }
+ res = tmp2;
+ }
+
+ return(res);
+}
+
+/******************************************************************************
+ *
+ * XPath/XPointer transforms
+ *
+ * xmlSecXPathDataList is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecXPathTransformSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecPtrList))
+#define xmlSecXPathTransformGetDataList(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecXPathTransformSize)) ? \
+ (xmlSecPtrListPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlSecPtrListPtr)NULL)
+#define xmlSecTransformXPathCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformXPathId) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformXPath2Id) || \
+ xmlSecTransformCheckId((transform), xmlSecTransformXPointerId))
+
+static int xmlSecTransformXPathInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformXPathFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformXPathExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecTransformXPathInitialize(xmlSecTransformPtr transform) {
+ xmlSecPtrListPtr dataList;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(dataList != NULL, -1);
+
+ ret = xmlSecPtrListInitialize(dataList, xmlSecXPathDataListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecTransformXPathFinalize(xmlSecTransformPtr transform) {
+ xmlSecPtrListPtr dataList;
+
+ xmlSecAssert(xmlSecTransformXPathCheckId(transform));
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId));
+
+ xmlSecPtrListFinalize(dataList);
+}
+
+static int
+xmlSecTransformXPathExecute(xmlSecTransformPtr transform, int last,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlDocPtr doc;
+
+ xmlSecAssert2(xmlSecTransformXPathCheckId(transform), -1);
+ xmlSecAssert2(transform->hereNode != NULL, -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(last != 0, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) > 0, -1);
+
+ doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc;
+ xmlSecAssert2(doc != NULL, -1);
+
+ transform->outNodes = xmlSecXPathDataListExecute(dataList, doc,
+ transform->hereNode, transform->inNodes);
+ if(transform->outNodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataExecute",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/******************************************************************************
+ *
+ * XPath transform
+ *
+ *****************************************************************************/
+static int xmlSecTransformXPathNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecTransformXPathKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXPathTransformSize, /* xmlSecSize objSize */
+
+ xmlSecNameXPath, /* const xmlChar* name; */
+ xmlSecXPathNs, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformXPathNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXPathGetKlass:
+ *
+ * The XPath transform evaluates given XPath expression and
+ * intersects the result with the previous nodes set. See
+ * http://www.w3.org/TR/xmldsig-core/#sec-XPath for more details.
+ *
+ * Returns: XPath transform id.
+ */
+xmlSecTransformId
+xmlSecTransformXPathGetKlass(void) {
+ return(&xmlSecTransformXPathKlass);
+}
+
+static const char xpathPattern[] = "(//. | //@* | //namespace::*)[boolean(%s)]";
+static int
+xmlSecTransformXPathNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ xmlNodePtr cur;
+ xmlChar* tmp;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPathId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ /* there is only one required node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPath, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPath));
+ return(-1);
+ }
+
+ /* read information from the node */
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataNodeRead(data, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* create full XPath expression */
+ xmlSecAssert2(data->expr != NULL, -1);
+ tmp = (xmlChar*) xmlMalloc(sizeof(xmlChar) * (xmlStrlen(data->expr) +
+ strlen(xpathPattern) + 1));
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d",
+ xmlStrlen(data->expr) + strlen(xpathPattern) + 1);
+ return(-1);
+ }
+ sprintf((char*)tmp, xpathPattern, (char*)data->expr);
+ xmlFree(data->expr);
+ data->expr = tmp;
+
+ /* set correct node set type and operation */
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ data->nodeSetType = xmlSecNodeSetNormal;
+
+ /* check that we have nothing else */
+ 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);
+}
+
+/******************************************************************************
+ *
+ * XPath2 transform
+ *
+ *****************************************************************************/
+static int xmlSecTransformXPath2NodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecTransformXPath2Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXPathTransformSize, /* xmlSecSize objSize */
+
+ xmlSecNameXPath2, /* const xmlChar* name; */
+ xmlSecXPath2Ns, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformXPath2NodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXPath2GetKlass:
+ *
+ * The XPath2 transform (http://www.w3.org/TR/xmldsig-filter2/).
+ *
+ * Returns: XPath2 transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformXPath2GetKlass(void) {
+ return(&xmlSecTransformXPath2Klass);
+}
+
+static int
+xmlSecTransformXPath2NodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ xmlNodePtr cur;
+ xmlChar* op;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPath2Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ /* There are only xpath nodes */
+ cur = xmlSecGetNextElementNode(node->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeXPath2, xmlSecXPath2Ns)) {
+ /* read information from the node */
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPath2);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataNodeRead(data, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* set correct node set type and operation */
+ data->nodeSetType = xmlSecNodeSetTree;
+ op = xmlGetProp(cur, xmlSecAttrFilter);
+ if(op == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrFilter),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ if(xmlStrEqual(op, xmlSecXPath2FilterIntersect)) {
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ } else if(xmlStrEqual(op, xmlSecXPath2FilterSubtract)) {
+ data->nodeSetOp = xmlSecNodeSetSubtraction;
+ } else if(xmlStrEqual(op, xmlSecXPath2FilterUnion)) {
+ data->nodeSetOp = xmlSecNodeSetUnion;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrFilter),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "filter=%s",
+ xmlSecErrorsSafeString(op));
+ xmlFree(op);
+ return(-1);
+ }
+ xmlFree(op);
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* check that we have nothing else */
+ 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);
+}
+
+/******************************************************************************
+ *
+ * XPointer transform
+ *
+ *****************************************************************************/
+static int xmlSecTransformXPointerNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecTransformXPointerKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXPathTransformSize, /* xmlSecSize objSize */
+
+ xmlSecNameXPointer, /* const xmlChar* name; */
+ xmlSecXPointerNs, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformXPathInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformXPathFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecTransformXPointerNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformXPathExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXPointerGetKlass:
+ *
+ * The XPointer transform klass
+ * (http://www.ietf.org/internet-drafts/draft-eastlake-xmldsig-uri-02.txt).
+ *
+ * Returns: XPointer transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformXPointerGetKlass(void) {
+ return(&xmlSecTransformXPointerKlass);
+}
+
+/**
+ * xmlSecTransformXPointerSetExpr:
+ * @transform: the pointer to XPointer transform.
+ * @expr: the XPointer expression.
+ * @nodeSetType: the type of evaluated XPointer expression.
+ * @hereNode: the pointer to "here" node.
+ *
+ * Sets the XPointer expression for an XPointer @transform.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformXPointerSetExpr(xmlSecTransformPtr transform, const xmlChar* expr,
+ xmlSecNodeSetType nodeSetType, xmlNodePtr hereNode) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1);
+ xmlSecAssert2(transform->hereNode == NULL, -1);
+ xmlSecAssert2(expr != NULL, -1);
+ xmlSecAssert2(hereNode != NULL, -1);
+
+ transform->hereNode = hereNode;
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataRegisterNamespaces(data, hereNode);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataRegisterNamespaces",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataSetExpr(data, expr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataSetExpr",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* set correct node set type and operation */
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ data->nodeSetType = nodeSetType;
+
+ return(0);
+}
+
+static int
+xmlSecTransformXPointerNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecPtrListPtr dataList;
+ xmlSecXPathDataPtr data;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXPointerId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ dataList = xmlSecXPathTransformGetDataList(transform);
+ xmlSecAssert2(xmlSecPtrListCheckId(dataList, xmlSecXPathDataListId), -1);
+ xmlSecAssert2(xmlSecPtrListGetSize(dataList) == 0, -1);
+
+ /* there is only one required node */
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeXPointer, xmlSecXPointerNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected=%s",
+ xmlSecErrorsSafeString(xmlSecNodeXPath));
+ return(-1);
+ }
+
+ /* read information from the node */
+ data = xmlSecXPathDataCreate(xmlSecXPathDataTypeXPointer);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecXPathDataNodeRead(data, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXPathDataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* append it to the list */
+ ret = xmlSecPtrListAdd(dataList, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecXPathDataDestroy(data);
+ return(-1);
+ }
+
+ /* set correct node set type and operation */
+ data->nodeSetOp = xmlSecNodeSetIntersection;
+ data->nodeSetType = xmlSecNodeSetTree;
+
+ /* check that we have nothing else */
+ 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);
+}
+
+
+/******************************************************************************
+ *
+ * Visa3DHack transform
+ *
+ *****************************************************************************/
+#define xmlSecVisa3DHackTransformSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlChar*))
+#define xmlSecVisa3DHackTransformGetIDPtr(transform) \
+ ((xmlSecTransformCheckSize((transform), xmlSecVisa3DHackTransformSize)) ? \
+ (xmlChar**)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)) : \
+ (xmlChar**)NULL)
+#define xmlSecTransformVisa3DHackCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecTransformVisa3DHackId))
+
+static int xmlSecTransformVisa3DHackInitialize (xmlSecTransformPtr transform);
+static void xmlSecTransformVisa3DHackFinalize (xmlSecTransformPtr transform);
+static int xmlSecTransformVisa3DHackExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecTransformVisa3DHackKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecVisa3DHackTransformSize, /* xmlSecSize objSize */
+
+ BAD_CAST "Visa3DHackTransform", /* const xmlChar* name; */
+ NULL, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
+
+ xmlSecTransformVisa3DHackInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecTransformVisa3DHackFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ NULL, /* xmlSecTransformPushBinMethod pushBin; */
+ NULL, /* xmlSecTransformPopBinMethod popBin; */
+ xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
+ xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecTransformVisa3DHackExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformVisa3DHackGetKlass:
+ *
+ * The Visa3DHack transform klass. The only reason why we need this
+ * is Visa3D protocol. It doesn't follow XML/XPointer/XMLDSig specs and allows
+ * invalid XPointer expressions in the URI attribute. Since we couldn't evaluate
+ * such expressions thru XPath/XPointer engine, we need to have this hack here.
+ *
+ * Returns: Visa3DHack transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformVisa3DHackGetKlass(void) {
+ return(&xmlSecTransformVisa3DHackKlass);
+}
+
+/**
+ * xmlSecTransformVisa3DHackSetID:
+ * @transform: the pointer to Visa3DHack transform.
+ * @id: the ID value.
+ *
+ * Sets the ID value for an Visa3DHack @transform.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecTransformVisa3DHackSetID(xmlSecTransformPtr transform, const xmlChar* id) {
+ xmlChar** idPtr;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformVisa3DHackId), -1);
+ xmlSecAssert2(id != NULL, -1);
+
+ idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
+ xmlSecAssert2(idPtr != NULL, -1);
+ xmlSecAssert2((*idPtr) == NULL, -1);
+
+ (*idPtr) = xmlStrdup(id);
+ if((*idPtr) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecTransformVisa3DHackInitialize(xmlSecTransformPtr transform) {
+ xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1);
+
+ return(0);
+}
+
+static void
+xmlSecTransformVisa3DHackFinalize(xmlSecTransformPtr transform) {
+ xmlChar** idPtr;
+
+ xmlSecAssert(xmlSecTransformVisa3DHackCheckId(transform));
+
+ idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
+ xmlSecAssert(idPtr != NULL);
+
+ if((*idPtr) != NULL) {
+ xmlFree((*idPtr));
+ }
+ (*idPtr) = NULL;
+}
+
+static int
+xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlChar** idPtr;
+ xmlDocPtr doc;
+ xmlAttrPtr attr;
+ xmlNodeSetPtr nodeSet;
+
+ xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1);
+ xmlSecAssert2(transform->outNodes == NULL, -1);
+ xmlSecAssert2(last != 0, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform);
+ xmlSecAssert2(idPtr != NULL, -1);
+ xmlSecAssert2((*idPtr) != NULL, -1);
+
+ doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc;
+ xmlSecAssert2(doc != NULL, -1);
+
+ attr = xmlGetID(doc, (*idPtr));
+ if((attr == NULL) || (attr->parent == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlGetID",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "id=\"%s\"",
+ xmlSecErrorsSafeString((*idPtr)));
+ return(-1);
+ }
+
+ nodeSet = xmlXPathNodeSetCreate(attr->parent);
+ if(nodeSet == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlXPathNodeSetCreate",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "id=\"%s\"",
+ xmlSecErrorsSafeString((*idPtr)));
+ return(-1);
+ }
+
+ transform->outNodes = xmlSecNodeSetCreate(doc, nodeSet, xmlSecNodeSetTreeWithoutComments);
+ if(transform->outNodes == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNodeSetCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlXPathFreeNodeSet(nodeSet);
+ return(-1);
+ }
+ return(0);
+}
+
+
+
diff --git a/src/xslt.c b/src/xslt.c
new file mode 100644
index 00000000..e5e52685
--- /dev/null
+++ b/src/xslt.c
@@ -0,0 +1,518 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * XSLT Transform (http://www.w3.org/TR/xmldsig-core/#sec-XSLT)
+ *
+ * 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_XSLT
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/parser.h>
+#include <xmlsec/errors.h>
+
+/**************************************************************************
+ *
+ * Internal xslt ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecXsltCtx xmlSecXsltCtx, *xmlSecXsltCtxPtr;
+struct _xmlSecXsltCtx {
+ xsltStylesheetPtr xslt;
+ xmlParserCtxtPtr parserCtx;
+};
+
+/****************************************************************************
+ *
+ * XSLT transform
+ *
+ * xmlSecXsltCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecXsltSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecXsltCtx))
+#define xmlSecXsltGetCtx(transform) \
+ ((xmlSecXsltCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecXsltInitialize (xmlSecTransformPtr transform);
+static void xmlSecXsltFinalize (xmlSecTransformPtr transform);
+static int xmlSecXsltReadNode (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecXsltPushBin (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ int final,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecXsltExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecXslProcess (xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ xsltStylesheetPtr stylesheet);
+static xmlSecTransformKlass xmlSecXsltKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecXsltSize, /* xmlSecSize objSize */
+
+ xmlSecNameXslt, /* const xmlChar* name; */
+ xmlSecHrefXslt, /* const xmlChar* href; */
+ xmlSecTransformUsageDSigTransform, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecXsltInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecXsltFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecXsltReadNode, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecXsltPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecXsltExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecTransformXsltGetKlass:
+ *
+ * XSLT transform klass (http://www.w3.org/TR/xmldsig-core/#sec-XSLT):
+ *
+ * The normative specification for XSL Transformations is [XSLT].
+ * Specification of a namespace-qualified stylesheet element, which MUST be
+ * the sole child of the Transform element, indicates that the specified style
+ * sheet should be used. Whether this instantiates in-line processing of local
+ * XSLT declarations within the resource is determined by the XSLT processing
+ * model; the ordered application of multiple stylesheet may require multiple
+ * Transforms. No special provision is made for the identification of a remote
+ * stylesheet at a given URI because it can be communicated via an xsl:include
+ * or xsl:import within the stylesheet child of the Transform.
+ *
+ * This transform requires an octet stream as input. If the actual input is an
+ * XPath node-set, then the signature application should attempt to convert it
+ * to octets (apply Canonical XML]) as described in the Reference Processing
+ * Model (section 4.3.3.2).]
+ *
+ * The output of this transform is an octet stream. The processing rules for
+ * the XSL style sheet or transform element are stated in the XSLT specification
+ * [XSLT]. We RECOMMEND that XSLT transform authors use an output method of xml
+ * for XML and HTML. As XSLT implementations do not produce consistent
+ * serializations of their output, we further RECOMMEND inserting a transform
+ * after the XSLT transform to canonicalize the output. These steps will help
+ * to ensure interoperability of the resulting signatures among applications
+ * that support the XSLT transform. Note that if the output is actually HTML,
+ * then the result of these steps is logically equivalent [XHTML].
+ *
+ * Returns: pointer to XSLT transform klass.
+ */
+xmlSecTransformId
+xmlSecTransformXsltGetKlass(void) {
+ return(&xmlSecXsltKlass);
+}
+
+static int
+xmlSecXsltInitialize(xmlSecTransformPtr transform) {
+ xmlSecXsltCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
+
+ ctx = xmlSecXsltGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecXsltCtx));
+ return(0);
+}
+
+static void
+xmlSecXsltFinalize(xmlSecTransformPtr transform) {
+ xmlSecXsltCtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecTransformXsltId));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecXsltSize));
+
+ ctx = xmlSecXsltGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->xslt != NULL) {
+ xsltFreeStylesheet(ctx->xslt);
+ }
+ if(ctx->parserCtx != NULL) {
+ xmlFreeParserCtxt(ctx->parserCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecXsltCtx));
+}
+
+static int
+xmlSecXsltReadNode(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecXsltCtxPtr ctx;
+ xmlBufferPtr buffer;
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecXsltGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->xslt == NULL, -1);
+
+ /* read content in the buffer */
+ buffer = xmlBufferCreate();
+ if(buffer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlBufferCreate",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ cur = node->children;
+ while(cur != NULL) {
+ xmlNodeDump(buffer, cur->doc, cur, 0, 0);
+ cur = cur->next;
+ }
+
+ /* parse the buffer */
+ doc = xmlSecParseMemory(xmlBufferContent(buffer),
+ xmlBufferLength(buffer), 1);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecParseMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlBufferFree(buffer);
+ return(-1);
+ }
+
+ /* pre-process stylesheet */
+ ctx->xslt = xsltParseStylesheetDoc(doc);
+ if(ctx->xslt == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xsltParseStylesheetDoc",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ /* after parsing stylesheet doc is assigned
+ * to it and will be freed by xsltFreeStylesheet() */
+ xmlFreeDoc(doc);
+ xmlBufferFree(buffer);
+ return(-1);
+ }
+
+ xmlBufferFree(buffer);
+ return(0);
+}
+
+static int
+xmlSecXsltPushBin(xmlSecTransformPtr transform, const xmlSecByte* data,
+ xmlSecSize dataSize, int final, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecXsltCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecXsltGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->xslt != NULL, -1);
+
+ /* check/update current transform status */
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlSecAssert2(ctx->parserCtx == NULL, -1);
+
+ ctx->parserCtx = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
+ if(ctx->parserCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlCreatePushParserCtxt",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* required for c14n! */
+ ctx->parserCtx->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ ctx->parserCtx->replaceEntities = 1;
+
+ transform->status = xmlSecTransformStatusWorking;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ return(0);
+ } else if(transform->status != xmlSecTransformStatusWorking) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
+ xmlSecAssert2(ctx->parserCtx != NULL, -1);
+
+ /* push data to the input buffer */
+ if((data != NULL) && (dataSize > 0)) {
+ ret = xmlParseChunk(ctx->parserCtx, (const char*)data, dataSize, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "size=%d", dataSize);
+ return(-1);
+ }
+ }
+
+ /* finish parsing, apply xslt transforms and push to next in the chain */
+ if(final != 0) {
+ xmlDocPtr docIn;
+ xmlDocPtr docOut;
+ xmlOutputBufferPtr output;
+
+ /* finalize */
+ ret = xmlParseChunk(ctx->parserCtx, NULL, 0, 1);
+ if((ret != 0) || (ctx->parserCtx->myDoc == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlParseChunk",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* todo: check that document is well formed? */
+ docIn = ctx->parserCtx->myDoc;
+ ctx->parserCtx->myDoc = NULL;
+
+ docOut = xsltApplyStylesheet(ctx->xslt, docIn, NULL);
+ if(docOut == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xsltApplyStylesheet",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(docIn);
+ return(-1);
+ }
+ xmlFreeDoc(docIn);
+
+ if(transform->next != NULL) {
+ output = xmlSecTransformCreateOutputBuffer(transform->next, transformCtx);
+ if(output == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecTransformCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(docOut);
+ return(-1);
+ }
+ } else {
+ output = xmlSecBufferCreateOutputBuffer(&(transform->outBuf));
+ if(output == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(docOut);
+ return(-1);
+ }
+ }
+
+ ret = xsltSaveResultTo(output, docOut, ctx->xslt);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xsltSaveResultTo",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlOutputBufferClose(output);
+ xmlFreeDoc(docOut);
+ return(-1);
+ }
+ ret = xmlOutputBufferClose(output);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlOutputBufferClose",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(docOut);
+ return(-1);
+ }
+ xmlFreeDoc(docOut);
+
+ transform->status = xmlSecTransformStatusFinished;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecXsltExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecXsltCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformXsltId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecXsltSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecXsltGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->xslt != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ xmlSecAssert2(outSize == 0, -1);
+
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ ret = xmlSecXslProcess(in, out, ctx->xslt);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXslProcess",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ 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(inSize == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+/* TODO: create PopBin method instead */
+static int
+xmlSecXslProcess(xmlSecBufferPtr in, xmlSecBufferPtr out, xsltStylesheetPtr stylesheet) {
+ xmlDocPtr docIn = NULL;
+ xmlDocPtr docOut = NULL;
+ xmlOutputBufferPtr output = NULL;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(stylesheet != NULL, -1);
+
+ docIn = xmlSecParseMemory(xmlSecBufferGetData(in), xmlSecBufferGetSize(in), 1);
+ if(docIn == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecParseMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ docOut = xsltApplyStylesheet(stylesheet, docIn, NULL);
+ if(docOut == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xsltApplyStylesheet",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ output = xmlSecBufferCreateOutputBuffer(out);
+ if(output == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferCreateOutputBuffer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xsltSaveResultTo(output, docOut, stylesheet);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xsltSaveResultTo",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlOutputBufferClose(output);
+ output = NULL;
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlOutputBufferClose",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ res = 0;
+
+done:
+ if(output != NULL) xmlOutputBufferClose(output);
+ if(docIn != NULL) xmlFreeDoc(docIn);
+ if(docOut != NULL) xmlFreeDoc(docOut);
+ return(res);
+}
+
+#endif /* XMLSEC_NO_XSLT */
+