summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-11-13 12:30:55 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-11-13 12:30:55 -0800
commitf251dedaa31b48f7c05a4b53c112b40ebca890ef (patch)
treed6c78a1b273417506edb030c96772c8459f5831e /src
downloadxmlsec1-f251dedaa31b48f7c05a4b53c112b40ebca890ef.tar.gz
xmlsec1-f251dedaa31b48f7c05a4b53c112b40ebca890ef.tar.bz2
xmlsec1-f251dedaa31b48f7c05a4b53c112b40ebca890ef.zip
Imported Upstream version 1.2.18upstream/1.2.18
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am71
-rw-r--r--src/Makefile.in878
-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.c994
-rw-r--r--src/enveloped.c152
-rw-r--r--src/errors.c242
-rw-r--r--src/gcrypt/Makefile.am55
-rw-r--r--src/gcrypt/Makefile.in764
-rw-r--r--src/gcrypt/README9
-rw-r--r--src/gcrypt/app.c663
-rw-r--r--src/gcrypt/asn1.c602
-rw-r--r--src/gcrypt/asn1.h39
-rw-r--r--src/gcrypt/asymkeys.c1920
-rw-r--r--src/gcrypt/ciphers.c855
-rw-r--r--src/gcrypt/crypto.c315
-rw-r--r--src/gcrypt/digests.c614
-rw-r--r--src/gcrypt/globals.h30
-rw-r--r--src/gcrypt/hmac.c823
-rw-r--r--src/gcrypt/kw_aes.c593
-rw-r--r--src/gcrypt/kw_des.c607
-rw-r--r--src/gcrypt/signatures.c1490
-rw-r--r--src/gcrypt/symkeys.c441
-rw-r--r--src/globals.h25
-rw-r--r--src/gnutls/Makefile.am58
-rw-r--r--src/gnutls/Makefile.in786
-rw-r--r--src/gnutls/README6
-rw-r--r--src/gnutls/app.c998
-rw-r--r--src/gnutls/asymkeys.c455
-rw-r--r--src/gnutls/ciphers.c82
-rw-r--r--src/gnutls/crypto.c351
-rw-r--r--src/gnutls/digests.c112
-rw-r--r--src/gnutls/globals.h31
-rw-r--r--src/gnutls/hmac.c141
-rw-r--r--src/gnutls/kw_aes.c72
-rw-r--r--src/gnutls/kw_des.c51
-rw-r--r--src/gnutls/signatures.c148
-rw-r--r--src/gnutls/symkeys.c125
-rw-r--r--src/gnutls/x509.c1960
-rw-r--r--src/gnutls/x509utils.c1687
-rw-r--r--src/gnutls/x509utils.h143
-rw-r--r--src/gnutls/x509vfy.c802
-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/kw_aes_des.c493
-rw-r--r--src/kw_aes_des.h148
-rw-r--r--src/list.c534
-rw-r--r--src/membuf.c209
-rw-r--r--src/mscrypto/Makefile.am62
-rw-r--r--src/mscrypto/Makefile.in799
-rw-r--r--src/mscrypto/README39
-rw-r--r--src/mscrypto/app.c1289
-rw-r--r--src/mscrypto/certkeys.c2615
-rw-r--r--src/mscrypto/ciphers.c937
-rw-r--r--src/mscrypto/crypto.c889
-rw-r--r--src/mscrypto/csp_calg.h105
-rw-r--r--src/mscrypto/csp_oid.h114
-rw-r--r--src/mscrypto/digests.c668
-rw-r--r--src/mscrypto/globals.h39
-rw-r--r--src/mscrypto/hmac.c963
-rw-r--r--src/mscrypto/keysstore.c620
-rw-r--r--src/mscrypto/kt_rsa.c631
-rw-r--r--src/mscrypto/kw_aes.c662
-rw-r--r--src/mscrypto/kw_des.c730
-rw-r--r--src/mscrypto/mingw-crypt32.def36
-rw-r--r--src/mscrypto/private.h130
-rw-r--r--src/mscrypto/signatures.c960
-rw-r--r--src/mscrypto/symkeys.c824
-rw-r--r--src/mscrypto/x509.c2281
-rw-r--r--src/mscrypto/x509vfy.c1406
-rw-r--r--src/mscrypto/xmlsec-mingw.h210
-rw-r--r--src/nodeset.c610
-rw-r--r--src/nss/Makefile.am57
-rw-r--r--src/nss/Makefile.in798
-rw-r--r--src/nss/README128
-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.c444
-rw-r--r--src/nss/digests.c576
-rw-r--r--src/nss/globals.h24
-rw-r--r--src/nss/hmac.c855
-rw-r--r--src/nss/keysstore.c485
-rw-r--r--src/nss/keytrans.c753
-rw-r--r--src/nss/kw_aes.c681
-rw-r--r--src/nss/kw_des.c663
-rw-r--r--src/nss/pkikeys.c1554
-rw-r--r--src/nss/signatures.c841
-rw-r--r--src/nss/symkeys.c440
-rw-r--r--src/nss/x509.c2223
-rw-r--r--src/nss/x509vfy.c808
-rw-r--r--src/openssl/Makefile.am56
-rw-r--r--src/openssl/Makefile.in790
-rw-r--r--src/openssl/README17
-rw-r--r--src/openssl/app.c1628
-rw-r--r--src/openssl/bn.c163
-rw-r--r--src/openssl/ciphers.c856
-rw-r--r--src/openssl/crypto.c491
-rw-r--r--src/openssl/digests.c682
-rw-r--r--src/openssl/evp.c1559
-rw-r--r--src/openssl/globals.h24
-rw-r--r--src/openssl/hmac.c857
-rw-r--r--src/openssl/kt_rsa.c876
-rw-r--r--src/openssl/kw_aes.c513
-rw-r--r--src/openssl/kw_des.c563
-rw-r--r--src/openssl/signatures.c1065
-rw-r--r--src/openssl/symkeys.c447
-rw-r--r--src/openssl/x509.c2414
-rw-r--r--src/openssl/x509vfy.c1284
-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.c260
-rw-r--r--src/skeleton/globals.h24
-rw-r--r--src/soap.c1322
-rw-r--r--src/strings.c597
-rw-r--r--src/templates.c2091
-rw-r--r--src/transforms.c2902
-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.c617
133 files changed, 98459 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 00000000..3883ab6f
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,71 @@
+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 \
+ kw_aes_des.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 \
+ kw_aes_des.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..545abac5
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,878 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+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 kw_aes_des.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@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+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 \
+ kw_aes_des.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 \
+ kw_aes_des.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)/kw_aes_des.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):
+ @fail= 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):
+ @fail= 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..925c24bb
--- /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..53e66945
--- /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..06a31d5b
--- /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>
+ * Copyright (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..0efbfed2
--- /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..5967a35e
--- /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..6e8a56a6
--- /dev/null
+++ b/src/dl.c
@@ -0,0 +1,994 @@
+/**
+ * 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);
+
+/* conversion from ptr to func "the right way" */
+XMLSEC_PTR_TO_FUNC_IMPL(xmlSecCryptoGetFunctionsCallback)
+
+
+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 = XMLSEC_PTR_TO_FUNC(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 = XMLSEC_PTR_TO_FUNC(xmlSecCryptoGetFunctionsCallback,
+ GetProcAddress(
+ lib->handle,
+ (const 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);
+ }
+
+ /* done */
+ return(0);
+}
+
+
diff --git a/src/enveloped.c b/src/enveloped.c
new file mode 100644
index 00000000..8047d318
--- /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..c9886d36
--- /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/gcrypt/Makefile.am b/src/gcrypt/Makefile.am
new file mode 100644
index 00000000..734c429f
--- /dev/null
+++ b/src/gcrypt/Makefile.am
@@ -0,0 +1,55 @@
+NULL =
+
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-gcrypt.la \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -DGCRYPT_MIN_VERSION=\"$(GCRYPT_MIN_VERSION)\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(GCRYPT_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_SOURCES =\
+ app.c \
+ asn1.h \
+ asn1.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ hmac.c \
+ kw_aes.c \
+ kw_des.c \
+ symkeys.c \
+ asymkeys.c \
+ signatures.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_gcrypt_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_gcrypt_la_LIBADD = \
+ $(GCRYPT_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/gcrypt/Makefile.in b/src/gcrypt/Makefile.in
new file mode 100644
index 00000000..13a08d13
--- /dev/null
+++ b/src/gcrypt/Makefile.in
@@ -0,0 +1,764 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c
+subdir = src/gcrypt
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__libxmlsec1_gcrypt_la_SOURCES_DIST = app.c asn1.h asn1.c ciphers.c \
+ crypto.c digests.c hmac.c kw_aes.c kw_des.c symkeys.c \
+ asymkeys.c signatures.c globals.h ../strings.c
+am__objects_1 =
+@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_gcrypt_la-strings.lo
+am_libxmlsec1_gcrypt_la_OBJECTS = libxmlsec1_gcrypt_la-app.lo \
+ libxmlsec1_gcrypt_la-asn1.lo libxmlsec1_gcrypt_la-ciphers.lo \
+ libxmlsec1_gcrypt_la-crypto.lo libxmlsec1_gcrypt_la-digests.lo \
+ libxmlsec1_gcrypt_la-hmac.lo libxmlsec1_gcrypt_la-kw_aes.lo \
+ libxmlsec1_gcrypt_la-kw_des.lo libxmlsec1_gcrypt_la-symkeys.lo \
+ libxmlsec1_gcrypt_la-asymkeys.lo \
+ libxmlsec1_gcrypt_la-signatures.lo $(am__objects_1) \
+ $(am__objects_2)
+libxmlsec1_gcrypt_la_OBJECTS = $(am_libxmlsec1_gcrypt_la_OBJECTS)
+libxmlsec1_gcrypt_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_gcrypt_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_gcrypt_la_SOURCES)
+DIST_SOURCES = $(am__libxmlsec1_gcrypt_la_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CP = @CP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-gcrypt.la \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -DGCRYPT_MIN_VERSION=\"$(GCRYPT_MIN_VERSION)\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(GCRYPT_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_SOURCES = app.c asn1.h asn1.c ciphers.c crypto.c \
+ digests.c hmac.c kw_aes.c kw_des.c symkeys.c asymkeys.c \
+ signatures.c globals.h $(NULL) $(am__append_1)
+libxmlsec1_gcrypt_la_LIBADD = \
+ $(GCRYPT_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_gcrypt_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_gcrypt_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/gcrypt/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/gcrypt/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-gcrypt.la: $(libxmlsec1_gcrypt_la_OBJECTS) $(libxmlsec1_gcrypt_la_DEPENDENCIES)
+ $(libxmlsec1_gcrypt_la_LINK) -rpath $(libdir) $(libxmlsec1_gcrypt_la_OBJECTS) $(libxmlsec1_gcrypt_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-digests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_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_gcrypt_la-app.lo: app.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-app.Tpo -c -o libxmlsec1_gcrypt_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-app.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-app.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+
+libxmlsec1_gcrypt_la-asn1.lo: asn1.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-asn1.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Tpo -c -o libxmlsec1_gcrypt_la-asn1.lo `test -f 'asn1.c' || echo '$(srcdir)/'`asn1.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='asn1.c' object='libxmlsec1_gcrypt_la-asn1.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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-asn1.lo `test -f 'asn1.c' || echo '$(srcdir)/'`asn1.c
+
+libxmlsec1_gcrypt_la-ciphers.lo: ciphers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Tpo -c -o libxmlsec1_gcrypt_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+
+libxmlsec1_gcrypt_la-crypto.lo: crypto.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Tpo -c -o libxmlsec1_gcrypt_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+
+libxmlsec1_gcrypt_la-digests.lo: digests.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-digests.Tpo -c -o libxmlsec1_gcrypt_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-digests.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-digests.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+
+libxmlsec1_gcrypt_la-hmac.lo: hmac.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Tpo -c -o libxmlsec1_gcrypt_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+
+libxmlsec1_gcrypt_la-kw_aes.lo: kw_aes.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Tpo -c -o libxmlsec1_gcrypt_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+
+libxmlsec1_gcrypt_la-kw_des.lo: kw_des.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Tpo -c -o libxmlsec1_gcrypt_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+
+libxmlsec1_gcrypt_la-symkeys.lo: symkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Tpo -c -o libxmlsec1_gcrypt_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+
+libxmlsec1_gcrypt_la-asymkeys.lo: asymkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-asymkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Tpo -c -o libxmlsec1_gcrypt_la-asymkeys.lo `test -f 'asymkeys.c' || echo '$(srcdir)/'`asymkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='asymkeys.c' object='libxmlsec1_gcrypt_la-asymkeys.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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-asymkeys.lo `test -f 'asymkeys.c' || echo '$(srcdir)/'`asymkeys.c
+
+libxmlsec1_gcrypt_la-signatures.lo: signatures.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Tpo -c -o libxmlsec1_gcrypt_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+
+libxmlsec1_gcrypt_la-strings.lo: ../strings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-strings.Tpo -c -o libxmlsec1_gcrypt_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-strings.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-strings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_gcrypt_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_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_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/gcrypt/README b/src/gcrypt/README
new file mode 100644
index 00000000..dcaa5a0d
--- /dev/null
+++ b/src/gcrypt/README
@@ -0,0 +1,9 @@
+The xmlsec-gcrypt 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
+
+
diff --git a/src/gcrypt/app.c b/src/gcrypt/app.c
new file mode 100644
index 00000000..ab95f6dd
--- /dev/null
+++ b/src/gcrypt/app.c
@@ -0,0 +1,663 @@
+/**
+ * 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 <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/app.h>
+#include <xmlsec/gcrypt/crypto.h>
+
+#include "asn1.h"
+
+/**
+ * xmlSecGCryptAppInit:
+ * @config: the path to GCrypt 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
+xmlSecGCryptAppInit(const char* config ATTRIBUTE_UNUSED) {
+ /* Secure memory initialisation based on documentation from:
+ http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html
+ NOTE sample code don't check gcry_control(...) return code
+
+ All flags from:
+ http://www.gnupg.org/documentation/manuals/gcrypt/Controlling-the-library.html
+
+ Also libgcrypt NEWS entries:
++++++
+.....
+Noteworthy changes in version 1.4.3 (2008-09-18)
+------------------------------------------------
+
+ * Try to auto-initialize Libgcrypt to minimize the effect of
+ applications not doing that correctly. This is not a perfect
+ solution but given that many applicationion would totally fail
+ without such a hack, we try to help at least with the most common
+ cases. Folks, please read the manual to learn how to properly
+ initialize Libgcrypt!
+
+ * Auto-initialize the secure memory to 32k instead of aborting the
+ process.
+.....
++++++
+ */
+
+ /* Version check should be the very first call because it
+ makes sure that important subsystems are intialized. */
+
+ /* NOTE configure.in defines GCRYPT_MIN_VERSION */
+ if (!gcry_check_version (GCRYPT_MIN_VERSION)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_check_version",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* We don't want to see any warnings, e.g. because we have not yet
+ parsed program options which might be used to suppress such
+ warnings. */
+ gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
+
+ /* ... If required, other initialization goes here. Note that the
+ process might still be running with increased privileges and that
+ the secure memory has not been intialized. */
+
+ /* Allocate a pool of 32k secure memory. This make the secure memory
+ available and also drops privileges where needed. */
+ gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
+
+ /* It is now okay to let Libgcrypt complain when there was/is
+ a problem with the secure memory. */
+ gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
+
+ /* ... If required, other initialization goes here. */
+
+ /* Tell Libgcrypt that initialization has completed. */
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+ return(0);
+}
+
+/**
+ * xmlSecGCryptAppShutdown:
+ *
+ * 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
+xmlSecGCryptAppShutdown(void) {
+ gcry_error_t err;
+
+ err = gcry_control(GCRYCTL_TERM_SECMEM);
+ if (gcry_err_code(err)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_control(GCRYCTL_TERM_SECMEM)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecGCryptAppKeyLoad:
+ * @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
+xmlSecGCryptAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd,
+ void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecKeyPtr key;
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ ret = xmlSecBufferInitialize(&buffer, 4*1024);
+ 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) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ key = xmlSecGCryptAppKeyLoadMemory(xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer),
+ format, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppKeyLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ /* cleanup */
+ xmlSecBufferFinalize(&buffer);
+ return(key);
+}
+
+/**
+ * xmlSecGCryptAppKeyLoadMemory:
+ * @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
+xmlSecGCryptAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format,
+ const char *pwd ATTRIBUTE_UNUSED,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED)
+{
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyDataPtr key_data = NULL;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 0, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+ case xmlSecKeyDataFormatDer:
+ key_data = xmlSecGCryptParseDer(data, dataSize, xmlSecGCryptDerKeyTypeAuto);
+ if(key_data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptParseDer",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ case xmlSecKeyDataFormatPem:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppKeyLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+#ifndef XMLSEC_NO_X509
+ case xmlSecKeyDataFormatPkcs12:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppKeyLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+#endif /* XMLSEC_NO_X509 */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ /* we should have key data by now */
+ xmlSecAssert2(key_data != NULL, NULL);
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(key_data);
+ return(NULL);
+ }
+
+ ret = xmlSecKeySetValue(key, key_data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(key_data)));
+ xmlSecKeyDestroy(key);
+ xmlSecKeyDataDestroy(key_data);
+ return(NULL);
+ }
+ key_data = NULL; /* key_data is owned by key */
+
+ /* done */
+ return(key);
+}
+
+#ifndef XMLSEC_NO_X509
+/**
+ * xmlSecGCryptAppKeyCertLoad:
+ * @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
+xmlSecGCryptAppKeyCertLoad(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,
+ "xmlSecGCryptAppKeyCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecGCryptAppKeyCertLoadMemory:
+ * @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
+xmlSecGCryptAppKeyCertLoadMemory(xmlSecKeyPtr key,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppKeyCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecGCryptAppPkcs12Load:
+ * @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 xmlSecGCryptAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGCryptAppPkcs12Load(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,
+ "xmlSecGCryptAppPkcs12Load",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecGCryptAppPkcs12LoadMemory:
+ * @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 xmlSecGCryptAppKeyLoadMemory instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12 (not implemented yet).
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGCryptAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ const char *pwd ATTRIBUTE_UNUSED,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 0, NULL);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppPkcs12LoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+}
+
+/**
+ * xmlSecGCryptAppKeysMngrCertLoad:
+ * @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
+xmlSecGCryptAppKeysMngrCertLoad(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,
+ "xmlSecGCryptAppKeysMngrCertLoad",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+/**
+ * xmlSecGCryptAppKeysMngrCertLoadMemory:
+ * @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
+xmlSecGCryptAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* TODO */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppKeysMngrCertLoadMemory",
+ XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecGCryptAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId
+ * and a default GCrypt crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptAppDefaultKeysMngrInit(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 = xmlSecGCryptKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* TODO */
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecGCryptAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecGCryptAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptAppDefaultKeysMngrAdoptKey(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);
+}
+
+/**
+ * xmlSecGCryptAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecGCryptAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptAppDefaultKeysMngrLoad(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);
+}
+
+/**
+ * xmlSecGCryptAppDefaultKeysMngrSave:
+ * @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
+xmlSecGCryptAppDefaultKeysMngrSave(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);
+}
+
+/**
+ * xmlSecGCryptAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecGCryptAppGetDefaultPwdCallback(void) {
+ return(NULL);
+}
+
diff --git a/src/gcrypt/asn1.c b/src/gcrypt/asn1.c
new file mode 100644
index 00000000..b1388420
--- /dev/null
+++ b/src/gcrypt/asn1.c
@@ -0,0 +1,602 @@
+/**
+ * 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 <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/crypto.h>
+
+#include "asn1.h"
+
+/**************************************************************************
+ *
+ * ASN.1 parser is taken from GCrypt tests
+ *
+ *************************************************************************/
+
+/* ASN.1 classes. */
+enum
+{
+ UNIVERSAL = 0,
+ APPLICATION = 1,
+ ASNCONTEXT = 2,
+ PRIVATE = 3
+};
+
+
+/* ASN.1 tags. */
+enum
+{
+ TAG_NONE = 0,
+ TAG_BOOLEAN = 1,
+ TAG_INTEGER = 2,
+ TAG_BIT_STRING = 3,
+ TAG_OCTET_STRING = 4,
+ TAG_NULL = 5,
+ TAG_OBJECT_ID = 6,
+ TAG_OBJECT_DESCRIPTOR = 7,
+ TAG_EXTERNAL = 8,
+ TAG_REAL = 9,
+ TAG_ENUMERATED = 10,
+ TAG_EMBEDDED_PDV = 11,
+ TAG_UTF8_STRING = 12,
+ TAG_REALTIVE_OID = 13,
+ TAG_SEQUENCE = 16,
+ TAG_SET = 17,
+ TAG_NUMERIC_STRING = 18,
+ TAG_PRINTABLE_STRING = 19,
+ TAG_TELETEX_STRING = 20,
+ TAG_VIDEOTEX_STRING = 21,
+ TAG_IA5_STRING = 22,
+ TAG_UTC_TIME = 23,
+ TAG_GENERALIZED_TIME = 24,
+ TAG_GRAPHIC_STRING = 25,
+ TAG_VISIBLE_STRING = 26,
+ TAG_GENERAL_STRING = 27,
+ TAG_UNIVERSAL_STRING = 28,
+ TAG_CHARACTER_STRING = 29,
+ TAG_BMP_STRING = 30
+};
+
+/* ASN.1 Parser object. */
+struct tag_info
+{
+ int class; /* Object class. */
+ unsigned long tag; /* The tag of the object. */
+ unsigned long length; /* Length of the values. */
+ int nhdr; /* Length of the header (TL). */
+ unsigned int ndef:1; /* The object has an indefinite length. */
+ unsigned int cons:1; /* This is a constructed object. */
+};
+
+/* Parse the buffer at the address BUFFER which consists of the number
+ of octets as stored at BUFLEN. Return the tag and the length part
+ from the TLV triplet. Update BUFFER and BUFLEN on success. Checks
+ that the encoded length does not exhaust the length of the provided
+ buffer. */
+static int
+xmlSecGCryptAsn1ParseTag (xmlSecByte const **buffer, xmlSecSize *buflen, struct tag_info *ti)
+{
+ int c;
+ unsigned long tag;
+ const xmlSecByte *buf;
+ xmlSecSize length;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2((*buffer) != NULL, -1);
+ xmlSecAssert2(buflen != NULL, -1);
+ xmlSecAssert2(ti != NULL, -1);
+
+ /* initialize */
+ buf = *buffer;
+ length = *buflen;
+
+ ti->length = 0;
+ ti->ndef = 0;
+ ti->nhdr = 0;
+
+ /* Get the tag */
+ if (length <= 0) {
+ return(-1); /* Premature EOF. */
+ }
+ c = *buf++;
+ length--;
+ ti->nhdr++;
+
+ ti->class = (c & 0xc0) >> 6;
+ ti->cons = !!(c & 0x20);
+ tag = (c & 0x1f);
+
+ if (tag == 0x1f) {
+ tag = 0;
+ do {
+ tag <<= 7;
+ if (length <= 0) {
+ return(-1); /* Premature EOF. */
+ }
+ c = *buf++;
+ length--;
+ ti->nhdr++;
+ tag |= (c & 0x7f);
+ } while ( (c & 0x80) );
+ }
+ ti->tag = tag;
+
+ /* Get the length */
+ if(length <= 0) {
+ return -1; /* Premature EOF. */
+ }
+ c = *buf++;
+ length--;
+ ti->nhdr++;
+
+ if ( !(c & 0x80) ) {
+ ti->length = c;
+ } else if (c == 0x80) {
+ ti->ndef = 1;
+ } else if (c == 0xff) {
+ return -1; /* Forbidden length value. */
+ } else {
+ xmlSecSize len = 0;
+ int count = c & 0x7f;
+
+ for (; count; count--) {
+ len <<= 8;
+ if (length <= 0) {
+ return -1; /* Premature EOF. */
+ }
+ c = *buf++; length--;
+ ti->nhdr++;
+ len |= (c & 0xff);
+ }
+ ti->length = len;
+ }
+
+ if (ti->class == UNIVERSAL && !ti->tag) {
+ ti->length = 0;
+ }
+
+ if (ti->length > length) {
+ return(-1); /* Data larger than buffer. */
+ }
+
+ /* done */
+ *buffer = buf;
+ *buflen = length;
+ return(0);
+}
+
+static int
+xmlSecGCryptAsn1ParseIntegerSequence(xmlSecByte const **buffer, xmlSecSize *buflen,
+ gcry_mpi_t * params, int params_size) {
+ const xmlSecByte *buf;
+ xmlSecSize length;
+ struct tag_info ti;
+ gcry_error_t err;
+ int idx = 0;
+ int ret;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2((*buffer) != NULL, -1);
+ xmlSecAssert2(buflen != NULL, -1);
+ xmlSecAssert2(params != NULL, -1);
+ xmlSecAssert2(params_size > 0, -1);
+
+ /* initialize */
+ buf = *buffer;
+ length = *buflen;
+
+ /* read SEQUENCE */
+ memset(&ti, 0, sizeof(ti));
+ ret = xmlSecGCryptAsn1ParseTag (&buf, &length, &ti);
+ if((ret != 0) || (ti.tag != TAG_SEQUENCE) || ti.class || !ti.cons || ti.ndef) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsn1ParseTag",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "TAG_SEQUENCE is expected: tag=%d",
+ (int)ti.tag);
+ return(-1);
+ }
+
+ /* read INTEGERs */
+ for (idx = 0; ((idx < params_size) && (length > 0)); idx++) {
+ memset(&ti, 0, sizeof(ti));
+ ret = xmlSecGCryptAsn1ParseTag (&buf, &length, &ti);
+ if((ret != 0) || (ti.tag != TAG_INTEGER) || ti.class || ti.cons || ti.ndef)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsn1ParseTag",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "TAG_INTEGER is expected - index=%d, tag=%d",
+ (int)idx, (int)ti.tag);
+ return(-1);
+ }
+
+ err = gcry_mpi_scan(&(params[idx]), GCRYMPI_FMT_USG, buf, ti.length, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (params[idx] == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+ buf += ti.length;
+ length -= ti.length;
+ }
+
+ /* did we parse everything? */
+ if(length > 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsn1ParseTag",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "too many params - cur=%d, expected=%d",
+ (int)(idx - 1), (int)params_size);
+ return(-1);
+ }
+
+ /* done */
+ *buffer = buf;
+ *buflen = length;
+ return(idx);
+}
+
+xmlSecKeyDataPtr
+xmlSecGCryptParseDer(const xmlSecByte * der, xmlSecSize derlen,
+ enum xmlSecGCryptDerKeyType type) {
+ xmlSecKeyDataPtr key_data = NULL;
+ gcry_sexp_t s_pub_key = NULL;
+ gcry_sexp_t s_priv_key = NULL;
+ gcry_error_t err;
+ gcry_mpi_t keyparms[20];
+ int keyparms_num;
+ unsigned int idx;
+ int ret;
+
+ xmlSecAssert2(der != NULL, NULL);
+ xmlSecAssert2(derlen > 0, NULL);
+
+ /* Parse the ASN.1 structure. */
+ memset(&keyparms, 0, sizeof(keyparms));
+ ret = xmlSecGCryptAsn1ParseIntegerSequence(
+ &der, &derlen,
+ keyparms, sizeof(keyparms) / sizeof(keyparms[0])
+ );
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsn1ParseIntegerSequence",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ keyparms_num = ret;
+
+ /* The value of the first integer should be 0. */
+ if ((keyparms_num < 1) || (gcry_mpi_cmp_ui(keyparms[0], 0) != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsn1ParseTag",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "num=%d",
+ (int)keyparms_num);
+ goto done;
+ }
+
+ /* do we need to guess the key type? not robust but the best we can do */
+ if(type == xmlSecGCryptDerKeyTypeAuto) {
+ switch(keyparms_num) {
+ case 3:
+ /* Public RSA */
+ type = xmlSecGCryptDerKeyTypePublicRsa;
+ case 5:
+ /* Public DSA */
+ type = xmlSecGCryptDerKeyTypePublicDsa;
+ case 6:
+ /* Private DSA */
+ type = xmlSecGCryptDerKeyTypePrivateDsa;
+ break;
+ case 9:
+ /* Private RSA */
+ type = xmlSecGCryptDerKeyTypePrivateRsa;
+ break;
+ default:
+ /* unknown */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Unexpected number of parameters, unknown key type",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "keyparms_num=%d", (int)keyparms_num);
+ goto done;
+ }
+ }
+
+
+ switch(type) {
+#ifndef XMLSEC_NO_DSA
+ case xmlSecGCryptDerKeyTypePrivateDsa:
+ /* check we have enough params */
+ if(keyparms_num != 6) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Private DSA key: 6 parameters exepcted",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "parms_num=%d", (int)keyparms_num);
+ goto done;
+ }
+
+ /* Convert from OpenSSL parameter ordering to the OpenPGP order. */
+ /* First check that x < y; if not swap x and y */
+ if (gcry_mpi_cmp (keyparms[4], keyparms[5]) > 0) {
+ gcry_mpi_swap (keyparms[4], keyparms[5]);
+ }
+
+ /* Build the S-expressions */
+ err = gcry_sexp_build (&s_priv_key, NULL,
+ "(private-key(dsa(p%m)(q%m)(g%m)(x%m)(y%m)))",
+ keyparms[1], keyparms[2], keyparms[3], keyparms[4], keyparms[5]
+ );
+ if((err != GPG_ERR_NO_ERROR) || (s_priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private-key/dsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_pub_key, NULL,
+ "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ keyparms[1], keyparms[2], keyparms[3], keyparms[5]
+ );
+ if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(public-key/dsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* construct key and key data */
+ key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataDsaId);
+ if(key_data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataDsaId");
+ goto done;
+ }
+
+ ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(key_data, s_pub_key, s_priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataDsaAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataDsaId");
+ xmlSecKeyDataDestroy(key_data);
+ key_data = NULL;
+ goto done;
+ }
+ s_pub_key = NULL; /* owned by key_data now */
+ s_priv_key = NULL; /* owned by key_data now */
+ break;
+
+ case xmlSecGCryptDerKeyTypePublicDsa:
+ /* check we have enough params */
+ if(keyparms_num != 5) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Public DSA key: 5 parameters exepcted",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "parms_num=%d", (int)keyparms_num);
+ goto done;
+ }
+
+ /* Build the S-expression. */
+ err = gcry_sexp_build (&s_pub_key, NULL,
+ "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ keyparms[2], keyparms[3], keyparms[4], keyparms[1]
+ );
+ if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(public-key/dsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* construct key and key data */
+ key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataDsaId);
+ if(key_data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataDsaId");
+ goto done;
+ }
+
+ ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(key_data, s_pub_key, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataDsaAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataDsaId");
+ xmlSecKeyDataDestroy(key_data);
+ key_data = NULL;
+ goto done;
+ }
+ s_pub_key = NULL; /* owned by key_data now */
+ break;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+ case xmlSecGCryptDerKeyTypePrivateRsa:
+ /* check we have enough params */
+ if(keyparms_num != 9) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Private RSA key: 9 parameters exepcted",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "parms_num=%d", (int)keyparms_num);
+ goto done;
+ }
+
+ /* Convert from OpenSSL parameter ordering to the OpenPGP order. */
+ /* First check that p < q; if not swap p and q and recompute u. */
+ if (gcry_mpi_cmp (keyparms[4], keyparms[5]) > 0) {
+ gcry_mpi_swap (keyparms[4], keyparms[5]);
+ gcry_mpi_invm (keyparms[8], keyparms[4], keyparms[5]);
+ }
+
+ /* Build the S-expression. */
+ err = gcry_sexp_build (&s_priv_key, NULL,
+ "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
+ keyparms[1], keyparms[2],
+ keyparms[3], keyparms[4],
+ keyparms[5], keyparms[8]
+ );
+ if((err != GPG_ERR_NO_ERROR) || (s_priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private-key/rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_pub_key, NULL,
+ "(public-key(rsa(n%m)(e%m)))",
+ keyparms[1], keyparms[2]
+ );
+ if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(public-key/rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* construct key and key data */
+ key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataRsaId);
+ if(key_data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataRsaId");
+ goto done;
+ }
+
+ ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(key_data, s_pub_key, s_priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataRsaAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataRsaId");
+ xmlSecKeyDataDestroy(key_data);
+ key_data = NULL;
+ goto done;
+ }
+ s_pub_key = NULL; /* owned by key_data now */
+ s_priv_key = NULL; /* owned by key_data now */
+ break;
+
+ case xmlSecGCryptDerKeyTypePublicRsa:
+ /* check we have enough params */
+ if(keyparms_num != 3) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Public RSA key: 3 parameters exepcted",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "parms_num=%d", (int)keyparms_num);
+ goto done;
+ }
+
+ /* Build the S-expression. */
+ err = gcry_sexp_build (&s_pub_key, NULL,
+ "(public-key(rsa(n%m)(e%m)))",
+ keyparms[1], keyparms[2]
+ );
+ if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(public-key/rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* construct key and key data */
+ key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataRsaId);
+ if(key_data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataRsaId");
+ goto done;
+ }
+
+ ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(key_data, s_pub_key, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataRsaAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGCryptKeyDataRsaId");
+ xmlSecKeyDataDestroy(key_data);
+ key_data = NULL;
+ goto done;
+ }
+ s_pub_key = NULL; /* owned by key_data now */
+ break;
+#endif /* XMLSEC_NO_RSA */
+
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Unsupported key type",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "type=%d", (int)type);
+ goto done;
+ break;
+ }
+
+done:
+ if(s_priv_key != NULL) {
+ gcry_sexp_release(s_priv_key);
+ }
+ if(s_pub_key != NULL) {
+ gcry_sexp_release(s_pub_key);
+ }
+ for (idx = 0; idx < sizeof(keyparms) / sizeof(keyparms[0]); idx++) {
+ if(keyparms[idx] != NULL) {
+ gcry_mpi_release (keyparms[idx]);
+ }
+ }
+
+ return(key_data);
+}
diff --git a/src/gcrypt/asn1.h b/src/gcrypt/asn1.h
new file mode 100644
index 00000000..d05b5305
--- /dev/null
+++ b/src/gcrypt/asn1.h
@@ -0,0 +1,39 @@
+/*
+ * XML Security Library
+ *
+ * gcrypt/asn1.h: internal header only used during the compilation
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef __XMLSEC_GCRYPT_ASN1_H__
+#define __XMLSEC_GCRYPT_ASN1_H__
+
+#ifndef XMLSEC_PRIVATE
+#error "gcrypt/asn1.h file contains private xmlsec-gcrypt definitions and should not be used outside xmlsec or xmlsec-<crypto> libraries"
+#endif /* XMLSEC_PRIVATE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+enum xmlSecGCryptDerKeyType {
+ xmlSecGCryptDerKeyTypeAuto = 0,
+ xmlSecGCryptDerKeyTypePublicDsa,
+ xmlSecGCryptDerKeyTypePublicRsa,
+ xmlSecGCryptDerKeyTypePrivateDsa,
+ xmlSecGCryptDerKeyTypePrivateRsa
+};
+
+xmlSecKeyDataPtr xmlSecGCryptParseDer (const xmlSecByte * der,
+ xmlSecSize derlen,
+ enum xmlSecGCryptDerKeyType type);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /*__XMLSEC_GCRYPT_ASN1_H__ */
diff --git a/src/gcrypt/asymkeys.c b/src/gcrypt/asymkeys.c
new file mode 100644
index 00000000..8f0cec88
--- /dev/null
+++ b/src/gcrypt/asymkeys.c
@@ -0,0 +1,1920 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/crypto.h>
+
+/**************************************************************************
+ *
+ * Helpers
+ *
+ *************************************************************************/
+static gcry_sexp_t xmlSecGCryptAsymSExpDup (gcry_sexp_t sexp);
+
+
+/**************************************************************************
+ *
+ * Internal GCrypt asym key CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecGCryptAsymKeyDataCtx xmlSecGCryptAsymKeyDataCtx,
+ *xmlSecGCryptAsymKeyDataCtxPtr;
+struct _xmlSecGCryptAsymKeyDataCtx {
+ gcry_sexp_t pub_key;
+ gcry_sexp_t priv_key;
+};
+
+/******************************************************************************
+ *
+ * Asym key (dsa/rsa)
+ *
+ * xmlSecGCryptAsymKeyDataCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGCryptAsymKeyDataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecGCryptAsymKeyDataCtx))
+#define xmlSecGCryptAsymKeyDataGetCtx(data) \
+ ((xmlSecGCryptAsymKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecGCryptAsymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptAsymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecGCryptAsymKeyDataFinalize (xmlSecKeyDataPtr data);
+
+static int xmlSecGCryptAsymKeyDataAdoptKey (xmlSecKeyDataPtr data,
+ gcry_sexp_t key_pair);
+static int xmlSecGCryptAsymKeyDataAdoptKeyPair (xmlSecKeyDataPtr data,
+ gcry_sexp_t pub_key,
+ gcry_sexp_t priv_key);
+static gcry_sexp_t xmlSecGCryptAsymKeyDataGetPublicKey (xmlSecKeyDataPtr data);
+static gcry_sexp_t xmlSecGCryptAsymKeyDataGetPrivateKey (xmlSecKeyDataPtr data);
+static int xmlSecGCryptAsymKeyDataGenerate (xmlSecKeyDataPtr data,
+ const char * alg,
+ xmlSecSize key_size);
+static xmlSecKeyDataType xmlSecGCryptAsymKeyDataGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecGCryptAsymKeyDataGetSize (xmlSecKeyDataPtr data);
+
+
+static int
+xmlSecGCryptAsymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGCryptAsymKeyDataCtx));
+
+ return(0);
+}
+
+static int
+xmlSecGCryptAsymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctxDst;
+ xmlSecGCryptAsymKeyDataCtxPtr ctxSrc;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecGCryptAsymKeyDataSize), -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecGCryptAsymKeyDataSize), -1);
+
+ ctxDst = xmlSecGCryptAsymKeyDataGetCtx(dst);
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxDst->pub_key == NULL, -1);
+ xmlSecAssert2(ctxDst->priv_key == NULL, -1);
+
+ ctxSrc = xmlSecGCryptAsymKeyDataGetCtx(src);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ if(ctxSrc->pub_key != NULL) {
+ ctxDst->pub_key = xmlSecGCryptAsymSExpDup(ctxSrc->pub_key);
+ if(ctxDst->pub_key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecGCryptAsymSExpDup(pub_key)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(ctxSrc->priv_key != NULL) {
+ ctxDst->priv_key = xmlSecGCryptAsymSExpDup(ctxSrc->priv_key);
+ if(ctxDst->priv_key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecGCryptAsymSExpDup(priv_key)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static void
+xmlSecGCryptAsymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize));
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->pub_key != NULL) {
+ gcry_sexp_release(ctx->pub_key);
+ }
+ if(ctx->priv_key != NULL) {
+ gcry_sexp_release(ctx->priv_key);
+ }
+ memset(ctx, 0, sizeof(xmlSecGCryptAsymKeyDataCtx));
+}
+
+static int
+xmlSecGCryptAsymKeyDataAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t key_pair) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+ gcry_sexp_t pub_key = NULL;
+ gcry_sexp_t priv_key = NULL;
+ int res = -1;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
+ xmlSecAssert2(key_pair != NULL, -1);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* split the key pair, public part should be always present, private might
+ not be present */
+ pub_key = gcry_sexp_find_token(key_pair, "public-key", 0);
+ if(pub_key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(public-key)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ priv_key = gcry_sexp_find_token(key_pair, "private-key", 0);
+
+ /* assign */
+ if(xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsymKeyDataAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pub_key = NULL; /* data owns it now */
+ priv_key = NULL; /* data owns it now */
+
+ /* success */
+ res = 0;
+
+done:
+ if(pub_key != NULL) {
+ gcry_sexp_release(pub_key);
+ }
+
+ if(priv_key != NULL) {
+ gcry_sexp_release(priv_key);
+ }
+
+ /* done */
+ return(res);
+}
+
+static int
+xmlSecGCryptAsymKeyDataAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
+ xmlSecAssert2(pub_key != NULL, -1); /* public key should present always */
+/*
+ aleksey - we don't set optional parameters for RSA keys (p, k, u) and
+ because of that we can't actually test the key
+
+ xmlSecAssert2(((priv_key == NULL) || (gcry_pk_testkey(priv_key) == GPG_ERR_NO_ERROR)), -1);
+*/
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* release prev values and assign new ones */
+ if(ctx->pub_key != NULL) {
+ gcry_sexp_release(ctx->pub_key);
+ }
+ if(ctx->priv_key != NULL) {
+ gcry_sexp_release(ctx->priv_key);
+ }
+
+ ctx->pub_key = pub_key;
+ ctx->priv_key = priv_key;
+
+ /* done */
+ return(0);
+}
+
+static gcry_sexp_t
+xmlSecGCryptAsymKeyDataGetPublicKey(xmlSecKeyDataPtr data) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), NULL);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->pub_key);
+}
+
+static gcry_sexp_t
+xmlSecGCryptAsymKeyDataGetPrivateKey(xmlSecKeyDataPtr data) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), NULL);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->priv_key);
+}
+
+static int
+xmlSecGCryptAsymKeyDataGenerate(xmlSecKeyDataPtr data, const char * alg, xmlSecSize key_size) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+ gcry_sexp_t key_spec = NULL;
+ gcry_sexp_t key_pair = NULL;
+ gcry_error_t err;
+ int ret;
+ int res = -1;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
+ xmlSecAssert2(alg != NULL, -1);
+ xmlSecAssert2(key_size > 0, -1);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ err = gcry_sexp_build(&key_spec, NULL,
+ "(genkey (%s (nbits %d)(transient-key)))",
+ alg, (int)key_size);
+ if((err != GPG_ERR_NO_ERROR) || (key_spec == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(genkey)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_pk_genkey(&key_pair, key_spec);
+ if((err != GPG_ERR_NO_ERROR) || (key_pair == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_genkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ ret = xmlSecGCryptAsymKeyDataAdoptKey(data, key_pair);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAsymKeyDataAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", (int)ret);
+ goto done;
+ }
+ key_pair = NULL; /* now owned by data */
+
+ /* success */
+ res = 0;
+
+done:
+ if(key_spec != NULL) {
+ gcry_sexp_release(key_spec);
+ }
+ if(key_pair != NULL) {
+ gcry_sexp_release(key_pair);
+ }
+
+ return(res);
+}
+
+static xmlSecKeyDataType
+xmlSecGCryptAsymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), xmlSecKeyDataTypeUnknown);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown);
+
+ if((ctx->priv_key != NULL) && (ctx->pub_key != NULL)) {
+ return (xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else if(ctx->pub_key != NULL) {
+ return (xmlSecKeyDataTypePublic);
+ }
+
+ return (xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecGCryptAsymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecGCryptAsymKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), xmlSecKeyDataTypeUnknown);
+
+ ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ /* use pub key since it is more often you have it than not */
+ return (ctx->pub_key != NULL) ? gcry_pk_get_nbits(ctx->pub_key) : 0;
+}
+
+/******************************************************************************
+ *
+ * helper functions
+ *
+ *****************************************************************************/
+static gcry_sexp_t
+xmlSecGCryptAsymSExpDup(gcry_sexp_t pKey) {
+ gcry_sexp_t res = NULL;
+ xmlSecByte *buf = NULL;
+ gcry_error_t err;
+ size_t size;
+
+ xmlSecAssert2(pKey != NULL, NULL);
+
+ size = gcry_sexp_sprint(pKey, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+ if(size == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_sprint",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ buf = (xmlSecByte *)xmlMalloc(size);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)size);
+ goto done;
+ }
+
+ size = gcry_sexp_sprint(pKey, GCRYSEXP_FMT_ADVANCED, buf, size);
+ if(size == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_sprint",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", (int)size);
+ goto done;
+ }
+
+ err = gcry_sexp_new(&res, buf, size, 1);
+ if((err != GPG_ERR_NO_ERROR) || (res == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+done:
+ if(buf != NULL) {
+ xmlFree(buf);
+ }
+ return (res);
+}
+
+/**
+ * xmlSecGCryptNodeGetMpiValue:
+ * @cur: the poitner to an XML node.
+ *
+ * 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 MPI produced from CryptoBinary string
+ * or NULL if an error occurs.
+ */
+static gcry_mpi_t
+xmlSecGCryptNodeGetMpiValue(const xmlNodePtr cur) {
+ xmlSecBuffer buf;
+ gcry_mpi_t res = NULL;
+ gcry_error_t err;
+ 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);
+ }
+
+ err = gcry_mpi_scan(&res, GCRYMPI_FMT_USG,
+ xmlSecBufferGetData(&buf),
+ xmlSecBufferGetSize(&buf),
+ NULL);
+ if((err != GPG_ERR_NO_ERROR) || (res == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ xmlSecBufferFinalize(&buf);
+ return(NULL);
+ }
+
+ /* done */
+ xmlSecBufferFinalize(&buf);
+ return(res);
+}
+
+/**
+ * xmlSecGCryptNodeSetMpiValue:
+ * @cur: the pointer to an XML node.
+ * @a: the mpi value
+ * @addLineBreaks: if the flag is equal to 1 then
+ * linebreaks will be added before and after
+ * new buffer content.
+ *
+ * Converts MPI 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.
+ */
+static int
+xmlSecGCryptNodeSetMpiValue(xmlNodePtr cur, const gcry_mpi_t a, int addLineBreaks) {
+ xmlSecBuffer buf;
+ gcry_error_t err;
+ size_t written = 0;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ written = 0;
+ err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &written, a);
+ if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_print",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&buf, written + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", (int)written + 1);
+ return(-1);
+ }
+
+ written = 0;
+ err = gcry_mpi_print(GCRYMPI_FMT_USG,
+ xmlSecBufferGetData(&buf),
+ xmlSecBufferGetMaxSize(&buf),
+ &written, a);
+ if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_print",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetSize(&buf, written);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "written=%d", (int)written);
+ 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);
+}
+
+/**
+ * xmlSecGCryptNodeSetSExpTokValue:
+ * @cur: the pointer to an XML node.
+ * @sexp: the sexp
+ * @tok: the token
+ * @addLineBreaks: if the flag is equal to 1 then
+ * linebreaks will be added before and after
+ * new buffer content.
+ *
+ * Converts MPI 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.
+ */
+static int
+xmlSecGCryptNodeSetSExpTokValue(xmlNodePtr cur, const gcry_sexp_t sexp,
+ const char * tok, int addLineBreaks)
+{
+ gcry_sexp_t val = NULL;
+ gcry_mpi_t mpi = NULL;
+ int res = -1;
+
+ xmlSecAssert2(cur != NULL, -1);
+ xmlSecAssert2(sexp != NULL, -1);
+ xmlSecAssert2(tok != NULL, -1);
+
+ val = gcry_sexp_find_token(sexp, tok, 0);
+ if(val == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "tok=%s",
+ xmlSecErrorsSafeString(tok));
+ goto done;
+ }
+
+ mpi = gcry_sexp_nth_mpi(val, 1, GCRYMPI_FMT_USG);
+ if(mpi == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "tok=%s",
+ xmlSecErrorsSafeString(tok));
+ goto done;
+ }
+
+ /* almost done */
+ res = xmlSecGCryptNodeSetMpiValue(cur, mpi, addLineBreaks);
+
+done:
+ if(mpi != NULL) {
+ gcry_mpi_release(mpi);
+ }
+ if(val != NULL) {
+ gcry_sexp_release(val);
+ }
+
+ return(res);
+}
+
+#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 xmlSecGCryptKeyDataDsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptKeyDataDsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecGCryptKeyDataDsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptKeyDataDsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptKeyDataDsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptKeyDataDsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecGCryptKeyDataDsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecGCryptKeyDataDsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecGCryptKeyDataDsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecGCryptKeyDataDsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecGCryptKeyDataDsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecGCryptAsymKeyDataSize,
+
+ /* data */
+ xmlSecNameDSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGCryptKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGCryptKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGCryptKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGCryptKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGCryptKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGCryptKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGCryptKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGCryptKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGCryptKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGCryptKeyDataDsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGCryptKeyDataDsaGetKlass(void) {
+ return(&xmlSecGCryptKeyDataDsaKlass);
+}
+
+/**
+ * xmlSecGCryptKeyDataDsaAdoptKey:
+ * @data: the pointer to DSA key data.
+ * @dsa_key: the pointer to GCrypt DSA key.
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptKeyDataDsaAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t dsa_key) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
+ xmlSecAssert2(dsa_key != NULL, -1);
+
+ return xmlSecGCryptAsymKeyDataAdoptKey(data, dsa_key);
+}
+
+
+/**
+ * xmlSecGCryptKeyDataDsaAdoptKeyPair:
+ * @data: the pointer to DSA key data.
+ * @pub_key: the pointer to GCrypt DSA pub key.
+ * @priv_key: the pointer to GCrypt DSA priv key.
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptKeyDataDsaAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
+ xmlSecAssert2(pub_key != NULL, -1);
+
+ return xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key);
+}
+
+/**
+ * xmlSecGCryptKeyDataDsaGetPublicKey:
+ * @data: the pointer to DSA key data.
+ *
+ * Gets the GCrypt DSA public key from DSA key data.
+ *
+ * Returns: pointer to GCrypt public DSA key or NULL if an error occurs.
+ */
+gcry_sexp_t
+xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), NULL);
+ return xmlSecGCryptAsymKeyDataGetPublicKey(data);
+}
+
+/**
+ * xmlSecGCryptKeyDataDsaGetPrivateKey:
+ * @data: the pointer to DSA key data.
+ *
+ * Gets the GCrypt DSA private key from DSA key data.
+ *
+ * Returns: pointer to GCrypt private DSA key or NULL if an error occurs.
+ */
+gcry_sexp_t
+xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), NULL);
+ return xmlSecGCryptAsymKeyDataGetPrivateKey(data);
+}
+
+static int
+xmlSecGCryptKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
+
+ return(xmlSecGCryptAsymKeyDataInitialize(data));
+}
+
+static int
+xmlSecGCryptKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGCryptKeyDataDsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGCryptKeyDataDsaId), -1);
+
+ return(xmlSecGCryptAsymKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecGCryptKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId));
+
+ xmlSecGCryptAsymKeyDataFinalize(data);
+}
+
+static int
+xmlSecGCryptKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ return xmlSecGCryptAsymKeyDataGenerate(data, "dsa", sizeBits);
+}
+
+static xmlSecKeyDataType
+xmlSecGCryptKeyDataDsaGetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), xmlSecKeyDataTypeUnknown);
+
+ return xmlSecGCryptAsymKeyDataGetType(data);
+}
+
+static xmlSecSize
+xmlSecGCryptKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), 0);
+
+ return xmlSecGCryptAsymKeyDataGetSize(data);
+}
+
+static void
+xmlSecGCryptKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== dsa key: size = %d\n",
+ xmlSecGCryptKeyDataDsaGetSize(data));
+}
+
+static void
+xmlSecGCryptKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
+ xmlSecGCryptKeyDataDsaGetSize(data));
+}
+
+static int
+xmlSecGCryptKeyDataDsaXmlRead(xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx)
+{
+ xmlNodePtr cur;
+ xmlSecKeyDataPtr data = NULL;
+ gcry_mpi_t p = NULL;
+ gcry_mpi_t q = NULL;
+ gcry_mpi_t g = NULL;
+ gcry_mpi_t x = NULL;
+ gcry_mpi_t y = NULL;
+ gcry_sexp_t pub_key = NULL;
+ gcry_sexp_t priv_key = NULL;
+ gcry_error_t err;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGCryptKeyDataDsaId, -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);
+ goto done;
+ }
+
+ 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;
+ }
+ p = xmlSecGCryptNodeGetMpiValue(cur);
+ if(p == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ 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;
+ }
+ q = xmlSecGCryptNodeGetMpiValue(cur);
+ if(q == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ 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;
+ }
+ g = xmlSecGCryptNodeGetMpiValue(cur);
+ if(g == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ 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
+ * we are not sure exactly what do we read */
+ x = xmlSecGCryptNodeGetMpiValue(cur);
+ if(x == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAX));
+ goto done;
+ }
+ 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;
+ }
+ y = xmlSecGCryptNodeGetMpiValue(cur);
+ if(y == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ 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;
+ }
+
+
+ /* construct pub/priv key pairs */
+ err = gcry_sexp_build(&pub_key, NULL,
+ "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ p, q, g, y);
+ if((err != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "gcry_sexp_build(public)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+ if(x != NULL) {
+ err = gcry_sexp_build(&priv_key, NULL,
+ "(private-key(dsa(p%m)(q%m)(g%m)(x%m)(y%m)))",
+ p, q, g, x, y);
+ if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "gcry_sexp_build(private)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+ }
+
+ /* create key data */
+ 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 = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGCryptKeyDataDsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pub_key = NULL; /* pub_key is owned by data now */
+ priv_key = NULL; /* priv_key is owned by data now */
+
+ /* set key */
+ 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; /* data is owned by key now */
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(p != NULL) {
+ gcry_mpi_release(p);
+ }
+
+ if(q != NULL) {
+ gcry_mpi_release(q);
+ }
+
+ if(g != NULL) {
+ gcry_mpi_release(g);
+ }
+
+ if(x != NULL) {
+ gcry_mpi_release(x);
+ }
+
+ if(y != NULL) {
+ gcry_mpi_release(y);
+ }
+
+ if(pub_key != NULL) {
+ gcry_sexp_release(pub_key);
+ }
+
+ if(priv_key != NULL) {
+ gcry_sexp_release(priv_key);
+ }
+
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ return(res);
+}
+
+static int
+xmlSecGCryptKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ gcry_sexp_t pub_priv_key;
+ gcry_sexp_t dsa = NULL;
+ int private = 0;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGCryptKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataDsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* find the private or public key */
+ pub_priv_key = xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyGetValue(key));
+ if(pub_priv_key == NULL) {
+ pub_priv_key = xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyGetValue(key));
+ if(pub_priv_key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptKeyDataDsaGetPublicKey()",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ } else {
+ private = 1;
+ }
+
+ dsa = gcry_sexp_find_token(pub_priv_key, "dsa", 0);
+ if(dsa == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "gcry_sexp_find_token(dsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "p", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ goto done;
+ }
+
+ /* 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "q", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ goto done;
+ }
+
+ /* 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "g", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ goto done;
+ }
+
+ /* next is X node: write it ONLY for private keys and ONLY if it is requested */
+ if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (private != 0)) {
+ 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "x", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAX));
+ goto done;
+ }
+ }
+
+ /* 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "y", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ goto done;
+ }
+
+ /* success */
+ res = 0;
+
+done:
+ if(dsa != NULL) {
+ gcry_sexp_release(dsa);
+ }
+
+ return(res);
+}
+
+#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 xmlSecGCryptKeyDataRsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptKeyDataRsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecGCryptKeyDataRsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptKeyDataRsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptKeyDataRsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptKeyDataRsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecGCryptKeyDataRsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecGCryptKeyDataRsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecGCryptKeyDataRsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecGCryptKeyDataRsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static xmlSecKeyDataKlass xmlSecGCryptKeyDataRsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecGCryptAsymKeyDataSize,
+
+ /* data */
+ xmlSecNameRSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGCryptKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGCryptKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGCryptKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGCryptKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGCryptKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGCryptKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGCryptKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGCryptKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGCryptKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGCryptKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptKeyDataRsaGetKlass:
+ *
+ * The GCrypt RSA key data klass.
+ *
+ * Returns: pointer to GCrypt RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGCryptKeyDataRsaGetKlass(void) {
+ return(&xmlSecGCryptKeyDataRsaKlass);
+}
+
+/**
+ * xmlSecGCryptKeyDataRsaAdoptKey:
+ * @data: the pointer to RSA key data.
+ * @rsa_key: the pointer to GCrypt RSA key.
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptKeyDataRsaAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t rsa_key) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
+ xmlSecAssert2(rsa_key != NULL, -1);
+
+ return xmlSecGCryptAsymKeyDataAdoptKey(data, rsa_key);
+}
+
+
+/**
+ * xmlSecGCryptKeyDataRsaAdoptKeyPair:
+ * @data: the pointer to RSA key data.
+ * @pub_key: the pointer to GCrypt RSA pub key.
+ * @priv_key: the pointer to GCrypt RSA priv key.
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptKeyDataRsaAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
+ xmlSecAssert2(pub_key != NULL, -1);
+
+ return xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key);
+}
+
+/**
+ * xmlSecGCryptKeyDataRsaGetPublicKey:
+ * @data: the pointer to RSA key data.
+ *
+ * Gets the GCrypt RSA public key from RSA key data.
+ *
+ * Returns: pointer to GCrypt public RSA key or NULL if an error occurs.
+ */
+gcry_sexp_t
+xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), NULL);
+ return xmlSecGCryptAsymKeyDataGetPublicKey(data);
+}
+
+/**
+ * xmlSecGCryptKeyDataRsaGetPrivateKey:
+ * @data: the pointer to RSA key data.
+ *
+ * Gets the GCrypt RSA private key from RSA key data.
+ *
+ * Returns: pointer to GCrypt private RSA key or NULL if an error occurs.
+ */
+gcry_sexp_t
+xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), NULL);
+ return xmlSecGCryptAsymKeyDataGetPrivateKey(data);
+}
+
+static int
+xmlSecGCryptKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
+
+ return(xmlSecGCryptAsymKeyDataInitialize(data));
+}
+
+static int
+xmlSecGCryptKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGCryptKeyDataRsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGCryptKeyDataRsaId), -1);
+
+ return(xmlSecGCryptAsymKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecGCryptKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId));
+
+ xmlSecGCryptAsymKeyDataFinalize(data);
+}
+
+static int
+xmlSecGCryptKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ return xmlSecGCryptAsymKeyDataGenerate(data, "rsa", sizeBits);
+}
+
+static xmlSecKeyDataType
+xmlSecGCryptKeyDataRsaGetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), xmlSecKeyDataTypeUnknown);
+
+ return xmlSecGCryptAsymKeyDataGetType(data);
+}
+
+static xmlSecSize
+xmlSecGCryptKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), 0);
+
+ return xmlSecGCryptAsymKeyDataGetSize(data);
+}
+
+static void
+xmlSecGCryptKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== rsa key: size = %d\n",
+ xmlSecGCryptKeyDataRsaGetSize(data));
+}
+
+static void
+xmlSecGCryptKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
+ xmlSecGCryptKeyDataRsaGetSize(data));
+}
+
+static int
+xmlSecGCryptKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ xmlSecKeyDataPtr data = NULL;
+ gcry_mpi_t n = NULL;
+ gcry_mpi_t e = NULL;
+ gcry_mpi_t d = NULL;
+ gcry_sexp_t pub_key = NULL;
+ gcry_sexp_t priv_key = NULL;
+ gcry_error_t err;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGCryptKeyDataRsaId, -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");
+ goto done;
+ }
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* first is Modulus node. It is REQUIRED */
+ 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;
+ }
+ n = xmlSecGCryptNodeGetMpiValue(cur);
+ if(n == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is Exponent node. It is REQUIRED */
+ 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;
+ }
+ e = xmlSecGCryptNodeGetMpiValue(cur);
+ if(e == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
+ /* next is PrivateExponent node. It is REQUIRED for private key */
+ d = xmlSecGCryptNodeGetMpiValue(cur);
+ if(d == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeGetMpiValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent));
+ goto done;
+ }
+ 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;
+ }
+
+ /* construct pub/priv key pairs */
+ err = gcry_sexp_build(&pub_key, NULL,
+ "(public-key(rsa(n%m)(e%m)))",
+ n, e);
+ if((err != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "gcry_sexp_build(public)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+ if(d != NULL) {
+ err = gcry_sexp_build(&priv_key, NULL,
+ "(private-key(rsa(n%m)(e%m)(d%m)))",
+ n, e, d);
+ if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "gcry_sexp_build(private)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+ }
+
+
+ /* create key data */
+ 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 = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGCryptKeyDataRsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pub_key = NULL; /* pub_key is owned by data now */
+ priv_key = NULL; /* priv_key is owned by data now */
+
+ /* set key */
+ 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; /* data is owned by key now */
+
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(n != NULL) {
+ gcry_mpi_release(n);
+ }
+
+ if(e != NULL) {
+ gcry_mpi_release(e);
+ }
+
+ if(d != NULL) {
+ gcry_mpi_release(d);
+ }
+
+ if(pub_key != NULL) {
+ gcry_sexp_release(pub_key);
+ }
+
+ if(priv_key != NULL) {
+ gcry_sexp_release(priv_key);
+ }
+
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ return(res);
+
+}
+
+static int
+xmlSecGCryptKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ gcry_sexp_t pub_priv_key;
+ gcry_sexp_t rsa = NULL;
+ int private = 0;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGCryptKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataRsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* find the private or public key */
+ pub_priv_key = xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyGetValue(key));
+ if(pub_priv_key == NULL) {
+ pub_priv_key = xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyGetValue(key));
+ if(pub_priv_key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptKeyDataRsaGetPublicKey()",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ } else {
+ private = 1;
+ }
+
+ rsa = gcry_sexp_find_token(pub_priv_key, "rsa", 0);
+ if(rsa == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "gcry_sexp_find_token(rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "n", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ goto done;
+ }
+
+ /* 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "e", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ goto done;
+ }
+
+ /* next is PrivateExponent node: write it ONLY for private keys and ONLY if it is requested */
+ if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (private != 0)) {
+ 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));
+ goto done;
+ }
+ ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "d", 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGCryptNodeSetSExpTokValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent));
+ goto done;
+ }
+ }
+
+ /* success */
+ res = 0;
+
+done:
+ if(rsa != NULL) {
+ gcry_sexp_release(rsa);
+ }
+
+ return(res);
+}
+
+#endif /* XMLSEC_NO_RSA */
diff --git a/src/gcrypt/ciphers.c b/src/gcrypt/ciphers.c
new file mode 100644
index 00000000..6192b8b2
--- /dev/null
+++ b/src/gcrypt/ciphers.c
@@ -0,0 +1,855 @@
+/**
+ * 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 <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/crypto.h>
+
+/**************************************************************************
+ *
+ * Internal GCrypt Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGCryptBlockCipherCtx xmlSecGCryptBlockCipherCtx,
+ *xmlSecGCryptBlockCipherCtxPtr;
+struct _xmlSecGCryptBlockCipherCtx {
+ int cipher;
+ int mode;
+ gcry_cipher_hd_t cipherCtx;
+ xmlSecKeyDataId keyId;
+ int keyInitialized;
+ int ctxInitialized;
+};
+
+static int xmlSecGCryptBlockCipherCtxInit (xmlSecGCryptBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptBlockCipherCtxUpdate (xmlSecGCryptBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptBlockCipherCtxFinal (xmlSecGCryptBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int
+xmlSecGCryptBlockCipherCtxInit(xmlSecGCryptBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ gcry_err_code_t err;
+ 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);
+ err = gcry_cipher_setiv(ctx->cipherCtx, iv, blockLen);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ 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 */
+ err = gcry_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ 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
+xmlSecGCryptBlockCipherCtxUpdate(xmlSecGCryptBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, inBlocks, outSize;
+ int blockLen;
+ xmlSecByte* outBuf;
+ gcry_err_code_t err;
+ 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) {
+ err = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+ } else {
+ err = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ 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
+xmlSecGCryptBlockCipherCtxFinal(xmlSecGCryptBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, outSize;
+ int blockLen, outLen = 0;
+ xmlSecByte* inBuf;
+ xmlSecByte* outBuf;
+ gcry_err_code_t err;
+ 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) {
+ err = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+ } else {
+ err = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "gcry_cipher_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ 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
+ *
+ * xmlSecGCryptBlockCipherCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecGCryptBlockCipherSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptBlockCipherCtx))
+#define xmlSecGCryptBlockCipherGetCtx(transform) \
+ ((xmlSecGCryptBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGCryptBlockCipherInitialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptBlockCipherFinalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptBlockCipherSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGCryptBlockCipherSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGCryptBlockCipherExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptBlockCipherCheckId (xmlSecTransformPtr transform);
+
+
+
+static int
+xmlSecGCryptBlockCipherCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DES
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDes3CbcId)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes128CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes192CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes256CbcId)) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
+
+static int
+xmlSecGCryptBlockCipherInitialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptBlockCipherCtxPtr ctx;
+ gcry_error_t err;
+
+ xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
+
+ ctx = xmlSecGCryptBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGCryptBlockCipherCtx));
+
+#ifndef XMLSEC_NO_DES
+ if(transform->id == xmlSecGCryptTransformDes3CbcId) {
+ ctx->cipher = GCRY_CIPHER_3DES;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGCryptKeyDataDesId;
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(transform->id == xmlSecGCryptTransformAes128CbcId) {
+ ctx->cipher = GCRY_CIPHER_AES128;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGCryptKeyDataAesId;
+ } else if(transform->id == xmlSecGCryptTransformAes192CbcId) {
+ ctx->cipher = GCRY_CIPHER_AES192;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGCryptKeyDataAesId;
+ } else if(transform->id == xmlSecGCryptTransformAes256CbcId) {
+ ctx->cipher = GCRY_CIPHER_AES256;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->keyId = xmlSecGCryptKeyDataAesId;
+ } 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);
+ }
+
+ err = gcry_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_cipher_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecGCryptBlockCipherFinalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptBlockCipherCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGCryptBlockCipherCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize));
+
+ ctx = xmlSecGCryptBlockCipherGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->cipherCtx != NULL) {
+ gcry_cipher_close(ctx->cipherCtx);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecGCryptBlockCipherCtx));
+}
+
+static int
+xmlSecGCryptBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGCryptBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecGCryptBlockCipherGetCtx(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
+xmlSecGCryptBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGCryptBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ gcry_err_code_t err;
+
+ xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecGCryptBlockCipherGetCtx(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);
+ err = gcry_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_cipher_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ ctx->keyInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecGCryptBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecGCryptBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ if(ctx->ctxInitialized == 0) {
+ ret = xmlSecGCryptBlockCipherCtxInit(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGCryptBlockCipherCtxInit",
+ 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 = xmlSecGCryptBlockCipherCtxUpdate(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGCryptBlockCipherCtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(last) {
+ ret = xmlSecGCryptBlockCipherCtxFinal(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGCryptBlockCipherCtxFinal",
+ 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 xmlSecGCryptAes128CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes128Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes128Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformAes128CbcGetKlass(void) {
+ return(&xmlSecGCryptAes128CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecGCryptAes192CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes192Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes192Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformAes192CbcGetKlass(void) {
+ return(&xmlSecGCryptAes192CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecGCryptAes256CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes256Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes256Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformAes256CbcGetKlass(void) {
+ return(&xmlSecGCryptAes256CbcKlass);
+}
+
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+static xmlSecTransformKlass xmlSecGCryptDes3CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameDes3Cbc, /* const xmlChar* name; */
+ xmlSecHrefDes3Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformDes3CbcGetKlass(void) {
+ return(&xmlSecGCryptDes3CbcKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/gcrypt/crypto.c b/src/gcrypt/crypto.c
new file mode 100644
index 00000000..11def388
--- /dev/null
+++ b/src/gcrypt/crypto.c
@@ -0,0 +1,315 @@
+/**
+ * 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 <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/gcrypt/app.h>
+#include <xmlsec/gcrypt/crypto.h>
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecGCryptFunctions = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_gcrypt:
+ *
+ * Gets the pointer to xmlsec-gcrypt functions table.
+ *
+ * Returns: the xmlsec-gcrypt functions table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_gcrypt(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecGCryptFunctions != NULL) {
+ return(gXmlSecGCryptFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecGCryptFunctions = &functions;
+
+ /********************************************************************
+ *
+ * Crypto Init/shutdown
+ *
+ ********************************************************************/
+ gXmlSecGCryptFunctions->cryptoInit = xmlSecGCryptInit;
+ gXmlSecGCryptFunctions->cryptoShutdown = xmlSecGCryptShutdown;
+ gXmlSecGCryptFunctions->cryptoKeysMngrInit = xmlSecGCryptKeysMngrInit;
+
+ /********************************************************************
+ *
+ * Key data ids
+ *
+ ********************************************************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecGCryptFunctions->keyDataAesGetKlass = xmlSecGCryptKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecGCryptFunctions->keyDataDesGetKlass = xmlSecGCryptKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecGCryptFunctions->keyDataDsaGetKlass = xmlSecGCryptKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecGCryptFunctions->keyDataHmacGetKlass = xmlSecGCryptKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecGCryptFunctions->keyDataRsaGetKlass = xmlSecGCryptKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+
+ /********************************************************************
+ *
+ * Key data store ids
+ *
+ ********************************************************************/
+
+ /********************************************************************
+ *
+ * Crypto transforms ids
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecGCryptFunctions->transformAes128CbcGetKlass = xmlSecGCryptTransformAes128CbcGetKlass;
+ gXmlSecGCryptFunctions->transformAes192CbcGetKlass = xmlSecGCryptTransformAes192CbcGetKlass;
+ gXmlSecGCryptFunctions->transformAes256CbcGetKlass = xmlSecGCryptTransformAes256CbcGetKlass;
+ gXmlSecGCryptFunctions->transformKWAes128GetKlass = xmlSecGCryptTransformKWAes128GetKlass;
+ gXmlSecGCryptFunctions->transformKWAes192GetKlass = xmlSecGCryptTransformKWAes192GetKlass;
+ gXmlSecGCryptFunctions->transformKWAes256GetKlass = xmlSecGCryptTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecGCryptFunctions->transformDes3CbcGetKlass = xmlSecGCryptTransformDes3CbcGetKlass;
+ gXmlSecGCryptFunctions->transformKWDes3GetKlass = xmlSecGCryptTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGCryptFunctions->transformDsaSha1GetKlass = xmlSecGCryptTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecGCryptFunctions->transformHmacMd5GetKlass = xmlSecGCryptTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecGCryptFunctions->transformHmacRipemd160GetKlass = xmlSecGCryptTransformHmacRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGCryptFunctions->transformHmacSha1GetKlass = xmlSecGCryptTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecGCryptFunctions->transformHmacSha256GetKlass = xmlSecGCryptTransformHmacSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecGCryptFunctions->transformHmacSha384GetKlass = xmlSecGCryptTransformHmacSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecGCryptFunctions->transformHmacSha512GetKlass = xmlSecGCryptTransformHmacSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* MD5 ********************************/
+#ifndef XMLSEC_NO_MD5
+ gXmlSecGCryptFunctions->transformMd5GetKlass = xmlSecGCryptTransformMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+ /******************************* RIPEMD160 ********************************/
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecGCryptFunctions->transformRipemd160GetKlass = xmlSecGCryptTransformRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecGCryptFunctions->transformRsaMd5GetKlass = xmlSecGCryptTransformRsaMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecGCryptFunctions->transformRsaRipemd160GetKlass = xmlSecGCryptTransformRsaRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGCryptFunctions->transformRsaSha1GetKlass = xmlSecGCryptTransformRsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecGCryptFunctions->transformRsaSha256GetKlass = xmlSecGCryptTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecGCryptFunctions->transformRsaSha384GetKlass = xmlSecGCryptTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecGCryptFunctions->transformRsaSha512GetKlass = xmlSecGCryptTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGCryptFunctions->transformSha1GetKlass = xmlSecGCryptTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecGCryptFunctions->transformSha256GetKlass = xmlSecGCryptTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecGCryptFunctions->transformSha384GetKlass = xmlSecGCryptTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecGCryptFunctions->transformSha512GetKlass = xmlSecGCryptTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+
+ /********************************************************************
+ *
+ * High level routines form xmlsec command line utility
+ *
+ ********************************************************************/
+ gXmlSecGCryptFunctions->cryptoAppInit = xmlSecGCryptAppInit;
+ gXmlSecGCryptFunctions->cryptoAppShutdown = xmlSecGCryptAppShutdown;
+ gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrInit = xmlSecGCryptAppDefaultKeysMngrInit;
+ gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecGCryptAppDefaultKeysMngrAdoptKey;
+ gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecGCryptAppDefaultKeysMngrLoad;
+ gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrSave = xmlSecGCryptAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecGCryptFunctions->cryptoAppKeysMngrCertLoad = xmlSecGCryptAppKeysMngrCertLoad;
+ gXmlSecGCryptFunctions->cryptoAppPkcs12Load = xmlSecGCryptAppPkcs12Load;
+ gXmlSecGCryptFunctions->cryptoAppKeyCertLoad = xmlSecGCryptAppKeyCertLoad;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecGCryptFunctions->cryptoAppKeyLoad = xmlSecGCryptAppKeyLoad;
+ gXmlSecGCryptFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecGCryptAppGetDefaultPwdCallback();
+
+ return(gXmlSecGCryptFunctions);
+}
+
+
+/**
+ * xmlSecGCryptInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptInit (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_gcrypt()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecGCryptShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptShutdown(void) {
+ return(0);
+}
+
+/**
+ * xmlSecGCryptKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds GCrypt specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGCryptKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* TODO: add key data stores */
+ return(0);
+}
+
+/**
+ * xmlSecGCryptGenerateRandom:
+ * @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
+xmlSecGCryptGenerateRandom(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/gcrypt/digests.c b/src/gcrypt/digests.c
new file mode 100644
index 00000000..dcbe4c7f
--- /dev/null
+++ b/src/gcrypt/digests.c
@@ -0,0 +1,614 @@
+/**
+ * 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 <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/app.h>
+#include <xmlsec/gcrypt/crypto.h>
+
+/**************************************************************************
+ *
+ * Internal GCRYPT Digest CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGCryptDigestCtx xmlSecGCryptDigestCtx, *xmlSecGCryptDigestCtxPtr;
+struct _xmlSecGCryptDigestCtx {
+ int digest;
+ gcry_md_hd_t digestCtx;
+ xmlSecByte dgst[XMLSEC_GCRYPT_MAX_DIGEST_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+/******************************************************************************
+ *
+ * Digest transforms
+ *
+ * xmlSecGCryptDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGCryptDigestSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptDigestCtx))
+#define xmlSecGCryptDigestGetCtx(transform) \
+ ((xmlSecGCryptDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGCryptDigestInitialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptDigestFinalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptDigestVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptDigestExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptDigestCheckId (xmlSecTransformPtr transform);
+
+static int
+xmlSecGCryptDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+ /* not found */
+ {
+ return(0);
+ }
+
+ /* just in case */
+ return(0);
+}
+
+static int
+xmlSecGCryptDigestInitialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptDigestCtxPtr ctx;
+ gcry_error_t err;
+
+ xmlSecAssert2(xmlSecGCryptDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize), -1);
+
+ ctx = xmlSecGCryptDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecGCryptDigestCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha256Id)) {
+ ctx->digest = GCRY_MD_SHA256;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha384Id)) {
+ ctx->digest = GCRY_MD_SHA384;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha512Id)) {
+ ctx->digest = GCRY_MD_SHA512;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformMd5Id)) {
+ ctx->digest = GCRY_MD_MD5;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRipemd160Id)) {
+ ctx->digest = GCRY_MD_RMD160;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* create digest ctx */
+ err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecGCryptDigestFinalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptDigestCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGCryptDigestCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize));
+
+ ctx = xmlSecGCryptDigestGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ gcry_md_close(ctx->digestCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecGCryptDigestCtx));
+}
+
+static int
+xmlSecGCryptDigestVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGCryptDigestCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptDigestGetCtx(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
+xmlSecGCryptDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptDigestCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptDigestCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize), -1);
+
+ ctx = xmlSecGCryptDigestGetCtx(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 != 0) {
+ 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 xmlSecGCryptSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha1, /* const xmlChar* name; */
+ xmlSecHrefSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformSha1GetKlass(void) {
+ return(&xmlSecGCryptSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * SHA256 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha256, /* const xmlChar* name; */
+ xmlSecHrefSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformSha256GetKlass:
+ *
+ * SHA256 digest transform klass.
+ *
+ * Returns: pointer to SHA256 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformSha256GetKlass(void) {
+ return(&xmlSecGCryptSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * SHA384 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha384, /* const xmlChar* name; */
+ xmlSecHrefSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformSha384GetKlass:
+ *
+ * SHA384 digest transform klass.
+ *
+ * Returns: pointer to SHA384 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformSha384GetKlass(void) {
+ return(&xmlSecGCryptSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * SHA512 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha512, /* const xmlChar* name; */
+ xmlSecHrefSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformSha512GetKlass:
+ *
+ * SHA512 digest transform klass.
+ *
+ * Returns: pointer to SHA512 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformSha512GetKlass(void) {
+ return(&xmlSecGCryptSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_MD5
+/******************************************************************************
+ *
+ * MD5 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameMd5, /* const xmlChar* name; */
+ xmlSecHrefMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformMd5GetKlass:
+ *
+ * MD5 digest transform klass.
+ *
+ * Returns: pointer to MD5 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformMd5GetKlass(void) {
+ return(&xmlSecGCryptMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+/******************************************************************************
+ *
+ * RIPEMD160 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameRipemd160, /* const xmlChar* name; */
+ xmlSecHrefRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRipemd160GetKlass:
+ *
+ * RIPEMD160 digest transform klass.
+ *
+ * Returns: pointer to RIPEMD160 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRipemd160GetKlass(void) {
+ return(&xmlSecGCryptRipemd160Klass);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
diff --git a/src/gcrypt/globals.h b/src/gcrypt/globals.h
new file mode 100644
index 00000000..7bc03c1c
--- /dev/null
+++ b/src/gcrypt/globals.h
@@ -0,0 +1,30 @@
+/*
+ * 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
+
+
+#define XMLSEC_GCRYPT_MAX_DIGEST_SIZE 256
+#define XMLSEC_GCRYPT_REPORT_ERROR(err) \
+ "error code=%d; error message='%s'", \
+ (int)err, xmlSecErrorsSafeString(gcry_strerror((err)))
+
+#endif /* ! __XMLSEC_GLOBALS_H__ */
diff --git a/src/gcrypt/hmac.c b/src/gcrypt/hmac.c
new file mode 100644
index 00000000..192cb17b
--- /dev/null
+++ b/src/gcrypt/hmac.c
@@ -0,0 +1,823 @@
+/**
+ * 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 <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/app.h>
+#include <xmlsec/gcrypt/crypto.h>
+
+/* sizes in bits */
+#define XMLSEC_GCRYPT_MIN_HMAC_SIZE 80
+#define XMLSEC_GCRYPT_MAX_HMAC_SIZE (128 * 8)
+
+/**************************************************************************
+ *
+ * Configuration
+ *
+ *****************************************************************************/
+static int g_xmlsec_gcrypt_hmac_min_length = XMLSEC_GCRYPT_MIN_HMAC_SIZE;
+
+/**
+ * xmlSecGCryptHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecGCryptHmacGetMinOutputLength(void)
+{
+ return g_xmlsec_gcrypt_hmac_min_length;
+}
+
+/**
+ * xmlSecGCryptHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecGCryptHmacSetMinOutputLength(int min_length)
+{
+ g_xmlsec_gcrypt_hmac_min_length = min_length;
+}
+
+/**************************************************************************
+ *
+ * Internal GCRYPT HMAC CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGCryptHmacCtx xmlSecGCryptHmacCtx, *xmlSecGCryptHmacCtxPtr;
+struct _xmlSecGCryptHmacCtx {
+ int digest;
+ gcry_md_hd_t digestCtx;
+ xmlSecByte dgst[XMLSEC_GCRYPT_MAX_HMAC_SIZE / 8];
+ xmlSecSize dgstSize; /* dgst size in bits */
+};
+
+/******************************************************************************
+ *
+ * HMAC transforms
+ *
+ * xmlSecGCryptHmacCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGCryptHmacGetCtx(transform) \
+ ((xmlSecGCryptHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecGCryptHmacSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptHmacCtx))
+
+static int xmlSecGCryptHmacCheckId (xmlSecTransformPtr transform);
+static int xmlSecGCryptHmacInitialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptHmacFinalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptHmacNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptHmacSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGCryptHmacSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGCryptHmacVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptHmacExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecGCryptHmacCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+ /* not found */
+ {
+ return(0);
+ }
+
+ /* just in case */
+ return(0);
+}
+
+
+static int
+xmlSecGCryptHmacInitialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptHmacCtxPtr ctx;
+ gcry_error_t err;
+
+ xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1);
+
+ ctx = xmlSecGCryptHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGCryptHmacCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha256Id)) {
+ ctx->digest = GCRY_MD_SHA256;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha384Id)) {
+ ctx->digest = GCRY_MD_SHA384;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha512Id)) {
+ ctx->digest = GCRY_MD_SHA512;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacRipemd160Id)) {
+ ctx->digest = GCRY_MD_RMD160;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacMd5Id)) {
+ ctx->digest = GCRY_MD_MD5;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+ /* not found */
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* open context */
+ err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecGCryptHmacFinalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptHmacCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGCryptHmacCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize));
+
+ ctx = xmlSecGCryptHmacGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ gcry_md_close(ctx->digestCtx);
+ }
+ memset(ctx, 0, sizeof(xmlSecGCryptHmacCtx));
+}
+
+/**
+ * xmlSecGCryptHmacNodeRead:
+ *
+ * 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
+xmlSecGCryptHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptHmacCtxPtr ctx;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) {
+ xmlChar *content;
+
+ content = xmlNodeGetContent(cur);
+ if(content != NULL) {
+ ctx->dgstSize = atoi((char*)content);
+ xmlFree(content);
+ }
+
+ /* Ensure that HMAC length is greater than min specified.
+ Otherwise, an attacker can set this length to 0 or very
+ small value
+ */
+ if((int)ctx->dgstSize < xmlSecGCryptHmacGetMinOutputLength()) {
+ 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
+xmlSecGCryptHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGCryptHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1);
+
+ ctx = xmlSecGCryptHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecGCryptKeyDataHmacId;
+ keyReq->keyType= xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGCryptHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGCryptHmacCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+ gcry_error_t err;
+
+ xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecGCryptHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecGCryptKeyDataHmacId), -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);
+ }
+
+ err = gcry_md_setkey(ctx->digestCtx, xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecGCryptHmacVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ static xmlSecByte last_byte_masks[] =
+ { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+
+ xmlSecGCryptHmacCtxPtr ctx;
+ xmlSecByte mask;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptHmacGetCtx(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
+xmlSecGCryptHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptHmacCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecByte* dgst;
+ xmlSecSize dgstSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptHmacGetCtx(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);
+}
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * HMAC SHA1
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptHmacSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha1, /* const xmlChar* name; */
+ xmlSecHrefHmacSha1, /* const xmlChar *href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformHmacSha1GetKlass(void) {
+ return(&xmlSecGCryptHmacSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * HMAC SHA256
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptHmacSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha256, /* const xmlChar* name; */
+ xmlSecHrefHmacSha256, /* const xmlChar *href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformHmacSha256GetKlass(void) {
+ return(&xmlSecGCryptHmacSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * HMAC SHA384
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptHmacSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha384, /* const xmlChar* name; */
+ xmlSecHrefHmacSha384, /* const xmlChar *href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformHmacSha384GetKlass(void) {
+ return(&xmlSecGCryptHmacSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * HMAC SHA512
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptHmacSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha512, /* const xmlChar* name; */
+ xmlSecHrefHmacSha512, /* const xmlChar *href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformHmacSha512GetKlass(void) {
+ return(&xmlSecGCryptHmacSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+
+#ifndef XMLSEC_NO_RIPEMD160
+/******************************************************************************
+ *
+ * HMAC Ripemd160
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptHmacRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacRipemd160, /* const xmlChar* name; */
+ xmlSecHrefHmacRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformHmacRipemd160GetKlass(void) {
+ return(&xmlSecGCryptHmacRipemd160Klass);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+/******************************************************************************
+ *
+ * HMAC MD5
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptHmacMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacMd5, /* const xmlChar* name; */
+ xmlSecHrefHmacMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformHmacMd5GetKlass(void) {
+ return(&xmlSecGCryptHmacMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+
+#endif /* XMLSEC_NO_HMAC */
diff --git a/src/gcrypt/kw_aes.c b/src/gcrypt/kw_aes.c
new file mode 100644
index 00000000..38ac8956
--- /dev/null
+++ b/src/gcrypt/kw_aes.c
@@ -0,0 +1,593 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_AES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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/gcrypt/crypto.h>
+
+#include "../kw_aes_des.h"
+
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecGCryptKWAesBlockEncrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static int xmlSecGCryptKWAesBlockDecrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static xmlSecKWAesKlass xmlSecGCryptKWAesKlass = {
+ /* callbacks */
+ xmlSecGCryptKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */
+ xmlSecGCryptKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL /* void* reserved1; */
+};
+
+
+/*********************************************************************
+ *
+ * AES KW transforms
+ *
+ ********************************************************************/
+typedef struct _xmlSecGCryptKWAesCtx xmlSecGCryptKWAesCtx,
+ *xmlSecGCryptKWAesCtxPtr;
+struct _xmlSecGCryptKWAesCtx {
+ int cipher;
+ int mode;
+ int flags;
+ xmlSecSize blockSize;
+ xmlSecSize keyExpectedSize;
+
+ xmlSecBuffer keyBuffer;
+};
+#define xmlSecGCryptKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptKWAesCtx))
+#define xmlSecGCryptKWAesGetCtx(transform) \
+ ((xmlSecGCryptKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecGCryptKWAesCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecGCryptTransformKWAes128Id) || \
+ xmlSecTransformCheckId((transform), xmlSecGCryptTransformKWAes192Id) || \
+ xmlSecTransformCheckId((transform), xmlSecGCryptTransformKWAes256Id))
+
+static int xmlSecGCryptKWAesInitialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptKWAesFinalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptKWAesSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGCryptKWAesSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGCryptKWAesExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecGCryptKWAesInitialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptKWAesCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1);
+
+ ctx = xmlSecGCryptKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWAes128Id)) {
+ ctx->cipher = GCRY_CIPHER_AES128;
+ ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWAes192Id)) {
+ ctx->cipher = GCRY_CIPHER_AES192;
+ ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWAes256Id)) {
+ ctx->cipher = GCRY_CIPHER_AES256;
+ ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
+ ctx->flags = GCRY_CIPHER_SECURE; /* we are paranoid */
+ ctx->blockSize = gcry_cipher_get_algo_blklen(ctx->cipher);
+ xmlSecAssert2(ctx->blockSize > 0, -1);
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecGCryptKWAesGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecGCryptKWAesFinalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptKWAesCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGCryptKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize));
+
+ ctx = xmlSecGCryptKWAesGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecGCryptKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGCryptKWAesCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecGCryptKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecGCryptKeyDataAesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * ctx->keyExpectedSize;
+
+ return(0);
+}
+
+static int
+xmlSecGCryptKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGCryptKWAesCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataAesId), -1);
+
+ ctx = xmlSecGCryptKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < ctx->keyExpectedSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer),
+ xmlSecBufferGetData(buffer),
+ ctx->keyExpectedSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d",
+ ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGCryptKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptKWAesCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == ctx->keyExpectedSize, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % 8) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d(not 8 bytes aligned)", inSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+ outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_KW_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWAesEncode(&xmlSecGCryptKWAesKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWAesDecode(&xmlSecGCryptKWAesKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "inSize%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+
+static xmlSecTransformKlass xmlSecGCryptKWAes128Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes128, /* const xmlChar* name; */
+ xmlSecHrefKWAes128, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformKWAes128GetKlass(void) {
+ return(&xmlSecGCryptKWAes128Klass);
+}
+
+static xmlSecTransformKlass xmlSecGCryptKWAes192Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes192, /* const xmlChar* name; */
+ xmlSecHrefKWAes192, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+
+/**
+ * xmlSecGCryptTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformKWAes192GetKlass(void) {
+ return(&xmlSecGCryptKWAes192Klass);
+}
+
+static xmlSecTransformKlass xmlSecGCryptKWAes256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes256, /* const xmlChar* name; */
+ xmlSecHrefKWAes256, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformKWAes256GetKlass(void) {
+ return(&xmlSecGCryptKWAes256Klass);
+}
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static unsigned char g_zero_iv[XMLSEC_KW_AES_BLOCK_SIZE] =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static int
+xmlSecGCryptKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ xmlSecGCryptKWAesCtxPtr ctx = (xmlSecGCryptKWAesCtxPtr)context;
+ gcry_cipher_hd_t cipherCtx;
+ gcry_error_t err;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= ctx->blockSize, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= ctx->blockSize, -1);
+
+ err = gcry_cipher_open(&cipherCtx, ctx->cipher, ctx->mode, ctx->flags);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ err = gcry_cipher_setkey(cipherCtx,
+ xmlSecBufferGetData(&ctx->keyBuffer),
+ xmlSecBufferGetSize(&ctx->keyBuffer));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* use zero IV and CBC mode to ensure we get result as-is */
+ err = gcry_cipher_setiv(cipherCtx, g_zero_iv, sizeof(g_zero_iv));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ err = gcry_cipher_encrypt(cipherCtx, out, outSize, in, inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ gcry_cipher_close(cipherCtx);
+ return(-1);
+ }
+ gcry_cipher_close(cipherCtx);
+
+ return(ctx->blockSize);
+}
+
+static int
+xmlSecGCryptKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ xmlSecGCryptKWAesCtxPtr ctx = (xmlSecGCryptKWAesCtxPtr)context;
+ gcry_cipher_hd_t cipherCtx;
+ gcry_error_t err;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= ctx->blockSize, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= ctx->blockSize, -1);
+
+ err = gcry_cipher_open(&cipherCtx, ctx->cipher, ctx->mode, ctx->flags);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ err = gcry_cipher_setkey(cipherCtx,
+ xmlSecBufferGetData(&ctx->keyBuffer),
+ xmlSecBufferGetSize(&ctx->keyBuffer));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* use zero IV and CBC mode to ensure we get result as-is */
+ err = gcry_cipher_setiv(cipherCtx, g_zero_iv, sizeof(g_zero_iv));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ err = gcry_cipher_decrypt(cipherCtx, out, outSize, in, inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ gcry_cipher_close(cipherCtx);
+ return(-1);
+ }
+ gcry_cipher_close(cipherCtx);
+
+ return(ctx->blockSize);
+}
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/gcrypt/kw_des.c b/src/gcrypt/kw_des.c
new file mode 100644
index 00000000..b93eb9f5
--- /dev/null
+++ b/src/gcrypt/kw_des.c
@@ -0,0 +1,607 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_DES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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/gcrypt/crypto.h>
+
+#include "../kw_aes_des.h"
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecGCryptKWDes3GenerateRandom (void * context,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecGCryptKWDes3Sha1 (void * context,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecGCryptKWDes3BlockEncrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecGCryptKWDes3BlockDecrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+
+static xmlSecKWDes3Klass xmlSecGCryptKWDes3ImplKlass = {
+ /* callbacks */
+ xmlSecGCryptKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */
+ xmlSecGCryptKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */
+ xmlSecGCryptKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */
+ xmlSecGCryptKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static int xmlSecGCryptKWDes3Encrypt (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *iv,
+ xmlSecSize ivSize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize,
+ int enc);
+
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+typedef struct _xmlSecGCryptKWDes3Ctx xmlSecGCryptKWDes3Ctx,
+ *xmlSecGCryptKWDes3CtxPtr;
+struct _xmlSecGCryptKWDes3Ctx {
+ xmlSecBuffer keyBuffer;
+};
+#define xmlSecGCryptKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptKWDes3Ctx))
+#define xmlSecGCryptKWDes3GetCtx(transform) \
+ ((xmlSecGCryptKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGCryptKWDes3Initialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptKWDes3Finalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptKWDes3SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGCryptKWDes3SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGCryptKWDes3Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecGCryptKWDes3Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptKWDes3Size, /* xmlSecSize objSize */
+
+ xmlSecNameKWDes3, /* const xmlChar* name; */
+ xmlSecHrefKWDes3, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecGCryptKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecGCryptKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformKWDes3GetKlass(void) {
+ return(&xmlSecGCryptKWDes3Klass);
+}
+
+static int
+xmlSecGCryptKWDes3Initialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptKWDes3CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1);
+
+ ctx = xmlSecGCryptKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecGCryptKWDes3Finalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptKWDes3CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size));
+
+ ctx = xmlSecGCryptKWDes3GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecGCryptKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGCryptKWDes3CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecGCryptKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecGCryptKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecGCryptKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGCryptKWDes3CtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataDesId), -1);
+
+ ctx = xmlSecGCryptKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key length %d is not enough (%d expected)",
+ keySize, XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGCryptKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptKWDes3CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d bytes - not %d bytes aligned",
+ inSize, XMLSEC_KW_DES3_BLOCK_LENGTH);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 16 bytes longer plus one block just in case */
+ outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH;
+ } else {
+ /* just in case, add a block */
+ outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWDes3Encode(&xmlSecGCryptKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWDes3Decode(&xmlSecGCryptKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecGCryptKWDes3Sha1(void * context,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context;
+ gcry_md_hd_t digestCtx;
+ unsigned char * res;
+ unsigned int len;
+ gcry_error_t err;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ len = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
+ xmlSecAssert2(outSize >= len, -1);
+
+ err = gcry_md_open(&digestCtx, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_md_open(GCRY_MD_SHA1)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ gcry_md_write(digestCtx, in, inSize);
+
+ err = gcry_md_final(digestCtx);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_md_final",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ gcry_md_close(digestCtx);
+ return(-1);
+ }
+
+ res = gcry_md_read(digestCtx, GCRY_MD_SHA1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_md_read(GCRY_MD_SHA1)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_md_close(digestCtx);
+ return(-1);
+ }
+
+ /* done */
+ xmlSecAssert2(outSize >= len, -1);
+ memcpy(out, res, len);
+ gcry_md_close(digestCtx);
+ return(len);
+}
+
+static int
+xmlSecGCryptKWDes3GenerateRandom(void * context,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ gcry_randomize(out, outSize, GCRY_STRONG_RANDOM);
+ return((int)outSize);
+}
+
+static int
+xmlSecGCryptKWDes3BlockEncrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecGCryptKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)),
+ XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 1); /* encrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+static int
+xmlSecGCryptKWDes3BlockDecrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecGCryptKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)),
+ XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 0); /* decrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(ret);
+}
+
+static int
+xmlSecGCryptKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *iv, xmlSecSize ivSize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize,
+ int enc) {
+ size_t key_len = gcry_cipher_get_algo_keylen(GCRY_CIPHER_3DES);
+ size_t block_len = gcry_cipher_get_algo_blklen(GCRY_CIPHER_3DES);
+ gcry_cipher_hd_t cipherCtx;
+ gcry_error_t err;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize >= key_len, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= block_len, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ err = gcry_cipher_open(&cipherCtx, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_open(GCRY_CIPHER_3DES)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ err = gcry_cipher_setkey(cipherCtx, key, keySize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_setkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ err = gcry_cipher_setiv(cipherCtx, iv, ivSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_setiv",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ if(enc) {
+ err = gcry_cipher_encrypt(cipherCtx, out, outSize, in, inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ gcry_cipher_close(cipherCtx);
+ return(-1);
+ }
+ } else {
+ err = gcry_cipher_decrypt(cipherCtx, out, outSize, in, inSize);
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_cipher_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ gcry_cipher_close(cipherCtx);
+ return(-1);
+ }
+ }
+
+ /* done */
+ gcry_cipher_close(cipherCtx);
+ return((int)inSize); /* out size == in size */
+}
+
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/gcrypt/signatures.c b/src/gcrypt/signatures.c
new file mode 100644
index 00000000..c49638e4
--- /dev/null
+++ b/src/gcrypt/signatures.c
@@ -0,0 +1,1490 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/crypto.h>
+
+
+/**************************************************************************
+ *
+ * Forward declarations for actual sign/verify implementations
+ *
+ *****************************************************************************/
+typedef int (*xmlSecGCryptPkSignMethod) (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ xmlSecBufferPtr out);
+typedef int (*xmlSecGCryptPkVerifyMethod) (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+
+#ifndef XMLSEC_NO_DSA
+static int xmlSecGCryptDsaPkSign (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ xmlSecBufferPtr out);
+static int xmlSecGCryptDsaPkVerify (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+static int xmlSecGCryptRsaPkcs1PkSign (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ xmlSecBufferPtr out);
+static int xmlSecGCryptRsaPkcs1PkVerify (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+#endif /* XMLSEC_NO_RSA */
+
+
+/**************************************************************************
+ *
+ * Internal GCrypt signatures ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGCryptPkSignatureCtx xmlSecGCryptPkSignatureCtx,
+ *xmlSecGCryptPkSignatureCtxPtr;
+
+
+struct _xmlSecGCryptPkSignatureCtx {
+ int digest;
+ xmlSecKeyDataId keyId;
+ xmlSecGCryptPkSignMethod sign;
+ xmlSecGCryptPkVerifyMethod verify;
+
+ gcry_md_hd_t digestCtx;
+ xmlSecKeyDataPtr key_data;
+
+ xmlSecByte dgst[XMLSEC_GCRYPT_MAX_DIGEST_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+
+/******************************************************************************
+ *
+ * Pk Signature transforms
+ *
+ * xmlSecGCryptPkSignatureCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGCryptPkSignatureSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptPkSignatureCtx))
+#define xmlSecGCryptPkSignatureGetCtx(transform) \
+ ((xmlSecGCryptPkSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGCryptPkSignatureCheckId (xmlSecTransformPtr transform);
+static int xmlSecGCryptPkSignatureInitialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptPkSignatureFinalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptPkSignatureSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGCryptPkSignatureSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGCryptPkSignatureVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptPkSignatureExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecGCryptPkSignatureCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ {
+ return(0);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGCryptPkSignatureInitialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ gcry_error_t err;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGCryptPkSignatureCtx));
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDsaSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ ctx->keyId = xmlSecGCryptKeyDataDsaId;
+ ctx->sign = xmlSecGCryptDsaPkSign;
+ ctx->verify = xmlSecGCryptDsaPkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaMd5Id)) {
+ ctx->digest = GCRY_MD_MD5;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaRipemd160Id)) {
+ ctx->digest = GCRY_MD_RMD160;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha256Id)) {
+ ctx->digest = GCRY_MD_SHA256;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha384Id)) {
+ ctx->digest = GCRY_MD_SHA384;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha512Id)) {
+ ctx->digest = GCRY_MD_SHA512;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } 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);
+ }
+
+ /* create digest ctx */
+ err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* done */
+ return(0);
+}
+
+static void
+xmlSecGCryptPkSignatureFinalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGCryptPkSignatureCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize));
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->key_data != NULL) {
+ xmlSecKeyDataDestroy(ctx->key_data);
+ }
+ if(ctx->digestCtx != NULL) {
+ gcry_md_close(ctx->digestCtx);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecGCryptPkSignatureCtx));
+}
+
+static int
+xmlSecGCryptPkSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ xmlSecKeyDataPtr key_data;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ key_data = xmlSecKeyGetValue(key);
+ xmlSecAssert2(key_data != NULL, -1);
+
+ if(ctx->key_data != NULL) {
+ xmlSecKeyDataDestroy(ctx->key_data);
+ }
+
+ ctx->key_data = xmlSecKeyDataDuplicate(key_data);
+ if(ctx->key_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
+xmlSecGCryptPkSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(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
+xmlSecGCryptPkSignatureVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->sign != NULL, -1);
+ xmlSecAssert2(ctx->verify != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+ xmlSecAssert2(ctx->key_data != NULL, -1);
+
+ ret = ctx->verify(ctx->digest, ctx->key_data, ctx->dgst, ctx->dgstSize, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "ctx->verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* check result */
+ if(ret == 1) {
+ transform->status = xmlSecTransformStatusOk;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "ctx->verify",
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "signature do not match");
+ transform->status = xmlSecTransformStatusFail;
+ }
+
+ /* done */
+ return(0);
+}
+
+static int
+xmlSecGCryptPkSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize;
+ xmlSecSize outSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->sign != NULL, -1);
+ xmlSecAssert2(ctx->verify != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->key_data != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ /* do nothing, already initialized */
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ /* update the digest */
+ 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);
+ }
+ }
+
+ /* generate digest and signature */
+ if(last != 0) {
+ 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);
+
+ xmlSecAssert2(outSize == 0, -1);
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = ctx->sign(ctx->digest, ctx->key_data, ctx->dgst, ctx->dgstSize, out);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "ctx->sign",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* done */
+ 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);
+}
+
+/*****************************************************************************
+ *
+ * Helper
+ *
+ ****************************************************************************/
+static int
+xmlSecGCryptAppendMpi(gcry_mpi_t a, xmlSecBufferPtr out, xmlSecSize min_size) {
+ xmlSecSize outSize;
+ size_t written;
+ gpg_error_t err;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ /* current size */
+ outSize = xmlSecBufferGetSize(out);
+
+ /* figure out how much space we need */
+ written = 0;
+ err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &written, a);
+ if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_print",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* add zeros at the beggining (if needed) */
+ if((min_size > 0) && (written < min_size)) {
+ outSize += (min_size - written);
+ }
+
+ /* allocate space */
+ ret = xmlSecBufferSetMaxSize(out, outSize + written + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", (int)(outSize + written + 1));
+ return(-1);
+ }
+ xmlSecAssert2(xmlSecBufferGetMaxSize(out) > outSize, -1);
+
+ /* add zeros at the beggining (if needed) */
+ if((min_size > 0) && (written < min_size)) {
+ xmlSecSize ii;
+ xmlSecByte * p = xmlSecBufferGetData(out);
+
+ for(ii = 0; ii < (min_size - written); ++ii) {
+ p[outSize - ii - 1] = 0;
+ }
+ }
+
+ /* write out */
+ written = 0;
+ err = gcry_mpi_print(GCRYMPI_FMT_USG,
+ xmlSecBufferGetData(out) + outSize,
+ xmlSecBufferGetMaxSize(out) - outSize,
+ &written, a);
+ if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_print",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* reset size */
+ ret = xmlSecBufferSetSize(out, outSize + written);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ (int)(outSize + written));
+ return(-1);
+ }
+
+ /* done */
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * DSA-SHA1 signature transform
+ *
+ * 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>
+ *
+ ***************************************************************************/
+static int
+xmlSecGCryptDsaPkSign(int digest ATTRIBUTE_UNUSED, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ xmlSecBufferPtr out) {
+ gcry_mpi_t m_hash = NULL;
+ gcry_sexp_t s_data = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gcry_sexp_t s_r = NULL;
+ gcry_sexp_t s_s = NULL;
+ gcry_mpi_t m_r = NULL;
+ gcry_mpi_t m_s = NULL;
+ gcry_sexp_t s_tmp;
+ gpg_error_t err;
+ int ret;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataDsaGetPrivateKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ /* get the current digest, can't use "hash" :( */
+ err = gcry_mpi_scan(&m_hash, GCRYMPI_FMT_USG, dgst, dgstSize, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_hash == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(hash)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags raw)(value %m))",
+ m_hash);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* create signature */
+ err = gcry_pk_sign(&s_sig, s_data, xmlSecGCryptKeyDataDsaGetPrivateKey(key_data));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_sign",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* find signature value */
+ s_tmp = gcry_sexp_find_token(s_sig, "sig-val", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ s_tmp = gcry_sexp_find_token(s_sig, "dsa", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ /* r */
+ s_r = gcry_sexp_find_token(s_sig, "r", 0);
+ if(s_r == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(r)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ m_r = gcry_sexp_nth_mpi(s_r, 1, GCRYMPI_FMT_USG);
+ if(m_r == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi(r)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* s */
+ s_s = gcry_sexp_find_token(s_sig, "s", 0);
+ if(s_s == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ m_s = gcry_sexp_nth_mpi(s_s, 1, GCRYMPI_FMT_USG);
+ if(m_s == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* write out: r + s */
+ ret = xmlSecGCryptAppendMpi(m_r, out, 20);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppendMpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBufferGetSize(out) == 20, -1);
+ ret = xmlSecGCryptAppendMpi(m_s, out, 20);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppendMpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBufferGetSize(out) == (20 + 20), -1);
+
+ /* done */
+ res = 0;
+
+done:
+ if(m_hash != NULL) {
+ gcry_mpi_release(m_hash);
+ }
+ if(m_r != NULL) {
+ gcry_mpi_release(m_r);
+ }
+ if(m_s != NULL) {
+ gcry_mpi_release(m_s);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+ if(s_r != NULL) {
+ gcry_sexp_release(s_r);
+ }
+ if(s_s != NULL) {
+ gcry_sexp_release(s_s);
+ }
+
+ return(res);
+}
+
+static int
+xmlSecGCryptDsaPkVerify(int digest ATTRIBUTE_UNUSED, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ const xmlSecByte* data, xmlSecSize dataSize) {
+ gcry_mpi_t m_hash = NULL;
+ gcry_sexp_t s_data = NULL;
+ gcry_mpi_t m_sig_r = NULL;
+ gcry_mpi_t m_sig_s = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gpg_error_t err;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataDsaGetPublicKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize == (20 + 20), -1);
+
+ /* get the current digest, can't use "hash" :( */
+ err = gcry_mpi_scan(&m_hash, GCRYMPI_FMT_USG, dgst, dgstSize, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_hash == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(hash)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags raw)(value %m))",
+ m_hash);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* get the existing signature */
+ err = gcry_mpi_scan(&m_sig_r, GCRYMPI_FMT_USG, data, 20, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_sig_r == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(r)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+ err = gcry_mpi_scan(&m_sig_s, GCRYMPI_FMT_USG, data + 20, 20, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_sig_s == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_sig, NULL,
+ "(sig-val(dsa(r %m)(s %m)))",
+ m_sig_r, m_sig_s);
+ if((err != GPG_ERR_NO_ERROR) || (s_sig == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* verify signature */
+ err = gcry_pk_verify(s_sig, s_data, xmlSecGCryptKeyDataDsaGetPublicKey(key_data));
+ if(err == GPG_ERR_NO_ERROR) {
+ res = 1; /* good signature */
+ } else if(err == GPG_ERR_BAD_SIGNATURE) {
+ res = 0; /* bad signature */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* done */
+done:
+ if(m_hash != NULL) {
+ gcry_mpi_release(m_hash);
+ }
+ if(m_sig_r != NULL) {
+ gcry_mpi_release(m_sig_r);
+ }
+ if(m_sig_s != NULL) {
+ gcry_mpi_release(m_sig_s);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+
+ return(res);
+}
+
+
+static xmlSecTransformKlass xmlSecGCryptDsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameDsaSha1, /* const xmlChar* name; */
+ xmlSecHrefDsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformDsaSha1GetKlass(void) {
+ return(&xmlSecGCryptDsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg:
+ *
+ * The SignatureValue content for an RSA signature is the base64 [MIME]
+ * encoding of the octet string computed as per RFC 2437 [PKCS1,
+ * section 8.1.1: Signature generation for the RSASSA-PKCS1-v1_5 signature
+ * scheme]. As specified in the EMSA-PKCS1-V1_5-ENCODE function RFC 2437
+ * [PKCS1, section 9.2.1], the value input to the signature function MUST
+ * contain a pre-pended algorithm object identifier for the hash function,
+ * but the availability of an ASN.1 parser and recognition of OIDs is not
+ * required of a signature verifier. The PKCS#1 v1.5 representation appears
+ * as:
+ *
+ * CRYPT (PAD (ASN.1 (OID, DIGEST (data))))
+ *
+ * Note that the padded ASN.1 will be of the following form:
+ *
+ * 01 | FF* | 00 | prefix | hash
+ *
+ * where "|" is concatenation, "01", "FF", and "00" are fixed octets of
+ * the corresponding hexadecimal value, "hash" is the SHA1 digest of the
+ * data, and "prefix" is the ASN.1 BER SHA1 algorithm designator prefix
+ * required in PKCS1 [RFC 2437], that is,
+ *
+ * hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
+ *
+ * This prefix is included to make it easier to use standard cryptographic
+ * libraries. The FF octet MUST be repeated the maximum number of times such
+ * that the value of the quantity being CRYPTed is one octet shorter than
+ * the RSA modulus.
+ *
+ ***************************************************************************/
+static int
+xmlSecGCryptRsaPkcs1PkSign(int digest, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ xmlSecBufferPtr out) {
+ gcry_sexp_t s_data = NULL;
+ gcry_mpi_t m_sig = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gcry_sexp_t s_tmp;
+ gpg_error_t err;
+ int ret;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataRsaGetPrivateKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ /* get the current digest */
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags pkcs1)(hash %s %b))",
+ gcry_md_algo_name(digest),
+ (int)dgstSize, dgst);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* create signature */
+ err = gcry_pk_sign(&s_sig, s_data, xmlSecGCryptKeyDataRsaGetPrivateKey(key_data));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_sign",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* find signature value */
+ s_tmp = gcry_sexp_find_token(s_sig, "sig-val", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ s_tmp = gcry_sexp_find_token(s_sig, "rsa", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ s_tmp = gcry_sexp_find_token(s_sig, "s", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ m_sig = gcry_sexp_nth_mpi(s_sig, 1, GCRYMPI_FMT_USG);
+ if(m_sig == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi(1)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* write out */
+ ret = xmlSecGCryptAppendMpi(m_sig, out, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppendMpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* done */
+ res = 0;
+
+done:
+ if(m_sig != NULL) {
+ gcry_mpi_release(m_sig);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+
+ return(res);
+}
+
+static int
+xmlSecGCryptRsaPkcs1PkVerify(int digest, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ const xmlSecByte* data, xmlSecSize dataSize) {
+ gcry_sexp_t s_data = NULL;
+ gcry_mpi_t m_sig = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gpg_error_t err;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataRsaGetPublicKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+
+ /* get the current digest */
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags pkcs1)(hash %s %b))",
+ gcry_md_algo_name(digest),
+ (int)dgstSize, dgst);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* get the existing signature */
+ err = gcry_mpi_scan(&m_sig, GCRYMPI_FMT_USG, data, dataSize, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_sig == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_sig, NULL,
+ "(sig-val(rsa(s %m)))",
+ m_sig);
+ if((err != GPG_ERR_NO_ERROR) || (s_sig == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* verify signature */
+ err = gcry_pk_verify(s_sig, s_data, xmlSecGCryptKeyDataRsaGetPublicKey(key_data));
+ if(err == GPG_ERR_NO_ERROR) {
+ res = 1; /* good signature */
+ } else if(err == GPG_ERR_BAD_SIGNATURE) {
+ res = 0; /* bad signature */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* done */
+done:
+ if(m_sig != NULL) {
+ gcry_mpi_release(m_sig);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+
+ return(res);
+}
+
+
+#ifndef XMLSEC_NO_MD5
+/****************************************************************************
+ *
+ * RSA-MD5 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaMd5, /* const xmlChar* name; */
+ xmlSecHrefRsaMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaMd5GetKlass(void) {
+ return(&xmlSecGCryptRsaMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+/****************************************************************************
+ *
+ * RSA-RIPEMD160 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaRipemd160, /* const xmlChar* name; */
+ xmlSecHrefRsaRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaRipemd160GetKlass:
+ *
+ * The RSA-RIPEMD160 signature transform klass.
+ *
+ * Returns: RSA-RIPEMD160 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaRipemd160GetKlass(void) {
+ return(&xmlSecGCryptRsaRipemd160Klass);
+}
+
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha1, /* const xmlChar* name; */
+ xmlSecHrefRsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha1GetKlass(void) {
+ return(&xmlSecGCryptRsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha256, /* const xmlChar* name; */
+ xmlSecHrefRsaSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha256GetKlass(void) {
+ return(&xmlSecGCryptRsaSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha384, /* const xmlChar* name; */
+ xmlSecHrefRsaSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha384GetKlass(void) {
+ return(&xmlSecGCryptRsaSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha512, /* const xmlChar* name; */
+ xmlSecHrefRsaSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha512GetKlass(void) {
+ return(&xmlSecGCryptRsaSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+
+
diff --git a/src/gcrypt/symkeys.c b/src/gcrypt/symkeys.c
new file mode 100644
index 00000000..88272fe3
--- /dev/null
+++ b/src/gcrypt/symkeys.c
@@ -0,0 +1,441 @@
+/**
+ *
+ * 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/gcrypt/crypto.h>
+
+
+/*****************************************************************************
+ *
+ * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary
+ *
+ ****************************************************************************/
+static int xmlSecGCryptSymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptSymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecGCryptSymKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecGCryptSymKeyDataXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptSymKeyDataXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptSymKeyDataBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlSecByte** buf,
+ xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGCryptSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecGCryptSymKeyDataGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecGCryptSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecGCryptSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecGCryptSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecGCryptSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+#define xmlSecGCryptSymKeyDataCheckId(data) \
+ (xmlSecKeyDataIsValid((data)) && \
+ xmlSecGCryptSymKeyDataKlassCheck((data)->id))
+
+static int
+xmlSecGCryptSymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), -1);
+
+ return(xmlSecKeyDataBinaryValueInitialize(data));
+}
+
+static int
+xmlSecGCryptSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(dst), -1);
+ xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ return(xmlSecKeyDataBinaryValueDuplicate(dst, src));
+}
+
+static void
+xmlSecGCryptSymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecGCryptSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueFinalize(data);
+}
+
+static int
+xmlSecGCryptSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecGCryptSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecGCryptSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecGCryptSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecGCryptSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecGCryptGenerateRandom(buffer, (sizeBits + 7) / 8));
+}
+
+static xmlSecKeyDataType
+xmlSecGCryptSymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown);
+
+ return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecGCryptSymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), 0);
+
+ return(xmlSecKeyDataBinaryValueGetSize(data));
+}
+
+static void
+xmlSecGCryptSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecGCryptSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugDump(data, output);
+}
+
+static void
+xmlSecGCryptSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecGCryptSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugXmlDump(data, output);
+}
+
+static int
+xmlSecGCryptSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) {
+#ifndef XMLSEC_NO_DES
+ if(klass == xmlSecGCryptKeyDataDesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(klass == xmlSecGCryptKeyDataAesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_HMAC
+ if(klass == xmlSecGCryptKeyDataHmacId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_HMAC */
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_AES
+/**************************************************************************
+ *
+ * <xmlsec:AESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecGCryptKeyDataAesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameAESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefAESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGCryptSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGCryptSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGCryptSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGCryptSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGCryptSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGCryptSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGCryptSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGCryptSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecGCryptSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecGCryptSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGCryptSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGCryptSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGCryptKeyDataAesGetKlass(void) {
+ return(&xmlSecGCryptKeyDataAesKlass);
+}
+
+/**
+ * xmlSecGCryptKeyDataAesSet:
+ * @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
+xmlSecGCryptKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataAesId), -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 xmlSecGCryptKeyDataDesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameDESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGCryptSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGCryptSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGCryptSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGCryptSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGCryptSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGCryptSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGCryptSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGCryptSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecGCryptSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecGCryptSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGCryptSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGCryptSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGCryptKeyDataDesGetKlass(void) {
+ return(&xmlSecGCryptKeyDataDesKlass);
+}
+
+/**
+ * xmlSecGCryptKeyDataDesSet:
+ * @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
+xmlSecGCryptKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDesId), -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 xmlSecGCryptKeyDataHmacKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameHMACKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefHMACKeyValue, /* const xmlChar* href; */
+ xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGCryptSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGCryptSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGCryptSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecGCryptSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGCryptSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecGCryptSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGCryptSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGCryptSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecGCryptSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecGCryptSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGCryptSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGCryptSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGCryptKeyDataHmacGetKlass(void) {
+ return(&xmlSecGCryptKeyDataHmacKlass);
+}
+
+/**
+ * xmlSecGCryptKeyDataHmacSet:
+ * @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
+xmlSecGCryptKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataHmacId), -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/globals.h b/src/globals.h
new file mode 100644
index 00000000..31a57d6b
--- /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..84ce637a
--- /dev/null
+++ b/src/gnutls/Makefile.am
@@ -0,0 +1,58 @@
+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 \
+ kw_aes.c \
+ kw_des.c \
+ symkeys.c \
+ asymkeys.c \
+ signatures.c \
+ x509utils.h \
+ x509utils.c \
+ x509.c \
+ x509vfy.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_gnutls_la_SOURCES += ../strings.c
+endif
+
+# xmlsec-gnutls library requires xmlsec-gcrypt
+libxmlsec1_gnutls_la_LIBADD = \
+ $(GNUTLS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ ../gcrypt/libxmlsec1-gcrypt.la \
+ $(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..93a57352
--- /dev/null
+++ b/src/gnutls/Makefile.in
@@ -0,0 +1,786 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c
+subdir = src/gnutls
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__libxmlsec1_gnutls_la_SOURCES_DIST = app.c ciphers.c crypto.c \
+ digests.c hmac.c kw_aes.c kw_des.c symkeys.c asymkeys.c \
+ signatures.c x509utils.h x509utils.c x509.c x509vfy.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-kw_aes.lo libxmlsec1_gnutls_la-kw_des.lo \
+ libxmlsec1_gnutls_la-symkeys.lo \
+ libxmlsec1_gnutls_la-asymkeys.lo \
+ libxmlsec1_gnutls_la-signatures.lo \
+ libxmlsec1_gnutls_la-x509utils.lo libxmlsec1_gnutls_la-x509.lo \
+ libxmlsec1_gnutls_la-x509vfy.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@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-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 kw_aes.c kw_des.c symkeys.c asymkeys.c signatures.c \
+ x509utils.h x509utils.c x509.c x509vfy.c globals.h $(NULL) \
+ $(am__append_1)
+
+# xmlsec-gnutls library requires xmlsec-gcrypt
+libxmlsec1_gnutls_la_LIBADD = \
+ $(GNUTLS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ ../gcrypt/libxmlsec1-gcrypt.la \
+ $(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-asymkeys.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-kw_aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-kw_des.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-signatures.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@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_la-x509utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gnutls_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_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-kw_aes.lo: kw_aes.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-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-kw_aes.Tpo -c -o libxmlsec1_gnutls_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-kw_aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+
+libxmlsec1_gnutls_la-kw_des.lo: kw_des.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-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-kw_des.Tpo -c -o libxmlsec1_gnutls_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-kw_des.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.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-asymkeys.lo: asymkeys.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-asymkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-asymkeys.Tpo -c -o libxmlsec1_gnutls_la-asymkeys.lo `test -f 'asymkeys.c' || echo '$(srcdir)/'`asymkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-asymkeys.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-asymkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='asymkeys.c' object='libxmlsec1_gnutls_la-asymkeys.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-asymkeys.lo `test -f 'asymkeys.c' || echo '$(srcdir)/'`asymkeys.c
+
+libxmlsec1_gnutls_la-signatures.lo: signatures.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-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-signatures.Tpo -c -o libxmlsec1_gnutls_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-signatures.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-signatures.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+
+libxmlsec1_gnutls_la-x509utils.lo: x509utils.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-x509utils.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-x509utils.Tpo -c -o libxmlsec1_gnutls_la-x509utils.lo `test -f 'x509utils.c' || echo '$(srcdir)/'`x509utils.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-x509utils.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-x509utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509utils.c' object='libxmlsec1_gnutls_la-x509utils.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-x509utils.lo `test -f 'x509utils.c' || echo '$(srcdir)/'`x509utils.c
+
+libxmlsec1_gnutls_la-x509.lo: x509.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-x509.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-x509.Tpo -c -o libxmlsec1_gnutls_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-x509.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-x509.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+
+libxmlsec1_gnutls_la-x509vfy.lo: x509vfy.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-x509vfy.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gnutls_la-x509vfy.Tpo -c -o libxmlsec1_gnutls_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_gnutls_la-x509vfy.Tpo $(DEPDIR)/libxmlsec1_gnutls_la-x509vfy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509vfy.c' object='libxmlsec1_gnutls_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_gnutls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gnutls_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.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..404aa878
--- /dev/null
+++ b/src/gnutls/README
@@ -0,0 +1,6 @@
+The xmlsec-gnutls uses both libgcrypt and libgnutls because GnuTLS
+does not provide direct access to low-level crypto operations (digests,
+hmac, aes, des, etc.).
+
+
+
diff --git a/src/gnutls/app.c b/src/gnutls/app.c
new file mode 100644
index 00000000..856257f3
--- /dev/null
+++ b/src/gnutls/app.c
@@ -0,0 +1,998 @@
+/**
+ * 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 <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>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+#include <xmlsec/gcrypt/app.h>
+
+static xmlSecKeyPtr xmlSecGnuTLSAppKeyFromCertLoad (const char *filename,
+ xmlSecKeyDataFormat format);
+static xmlSecKeyPtr xmlSecGnuTLSAppKeyFromCertLoadMemory (const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecKeyDataFormat format);
+
+/**
+ * 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) {
+ int err;
+
+ err = gnutls_global_init();
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_global_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ return(xmlSecGCryptAppInit(config));
+}
+
+/**
+ * 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(xmlSecGCryptAppShutdown());
+}
+
+/**
+ * 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.
+ *
+ * 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) {
+ xmlSecKeyPtr key;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+#ifndef XMLSEC_NO_X509
+ case xmlSecKeyDataFormatPkcs12:
+ key = xmlSecGnuTLSAppPkcs12Load(filename, pwd, pwdCallback, pwdCallbackCtx);
+ break;
+ case xmlSecKeyDataFormatCertPem:
+ case xmlSecKeyDataFormatCertDer:
+ key = xmlSecGnuTLSAppKeyFromCertLoad(filename, format);
+ break;
+#endif /* XMLSEC_NO_X509 */
+ default:
+ key = xmlSecGCryptAppKeyLoad(filename, format, pwd, pwdCallback, pwdCallbackCtx);
+ break;
+ }
+
+ return(key);
+}
+
+/**
+ * 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.
+ *
+ * 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) {
+ xmlSecKeyPtr key;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+#ifndef XMLSEC_NO_X509
+ case xmlSecKeyDataFormatPkcs12:
+ key = xmlSecGnuTLSAppPkcs12LoadMemory(data, dataSize, pwd, pwdCallback, pwdCallbackCtx);
+ break;
+ case xmlSecKeyDataFormatCertPem:
+ case xmlSecKeyDataFormatCertDer:
+ key = xmlSecGnuTLSAppKeyFromCertLoadMemory(data, dataSize, format);
+ break;
+#endif /* XMLSEC_NO_X509 */
+ default:
+ key = xmlSecGCryptAppKeyLoadMemory(data, dataSize, format, pwd, pwdCallback, pwdCallbackCtx);
+ break;
+ }
+ return(key);
+}
+
+#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.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeyCertLoad(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, 4*1024);
+ 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) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSAppKeyCertLoadMemory(key,
+ xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer),
+ format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeyCertLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ /* cleanup */
+ xmlSecBufferFinalize(&buffer);
+ return(0);
+}
+
+/**
+ * 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.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeyCertLoadMemory(xmlSecKeyPtr key,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ gnutls_x509_crt_t cert;
+ xmlSecKeyDataPtr keyData;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ keyData = xmlSecKeyEnsureData(key, xmlSecGnuTLSKeyDataX509Id);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cert = xmlSecGnuTLSX509CertRead(data, dataSize, format);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(keyData, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * 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.
+ * 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,
+ void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecKeyPtr key;
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+
+ ret = xmlSecBufferInitialize(&buffer, 4*1024);
+ 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) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ key = xmlSecGnuTLSAppPkcs12LoadMemory(xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer),
+ pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppPkcs12LoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ /* cleanup */
+ xmlSecBufferFinalize(&buffer);
+ return(key);
+}
+
+/**
+ * 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.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecGnuTLSAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ const char *pwd,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED)
+{
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyPtr res = NULL;
+ xmlSecPtrList certsList;
+ xmlSecKeyDataPtr keyData = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ gnutls_x509_privkey_t priv_key = NULL;
+ gnutls_x509_crt_t key_cert = NULL;
+ xmlSecSize certsSize;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 0, NULL);
+
+ /* prepare */
+ ret = xmlSecPtrListInitialize(&(certsList), xmlSecGnuTLSX509CrtListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "certsList");
+ return(NULL);
+ }
+
+ /* load pkcs12 */
+ ret = xmlSecGnuTLSPkcs12LoadMemory(data, dataSize, pwd, &priv_key, &key_cert, &certsList);
+ if((ret < 0) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSPkcs12LoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* create key */
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* create key value data */
+ keyData = xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(priv_key);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ priv_key = NULL; /* owned by keyData now */
+
+ 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; /* owned by key now */
+
+
+ /* create x509 certs data */
+ certsSize = xmlSecPtrListGetSize(&certsList);
+ if((certsSize > 0) || (key_cert != NULL)) {
+ xmlSecSize ii;
+
+ x509Data = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataX509Id)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* set key's cert */
+ if(key_cert != NULL) {
+ ret = xmlSecGnuTLSKeyDataX509AdoptKeyCert(x509Data, key_cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ key_cert = NULL; /* owned by x509Data now */
+ }
+
+ /* copy all other certs */
+ for(ii = 0; ii < certsSize; ++ii) {
+ gnutls_x509_crt_t cert = xmlSecPtrListRemoveAndReturn(&certsList, ii);
+ if(cert == NULL) {
+ continue;
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(x509Data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert);
+ goto done;
+ }
+ }
+
+ /* set in the key */
+ 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; /* owned by key now */
+ }
+
+ /* success!!! */
+ res = key;
+ key = NULL;
+
+done:
+ if(key_cert != NULL) {
+ gnutls_x509_crt_deinit(key_cert);
+ }
+ if(priv_key != NULL) {
+ gnutls_x509_privkey_deinit(priv_key);
+ }
+ if(keyData != NULL) {
+ xmlSecKeyDataDestroy(keyData);
+ }
+ if(x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ xmlSecPtrListFinalize(&certsList);
+ return(res);
+}
+
+static xmlSecKeyPtr
+xmlSecGnuTLSAppKeyFromCertLoad(const char *filename,
+ xmlSecKeyDataFormat format)
+{
+ xmlSecKeyPtr key;
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+
+ ret = xmlSecBufferInitialize(&buffer, 4*1024);
+ 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) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ key = xmlSecGnuTLSAppKeyFromCertLoadMemory(
+ xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer),
+ format);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeyFromCertLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(NULL);
+ }
+
+ /* cleanup */
+ xmlSecBufferFinalize(&buffer);
+ return(key);
+}
+
+static xmlSecKeyPtr
+xmlSecGnuTLSAppKeyFromCertLoadMemory(const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecKeyDataFormat format)
+{
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyDataPtr keyData = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ gnutls_x509_crt_t cert = NULL;
+ xmlSecKeyPtr res = NULL;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(dataSize > 0, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* read cert */
+ cert = xmlSecGnuTLSX509CertRead(data, dataSize, format);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* create key */
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* create key value data */
+ keyData = xmlSecGnuTLSX509CertGetKey(cert);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetKey",
+ 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; /* owned by key now */
+
+ /* create x509 data */
+ x509Data = xmlSecKeyEnsureData(key, xmlSecGnuTLSKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ ret = xmlSecGnuTLSKeyDataX509AdoptKeyCert(x509Data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ cert = NULL; /* owned by x509Data now */
+
+ /* success */
+ res = key;
+ key = NULL;
+
+done:
+ if(cert != NULL) {
+ gnutls_x509_crt_deinit(cert);
+ }
+ if(keyData != NULL) {
+ xmlSecKeyDataDestroy(keyData);
+ }
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ return(res);
+}
+
+/**
+ * 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.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr,
+ const char *filename,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ xmlSecBuffer buffer;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ ret = xmlSecBufferInitialize(&buffer, 4*1024);
+ 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) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferReadFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSAppKeysMngrCertLoadMemory(mngr,
+ xmlSecBufferGetData(&buffer),
+ xmlSecBufferGetSize(&buffer),
+ format,
+ type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSAppKeysMngrCertLoadMemory",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(filename));
+ xmlSecBufferFinalize(&buffer);
+ return(-1);
+ }
+
+ /* cleanup */
+ xmlSecBufferFinalize(&buffer);
+ return(0);
+}
+
+/**
+ * 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.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ xmlSecKeyDataStorePtr x509Store;
+ gnutls_x509_crt_t cert;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecGnuTLSX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSX509StoreId");
+ return(-1);
+ }
+
+ cert = xmlSecGnuTLSX509CertRead(data, dataSize, format);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSX509StoreAdoptCert(x509Store, cert, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509StoreAdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#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/asymkeys.c b/src/gnutls/asymkeys.c
new file mode 100644
index 00000000..6ac68a78
--- /dev/null
+++ b/src/gnutls/asymkeys.c
@@ -0,0 +1,455 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+#include <gcrypt.h>
+
+static void xmlSecGnuTLSDestroyParams(gnutls_datum_t * params, xmlSecSize num) {
+ xmlSecSize ii;
+
+ xmlSecAssert(params != NULL);
+ for(ii = 0; ii < num; ++ii) {
+ gnutls_free(params[ii].data);
+ }
+}
+
+static void xmlSecGnuTLSDestroyMpis(gcry_mpi_t * mpis, xmlSecSize num) {
+ xmlSecSize ii;
+
+ xmlSecAssert(mpis != NULL);
+ for(ii = 0; ii < num; ++ii) {
+ gcry_mpi_release(mpis[ii]);
+ }
+}
+
+static int xmlSecGnuTLSConvertParamsToMpis(gnutls_datum_t * params, xmlSecSize paramsNum,
+ gcry_mpi_t * mpis, xmlSecSize mpisNum) {
+
+ xmlSecSize ii;
+ int rc;
+
+ xmlSecAssert2(params != NULL, -1);
+ xmlSecAssert2(mpis != NULL, -1);
+ xmlSecAssert2(paramsNum == mpisNum, -1);
+
+ for(ii = 0; ii < paramsNum; ++ii) {
+ rc = gcry_mpi_scan(&(mpis[ii]), GCRYMPI_FMT_USG, params[ii].data, params[ii].size, NULL);
+ if((rc != GPG_ERR_NO_ERROR) || (mpis[ii] == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, ii); /* destroy up to now */
+ return(-1);
+ }
+ }
+
+ /* done */
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+
+/**
+ * xmlSecGnuTLSKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataDsaGetKlass(void) {
+ return (xmlSecGCryptKeyDataDsaGetKlass());
+}
+
+/**
+ * xmlSecGnuTLSKeyDataDsaAdoptPrivateKey:
+ * @data: the pointer to DSA key data.
+ * @dsa_key: the pointer to GnuTLS DSA private key.
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(xmlSecKeyDataPtr data, gnutls_x509_privkey_t dsa_key) {
+ gnutls_datum_t params[5];
+ gcry_mpi_t mpis[5];
+ gcry_sexp_t priv_key = NULL;
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int err;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataDsaId), -1);
+ xmlSecAssert2(dsa_key != NULL, -1);
+ xmlSecAssert2(gnutls_x509_privkey_get_pk_algorithm(dsa_key) == GNUTLS_PK_DSA, -1);
+
+ /* get raw values */
+ err = gnutls_x509_privkey_export_dsa_raw(dsa_key,
+ &(params[0]), &(params[1]), &(params[2]),
+ &(params[3]), &(params[4]));
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_export_dsa_raw",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(priv_key), NULL, "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
+ mpis[0], mpis[1], mpis[2], mpis[3], mpis[4]);
+ if((rc != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/dsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ mpis[0], mpis[1], mpis[2], mpis[3]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ gcry_sexp_release(priv_key);
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataDsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ gcry_sexp_release(priv_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_x509_privkey_deinit(dsa_key);
+ return(0);
+}
+
+
+/**
+ * xmlSecGnuTLSKeyDataDsaAdoptPublicKey:
+ * @data: the pointer to DSA key data.
+ * @p: the pointer to p component of the DSA public key
+ * @q: the pointer to q component of the DSA public key
+ * @g: the pointer to g component of the DSA public key
+ * @y: the pointer to y component of the DSA public key
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataDsaAdoptPublicKey(xmlSecKeyDataPtr data,
+ gnutls_datum_t * p, gnutls_datum_t * q,
+ gnutls_datum_t * g, gnutls_datum_t * y) {
+ gnutls_datum_t params[4];
+ gcry_mpi_t mpis[4];
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataDsaId), -1);
+ xmlSecAssert2(p != NULL, -1);
+ xmlSecAssert2(q != NULL, -1);
+ xmlSecAssert2(g != NULL, -1);
+ xmlSecAssert2(y != NULL, -1);
+
+ /* copy */
+ memcpy(&(params[0]), p, sizeof(*p));
+ memcpy(&(params[1]), q, sizeof(*q));
+ memcpy(&(params[2]), g, sizeof(*g));
+ memcpy(&(params[3]), y, sizeof(*y));
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ /* don't destroy params - we got them from outside !!! */
+ return(-1);
+ }
+ /* don't destroy params - we got them from outside !!! */
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ mpis[0], mpis[1], mpis[2], mpis[3]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataDsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_free(p->data);
+ gnutls_free(q->data);
+ gnutls_free(g->data);
+ gnutls_free(y->data);
+ return(0);
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+
+#ifndef XMLSEC_NO_RSA
+
+/**
+ * xmlSecGnuTLSKeyDataRsaGetKlass:
+ *
+ * The GnuTLS RSA key data klass.
+ *
+ * Returns: pointer to GnuTLS RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataRsaGetKlass(void) {
+ return (xmlSecGCryptKeyDataRsaGetKlass());
+}
+
+/**
+ * xmlSecGnuTLSKeyDataRsaAdoptPrivateKey:
+ * @data: the pointer to RSA key data.
+ * @rsa_key: the pointer to GnuTLS RSA private key.
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(xmlSecKeyDataPtr data, gnutls_x509_privkey_t rsa_key) {
+ gnutls_datum_t params[6];
+ gcry_mpi_t mpis[6];
+ gcry_sexp_t priv_key = NULL;
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int err;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataRsaId), -1);
+ xmlSecAssert2(rsa_key != NULL, -1);
+ xmlSecAssert2(gnutls_x509_privkey_get_pk_algorithm(rsa_key) == GNUTLS_PK_RSA, -1);
+
+ /* get raw values */
+ err = gnutls_x509_privkey_export_rsa_raw(rsa_key,
+ &(params[0]), &(params[1]), &(params[2]),
+ &(params[3]), &(params[4]), &(params[5]));
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_export_rsa_raw",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(priv_key), NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
+ mpis[0], mpis[1], mpis[2],
+ mpis[3], mpis[4], mpis[5]);
+ if((rc != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(rsa((n%m)(e%m))))",
+ mpis[0], mpis[1]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ gcry_sexp_release(priv_key);
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataRsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ gcry_sexp_release(priv_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_x509_privkey_deinit(rsa_key);
+ return(0);
+}
+
+
+/**
+ * xmlSecGnuTLSKeyDataRsaAdoptPublicKey:
+ * @data: the pointer to RSA key data.
+ * @m: the pointer to m component of the RSA public key
+ * @e: the pointer to e component of the RSA public key
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataRsaAdoptPublicKey(xmlSecKeyDataPtr data,
+ gnutls_datum_t * m, gnutls_datum_t * e) {
+ gnutls_datum_t params[2];
+ gcry_mpi_t mpis[2];
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataRsaId), -1);
+ xmlSecAssert2(m != NULL, -1);
+ xmlSecAssert2(e != NULL, -1);
+
+ /* copy */
+ memcpy(&(params[0]), m, sizeof(*m));
+ memcpy(&(params[1]), e, sizeof(*e));
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ /* don't destroy params - we got them from outside !!! */
+ return(-1);
+ }
+ /* don't destroy params - we got them from outside !!! */
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(rsa((n%m)(e%m))))",
+ mpis[0], mpis[1]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataRsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_free(m->data);
+ gnutls_free(e->data);
+ return(0);
+}
+#endif /* XMLSEC_NO_RSA */
diff --git a/src/gnutls/ciphers.c b/src/gnutls/ciphers.c
new file mode 100644
index 00000000..eacfede6
--- /dev/null
+++ b/src/gnutls/ciphers.c
@@ -0,0 +1,82 @@
+/**
+ * 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 <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+
+
+
+
+#ifndef XMLSEC_NO_AES
+
+/**
+ * xmlSecGnuTLSTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformAes128CbcGetKlass(void) {
+ return (xmlSecGCryptTransformAes128CbcGetKlass());
+}
+
+/**
+ * xmlSecGnuTLSTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformAes192CbcGetKlass(void) {
+ return (xmlSecGCryptTransformAes192CbcGetKlass());
+}
+
+/**
+ * xmlSecGnuTLSTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformAes256CbcGetKlass(void) {
+ return (xmlSecGCryptTransformAes256CbcGetKlass());
+}
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**
+ * xmlSecGnuTLSTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformDes3CbcGetKlass(void) {
+ return (xmlSecGCryptTransformDes3CbcGetKlass());
+}
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/gnutls/crypto.c b/src/gnutls/crypto.c
new file mode 100644
index 00000000..83175e69
--- /dev/null
+++ b/src/gnutls/crypto.c
@@ -0,0 +1,351 @@
+/**
+ * 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 <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>
+#include <xmlsec/gnutls/x509.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_DSA
+ gXmlSecGnuTLSFunctions->keyDataDsaGetKlass = xmlSecGnuTLSKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecGnuTLSFunctions->keyDataHmacGetKlass = xmlSecGnuTLSKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecGnuTLSFunctions->keyDataRsaGetKlass = xmlSecGnuTLSKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_X509
+ gXmlSecGnuTLSFunctions->keyDataX509GetKlass = xmlSecGnuTLSKeyDataX509GetKlass;
+ gXmlSecGnuTLSFunctions->keyDataRawX509CertGetKlass = xmlSecGnuTLSKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /********************************************************************
+ *
+ * Key data store ids
+ *
+ ********************************************************************/
+#ifndef XMLSEC_NO_X509
+ gXmlSecGnuTLSFunctions->x509StoreGetKlass = xmlSecGnuTLSX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /********************************************************************
+ *
+ * Crypto transforms ids
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecGnuTLSFunctions->transformAes128CbcGetKlass = xmlSecGnuTLSTransformAes128CbcGetKlass;
+ gXmlSecGnuTLSFunctions->transformAes192CbcGetKlass = xmlSecGnuTLSTransformAes192CbcGetKlass;
+ gXmlSecGnuTLSFunctions->transformAes256CbcGetKlass = xmlSecGnuTLSTransformAes256CbcGetKlass;
+ gXmlSecGnuTLSFunctions->transformKWAes128GetKlass = xmlSecGnuTLSTransformKWAes128GetKlass;
+ gXmlSecGnuTLSFunctions->transformKWAes192GetKlass = xmlSecGnuTLSTransformKWAes192GetKlass;
+ gXmlSecGnuTLSFunctions->transformKWAes256GetKlass = xmlSecGnuTLSTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecGnuTLSFunctions->transformDes3CbcGetKlass = xmlSecGnuTLSTransformDes3CbcGetKlass;
+ gXmlSecGnuTLSFunctions->transformKWDes3GetKlass = xmlSecGnuTLSTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGnuTLSFunctions->transformDsaSha1GetKlass = xmlSecGnuTLSTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecGnuTLSFunctions->transformHmacMd5GetKlass = xmlSecGnuTLSTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecGnuTLSFunctions->transformHmacRipemd160GetKlass = xmlSecGnuTLSTransformHmacRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGnuTLSFunctions->transformHmacSha1GetKlass = xmlSecGnuTLSTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecGnuTLSFunctions->transformHmacSha256GetKlass = xmlSecGnuTLSTransformHmacSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecGnuTLSFunctions->transformHmacSha384GetKlass = xmlSecGnuTLSTransformHmacSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecGnuTLSFunctions->transformHmacSha512GetKlass = xmlSecGnuTLSTransformHmacSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* MD5 ********************************/
+#ifndef XMLSEC_NO_MD5
+ gXmlSecGnuTLSFunctions->transformMd5GetKlass = xmlSecGnuTLSTransformMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+ /******************************* RIPEMD160 ********************************/
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecGnuTLSFunctions->transformRipemd160GetKlass = xmlSecGnuTLSTransformRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecGnuTLSFunctions->transformRsaMd5GetKlass = xmlSecGnuTLSTransformRsaMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecGnuTLSFunctions->transformRsaRipemd160GetKlass = xmlSecGnuTLSTransformRsaRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGnuTLSFunctions->transformRsaSha1GetKlass = xmlSecGnuTLSTransformRsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecGnuTLSFunctions->transformRsaSha256GetKlass = xmlSecGnuTLSTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecGnuTLSFunctions->transformRsaSha384GetKlass = xmlSecGnuTLSTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecGnuTLSFunctions->transformRsaSha512GetKlass = xmlSecGnuTLSTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecGnuTLSFunctions->transformSha1GetKlass = xmlSecGnuTLSTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecGnuTLSFunctions->transformSha256GetKlass = xmlSecGnuTLSTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecGnuTLSFunctions->transformSha384GetKlass = xmlSecGnuTLSTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecGnuTLSFunctions->transformSha512GetKlass = xmlSecGnuTLSTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+
+ /********************************************************************
+ *
+ * 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) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+#ifndef XMLSEC_NO_X509
+ /* create x509 store if needed */
+ if(xmlSecKeysMngrGetDataStore(mngr, xmlSecGnuTLSX509StoreId) == NULL) {
+ xmlSecKeyDataStorePtr x509Store;
+
+ x509Store = xmlSecKeyDataStoreCreate(xmlSecGnuTLSX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSX509StoreId");
+ 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);
+}
+
+/**
+ * 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..2df20706
--- /dev/null
+++ b/src/gnutls/digests.c
@@ -0,0 +1,112 @@
+/**
+ * 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 <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>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+
+#ifndef XMLSEC_NO_SHA1
+/**
+ * xmlSecGnuTLSTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformSha1GetKlass(void) {
+ return (xmlSecGCryptTransformSha1GetKlass());
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+/**
+ * xmlSecGnuTLSTransformSha256GetKlass:
+ *
+ * SHA256 digest transform klass.
+ *
+ * Returns: pointer to SHA256 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformSha256GetKlass(void) {
+ return (xmlSecGCryptTransformSha256GetKlass());
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/**
+ * xmlSecGnuTLSTransformSha384GetKlass:
+ *
+ * SHA384 digest transform klass.
+ *
+ * Returns: pointer to SHA384 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformSha384GetKlass(void) {
+ return (xmlSecGCryptTransformSha384GetKlass());
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/**
+ * xmlSecGnuTLSTransformSha512GetKlass:
+ *
+ * SHA512 digest transform klass.
+ *
+ * Returns: pointer to SHA512 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformSha512GetKlass(void) {
+ return (xmlSecGCryptTransformSha512GetKlass());
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_MD5
+
+/**
+ * xmlSecGnuTLSTransformMd5GetKlass:
+ *
+ * MD5 digest transform klass.
+ *
+ * Returns: pointer to MD5 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformMd5GetKlass(void) {
+ return (xmlSecGCryptTransformMd5GetKlass());
+}
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+/**
+ * xmlSecGnuTLSTransformRipemd160GetKlass:
+ *
+ * RIPEMD160 digest transform klass.
+ *
+ * Returns: pointer to RIPEMD160 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRipemd160GetKlass(void) {
+ return (xmlSecGCryptTransformRipemd160GetKlass());
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
diff --git a/src/gnutls/globals.h b/src/gnutls/globals.h
new file mode 100644
index 00000000..b49e2404
--- /dev/null
+++ b/src/gnutls/globals.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+#define XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err) \
+ "error code=%d; error message='%s'", \
+ (int)err, xmlSecErrorsSafeString(gcry_strerror((err)))
+#define XMLSEC_GNUTLS_REPORT_ERROR(err) \
+ "error code=%d; error message='%s'", \
+ (int)err, xmlSecErrorsSafeString(gnutls_strerror((err)))
+
+#endif /* ! __XMLSEC_GLOBALS_H__ */
diff --git a/src/gnutls/hmac.c b/src/gnutls/hmac.c
new file mode 100644
index 00000000..5d1acfc2
--- /dev/null
+++ b/src/gnutls/hmac.c
@@ -0,0 +1,141 @@
+/**
+ * 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 <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>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+
+/**
+ * xmlSecGnuTLSHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecGnuTLSHmacGetMinOutputLength(void)
+{
+ return xmlSecGCryptHmacGetMinOutputLength();
+}
+
+/**
+ * xmlSecGnuTLSHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecGnuTLSHmacSetMinOutputLength(int min_length)
+{
+ xmlSecGCryptHmacSetMinOutputLength(min_length);
+}
+
+
+
+#ifndef XMLSEC_NO_SHA1
+/**
+ * xmlSecGnuTLSTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacSha1GetKlass(void) {
+ return (xmlSecGCryptTransformHmacSha1GetKlass());
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/**
+ * xmlSecGnuTLSTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacSha256GetKlass(void) {
+ return (xmlSecGCryptTransformHmacSha256GetKlass());
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/**
+ * xmlSecGnuTLSTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacSha384GetKlass(void) {
+ return (xmlSecGCryptTransformHmacSha384GetKlass());
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/**
+ * xmlSecGnuTLSTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacSha512GetKlass(void) {
+ return (xmlSecGCryptTransformHmacSha512GetKlass());
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+
+#ifndef XMLSEC_NO_RIPEMD160
+/**
+ * xmlSecGnuTLSTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacRipemd160GetKlass(void) {
+ return (xmlSecGCryptTransformHmacRipemd160GetKlass());
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+/**
+ * xmlSecGnuTLSTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformHmacMd5GetKlass(void) {
+ return (xmlSecGCryptTransformHmacMd5GetKlass());
+}
+#endif /* XMLSEC_NO_MD5 */
+
+
+#endif /* XMLSEC_NO_HMAC */
diff --git a/src/gnutls/kw_aes.c b/src/gnutls/kw_aes.c
new file mode 100644
index 00000000..63f8a6be
--- /dev/null
+++ b/src/gnutls/kw_aes.c
@@ -0,0 +1,72 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_AES
+#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/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+
+
+
+/**
+ * xmlSecGnuTLSTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformKWAes128GetKlass(void) {
+ return(xmlSecGCryptTransformKWAes128GetKlass());
+}
+
+/**
+ * xmlSecGnuTLSTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformKWAes192GetKlass(void) {
+ return(xmlSecGCryptTransformKWAes192GetKlass());
+}
+
+/**
+ * xmlSecGnuTLSTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformKWAes256GetKlass(void) {
+ return(xmlSecGCryptTransformKWAes256GetKlass());
+}
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/gnutls/kw_des.c b/src/gnutls/kw_des.c
new file mode 100644
index 00000000..5d2a2e55
--- /dev/null
+++ b/src/gnutls/kw_des.c
@@ -0,0 +1,51 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_DES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.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/crypto.h>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+
+
+/**
+ * xmlSecGnuTLSTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformKWDes3GetKlass(void) {
+ return(xmlSecGCryptTransformKWDes3GetKlass());
+}
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/gnutls/signatures.c b/src/gnutls/signatures.c
new file mode 100644
index 00000000..98d1f832
--- /dev/null
+++ b/src/gnutls/signatures.c
@@ -0,0 +1,148 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+#include <gcrypt.h>
+
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+
+/**
+ * xmlSecGnuTLSTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformDsaSha1GetKlass(void) {
+ return (xmlSecGCryptTransformDsaSha1GetKlass());
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+
+/**
+ * xmlSecGnuTLSTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRsaMd5GetKlass(void) {
+ return (xmlSecGCryptTransformRsaMd5GetKlass());
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+
+/**
+ * xmlSecGnuTLSTransformRsaRipemd160GetKlass:
+ *
+ * The RSA-RIPEMD160 signature transform klass.
+ *
+ * Returns: RSA-RIPEMD160 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRsaRipemd160GetKlass(void) {
+ return (xmlSecGCryptTransformRsaRipemd160GetKlass());
+}
+
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+/**
+ * xmlSecGnuTLSTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRsaSha1GetKlass(void) {
+ return (xmlSecGCryptTransformRsaSha1GetKlass());
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+
+/**
+ * xmlSecGnuTLSTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRsaSha256GetKlass(void) {
+ return (xmlSecGCryptTransformRsaSha256GetKlass());
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+
+/**
+ * xmlSecGnuTLSTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRsaSha384GetKlass(void) {
+ return (xmlSecGCryptTransformRsaSha384GetKlass());
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/**
+ * xmlSecGnuTLSTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformRsaSha512GetKlass(void) {
+ return (xmlSecGCryptTransformRsaSha512GetKlass());
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+
+
diff --git a/src/gnutls/symkeys.c b/src/gnutls/symkeys.c
new file mode 100644
index 00000000..b1521d62
--- /dev/null
+++ b/src/gnutls/symkeys.c
@@ -0,0 +1,125 @@
+/**
+ *
+ * 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>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+
+
+
+#ifndef XMLSEC_NO_AES
+/**
+ * xmlSecGnuTLSKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataAesGetKlass(void) {
+ return (xmlSecGCryptKeyDataAesGetKlass());
+}
+
+/**
+ * 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) {
+ return (xmlSecGCryptKeyDataAesSet(data, buf, bufSize));
+}
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**
+ * xmlSecGnuTLSKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataDesGetKlass(void) {
+ return (xmlSecGCryptKeyDataDesGetKlass());
+}
+
+/**
+ * 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) {
+ return (xmlSecGCryptKeyDataDesSet(data, buf, bufSize));
+}
+
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_HMAC
+
+/**
+ * xmlSecGnuTLSKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataHmacGetKlass(void) {
+ return (xmlSecGCryptKeyDataHmacGetKlass());
+}
+
+/**
+ * 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) {
+ return (xmlSecGCryptKeyDataHmacSet(data, buf, bufSize));
+}
+
+#endif /* XMLSEC_NO_HMAC */
+
diff --git a/src/gnutls/x509.c b/src/gnutls/x509.c
new file mode 100644
index 00000000..52d46ab4
--- /dev/null
+++ b/src/gnutls/x509.c
@@ -0,0 +1,1960 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 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 <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/private.h>
+
+#include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+/*************************************************************************
+ *
+ * X509 utility functions
+ *
+ ************************************************************************/
+static int xmlSecGnuTLSX509DataNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509CertificateNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509CertificateNodeWrite (gnutls_x509_crt_t cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509SubjectNameNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509SubjectNameNodeWrite (gnutls_x509_crt_t cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509IssuerSerialNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509IssuerSerialNodeWrite (gnutls_x509_crt_t cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509SKINodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509SKINodeWrite (gnutls_x509_crt_t cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509CRLNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSX509CRLNodeWrite (gnutls_x509_crl_t crl,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data,
+ xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+/*************************************************************************
+ *
+ * Internal GnuTLS X509 data CTX
+ *
+ ************************************************************************/
+typedef struct _xmlSecGnuTLSX509DataCtx xmlSecGnuTLSX509DataCtx,
+ *xmlSecGnuTLSX509DataCtxPtr;
+struct _xmlSecGnuTLSX509DataCtx {
+ gnutls_x509_crt_t keyCert;
+ xmlSecPtrList certsList;
+ xmlSecPtrList 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) >
+ *
+ * -----------------------------------------------------------------------
+ *
+ * xmlSecGnuTLSX509DataCtx is located after xmlSecTransform
+ *
+ *************************************************************************/
+#define xmlSecGnuTLSX509DataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecGnuTLSX509DataCtx))
+#define xmlSecGnuTLSX509DataGetCtx(data) \
+ ((xmlSecGnuTLSX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecGnuTLSKeyDataX509Initialize (xmlSecKeyDataPtr data);
+static int xmlSecGnuTLSKeyDataX509Duplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecGnuTLSKeyDataX509Finalize (xmlSecKeyDataPtr data);
+static int xmlSecGnuTLSKeyDataX509XmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecGnuTLSKeyDataX509XmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyDataType xmlSecGnuTLSKeyDataX509GetType (xmlSecKeyDataPtr data);
+static const xmlChar* xmlSecGnuTLSKeyDataX509GetIdentifier (xmlSecKeyDataPtr data);
+
+static void xmlSecGnuTLSKeyDataX509DebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecGnuTLSKeyDataX509DebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+
+
+static xmlSecKeyDataKlass xmlSecGnuTLSKeyDataX509Klass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecGnuTLSX509DataSize,
+
+ /* data */
+ xmlSecNameX509Data,
+ xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefX509Data, /* const xmlChar* href; */
+ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecGnuTLSKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecGnuTLSKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecGnuTLSKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecGnuTLSKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ xmlSecGnuTLSKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecGnuTLSKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecGnuTLSKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecGnuTLSKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecGnuTLSKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetKlass:
+ *
+ * The GnuTLS X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data).
+ *
+ * Returns: the X509 data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataX509GetKlass(void) {
+ return(&xmlSecGnuTLSKeyDataX509Klass);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetKeyCert:
+ * @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.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->keyCert);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509AdoptKeyCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to GnuTLS X509 certificate.
+ *
+ * Sets the key's certificate in @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGnuTLSKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, gnutls_x509_crt_t cert) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->keyCert != NULL) {
+ gnutls_x509_crt_deinit(ctx->keyCert);
+ }
+ ctx->keyCert = cert;
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509AdoptCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to GnuTLS X509 certificate.
+ *
+ * Adds certificate to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGnuTLSKeyDataX509AdoptCert(xmlSecKeyDataPtr data, gnutls_x509_crt_t cert) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecPtrListAdd(&(ctx->certsList), cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetCert:
+ * @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.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(xmlSecPtrListGetItem(&(ctx->certsList), pos));
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetCertsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of certificates in @data.
+ *
+ * Returns: te number of certificates in @data.
+ */
+xmlSecSize
+xmlSecGnuTLSKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), 0);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(xmlSecPtrListGetSize(&(ctx->certsList)));
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509AdoptCrl:
+ * @data: the pointer to X509 key data.
+ * @crl: the pointer to GnuTLS X509 crl.
+ *
+ * Adds crl to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGnuTLSKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, gnutls_x509_crl_t crl) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(crl != NULL, -1);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecPtrListAdd(&(ctx->crlsList), crl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetCrl:
+ * @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.
+ */
+gnutls_x509_crl_t
+xmlSecGnuTLSKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(xmlSecPtrListGetItem(&(ctx->crlsList), pos));
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetCrlsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of crls in @data.
+ *
+ * Returns: te number of crls in @data.
+ */
+xmlSecSize
+xmlSecGnuTLSKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), 0);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(xmlSecPtrListGetSize(&(ctx->crlsList)));
+}
+
+
+static int
+xmlSecGnuTLSKeyDataX509Initialize(xmlSecKeyDataPtr data) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGnuTLSX509DataCtx));
+
+ ret = xmlSecPtrListInitialize(&(ctx->certsList), xmlSecGnuTLSX509CrtListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "certsList");
+ return(-1);
+ }
+
+ ret = xmlSecPtrListInitialize(&(ctx->crlsList), xmlSecGnuTLSX509CrlListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "crlsList");
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGnuTLSKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecGnuTLSX509DataCtxPtr ctxSrc;
+ xmlSecGnuTLSX509DataCtxPtr ctxDst;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGnuTLSKeyDataX509Id), -1);
+
+ ctxSrc = xmlSecGnuTLSX509DataGetCtx(src);
+ xmlSecAssert2(ctxSrc != NULL, 0);
+ ctxDst = xmlSecGnuTLSX509DataGetCtx(dst);
+ xmlSecAssert2(ctxDst != NULL, 0);
+
+ /* copy key cert if exist */
+ if(ctxDst->keyCert != NULL) {
+ gnutls_x509_crt_deinit(ctxDst->keyCert);
+ ctxDst->keyCert = NULL;
+ }
+ if(ctxSrc->keyCert != NULL) {
+ ctxDst->keyCert = xmlSecGnuTLSX509CertDup(ctxSrc->keyCert);
+ if(ctxDst->keyCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecGnuTLSX509CertDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* copy certsList if exists */
+ xmlSecPtrListEmpty(&(ctxDst->certsList));
+ ret = xmlSecPtrListCopy(&(ctxDst->certsList), &(ctxSrc->certsList));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "certsList");
+ return(-1);
+ }
+
+ /* copy crlsList if exists */
+ xmlSecPtrListEmpty(&(ctxDst->crlsList));
+ ret = xmlSecPtrListCopy(&(ctxDst->crlsList), &(ctxSrc->crlsList));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "crlsList");
+ return(-1);
+ }
+ /* done */
+ return(0);
+}
+
+static void
+xmlSecGnuTLSKeyDataX509Finalize(xmlSecKeyDataPtr data) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id));
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecPtrListFinalize(&(ctx->crlsList));
+ xmlSecPtrListFinalize(&(ctx->certsList));
+ if(ctx->keyCert != NULL) {
+ gnutls_x509_crt_deinit(ctx->keyCert);
+ }
+ memset(ctx, 0, sizeof(xmlSecGnuTLSX509DataCtx));
+}
+
+static int
+xmlSecGnuTLSKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGnuTLSKeyDataX509Id, -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 = xmlSecGnuTLSX509DataNodeRead(data, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSX509DataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
+ ret = xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecGnuTLSKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ gnutls_x509_crt_t cert;
+ gnutls_x509_crl_t crl;
+ xmlSecSize size, pos;
+ int content;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGnuTLSKeyDataX509Id, -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 = xmlSecGnuTLSKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecGnuTLSKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) {
+ ret = xmlSecGnuTLSX509CertificateNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSX509CertificateNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) {
+ ret = xmlSecGnuTLSX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSX509SubjectNameNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) {
+ ret = xmlSecGnuTLSX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSX509IssuerSerialNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SKI_NODE) != 0) {
+ ret = xmlSecGnuTLSX509SKINodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSX509SKINodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ /* write crls if needed */
+ if((content & XMLSEC_X509DATA_CRL_NODE) != 0) {
+ size = xmlSecGnuTLSKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ crl = xmlSecGnuTLSKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSX509CRLNodeWrite(crl, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSX509CRLNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ /* done */
+ return(0);
+}
+
+
+static xmlSecKeyDataType
+xmlSecGnuTLSKeyDataX509GetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), xmlSecKeyDataTypeUnknown);
+
+ /* TODO: return verified/not verified status */
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static const xmlChar*
+xmlSecGnuTLSKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+ /* TODO */
+ return(NULL);
+}
+
+static void
+xmlSecGnuTLSKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== X509 Data:\n");
+
+ /* key cert */
+ {
+ gnutls_x509_crt_t cert;
+
+ cert = xmlSecGnuTLSKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "==== Key Certificate:\n");
+ xmlSecGnuTLSX509CertDebugDump(cert, output);
+ }
+ }
+
+ /* other certs */
+ size = xmlSecGnuTLSKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ gnutls_x509_crt_t cert;
+
+ cert = xmlSecGnuTLSKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "==== Certificate:\n");
+ xmlSecGnuTLSX509CertDebugDump(cert, output);
+ }
+
+ /* crls */
+ size = xmlSecGnuTLSKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ gnutls_x509_crl_t crl;
+
+ crl = xmlSecGnuTLSKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "==== Crl:\n");
+ xmlSecGnuTLSX509CrlDebugDump(crl, output);
+ }
+}
+
+static void
+xmlSecGnuTLSKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<X509Data>\n");
+
+ /* key cert */
+ {
+ gnutls_x509_crt_t cert;
+
+ cert = xmlSecGnuTLSKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "<KeyCertificate>\n");
+ xmlSecGnuTLSX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</KeyCertificate>\n");
+ }
+ }
+
+ /* other certs */
+ size = xmlSecGnuTLSKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ gnutls_x509_crt_t cert;
+
+ cert = xmlSecGnuTLSKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "<Certificate>\n");
+ xmlSecGnuTLSX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</Certificate>\n");
+ }
+
+ /* other crls */
+ size = xmlSecGnuTLSKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ gnutls_x509_crl_t crl;
+
+ crl = xmlSecGnuTLSKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "<CRL>\n");
+ xmlSecGnuTLSX509CrlDebugXmlDump(crl, output);
+ fprintf(output, "</CRL>\n");
+ }
+
+ /* we don't print out crls */
+ fprintf(output, "</X509Data>\n");
+}
+
+static int
+xmlSecGnuTLSX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -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 = xmlSecGnuTLSX509CertificateNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+ ret = xmlSecGnuTLSX509SubjectNameNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+ ret = xmlSecGnuTLSX509IssuerSerialNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+ ret = xmlSecGnuTLSX509SKINodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+ ret = xmlSecGnuTLSX509CRLNodeRead(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
+xmlSecGnuTLSX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ gnutls_x509_crt_t cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -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 = xmlSecGnuTLSX509CertBase64DerRead(content);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CertBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509CertificateNodeWrite(gnutls_x509_crt_t 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 = xmlSecGnuTLSX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertBase64DerWrite",
+ 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);
+}
+
+
+
+#define XMLSEC_GNUTLS_IS_SPACE(ch) \
+ (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n'))
+
+static void
+xmlSecGnuTLSX509Trim(xmlChar * str) {
+ xmlChar * p, * q;
+
+ xmlSecAssert(str != NULL);
+
+ /* skip spaces from the beggining */
+ p = str;
+ while(XMLSEC_GNUTLS_IS_SPACE(*p) && ((*p) != '\0')) ++p;
+ if(p != str) {
+ for(q = str; ; ++q, ++p) {
+ (*q) = (*p);
+ if((*p) == '\0') {
+ break;
+ }
+ }
+ }
+
+ /* skip spaces from the end */
+ for(p = str; (*p) != '\0'; ++p);
+ while((p > str) && (XMLSEC_GNUTLS_IS_SPACE(*(p - 1)))) *(--p) = '\0';
+}
+
+static int
+xmlSecGnuTLSX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* subject;
+ gnutls_x509_crt_t cert;
+ gnutls_x509_crt_t cert2;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+ 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);
+ }
+
+ xmlSecGnuTLSX509Trim(subject);
+ cert = xmlSecGnuTLSX509StoreFindCert(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 = xmlSecGnuTLSX509CertDup(cert);
+ if(cert2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CertDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ xmlFree(subject);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert2);
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509SubjectNameNodeWrite(gnutls_x509_crt_t cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* add node */
+ cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SubjectName));
+ return(-1);
+ }
+
+ /* get subject */
+ buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSubjectDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set value */
+ xmlSecNodeEncodeAndSetContent(cur, buf);
+
+ /* done */
+ xmlFree(buf);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlNodePtr cur;
+ xmlChar *issuerName;
+ xmlChar *issuerSerial;
+ gnutls_x509_crt_t cert;
+ gnutls_x509_crt_t cert2;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+ 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);
+ }
+
+ xmlSecGnuTLSX509Trim(issuerName);
+ xmlSecGnuTLSX509Trim(issuerSerial);
+ cert = xmlSecGnuTLSX509StoreFindCert(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 = xmlSecGnuTLSX509CertDup(cert);
+ if(cert2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CertDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert2);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509IssuerSerialNodeWrite(gnutls_x509_crt_t 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 = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNameNode, buf);
+ xmlFree(buf);
+
+ buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerSerial",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNumberNode, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+
+static int
+xmlSecGnuTLSX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* ski;
+ gnutls_x509_crt_t cert;
+ gnutls_x509_crt_t cert2;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+ 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);
+ }
+
+ xmlSecGnuTLSX509Trim(ski);
+ cert = xmlSecGnuTLSX509StoreFindCert(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 = xmlSecGnuTLSX509CertDup(cert);
+ if(cert2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CertDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert2);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ xmlFree(ski);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509SKINodeWrite(gnutls_x509_crt_t cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar *buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* add node */
+ cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "new_node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+ return(-1);
+ }
+
+ /* write value */
+ buf = xmlSecGnuTLSX509CertGetSKI(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSKI",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ xmlSecNodeEncodeAndSetContent(cur, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ gnutls_x509_crl_t crl;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -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 = xmlSecGnuTLSX509CrlBase64DerRead(content);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CrlBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCrl(data, crl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crl_deinit(crl);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509CRLNodeWrite(gnutls_x509_crl_t 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 = xmlSecGnuTLSX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CrlBase64DerWrite",
+ 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
+xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecGnuTLSX509DataCtxPtr ctx;
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ ctx = xmlSecGnuTLSX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+ 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) && (xmlSecPtrListGetSize(&(ctx->certsList)) > 0) && (xmlSecKeyGetValue(key) == NULL)) {
+ gnutls_x509_crt_t cert;
+
+ cert = xmlSecGnuTLSX509StoreVerify(x509Store, &(ctx->certsList), &(ctx->crlsList), keyInfoCtx);
+ if(cert != NULL) {
+ xmlSecKeyDataPtr keyValue;
+
+ ctx->keyCert = xmlSecGnuTLSX509CertDup(cert);
+ if(ctx->keyCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CertDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ keyValue = xmlSecGnuTLSX509CertGetKey(ctx->keyCert);
+ if(keyValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecGnuTLSX509CertGetKey",
+ 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);
+ }
+
+ /* get expiration time */
+ key->notValidBefore = gnutls_x509_crt_get_activation_time(ctx->keyCert);
+ if(key->notValidBefore == (time_t)-1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "gnutls_x509_crt_get_activation_time",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ key->notValidAfter = gnutls_x509_crt_get_expiration_time(ctx->keyCert);
+ if(key->notValidAfter == (time_t)-1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "gnutls_x509_crt_get_expiration_time",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ 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);
+}
+
+/**
+ * xmlSecGnuTLSX509CertGetKey:
+ * @cert: the certificate.
+ *
+ * Extracts public key from the @cert.
+ *
+ * Returns: public key value or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecGnuTLSX509CertGetKey(gnutls_x509_crt_t cert) {
+ xmlSecKeyDataPtr data;
+ int alg;
+ unsigned int bits;
+ int err;
+ int ret;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ alg = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
+ if(alg < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_pk_algorithm",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(alg));
+ return(NULL);
+ }
+
+ switch(alg) {
+#ifndef XMLSEC_NO_RSA
+ case GNUTLS_PK_RSA:
+ {
+ gnutls_datum_t m, e;
+
+ data = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataRsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSKeyDataRsaId");
+ return(NULL);
+ }
+
+ err = gnutls_x509_crt_get_pk_rsa_raw(cert, &m, &e);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_pk_rsa_raw",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ ret = xmlSecGnuTLSKeyDataRsaAdoptPublicKey(data, &m, &e);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataRsaAdoptPublicKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_free(m.data);
+ gnutls_free(e.data);
+ return(NULL);
+ }
+ /* m and e are owned by data now */
+ }
+ break;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+ case GNUTLS_PK_DSA:
+ {
+ gnutls_datum_t p, q, g, y;
+
+ data = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataDsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSKeyDataDsaId");
+ return(NULL);
+ }
+
+ err = gnutls_x509_crt_get_pk_dsa_raw(cert, &p, &q, &g, &y);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_pk_dsa_raw",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ ret = xmlSecGnuTLSKeyDataDsaAdoptPublicKey(data, &p, &q, &g, &y);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataDsaAdoptPublicKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_free(p.data);
+ gnutls_free(q.data);
+ gnutls_free(g.data);
+ gnutls_free(y.data);
+ return(NULL);
+ }
+ /* p, q, g and y are owned by data now */
+ }
+ break;
+#endif /* XMLSEC_NO_DSA */
+
+ default:
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_pk_algorithm",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "Unsupported algorithm %d", (int)alg);
+ return(NULL);
+ }
+ }
+
+ /* data */
+ return(data);
+}
+
+
+/**************************************************************************
+ *
+ * Raw X509 Certificate processing
+ *
+ *
+ *************************************************************************/
+static int xmlSecGnuTLSKeyDataRawX509CertBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecGnuTLSKeyDataRawX509CertKlass = {
+ 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; */
+ xmlSecGnuTLSKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 certificates key data klass.
+ *
+ * Returns: raw X509 certificates key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataRawX509CertGetKlass(void) {
+ return(&xmlSecGnuTLSKeyDataRawX509CertKlass);
+}
+
+static int
+xmlSecGnuTLSKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ gnutls_x509_crt_t cert;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecGnuTLSKeyDataRawX509CertId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ cert = xmlSecGnuTLSX509CertRead(buf, bufSize, xmlSecKeyDataFormatCertDer);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ data = xmlSecKeyEnsureData(key, xmlSecGnuTLSKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gnutls_x509_crt_deinit(cert);
+ return(-1);
+ }
+
+ ret = xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecGnuTLSKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/gnutls/x509utils.c b/src/gnutls/x509utils.c
new file mode 100644
index 00000000..0dc70003
--- /dev/null
+++ b/src/gnutls/x509utils.c
@@ -0,0 +1,1687 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 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 <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/pkcs12.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/private.h>
+
+#include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+
+/**************************************************************************
+ *
+ * X509 crt list
+ *
+ *****************************************************************************/
+static xmlSecPtr xmlSecGnuTLSX509CrtListDuplicateItem (xmlSecPtr ptr);
+static void xmlSecGnuTLSX509CrtListDestroyItem (xmlSecPtr ptr);
+static void xmlSecGnuTLSX509CrtListDebugDumpItem (xmlSecPtr ptr,
+ FILE* output);
+static void xmlSecGnuTLSX509CrtListDebugXmlDumpItem (xmlSecPtr ptr,
+ FILE* output);
+
+static xmlSecPtrListKlass xmlSecGnuTLSX509CrtListKlass = {
+ BAD_CAST "gnutls-x509-crt-list",
+ xmlSecGnuTLSX509CrtListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ xmlSecGnuTLSX509CrtListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ xmlSecGnuTLSX509CrtListDebugDumpItem, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ xmlSecGnuTLSX509CrtListDebugXmlDumpItem, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+xmlSecPtrListId
+xmlSecGnuTLSX509CrtListGetKlass(void) {
+ return(&xmlSecGnuTLSX509CrtListKlass);
+}
+
+static xmlSecPtr
+xmlSecGnuTLSX509CrtListDuplicateItem(xmlSecPtr ptr) {
+ xmlSecAssert2(ptr != NULL, NULL);
+
+ return xmlSecGnuTLSX509CertDup((gnutls_x509_crt_t)ptr);
+}
+
+static void
+xmlSecGnuTLSX509CrtListDestroyItem(xmlSecPtr ptr) {
+ xmlSecAssert(ptr != NULL);
+
+ gnutls_x509_crt_deinit((gnutls_x509_crt_t)ptr);
+}
+
+static void
+xmlSecGnuTLSX509CrtListDebugDumpItem(xmlSecPtr ptr, FILE* output) {
+ xmlSecAssert(ptr != NULL);
+ xmlSecAssert(output != NULL);
+
+ xmlSecGnuTLSX509CertDebugDump((gnutls_x509_crt_t)ptr, output);
+}
+
+
+static void
+xmlSecGnuTLSX509CrtListDebugXmlDumpItem(xmlSecPtr ptr, FILE* output) {
+ xmlSecAssert(ptr != NULL);
+ xmlSecAssert(output != NULL);
+
+ xmlSecGnuTLSX509CertDebugXmlDump((gnutls_x509_crt_t)ptr, output);
+}
+
+/**************************************************************************
+ *
+ * X509 crl list
+ *
+ *****************************************************************************/
+static xmlSecPtr xmlSecGnuTLSX509CrlListDuplicateItem (xmlSecPtr ptr);
+static void xmlSecGnuTLSX509CrlListDestroyItem (xmlSecPtr ptr);
+static void xmlSecGnuTLSX509CrlListDebugDumpItem (xmlSecPtr ptr,
+ FILE* output);
+static void xmlSecGnuTLSX509CrlListDebugXmlDumpItem (xmlSecPtr ptr,
+ FILE* output);
+
+static xmlSecPtrListKlass xmlSecGnuTLSX509CrlListKlass = {
+ BAD_CAST "gnutls-x509-crl-list",
+ xmlSecGnuTLSX509CrlListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ xmlSecGnuTLSX509CrlListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ xmlSecGnuTLSX509CrlListDebugDumpItem, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ xmlSecGnuTLSX509CrlListDebugXmlDumpItem, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+xmlSecPtrListId
+xmlSecGnuTLSX509CrlListGetKlass(void) {
+ return(&xmlSecGnuTLSX509CrlListKlass);
+}
+
+static xmlSecPtr
+xmlSecGnuTLSX509CrlListDuplicateItem(xmlSecPtr ptr) {
+ xmlSecAssert2(ptr != NULL, NULL);
+
+ return xmlSecGnuTLSX509CrlDup((gnutls_x509_crl_t)ptr);
+}
+
+static void
+xmlSecGnuTLSX509CrlListDestroyItem(xmlSecPtr ptr) {
+ xmlSecAssert(ptr != NULL);
+
+ gnutls_x509_crl_deinit((gnutls_x509_crl_t)ptr);
+}
+
+static void
+xmlSecGnuTLSX509CrlListDebugDumpItem(xmlSecPtr ptr, FILE* output) {
+ xmlSecAssert(ptr != NULL);
+ xmlSecAssert(output != NULL);
+
+ xmlSecGnuTLSX509CrlDebugDump((gnutls_x509_crl_t)ptr, output);
+}
+
+
+static void
+xmlSecGnuTLSX509CrlListDebugXmlDumpItem(xmlSecPtr ptr, FILE* output) {
+ xmlSecAssert(ptr != NULL);
+ xmlSecAssert(output != NULL);
+
+ xmlSecGnuTLSX509CrlDebugXmlDump((gnutls_x509_crl_t)ptr, output);
+}
+
+/*************************************************************************
+ *
+ * x509 certs utils/helpers
+ *
+ ************************************************************************/
+
+/* HACK: gnutls doesn't have cert duplicate function, so we simply
+ write cert out and then read it back */
+gnutls_x509_crt_t
+xmlSecGnuTLSX509CertDup(gnutls_x509_crt_t src) {
+ xmlChar * buf = NULL;
+ gnutls_x509_crt_t res = NULL;
+
+ xmlSecAssert2(src != NULL, NULL);
+
+ buf = xmlSecGnuTLSX509CertBase64DerWrite(src, 0);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertBase64DerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ res = xmlSecGnuTLSX509CertBase64DerRead(buf);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(buf);
+ return (NULL);
+ }
+
+ /* done */
+ xmlFree(buf);
+ return (res);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetSubjectDN(gnutls_x509_crt_t cert) {
+ char* buf = NULL;
+ size_t bufSize = 0;
+ int err;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get subject size */
+ err = gnutls_x509_crt_get_dn(cert, NULL, &bufSize);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_dn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (char *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* finally write it out */
+ err = gnutls_x509_crt_get_dn(cert, buf, &bufSize);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_dn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ return(BAD_CAST buf);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetIssuerDN(gnutls_x509_crt_t cert) {
+ char* buf = NULL;
+ size_t bufSize = 0;
+ int err;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get issuer size */
+ err = gnutls_x509_crt_get_issuer_dn(cert, NULL, &bufSize);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_issuer_dn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (char *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* finally write it out */
+ err = gnutls_x509_crt_get_issuer_dn(cert, buf, &bufSize);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_issuer_dn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ return(BAD_CAST buf);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetIssuerSerial(gnutls_x509_crt_t cert) {
+ xmlChar * res = NULL;
+ unsigned char* buf = NULL;
+ size_t bufSize = 0;
+ int err;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get issuer serial size */
+ err = gnutls_x509_crt_get_serial(cert, NULL, &bufSize);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_serial",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (unsigned char *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* write it out */
+ err = gnutls_x509_crt_get_serial(cert, buf, &bufSize);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_serial",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* convert to string */
+ res = xmlSecGnuTLSASN1IntegerWrite(buf, bufSize);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSASN1IntegerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(buf);
+ return(res);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetSKI(gnutls_x509_crt_t cert) {
+ xmlChar * res = NULL;
+ xmlSecByte* buf = NULL;
+ size_t bufSize = 0;
+ unsigned int critical = 0;
+ int err;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get ski size */
+ err = gnutls_x509_crt_get_subject_key_id(cert, NULL, &bufSize, &critical);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_subject_key_id",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* write it out */
+ err = gnutls_x509_crt_get_subject_key_id(cert, buf, &bufSize, &critical);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_subject_key_id",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* convert to string */
+ res = xmlSecBase64Encode(buf, bufSize, 0);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(buf);
+ return(res);
+}
+
+
+gnutls_x509_crt_t
+xmlSecGnuTLSX509CertBase64DerRead(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(xmlSecGnuTLSX509CertRead((const xmlSecByte*)buf, ret, xmlSecKeyDataFormatCertDer));
+}
+
+gnutls_x509_crt_t
+xmlSecGnuTLSX509CertRead(const xmlSecByte* buf, xmlSecSize size, xmlSecKeyDataFormat format) {
+ gnutls_x509_crt_t cert = NULL;
+ gnutls_x509_crt_fmt_t fmt;
+ gnutls_datum_t data;
+ int err;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ /* figure out format */
+ switch(format) {
+ case xmlSecKeyDataFormatPem:
+ case xmlSecKeyDataFormatCertPem:
+ fmt = GNUTLS_X509_FMT_PEM;
+ break;
+ case xmlSecKeyDataFormatDer:
+ case xmlSecKeyDataFormatCertDer:
+ fmt = GNUTLS_X509_FMT_DER;
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ /* read cert */
+ err = gnutls_x509_crt_init(&cert);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ data.data = (unsigned char*)buf;
+ data.size = size;
+ err = gnutls_x509_crt_import(cert, &data, fmt);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_import",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ gnutls_x509_crt_deinit(cert);
+ return(NULL);
+ }
+
+ return(cert);
+}
+
+xmlChar*
+xmlSecGnuTLSX509CertBase64DerWrite(gnutls_x509_crt_t cert, int base64LineWrap) {
+ xmlChar * res = NULL;
+ xmlSecByte* buf = NULL;
+ size_t bufSize = 0;
+ int err;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get size */
+ err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &bufSize);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_export(GNUTLS_X509_FMT_DER)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* write it out */
+ err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, buf, &bufSize);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_export(GNUTLS_X509_FMT_DER)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* convert to string */
+ res = xmlSecBase64Encode(buf, bufSize, base64LineWrap);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(buf);
+ return(res);
+}
+
+void
+xmlSecGnuTLSX509CertDebugDump(gnutls_x509_crt_t cert, FILE* output) {
+ xmlChar * buf;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+ if(buf != NULL) {
+ fprintf(output, "==== Subject Name: %s\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "==== Subject Name: unknown\n");
+ }
+
+ buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+ if(buf != NULL) {
+ fprintf(output, "==== Issuer Name: %s\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "==== Issuer Name: unknown\n");
+ }
+
+ buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+ if(buf != NULL) {
+ fprintf(output, "==== Issuer Serial: %s\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "==== Issuer Serial: unknown\n");
+ }
+}
+
+void
+xmlSecGnuTLSX509CertDebugXmlDump(gnutls_x509_crt_t cert, FILE* output) {
+ xmlChar * buf;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+ if(buf != NULL) {
+ fprintf(output, "<SubjectName>%s</SubjectName>\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "<SubjectName>unknown</SubjectName>\n");
+ }
+
+ buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+ if(buf != NULL) {
+ fprintf(output, "<IssuerName>%s</IssuerName>\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "<IssuerName>unknown</IssuerName>\n");
+ }
+
+ buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+ if(buf != NULL) {
+ fprintf(output, "<SerialNumber>%s</SerialNumber>\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "<SerialNumber>unknown</SerialNumber>\n");
+ }
+}
+
+/*************************************************************************
+ *
+ * x509 crls utils/helpers
+ *
+ ************************************************************************/
+
+/* HACK: gnutls doesn't have crl duplicate function, so we simply
+ write crl out and then read it back */
+gnutls_x509_crl_t
+xmlSecGnuTLSX509CrlDup(gnutls_x509_crl_t src) {
+ xmlChar * buf = NULL;
+ gnutls_x509_crl_t res = NULL;
+
+ xmlSecAssert2(src != NULL, NULL);
+
+ buf = xmlSecGnuTLSX509CrlBase64DerWrite(src, 0);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CrlBase64DerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ res = xmlSecGnuTLSX509CrlBase64DerRead(buf);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CrlBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(buf);
+ return (NULL);
+ }
+
+ /* done */
+ xmlFree(buf);
+ return (res);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CrlGetIssuerDN(gnutls_x509_crl_t crl) {
+ char* buf = NULL;
+ size_t bufSize = 0;
+ int err;
+
+ xmlSecAssert2(crl != NULL, NULL);
+
+ /* get issuer size */
+ err = gnutls_x509_crl_get_issuer_dn(crl, NULL, &bufSize);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crl_get_issuer_dn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (char *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* finally write it out */
+ err = gnutls_x509_crl_get_issuer_dn(crl, buf, &bufSize);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crl_get_issuer_dn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ return(BAD_CAST buf);
+}
+
+gnutls_x509_crl_t
+xmlSecGnuTLSX509CrlBase64DerRead(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(xmlSecGnuTLSX509CrlRead((const xmlSecByte*)buf, ret, xmlSecKeyDataFormatCertDer));
+}
+
+gnutls_x509_crl_t
+xmlSecGnuTLSX509CrlRead(const xmlSecByte* buf, xmlSecSize size, xmlSecKeyDataFormat format) {
+ gnutls_x509_crl_t crl = NULL;
+ gnutls_x509_crt_fmt_t fmt;
+ gnutls_datum_t data;
+ int err;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ /* figure out format */
+ switch(format) {
+ case xmlSecKeyDataFormatPem:
+ case xmlSecKeyDataFormatCertPem:
+ fmt = GNUTLS_X509_FMT_PEM;
+ break;
+ case xmlSecKeyDataFormatDer:
+ case xmlSecKeyDataFormatCertDer:
+ fmt = GNUTLS_X509_FMT_DER;
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ /* read crl */
+ err = gnutls_x509_crl_init(&crl);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crl_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ data.data = (unsigned char*)buf;
+ data.size = size;
+ err = gnutls_x509_crl_import(crl, &data, fmt);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crl_import",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ gnutls_x509_crl_deinit(crl);
+ return(NULL);
+ }
+
+ return(crl);
+}
+
+xmlChar*
+xmlSecGnuTLSX509CrlBase64DerWrite(gnutls_x509_crl_t crl, int base64LineWrap) {
+ xmlChar * res = NULL;
+ xmlSecByte* buf = NULL;
+ size_t bufSize = 0;
+ int err;
+
+ xmlSecAssert2(crl != NULL, NULL);
+
+ /* get size */
+ err = gnutls_x509_crl_export(crl, GNUTLS_X509_FMT_DER, NULL, &bufSize);
+ if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crl_export(GNUTLS_X509_FMT_DER)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(NULL);
+ }
+
+ /* allocate buffer */
+ buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)bufSize);
+ return(NULL);
+ }
+
+ /* write it out */
+ err = gnutls_x509_crl_export(crl, GNUTLS_X509_FMT_DER, buf, &bufSize);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crl_export(GNUTLS_X509_FMT_DER)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* convert to string */
+ res = xmlSecBase64Encode(buf, bufSize, base64LineWrap);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(buf);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(buf);
+ return(res);
+}
+
+void
+xmlSecGnuTLSX509CrlDebugDump(gnutls_x509_crl_t crl, FILE* output) {
+ xmlChar * buf;
+
+ xmlSecAssert(crl != NULL);
+ xmlSecAssert(output != NULL);
+
+ buf = xmlSecGnuTLSX509CrlGetIssuerDN(crl);
+ if(buf != NULL) {
+ fprintf(output, "==== Issuer Name: %s\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "==== Issuer Name: unknown\n");
+ }
+}
+
+void
+xmlSecGnuTLSX509CrlDebugXmlDump(gnutls_x509_crl_t crl, FILE* output) {
+ xmlChar * buf;
+
+ xmlSecAssert(crl != NULL);
+ xmlSecAssert(output != NULL);
+
+ buf = xmlSecGnuTLSX509CrlGetIssuerDN(crl);
+ if(buf != NULL) {
+ fprintf(output, "<IssuerName>%s</IssuerName>\n", buf);
+ xmlFree(buf);
+ } else {
+ fprintf(output, "<IssuerName>unknown</IssuerName>\n");
+ }
+}
+
+/*************************************************************************
+ *
+ * Misc. utils/helpers
+ *
+ ************************************************************************/
+xmlChar*
+xmlSecGnuTLSASN1IntegerWrite(const unsigned char * data, size_t len) {
+ xmlChar *res = NULL;
+ int resLen = 64; /* not more than 64 chars */
+ unsigned long long int val = 0;
+ size_t ii = 0;
+ int shift = 0;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(len <= 9, NULL);
+
+ /* HACK : to be fixed after GnuTLS provides a way to read opaque ASN1 integer */
+ for(ii = len; ii > 0; --ii, shift += 8) {
+ val |= ((unsigned long long)data[ii - 1]) << shift;
+ }
+
+ res = (xmlChar*)xmlMalloc(resLen + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)resLen);
+ return (NULL);
+ }
+
+ xmlSecStrPrintf(res, resLen, BAD_CAST "%llu", val);
+ return(res);
+}
+
+/*************************************************************************
+ *
+ * pkcs12 utils/helpers
+ *
+ ************************************************************************/
+int
+xmlSecGnuTLSPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ const char *pwd,
+ gnutls_x509_privkey_t * priv_key,
+ gnutls_x509_crt_t * key_cert,
+ xmlSecPtrListPtr certsList)
+{
+ gnutls_pkcs12_t pkcs12 = NULL;
+ gnutls_pkcs12_bag_t bag = NULL;
+ gnutls_x509_crt_t cert = NULL;
+ gnutls_datum_t datum;
+ xmlSecSize certsSize;
+ int res = -1;
+ int idx;
+ int err;
+ int ret;
+
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+ xmlSecAssert2(priv_key != NULL, -1);
+ xmlSecAssert2((*priv_key) == NULL, -1);
+ xmlSecAssert2(key_cert!= NULL, -1);
+ xmlSecAssert2((*key_cert) == NULL, -1);
+ xmlSecAssert2(certsList != NULL, -1);
+
+ /* read pkcs12 in internal structure */
+ err = gnutls_pkcs12_init(&pkcs12);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ datum.data = (unsigned char *)data;
+ datum.size = dataSize;
+ err = gnutls_pkcs12_import(pkcs12, &datum, GNUTLS_X509_FMT_DER, 0);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_import",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* verify */
+ err = gnutls_pkcs12_verify_mac(pkcs12, pwd);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_verify_mac",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* scan the pkcs structure and find the first private key */
+ for(idx = 0; ; ++idx) {
+ int bag_type;
+ int elements_in_bag;
+ int ii;
+
+ err = gnutls_pkcs12_bag_init(&bag);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_bag_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gnutls_pkcs12_get_bag(pkcs12, idx, bag);
+ if(err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ /* scanned the whole pkcs12, stop */
+ break;
+ } else if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_get_bag",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* check if we need to decrypt the bag */
+ bag_type = gnutls_pkcs12_bag_get_type(bag, 0);
+ if(bag_type < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_bag_get_type",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(bag_type));
+ goto done;
+ }
+ if(bag_type == GNUTLS_BAG_ENCRYPTED) {
+ err = gnutls_pkcs12_bag_decrypt(bag, pwd);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_bag_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+ }
+
+ /* scan elements in bag */
+ elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
+ if(elements_in_bag < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_bag_get_count",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(bag_type));
+ goto done;
+ }
+ for(ii = 0; ii < elements_in_bag; ++ii) {
+ bag_type = gnutls_pkcs12_bag_get_type(bag, ii);
+ if(bag_type < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_bag_get_type",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(bag_type));
+ goto done;
+ }
+
+ err = gnutls_pkcs12_bag_get_data(bag, ii, &datum);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_pkcs12_bag_get_data",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ switch(bag_type) {
+ case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
+ case GNUTLS_BAG_PKCS8_KEY:
+ /* we want only the first private key */
+ if((*priv_key) == NULL) {
+ err = gnutls_x509_privkey_init(priv_key);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gnutls_x509_privkey_import_pkcs8((*priv_key),
+ &datum, GNUTLS_X509_FMT_DER,
+ pwd,
+ (bag_type == GNUTLS_BAG_PKCS8_KEY) ? GNUTLS_PKCS_PLAIN : 0);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_import_pkcs8",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+ }
+ break;
+ case GNUTLS_BAG_CERTIFICATE:
+ err = gnutls_x509_crt_init(&cert);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_import",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ ret = xmlSecPtrListAdd(certsList, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListAdd(certsList)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ cert = NULL; /* owned by certsList now */
+ break;
+ default:
+ /* ignore unknown bag element */
+ break;
+ }
+ }
+
+ /* done with bag */
+ gnutls_pkcs12_bag_deinit(bag);
+ bag = NULL;
+ }
+
+ /* check we have private key */
+ if((*priv_key) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Private key was not found in pkcs12 object");
+ goto done;
+ }
+
+ /* we will search for key cert using the key id */
+ certsSize = xmlSecPtrListGetSize(certsList);
+ if(certsSize > 0) {
+ size_t cert_id_size = 0;
+ size_t key_id_size = 0;
+ xmlSecByte cert_id[100];
+ xmlSecByte key_id[100];
+ xmlSecSize ii;
+
+ key_id_size = sizeof(key_id);
+ err = gnutls_x509_privkey_get_key_id((*priv_key), 0, key_id, &key_id_size);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_get_key_id",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+ for(ii = 0; ii < certsSize; ++ii) {
+ gnutls_x509_crt_t tmp;
+
+ tmp = xmlSecPtrListGetItem(certsList, ii);
+ if(tmp == NULL) {
+ continue;
+ }
+
+ cert_id_size = sizeof(cert_id);
+ err = gnutls_x509_crt_get_key_id(tmp, 0, cert_id, &cert_id_size);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_key_id",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* if key ids match, then this is THE key cert!!! */
+ if((key_id_size == cert_id_size) && (memcmp(key_id, cert_id, key_id_size) == 0)) {
+ (*key_cert) = xmlSecGnuTLSX509CertDup(tmp);
+ if((*key_cert) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ break;
+ }
+ }
+
+ /* check we have key cert */
+ if((*key_cert) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Certificate for the private key was not found in pkcs12 object");
+ goto done;
+ }
+ }
+
+
+ /* success!!! */
+ res = 0;
+
+done:
+ if(cert != NULL) {
+ gnutls_x509_crt_deinit(cert);
+ }
+ if(bag != NULL) {
+ gnutls_pkcs12_bag_deinit(bag);
+ }
+ if(pkcs12 != NULL) {
+ gnutls_pkcs12_deinit(pkcs12);
+ }
+ return(res);
+}
+
+xmlSecKeyDataPtr
+xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(gnutls_x509_privkey_t priv_key) {
+ xmlSecKeyDataPtr res = NULL;
+ int key_alg;
+ int ret;
+
+ xmlSecAssert2(priv_key != NULL, NULL);
+
+ /* create key value data */
+ key_alg = gnutls_x509_privkey_get_pk_algorithm(priv_key);
+ if(key_alg < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_get_pk_algorithm",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(key_alg));
+ return (NULL);
+ }
+ switch(key_alg) {
+#ifndef XMLSEC_NO_RSA
+ case GNUTLS_PK_RSA:
+ res = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataRsaId);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSKeyDataRsaId");
+ return(NULL);
+ }
+
+ ret = xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(res, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataRsaAdoptPrivateKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSKeyDataRsaId");
+ xmlSecKeyDataDestroy(res);
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+ case GNUTLS_PK_DSA:
+ res = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataDsaId);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSKeyDataDsaId");
+ return(NULL);
+ }
+
+ ret = xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(res, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSKeyDataDsaAdoptPrivateKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecGnuTLSKeyDataDsaId");
+ xmlSecKeyDataDestroy(res);
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_DSA */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_get_pk_algorithm",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "Unsupported algorithm %d", (int)key_alg);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/*************************************************************************
+ *
+ * LDAP DN parser
+ *
+ ************************************************************************/
+void
+xmlSecGnuTLSDnAttrsInitialize(xmlSecGnuTLSDnAttr * attrs, xmlSecSize attrsSize) {
+ xmlSecAssert(attrs != NULL);
+ xmlSecAssert(attrsSize > 0);
+
+ memset(attrs, 0, attrsSize * sizeof(xmlSecGnuTLSDnAttr));
+}
+
+void
+xmlSecGnuTLSDnAttrsDeinitialize(xmlSecGnuTLSDnAttr * attrs, xmlSecSize attrsSize) {
+ xmlSecSize ii;
+
+ xmlSecAssert(attrs != NULL);
+ xmlSecAssert(attrsSize > 0);
+
+ for(ii = 0; ii < attrsSize; ++ii) {
+ if(attrs[ii].key != NULL) {
+ xmlFree(attrs[ii].key);
+ }
+ if(attrs[ii].value != NULL) {
+ xmlFree(attrs[ii].value);
+ }
+ }
+ memset(attrs, 0, attrsSize * sizeof(xmlSecGnuTLSDnAttr));
+}
+
+const xmlSecGnuTLSDnAttr *
+xmlSecGnuTLSDnAttrrsFind(const xmlSecGnuTLSDnAttr * attrs,
+ xmlSecSize attrsSize,
+ const xmlChar * key)
+{
+ xmlSecSize ii;
+
+ xmlSecAssert2(attrs != NULL, NULL);
+ xmlSecAssert2(attrsSize > 0, NULL);
+ xmlSecAssert2(key != NULL, NULL);
+
+ for(ii = 0; ii < attrsSize; ++ii) {
+ /* simple case */
+ if(xmlStrcasecmp(key, attrs[ii].key) == 0) {
+ return(&(attrs[ii]));
+ }
+
+ /* special case for emailAddress (as usual) */
+ if((xmlStrcasecmp(key, BAD_CAST "emailAddress") == 0) &&
+ (xmlStrcasecmp(attrs[ii].key, BAD_CAST "email") == 0))
+ {
+ return(&(attrs[ii]));
+ }
+ if((xmlStrcasecmp(key, BAD_CAST "email") == 0) &&
+ (xmlStrcasecmp(attrs[ii].key, BAD_CAST "emailAddress") == 0))
+ {
+ return(&(attrs[ii]));
+ }
+ }
+
+ /* not found :( */
+ return(NULL);
+}
+
+int
+xmlSecGnuTLSDnAttrsEqual(const xmlSecGnuTLSDnAttr * ll, xmlSecSize llSize,
+ const xmlSecGnuTLSDnAttr * rr, xmlSecSize rrSize)
+{
+ xmlSecSize llNum = 0;
+ xmlSecSize rrNum = 0;
+ const xmlSecGnuTLSDnAttr * tmp;
+ xmlSecSize ii;
+
+ xmlSecAssert2(ll != NULL, -1);
+ xmlSecAssert2(llSize > 0, -1);
+ xmlSecAssert2(rr != NULL, -1);
+ xmlSecAssert2(rrSize > 0, -1);
+
+ /* compare number of non-nullattributes */
+ for(ii = 0; ii < llSize; ++ii) {
+ if(ll[ii].key != NULL) {
+ ++llNum;
+ }
+ }
+ for(ii = 0; ii < rrSize; ++ii) {
+ if(rr[ii].key != NULL) {
+ ++rrNum;
+ }
+ }
+ if(llNum != rrNum) {
+ return(0);
+ }
+
+ /* make sure that all ll attrs are equal to rr attrs */
+ for(ii = 0; ii < llSize; ++ii) {
+ if(ll[ii].key == NULL) {
+ continue;
+ }
+
+ tmp = xmlSecGnuTLSDnAttrrsFind(rr, rrSize, ll[ii].key);
+ if(tmp == NULL) {
+ return(0); /* attribute was not found */
+ }
+
+ if(!xmlStrEqual(ll[ii].value, tmp->value)) {
+ return(0); /* different values */
+ }
+ }
+
+ /* good!!! */
+ return(1);
+}
+
+/*
+Distinguished name syntax
+
+The formal syntax for a Distinguished Name (DN) is based on RFC 2253.
+The Backus Naur Form (BNF) syntax is defined as follows:
+
+ <name> ::= <name-component> ( <spaced-separator> )
+ | <name-component> <spaced-separator> <name>
+
+ <spaced-separator> ::= <optional-space>
+ <separator>
+ <optional-space>
+
+ <separator> ::= "," | ";"
+
+ <optional-space> ::= ( <CR> ) *( " " )
+
+ <name-component> ::= <attribute>
+ | <attribute> <optional-space> "+"
+ <optional-space> <name-component>
+
+ <attribute> ::= <string>
+ | <key> <optional-space> "=" <optional-space> <string>
+
+ <key> ::= 1*( <keychar> ) | "OID." <oid> | "oid." <oid>
+ <keychar> ::= letters, numbers, and space
+
+ <oid> ::= <digitstring> | <digitstring> "." <oid>
+ <digitstring> ::= 1*<digit>
+ <digit> ::= digits 0-9
+
+ <string> ::= *( <stringchar> | <pair> )
+ | '"' *( <stringchar> | <special> | <pair> ) '"'
+ | "#" <hex>
+
+
+ <special> ::= "," | "=" | <CR> | "+" | "<" | ">"
+ | "#" | ";"
+
+ <pair> ::= "\" ( <special> | "\" | '"')
+ <stringchar> ::= any character except <special> or "\" or '"'
+
+
+ <hex> ::= 2*<hexchar>
+ <hexchar> ::= 0-9, a-f, A-F
+
+A semicolon (;) character can be used to separate RDNs in a distinguished name,
+although the comma (,) character is the typical notation.
+
+White-space characters (spaces) might be present on either side of the comma or
+semicolon. The white-space characters are ignored, and the semicolon is replaced
+with a comma.
+
+In addition, space (' ' ASCII 32) characters may be present either before or
+after a '+' or '='. These space characters are ignored when parsing.
+*/
+enum xmlSecGnuTLSDnParseState {
+ xmlSecGnuTLSDnParseState_BeforeNameComponent = 0,
+ xmlSecGnuTLSDnParseState_Key,
+ xmlSecGnuTLSDnParseState_BeforeString,
+ xmlSecGnuTLSDnParseState_String,
+ xmlSecGnuTLSDnParseState_QuotedString,
+ xmlSecGnuTLSDnParseState_AfterQuotedString
+};
+
+#define XMLSEC_GNUTLS_IS_SPACE(ch) \
+ (((ch) == ' ') || ((ch) == '\n') || ((ch) == '\r'))
+
+int
+xmlSecGnuTLSDnAttrsParse(const xmlChar * dn,
+ xmlSecGnuTLSDnAttr * attrs, xmlSecSize attrsSize)
+{
+ xmlChar * tmp = NULL;
+ xmlChar * p;
+ xmlChar ch;
+ enum xmlSecGnuTLSDnParseState state;
+ int slash;
+ xmlSecSize pos;
+ int res = -1;
+
+ xmlSecAssert2(dn != NULL, -1);
+ xmlSecAssert2(attrs != NULL, -1);
+ xmlSecAssert2(attrsSize > 0, -1);
+
+ /* allocate buffer, we don't need more than string */
+ tmp = (xmlChar *)xmlMalloc(xmlStrlen(dn) + 1);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(xmlStrlen(dn) + 1));
+ goto done;
+ }
+
+ /* state machine */
+ state = xmlSecGnuTLSDnParseState_BeforeNameComponent;
+ slash = 0;
+ pos = 0;
+ p = tmp;
+ for(ch = (*dn); ; ch = *(++dn)) {
+ switch(state) {
+ case xmlSecGnuTLSDnParseState_BeforeNameComponent:
+ if(!XMLSEC_GNUTLS_IS_SPACE(ch)) {
+ *(p++) = ch; /* we are sure we have enough buffer */
+ state = xmlSecGnuTLSDnParseState_Key;
+ } else {
+ /* just skip space */
+ }
+ break;
+ case xmlSecGnuTLSDnParseState_Key:
+ /* we don't support
+ 1) <attribute><optional-space>"+"<optional-space><name-component>
+ 2) <attribute> ::= <string>
+ */
+ if(ch != '=') {
+ *(p++) = ch; /* we are sure we have enough buffer */
+ } else {
+ *(p) = '\0';
+ /* remove spaces back */
+ while((p > tmp) && (XMLSEC_GNUTLS_IS_SPACE(*(p - 1)))) {
+ *(--p) = '\0';
+ }
+
+ /* insert into the attrs */
+ if(pos >= attrsSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Not enough space: size=%d", (int)attrsSize);
+ goto done;
+ }
+ attrs[pos].key = xmlStrdup(tmp);
+ if(attrs[pos].key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(xmlStrlen(tmp) + 1));
+ goto done;
+ }
+
+ state = xmlSecGnuTLSDnParseState_BeforeString;
+ p = tmp;
+ }
+ break;
+ case xmlSecGnuTLSDnParseState_BeforeString:
+ if(!XMLSEC_GNUTLS_IS_SPACE(ch)) {
+ if(ch != '\"') {
+ state = xmlSecGnuTLSDnParseState_String;
+ slash = 0;
+ --dn; /* small hack, so we can look at the same char
+ again with the correct state */
+ } else {
+ state = xmlSecGnuTLSDnParseState_QuotedString;
+ slash = 0;
+ }
+ } else {
+ /* just skip space */
+ }
+ break;
+ case xmlSecGnuTLSDnParseState_String:
+ if(slash == 1) {
+ *(p++) = ch; /* we are sure we have enough buffer */
+ slash = 0;
+ } else if(ch == '\\') {
+ slash = 1;
+ } else if((ch == ',') || (ch == ';') || (ch == '\0')) {
+ *(p) = '\0';
+ /* remove spaces back */
+ while((p > tmp) && (XMLSEC_GNUTLS_IS_SPACE(*(p - 1)))) {
+ *(--p) = '\0';
+ }
+
+ attrs[pos].value = xmlStrdup(tmp);
+ if(attrs[pos].value == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(xmlStrlen(tmp) + 1));
+ goto done;
+ }
+ state = xmlSecGnuTLSDnParseState_BeforeNameComponent;
+ ++pos;
+ p = tmp;
+ } else {
+ *(p++) = ch; /* we are sure we have enough buffer */
+ }
+ break;
+ case xmlSecGnuTLSDnParseState_QuotedString:
+ if(slash == 1) {
+ *(p++) = ch; /* we are sure we have enough buffer */
+ slash = 0;
+ } else if(ch == '\\') {
+ slash = 1;
+ } else if(ch == '\"') {
+ *(p) = '\0';
+ /* don't remove spaces for quoted string */
+
+ attrs[pos].value = xmlStrdup(tmp);
+ if(attrs[pos].value == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(xmlStrlen(tmp) + 1));
+ goto done;
+ }
+ state = xmlSecGnuTLSDnParseState_AfterQuotedString;
+ ++pos;
+ p = tmp;
+ } else {
+ *(p++) = ch; /* we are sure we have enough buffer */
+ }
+ break;
+ case xmlSecGnuTLSDnParseState_AfterQuotedString:
+ if(!XMLSEC_GNUTLS_IS_SPACE(ch)) {
+ if((ch == ',') || (ch == ';') || (ch == '\0')) {
+ state = xmlSecGnuTLSDnParseState_BeforeNameComponent;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Unexpected character %c (expected space or ',' or ';')",
+ ch);
+ goto done;
+ }
+ } else {
+ /* just skip space */
+ }
+ break;
+ }
+
+ if(ch == '\0') {
+ /* done */
+ break;
+ }
+ }
+
+ /* check end state */
+ if(state != xmlSecGnuTLSDnParseState_BeforeNameComponent) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "Unexpected state %d at the end of parsing",
+ (int)state);
+ goto done;
+ }
+
+ /* debug
+ {
+ xmlSecSize ii;
+ for(ii = 0; ii < attrsSize; ++ii) {
+ if(attrs[ii].key != NULL) {
+ printf("DEBUG: attrs - %s=>%s\n", attrs[ii].key, attrs[ii].value);
+ }
+ }
+ }
+ */
+
+ /* done */
+ res = 0;
+
+done:
+ if(tmp != NULL) {
+ xmlFree(tmp);
+ }
+ return(res);
+}
+
+
+#endif /* XMLSEC_NO_X509 */
+
+
+
diff --git a/src/gnutls/x509utils.h b/src/gnutls/x509utils.h
new file mode 100644
index 00000000..b939b248
--- /dev/null
+++ b/src/gnutls/x509utils.h
@@ -0,0 +1,143 @@
+/*
+ * XML Security Library
+ *
+ * THIS IS A PRIVATE XMLSEC HEADER FILE
+ * DON'T USE IT IN YOUR APPLICATION
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef __XMLSEC_GNUTLS_X509UTILS_H__
+#define __XMLSEC_GNUTLS_X509UTILS_H__
+
+#ifndef XMLSEC_PRIVATE
+#error "gnutls/x509utils.h file contains private xmlsec definitions and should not be used outside xmlsec or xmlsec-<crypto> libraries"
+#endif /* XMLSEC_PRIVATE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef XMLSEC_NO_X509
+
+/**************************************************************************
+ *
+ * X509 certs list
+ *
+ *****************************************************************************/
+#define xmlSecGnuTLSX509CrtListId \
+ xmlSecGnuTLSX509CrtListGetKlass()
+xmlSecPtrListId xmlSecGnuTLSX509CrtListGetKlass (void);
+
+/**************************************************************************
+ *
+ * X509 crls list
+ *
+ *****************************************************************************/
+#define xmlSecGnuTLSX509CrlListId \
+ xmlSecGnuTLSX509CrlListGetKlass()
+xmlSecPtrListId xmlSecGnuTLSX509CrlListGetKlass (void);
+
+/*************************************************************************
+ *
+ * x509 certs utils/helpers
+ *
+ ************************************************************************/
+gnutls_x509_crt_t xmlSecGnuTLSX509CertDup (gnutls_x509_crt_t src);
+xmlChar * xmlSecGnuTLSX509CertGetSubjectDN (gnutls_x509_crt_t cert);
+xmlChar * xmlSecGnuTLSX509CertGetIssuerDN (gnutls_x509_crt_t cert);
+xmlChar * xmlSecGnuTLSX509CertGetIssuerSerial (gnutls_x509_crt_t cert);
+xmlChar * xmlSecGnuTLSX509CertGetSKI (gnutls_x509_crt_t cert);
+gnutls_x509_crt_t xmlSecGnuTLSX509CertRead (const xmlSecByte* buf,
+ xmlSecSize size,
+ xmlSecKeyDataFormat format);
+gnutls_x509_crt_t xmlSecGnuTLSX509CertBase64DerRead (xmlChar* buf);
+xmlChar* xmlSecGnuTLSX509CertBase64DerWrite (gnutls_x509_crt_t cert,
+ int base64LineWrap);
+void xmlSecGnuTLSX509CertDebugDump (gnutls_x509_crt_t cert,
+ FILE* output);
+void xmlSecGnuTLSX509CertDebugXmlDump (gnutls_x509_crt_t cert,
+ FILE* output);
+
+/*************************************************************************
+ *
+ * x509 crls utils/helpers
+ *
+ ************************************************************************/
+gnutls_x509_crl_t xmlSecGnuTLSX509CrlDup (gnutls_x509_crl_t src);
+xmlChar * xmlSecGnuTLSX509CrLGetIssuerDN (gnutls_x509_crl_t crl);
+gnutls_x509_crl_t xmlSecGnuTLSX509CrlRead (const xmlSecByte* buf,
+ xmlSecSize size,
+ xmlSecKeyDataFormat format);
+gnutls_x509_crl_t xmlSecGnuTLSX509CrlBase64DerRead (xmlChar* buf);
+xmlChar* xmlSecGnuTLSX509CrlBase64DerWrite (gnutls_x509_crl_t crl,
+ int base64LineWrap);
+void xmlSecGnuTLSX509CrlDebugDump (gnutls_x509_crl_t crl,
+ FILE* output);
+void xmlSecGnuTLSX509CrlDebugXmlDump (gnutls_x509_crl_t crl,
+ FILE* output);
+
+/*************************************************************************
+ *
+ * Misc. utils/helpers
+ *
+ ************************************************************************/
+xmlChar* xmlSecGnuTLSASN1IntegerWrite (const unsigned char * data,
+ size_t len);
+
+
+
+/*************************************************************************
+ *
+ * pkcs12 utils/helpers
+ *
+ ************************************************************************/
+int xmlSecGnuTLSPkcs12LoadMemory (const xmlSecByte* data,
+ xmlSecSize dataSize,
+ const char *pwd,
+ gnutls_x509_privkey_t * priv_key,
+ gnutls_x509_crt_t * key_cert,
+ xmlSecPtrListPtr certsList);
+
+/*************************************************************************
+ *
+ * keydata utils/helpers
+ *
+ ************************************************************************/
+xmlSecKeyDataPtr xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(gnutls_x509_privkey_t priv_key);
+
+
+/*************************************************************************
+ *
+ * LDAP DN parser
+ *
+ ************************************************************************/
+typedef struct _xmlSecGnuTLSDnAttr {
+ xmlChar * key;
+ xmlChar * value;
+} xmlSecGnuTLSDnAttr;
+
+void xmlSecGnuTLSDnAttrsInitialize (xmlSecGnuTLSDnAttr * attrs,
+ xmlSecSize attrsSize);
+void xmlSecGnuTLSDnAttrsDeinitialize (xmlSecGnuTLSDnAttr * attrs,
+ xmlSecSize attrsSize);
+const xmlSecGnuTLSDnAttr * xmlSecGnuTLSDnAttrrsFind (const xmlSecGnuTLSDnAttr * attrs,
+ xmlSecSize attrsSize,
+ const xmlChar * key);
+int xmlSecGnuTLSDnAttrsEqual (const xmlSecGnuTLSDnAttr * ll,
+ xmlSecSize llSize,
+ const xmlSecGnuTLSDnAttr * rr,
+ xmlSecSize rrSize);
+int xmlSecGnuTLSDnAttrsParse (const xmlChar * dn,
+ xmlSecGnuTLSDnAttr * attrs,
+ xmlSecSize attrsSize);
+#endif /* XMLSEC_NO_X509 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* ! __XMLSEC_GNUTLS_X509UTILS_H__ */
diff --git a/src/gnutls/x509vfy.c b/src/gnutls/x509vfy.c
new file mode 100644
index 00000000..fd15c5ac
--- /dev/null
+++ b/src/gnutls/x509vfy.c
@@ -0,0 +1,802 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 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/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+/**************************************************************************
+ *
+ * Internal GnuTLS X509 store CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecGnuTLSX509StoreCtx xmlSecGnuTLSX509StoreCtx,
+ *xmlSecGnuTLSX509StoreCtxPtr;
+struct _xmlSecGnuTLSX509StoreCtx {
+ xmlSecPtrList certsTrusted;
+ xmlSecPtrList certsUntrusted;
+};
+
+/****************************************************************************
+ *
+ * xmlSecGnuTLSKeyDataStoreX509Id:
+ *
+ * xmlSecGnuTLSX509StoreCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecGnuTLSX509StoreGetCtx(store) \
+ ((xmlSecGnuTLSX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
+ sizeof(xmlSecKeyDataStoreKlass)))
+#define xmlSecGnuTLSX509StoreSize \
+ (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecGnuTLSX509StoreCtx))
+
+static int xmlSecGnuTLSX509StoreInitialize (xmlSecKeyDataStorePtr store);
+static void xmlSecGnuTLSX509StoreFinalize (xmlSecKeyDataStorePtr store);
+
+static xmlSecKeyDataStoreKlass xmlSecGnuTLSX509StoreKlass = {
+ sizeof(xmlSecKeyDataStoreKlass),
+ xmlSecGnuTLSX509StoreSize,
+
+ /* data */
+ xmlSecNameX509Store, /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecGnuTLSX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
+ xmlSecGnuTLSX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static gnutls_x509_crt_t xmlSecGnuTLSX509FindCert (xmlSecPtrListPtr certs,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const xmlChar *issuerSerial,
+ const xmlChar *ski);
+static gnutls_x509_crt_t xmlSecGnuTLSX509FindSignedCert (xmlSecPtrListPtr certs,
+ gnutls_x509_crt_t cert);
+static gnutls_x509_crt_t xmlSecGnuTLSX509FindSignerCert (xmlSecPtrListPtr certs,
+ gnutls_x509_crt_t cert);
+
+
+/**
+ * xmlSecGnuTLSX509StoreGetKlass:
+ *
+ * The GnuTLS X509 certificates key data store klass.
+ *
+ * Returns: pointer to GnuTLS X509 certificates key data store klass.
+ */
+xmlSecKeyDataStoreId
+xmlSecGnuTLSX509StoreGetKlass(void) {
+ return(&xmlSecGnuTLSX509StoreKlass);
+}
+
+/**
+ * xmlSecGnuTLSX509StoreFindCert:
+ * @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.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSX509StoreFindCert(xmlSecKeyDataStorePtr store,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const xmlChar *issuerSerial,
+ const xmlChar *ski,
+ const xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecGnuTLSX509StoreCtxPtr ctx;
+ gnutls_x509_crt_t res = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ if(res == NULL) {
+ res = xmlSecGnuTLSX509FindCert(&(ctx->certsTrusted), subjectName, issuerName, issuerSerial, ski);
+ }
+ if(res == NULL) {
+ res = xmlSecGnuTLSX509FindCert(&(ctx->certsUntrusted), subjectName, issuerName, issuerSerial, ski);
+ }
+ return(res);
+}
+
+static int
+xmlSecGnuTLSX509CheckTime(const gnutls_x509_crt_t * cert_list,
+ xmlSecSize cert_list_length,
+ time_t ts)
+{
+ time_t notValidBefore, notValidAfter;
+ xmlSecSize ii;
+
+ xmlSecAssert2(cert_list != NULL, -1);
+
+ for(ii = 0; ii < cert_list_length; ++ii) {
+ const gnutls_x509_crt_t cert = cert_list[ii];
+ if(cert == NULL) {
+ continue;
+ }
+
+ /* get expiration times */
+ notValidBefore = gnutls_x509_crt_get_activation_time(cert);
+ if(notValidBefore == (time_t)-1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_activation_time",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ notValidAfter = gnutls_x509_crt_get_expiration_time(cert);
+ if(notValidAfter == (time_t)-1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_get_expiration_time",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* check */
+ if(ts < notValidBefore) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+ if(ts > notValidAfter) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+ }
+
+ /* GOOD! */
+ return(1);
+}
+
+/**
+ * xmlSecGnuTLSX509StoreVerify:
+ * @store: the pointer to X509 key data store klass.
+ * @certs: the untrusted certificates.
+ * @crls: the crls.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Verifies @certs list.
+ *
+ * Returns: pointer to the first verified certificate from @certs.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSX509StoreVerify(xmlSecKeyDataStorePtr store,
+ xmlSecPtrListPtr certs,
+ xmlSecPtrListPtr crls,
+ const xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecGnuTLSX509StoreCtxPtr ctx;
+ gnutls_x509_crt_t res = NULL;
+ xmlSecSize certs_size = 0;
+ gnutls_x509_crt_t * cert_list = NULL;
+ xmlSecSize cert_list_length;
+ gnutls_x509_crl_t * crl_list = NULL;
+ xmlSecSize crl_list_length;
+ gnutls_x509_crt_t * ca_list = NULL;
+ xmlSecSize ca_list_length;
+ time_t verification_time;
+ unsigned int flags = 0;
+ xmlSecSize ii;
+ int ret;
+ int err;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL);
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(crls != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ certs_size = xmlSecPtrListGetSize(certs);
+ if(certs_size <= 0) {
+ /* nothing to do */
+ return(NULL);
+ }
+
+ ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ /* Prepare */
+ cert_list_length = certs_size + xmlSecPtrListGetSize(&(ctx->certsUntrusted));
+ if(cert_list_length > 0) {
+ cert_list = (gnutls_x509_crt_t *)xmlMalloc(sizeof(gnutls_x509_crt_t) * cert_list_length);
+ if(cert_list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(sizeof(gnutls_x509_crt_t) * cert_list_length));
+ goto done;
+ }
+ }
+ crl_list_length = xmlSecPtrListGetSize(crls);
+ if(crl_list_length > 0) {
+ crl_list = (gnutls_x509_crl_t *)xmlMalloc(sizeof(gnutls_x509_crl_t) * crl_list_length);
+ if(crl_list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(sizeof(gnutls_x509_crl_t) * crl_list_length));
+ goto done;
+ }
+ for(ii = 0; ii < crl_list_length; ++ii) {
+ crl_list[ii] = xmlSecPtrListGetItem(crls, ii);
+ if(crl_list[ii] == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListGetItem(crls)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ }
+
+ ca_list_length = xmlSecPtrListGetSize(&(ctx->certsTrusted));
+ if(ca_list_length > 0) {
+ ca_list = (gnutls_x509_crt_t *)xmlMalloc(sizeof(gnutls_x509_crt_t) * ca_list_length);
+ if(ca_list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", (int)(sizeof(gnutls_x509_crt_t) * ca_list_length));
+ goto done;
+ }
+ for(ii = 0; ii < ca_list_length; ++ii) {
+ ca_list[ii] = xmlSecPtrListGetItem(&(ctx->certsTrusted), ii);
+ if(ca_list[ii] == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListGetItem(certsTrusted)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ }
+
+ /* gnutls doesn't allow to specify "verification" timestamp so
+ we have to do it ourselves */
+ verification_time = (keyInfoCtx->certsVerificationTime > 0) ?
+ keyInfoCtx->certsVerificationTime :
+ time(0);
+ flags |= GNUTLS_VERIFY_DISABLE_TIME_CHECKS;
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS) != 0) {
+ flags |= GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2;
+ flags |= GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5;
+ }
+
+ /* We are going to build all possible cert chains and try to verify them */
+ for(ii = 0; (ii < certs_size) && (res == NULL); ++ii) {
+ gnutls_x509_crt_t cert, cert2;
+ xmlSecSize cert_list_cur_length = 0;
+ unsigned int verify = 0;
+
+ cert = xmlSecPtrListGetItem(certs, ii);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListGetItem(certs)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* check if we are the "leaf" node in the certs chain */
+ if(xmlSecGnuTLSX509FindSignedCert(certs, cert) != NULL) {
+ continue;
+ }
+
+ /* build the chain */
+ for(cert2 = cert, cert_list_cur_length = 0;
+ (cert2 != NULL) && (cert_list_cur_length < cert_list_length);
+ ++cert_list_cur_length)
+ {
+ gnutls_x509_crt_t tmp;
+
+ /* store */
+ cert_list[cert_list_cur_length] = cert2;
+
+ /* find next */
+ tmp = xmlSecGnuTLSX509FindSignerCert(certs, cert2);
+ if(tmp == NULL) {
+ tmp = xmlSecGnuTLSX509FindSignerCert(&(ctx->certsUntrusted), cert2);
+ }
+ cert2 = tmp;
+ }
+
+ /* try to verify */
+ err = gnutls_x509_crt_list_verify(
+ cert_list, (int)cert_list_cur_length, /* certs chain */
+ ca_list, (int)ca_list_length, /* trusted cas */
+ crl_list, (int)crl_list_length, /* crls */
+ flags, /* flags */
+ &verify);
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_list_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ /* don't stop, continue! */
+ continue;
+ } else if(verify != 0){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_crt_list_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "Verification failed: verify=%u", verify);
+ /* don't stop, continue! */
+ continue;
+ }
+
+ /* gnutls doesn't allow to specify "verification" timestamp so
+ we have to do it ourselves */
+ ret = xmlSecGnuTLSX509CheckTime(cert_list, cert_list_cur_length, verification_time);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "Time verification failed");
+ /* don't stop, continue! */
+ continue;
+ }
+
+ /* DONE! */
+ res = cert;
+ }
+
+done:
+ /* cleanup */
+ if(ca_list != NULL) {
+ xmlFree(ca_list);
+ }
+ if(crl_list != NULL) {
+ xmlFree(crl_list);
+ }
+ if(cert_list != NULL) {
+ xmlFree(cert_list);
+ }
+
+ return(res);
+}
+
+/**
+ * xmlSecGnuTLSX509StoreAdoptCert:
+ * @store: the pointer to X509 key data store klass.
+ * @cert: the pointer to GnuTLS 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
+xmlSecGnuTLSX509StoreAdoptCert(xmlSecKeyDataStorePtr store, gnutls_x509_crt_t cert, xmlSecKeyDataType type) {
+ xmlSecGnuTLSX509StoreCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if((type & xmlSecKeyDataTypeTrusted) != 0) {
+ ret = xmlSecPtrListAdd(&(ctx->certsTrusted), cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListAdd(trusted)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ ret = xmlSecPtrListAdd(&(ctx->certsUntrusted), cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListAdd(untrusted)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* done */
+ return(0);
+}
+
+static int
+xmlSecGnuTLSX509StoreInitialize(xmlSecKeyDataStorePtr store) {
+ xmlSecGnuTLSX509StoreCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), -1);
+
+ ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGnuTLSX509StoreCtx));
+
+ ret = xmlSecPtrListInitialize(&(ctx->certsTrusted), xmlSecGnuTLSX509CrtListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListInitialize(trusted)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecPtrListInitialize(&(ctx->certsUntrusted), xmlSecGnuTLSX509CrtListId);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecPtrListInitialize(untrusted)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecGnuTLSX509StoreFinalize(xmlSecKeyDataStorePtr store) {
+ xmlSecGnuTLSX509StoreCtxPtr ctx;
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId));
+
+ ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecPtrListFinalize(&(ctx->certsTrusted));
+ xmlSecPtrListFinalize(&(ctx->certsUntrusted));
+
+ memset(ctx, 0, sizeof(xmlSecGnuTLSX509StoreCtx));
+}
+
+
+/*****************************************************************************
+ *
+ * Low-level x509 functions
+ *
+ *****************************************************************************/
+#define XMLSEC_GNUTLS_DN_ATTRS_SIZE 1024
+static int
+xmlSecGnuTLSX509DnsEqual(const xmlChar * ll, const xmlChar * rr) {
+ xmlSecGnuTLSDnAttr ll_attrs[XMLSEC_GNUTLS_DN_ATTRS_SIZE];
+ xmlSecGnuTLSDnAttr rr_attrs[XMLSEC_GNUTLS_DN_ATTRS_SIZE];
+ int ret;
+ int res = -1;
+
+ xmlSecAssert2(ll != NULL, -1);
+ xmlSecAssert2(rr != NULL, -1);
+
+ /* fast version first */
+ if(xmlStrEqual(ll, rr)) {
+ return(1);
+ }
+
+ /* prepare */
+ xmlSecGnuTLSDnAttrsInitialize(ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+ xmlSecGnuTLSDnAttrsInitialize(rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+
+ /* parse */
+ ret = xmlSecGnuTLSDnAttrsParse(ll, ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSDnAttrsParse(ll)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecGnuTLSDnAttrsParse(rr, rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSDnAttrsParse(rr)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* compare */
+ ret = xmlSecGnuTLSDnAttrsEqual(ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE,
+ rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+ if(ret == 1) {
+ res = 1;
+ } else if(ret == 0) {
+ res = 0;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSDnAttrsEqual",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+done:
+ xmlSecGnuTLSDnAttrsDeinitialize(ll_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+ xmlSecGnuTLSDnAttrsDeinitialize(rr_attrs, XMLSEC_GNUTLS_DN_ATTRS_SIZE);
+ return(res);
+}
+
+static gnutls_x509_crt_t
+xmlSecGnuTLSX509FindCert(xmlSecPtrListPtr certs,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const xmlChar *issuerSerial,
+ const xmlChar *ski) {
+ xmlSecSize ii, sz;
+
+ xmlSecAssert2(certs != NULL, NULL);
+
+ /* todo: this is not the fastest way to search certs */
+ sz = xmlSecPtrListGetSize(certs);
+ for(ii = 0; (ii < sz); ++ii) {
+ gnutls_x509_crt_t cert = xmlSecPtrListGetItem(certs, ii);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ return(NULL);
+ }
+
+ if(subjectName != NULL) {
+ xmlChar * tmp;
+
+ tmp = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSubjectDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ return(NULL);
+ }
+
+ if(xmlSecGnuTLSX509DnsEqual(subjectName, tmp) == 1) {
+ xmlFree(tmp);
+ return(cert);
+ }
+ xmlFree(tmp);
+ } else if((issuerName != NULL) && (issuerSerial != NULL)) {
+ xmlChar * tmp1;
+ xmlChar * tmp2;
+
+ tmp1 = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+ if(tmp1 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ return(NULL);
+ }
+
+ tmp2 = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+ if(tmp2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerSerial",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ xmlFree(tmp1);
+ return(NULL);
+ }
+
+ if((xmlSecGnuTLSX509DnsEqual(issuerName, tmp1) == 1) && xmlStrEqual(issuerSerial, tmp2)) {
+ xmlFree(tmp1);
+ xmlFree(tmp2);
+ return(cert);
+ }
+ xmlFree(tmp1);
+ xmlFree(tmp2);
+ } else if(ski != NULL) {
+ xmlChar * tmp;
+
+ tmp = xmlSecGnuTLSX509CertGetSKI(cert);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSKI",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ return(NULL);
+ }
+
+ if(xmlStrEqual(ski, tmp)) {
+ xmlFree(tmp);
+ return(cert);
+ }
+ xmlFree(tmp);
+ }
+ }
+
+ return(NULL);
+}
+
+/* signed cert has issuer dn equal to our's subject dn */
+static gnutls_x509_crt_t
+xmlSecGnuTLSX509FindSignedCert(xmlSecPtrListPtr certs, gnutls_x509_crt_t cert) {
+ gnutls_x509_crt_t res = NULL;
+ xmlChar * subject = NULL;
+ xmlSecSize ii, sz;
+
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get subject */
+ subject = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSubjectDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* todo: this is not the fastest way to search certs */
+ sz = xmlSecPtrListGetSize(certs);
+ for(ii = 0; (ii < sz) && (res == NULL); ++ii) {
+ gnutls_x509_crt_t tmp;
+ xmlChar * issuer;
+
+ tmp = xmlSecPtrListGetItem(certs, ii);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ issuer = xmlSecGnuTLSX509CertGetIssuerDN(tmp);
+ if(issuer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ /* are we done? */
+ if(xmlSecGnuTLSX509DnsEqual(subject, issuer) == 1) {
+ res = tmp;
+ }
+ xmlFree(issuer);
+ }
+
+done:
+ if(subject != NULL) {
+ xmlFree(subject);
+ }
+ return(res);
+}
+
+/* signer cert has subject dn equal to our's issuer dn */
+static gnutls_x509_crt_t
+xmlSecGnuTLSX509FindSignerCert(xmlSecPtrListPtr certs, gnutls_x509_crt_t cert) {
+ gnutls_x509_crt_t res = NULL;
+ xmlChar * issuer = NULL;
+ xmlSecSize ii, sz;
+
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(cert != NULL, NULL);
+
+ /* get issuer */
+ issuer = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+ if(issuer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetIssuerDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* todo: this is not the fastest way to search certs */
+ sz = xmlSecPtrListGetSize(certs);
+ for(ii = 0; (ii < sz) && (res == NULL); ++ii) {
+ gnutls_x509_crt_t tmp;
+ xmlChar * subject;
+
+ tmp = xmlSecPtrListGetItem(certs, ii);
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecPtrListGetItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ subject = xmlSecGnuTLSX509CertGetSubjectDN(tmp);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSX509CertGetSubjectDN",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%i", (int)ii);
+ goto done;
+ }
+
+ /* are we done? */
+ if((xmlSecGnuTLSX509DnsEqual(issuer, subject) == 1)) {
+ res = tmp;
+ }
+ xmlFree(subject);
+ }
+
+done:
+ if(issuer != NULL) {
+ xmlFree(issuer);
+ }
+ return(res);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+
diff --git a/src/io.c b/src/io.c
new file mode 100644
index 00000000..42e91337
--- /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..00390fa7
--- /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>
+
+
+/**************************************************************************
+ *
+ * High-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..1d2f7331
--- /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..de854ba6
--- /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 destroying returned 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
+ * destroying returned 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 freeing 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..31a03e97
--- /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/kw_aes_des.c b/src/kw_aes_des.c
new file mode 100644
index 00000000..022e720a
--- /dev/null
+++ b/src/kw_aes_des.c
@@ -0,0 +1,493 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Implementation of AES/DES Key Transport algorithm
+ *
+ * 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/errors.h>
+
+#include "kw_aes_des.h"
+
+#ifndef XMLSEC_NO_DES
+
+static int xmlSecKWDes3BufferReverse (xmlSecByte *buf,
+ xmlSecSize size);
+
+/********************************************************************
+ *
+ * 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.
+ *
+ * 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 xmlSecByte xmlSecKWDes3Iv[XMLSEC_KW_DES3_IV_LENGTH] = {
+ 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05
+};
+
+int
+xmlSecKWDes3Encode(xmlSecKWDes3Id kwDes3Id, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte sha1[XMLSEC_KW_DES3_SHA_DIGEST_LENGTH];
+ xmlSecByte iv[XMLSEC_KW_DES3_IV_LENGTH];
+ xmlSecSize s;
+ int ret;
+
+ xmlSecAssert2(xmlSecKWDes3CheckId(kwDes3Id), -1);
+ xmlSecAssert2(context != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + XMLSEC_KW_DES3_BLOCK_LENGTH + XMLSEC_KW_DES3_IV_LENGTH, -1);
+
+ /* step 2: calculate sha1 and CMS */
+ ret = kwDes3Id->sha1(context, in, inSize, sha1, sizeof(sha1));
+ if((ret < 0) || (ret != sizeof(sha1))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->sha1",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* step 3: construct WKCKS as WK || CKS */
+ memcpy(out, in, inSize);
+ memcpy(out + inSize, sha1, XMLSEC_KW_DES3_BLOCK_LENGTH);
+
+ /* step 4: generate random iv */
+ ret = kwDes3Id->generateRandom(context, iv, sizeof(iv));
+ if((ret < 0) || (ret != sizeof(iv))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->generateRandom",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* step 5: first encryption, result is TEMP1 */
+ ret = kwDes3Id->encrypt(context,
+ iv, sizeof(iv),
+ out, inSize + XMLSEC_KW_DES3_BLOCK_LENGTH,
+ out, outSize);
+ if((ret < 0) || ((xmlSecSize)ret != inSize + XMLSEC_KW_DES3_BLOCK_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* step 6: construct TEMP2=IV || TEMP1 */
+ memmove(out + XMLSEC_KW_DES3_IV_LENGTH, out, inSize + XMLSEC_KW_DES3_BLOCK_LENGTH);
+ memcpy(out, iv, XMLSEC_KW_DES3_IV_LENGTH);
+ s = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH + XMLSEC_KW_DES3_IV_LENGTH;
+
+ /* step 7: reverse octets order, result is TEMP3 */
+ ret = xmlSecKWDes3BufferReverse(out, s);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKWDes3BufferReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* step 8: second encryption with static IV */
+ ret = kwDes3Id->encrypt(context,
+ xmlSecKWDes3Iv, sizeof(xmlSecKWDes3Iv),
+ out, s,
+ out, outSize);
+ if((ret < 0) || ((xmlSecSize)ret != s)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ s = ret;
+ return(s);
+}
+
+int
+xmlSecKWDes3Decode(xmlSecKWDes3Id kwDes3Id, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize)
+{
+ xmlSecByte sha1[XMLSEC_KW_DES3_SHA_DIGEST_LENGTH];
+ xmlSecSize s;
+ int ret;
+
+ xmlSecAssert2(xmlSecKWDes3CheckId(kwDes3Id), -1);
+ xmlSecAssert2(context != NULL, -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 = kwDes3Id->decrypt(context,
+ xmlSecKWDes3Iv, sizeof(xmlSecKWDes3Iv),
+ in, inSize,
+ out, outSize);
+ if((ret < 0) || (ret < XMLSEC_KW_DES3_IV_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->decrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ s = ret;
+
+ /* step 3: reverse octets order in TEMP3, result is TEMP2 */
+ ret = xmlSecKWDes3BufferReverse(out, s);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKWDes3BufferReverse",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* steps 4 and 5: get IV and decrypt second time, result is WKCKS */
+ ret = kwDes3Id->decrypt(context,
+ out, XMLSEC_KW_DES3_IV_LENGTH,
+ out + XMLSEC_KW_DES3_IV_LENGTH, s - XMLSEC_KW_DES3_IV_LENGTH,
+ out, outSize);
+ if((ret < 0) || (ret < XMLSEC_KW_DES3_BLOCK_LENGTH)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->decrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+ s = ret - XMLSEC_KW_DES3_BLOCK_LENGTH;
+
+ /* steps 6 and 7: calculate SHA1 and validate it */
+ ret = kwDes3Id->sha1(context,
+ out, s,
+ sha1, sizeof(sha1));
+ if((ret < 0) || (ret != sizeof(sha1))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwDes3Id->sha1",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ /* check sha1 */
+ xmlSecAssert2(XMLSEC_KW_DES3_BLOCK_LENGTH <= sizeof(sha1), -1);
+ if(memcmp(sha1, out + s, XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "SHA1 does not match");
+ return(-1);
+ }
+
+ /* done */
+ return(s);
+}
+
+static int
+xmlSecKWDes3BufferReverse(xmlSecByte *buf, xmlSecSize size)
+{
+ xmlSecByte * p;
+ xmlSecByte ch;
+
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(size > 0, -1);
+
+ for(p = buf + size - 1; p >= buf; ++buf, --p) {
+ ch = (*p);
+ (*p) = (*buf);
+ (*buf) = ch;
+ }
+ return (0);
+}
+
+#endif /* XMLSEC_NO_DES */
+
+
+
+#ifndef XMLSEC_NO_AES
+/********************************************************************
+ *
+ * KT AES
+ *
+ * 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 xmlSecKWAesMagicBlock[XMLSEC_KW_AES_MAGIC_BLOCK_SIZE] = {
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
+};
+
+int
+xmlSecKWAesEncode(xmlSecKWAesId kwAesId, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte block[XMLSEC_KW_AES_BLOCK_SIZE];
+ xmlSecByte *p;
+ int N, i, j, t;
+ int ret;
+
+ xmlSecAssert2(kwAesId != NULL, -1);
+ xmlSecAssert2(kwAesId->encrypt != NULL, -1);
+ xmlSecAssert2(kwAesId->decrypt != NULL, -1);
+ xmlSecAssert2(context != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, -1);
+
+ /* prepend magic block */
+ if(in != out) {
+ memcpy(out + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
+ } else {
+ memmove(out + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
+ }
+ memcpy(out, xmlSecKWAesMagicBlock, XMLSEC_KW_AES_MAGIC_BLOCK_SIZE);
+
+ N = (inSize / 8);
+ if(N == 1) {
+ ret = kwAesId->encrypt(out, inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, out, outSize, context);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwAesId->encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } 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);
+
+ ret = kwAesId->encrypt(block, sizeof(block), block, sizeof(block), context);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwAesId->encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ block[7] ^= t;
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+
+ return(inSize + 8);
+}
+
+int
+xmlSecKWAesDecode(xmlSecKWAesId kwAesId, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize) {
+ xmlSecByte block[XMLSEC_KW_AES_BLOCK_SIZE];
+ xmlSecByte *p;
+ int N, i, j, t;
+ int ret;
+
+ xmlSecAssert2(kwAesId != NULL, -1);
+ xmlSecAssert2(kwAesId->encrypt != NULL, -1);
+ xmlSecAssert2(kwAesId->decrypt != NULL, -1);
+ xmlSecAssert2(context != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ /* copy input */
+ if(in != out) {
+ memcpy(out, in, inSize);
+ }
+
+ N = (inSize / 8) - 1;
+ if(N == 1) {
+ ret = kwAesId->decrypt(out, inSize, out, outSize, context);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwAesId->decrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } 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;
+
+ ret = kwAesId->decrypt(block, sizeof(block), block, sizeof(block), context);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "kwAesId->decrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+ /* do not left data in memory */
+ memset(block, 0, sizeof(block));
+
+ /* check the output */
+ if(memcmp(xmlSecKWAesMagicBlock, out, XMLSEC_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "bad magic block");
+ return(-1);
+ }
+
+ /* get rid of magic block */
+ memmove(out, out + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_KW_AES_MAGIC_BLOCK_SIZE);
+ return(inSize - XMLSEC_KW_AES_MAGIC_BLOCK_SIZE);
+}
+
+#endif /* XMLSEC_NO_AES */
+
diff --git a/src/kw_aes_des.h b/src/kw_aes_des.h
new file mode 100644
index 00000000..46e85273
--- /dev/null
+++ b/src/kw_aes_des.h
@@ -0,0 +1,148 @@
+/**
+ * XMLSec library
+ *
+ * THIS IS A PRIVATE XMLSEC HEADER FILE
+ * DON'T USE IT IN YOUR APPLICATION
+ *
+ * Implementation of AES/DES Key Transport algorithm
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin, All rights reserved.
+ */
+#ifndef __XMLSEC_KT_AES_DES_H__
+#define __XMLSEC_KT_AES_DES_H__
+
+#ifndef XMLSEC_PRIVATE
+#error "private.h file contains private xmlsec definitions and should not be used outside xmlsec or xmlsec-<crypto> libraries"
+#endif /* XMLSEC_PRIVATE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef XMLSEC_NO_DES
+/********************************************************************
+ *
+ * KT DES
+ *
+ ********************************************************************/
+#define XMLSEC_KW_DES3_KEY_LENGTH 24
+#define XMLSEC_KW_DES3_IV_LENGTH 8
+#define XMLSEC_KW_DES3_BLOCK_LENGTH 8
+#define XMLSEC_KW_DES3_SHA_DIGEST_LENGTH 20
+
+
+typedef int (*xmlSecKWDes3Sha1Method) (void * context,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+typedef int (*xmlSecKWDes3GenerateRandomMethod) (void * context,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+typedef int (*xmlSecKWDes3BlockEncryptMethod) (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+typedef int (*xmlSecKWDes3BlockDecryptMethod) (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+
+
+struct _xmlSecKWDes3Klass {
+ /* callbacks */
+ xmlSecKWDes3GenerateRandomMethod generateRandom;
+ xmlSecKWDes3Sha1Method sha1;
+ xmlSecKWDes3BlockEncryptMethod encrypt;
+ xmlSecKWDes3BlockDecryptMethod decrypt;
+
+ /* for the future */
+ void* reserved0;
+ void* reserved1;
+};
+typedef const struct _xmlSecKWDes3Klass xmlSecKWDes3Klass,
+ *xmlSecKWDes3Id;
+
+#define xmlSecKWDes3CheckId(id) \
+ ( \
+ ((id) != NULL) && \
+ ((id)->generateRandom != NULL) && \
+ ((id)->sha1 != NULL) && \
+ ((id)->encrypt != NULL) && \
+ ((id)->decrypt != NULL) \
+ )
+
+XMLSEC_EXPORT int
+xmlSecKWDes3Encode(xmlSecKWDes3Id kwDes3Id, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize);
+
+XMLSEC_EXPORT int
+xmlSecKWDes3Decode(xmlSecKWDes3Id kwDes3Id, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize);
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+/********************************************************************
+ *
+ * KT AES
+ *
+ ********************************************************************/
+#define XMLSEC_KW_AES_MAGIC_BLOCK_SIZE 8
+#define XMLSEC_KW_AES_BLOCK_SIZE 16
+#define XMLSEC_KW_AES128_KEY_SIZE 16
+#define XMLSEC_KW_AES192_KEY_SIZE 24
+#define XMLSEC_KW_AES256_KEY_SIZE 32
+
+typedef int (*xmlSecKWAesBlockEncryptMethod) (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+typedef int (*xmlSecKWAesBlockDecryptMethod) (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+
+
+struct _xmlSecKWAesKlass {
+ /* callbacks */
+ xmlSecKWAesBlockEncryptMethod encrypt;
+ xmlSecKWAesBlockDecryptMethod decrypt;
+
+ /* for the future */
+ void* reserved0;
+ void* reserved1;
+};
+typedef const struct _xmlSecKWAesKlass xmlSecKWAesKlass,
+ *xmlSecKWAesId;
+
+XMLSEC_EXPORT int
+xmlSecKWAesEncode(xmlSecKWAesId kwAesId, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize);
+
+XMLSEC_EXPORT int
+xmlSecKWAesDecode(xmlSecKWAesId kwAesId, void *context,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize);
+
+#endif /* XMLSEC_NO_AES */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __XMLSEC_KT_AES_DES_H__ */
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 00000000..d1a00533
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,534 @@
+/**
+ * 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);
+}
+
+/**
+ * xmlSecPtrListRemoveAndReturn:
+ * @list: the pointer to list.
+ * @pos: the position.
+ *
+ * Remove the list item at the position @pos and return it back.
+ *
+ * Returns: the pointer to the list item.
+ */
+xmlSecPtr
+xmlSecPtrListRemoveAndReturn(xmlSecPtrListPtr list, xmlSecSize pos) {
+ xmlSecPtr res;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+ xmlSecAssert2(list->data != NULL, NULL);
+ xmlSecAssert2(pos < list->use, NULL);
+
+ res = list->data[pos];
+ list->data[pos] = NULL;
+ if(pos == list->use - 1) {
+ --list->use;
+ }
+ return(res);
+}
+
+
+/**
+ * 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..eb78156c
--- /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..5cea654b
--- /dev/null
+++ b/src/mscrypto/Makefile.am
@@ -0,0 +1,62 @@
+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 =\
+ globals.h \
+ private.h \
+ app.c \
+ certkeys.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ hmac.c \
+ keysstore.c \
+ kw_aes.c \
+ kw_des.c \
+ kt_rsa.c \
+ signatures.c \
+ symkeys.c \
+ x509.c \
+ x509vfy.c \
+ csp_calg.h \
+ csp_oid.h \
+ xmlsec-mingw.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_mscrypto_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_mscrypto_la_LIBADD = \
+ $(MSCRYPTO_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(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..72d22a3b
--- /dev/null
+++ b/src/mscrypto/Makefile.in
@@ -0,0 +1,799 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c
+subdir = src/mscrypto
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__libxmlsec1_mscrypto_la_SOURCES_DIST = globals.h private.h app.c \
+ certkeys.c ciphers.c crypto.c digests.c hmac.c keysstore.c \
+ kw_aes.c kw_des.c kt_rsa.c signatures.c symkeys.c x509.c \
+ x509vfy.c csp_calg.h csp_oid.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-hmac.lo \
+ libxmlsec1_mscrypto_la-keysstore.lo \
+ libxmlsec1_mscrypto_la-kw_aes.lo \
+ libxmlsec1_mscrypto_la-kw_des.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@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+EXTRA_DIST = \
+ 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 = globals.h private.h app.c certkeys.c \
+ ciphers.c crypto.c digests.c hmac.c keysstore.c kw_aes.c \
+ kw_des.c kt_rsa.c signatures.c symkeys.c x509.c x509vfy.c \
+ csp_calg.h csp_oid.h xmlsec-mingw.h $(NULL) $(am__append_1)
+libxmlsec1_mscrypto_la_LIBADD = \
+ $(MSCRYPTO_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(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-hmac.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-kw_aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_mscrypto_la-kw_des.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-hmac.lo: hmac.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-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-hmac.Tpo -c -o libxmlsec1_mscrypto_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-hmac.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.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-kw_aes.lo: kw_aes.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-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-kw_aes.Tpo -c -o libxmlsec1_mscrypto_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-kw_aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+
+libxmlsec1_mscrypto_la-kw_des.lo: kw_des.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-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_mscrypto_la-kw_des.Tpo -c -o libxmlsec1_mscrypto_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_mscrypto_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_mscrypto_la-kw_des.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_mscrypto_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_mscrypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_mscrypto_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.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..0b3f4b6b
--- /dev/null
+++ b/src/mscrypto/README
@@ -0,0 +1,39 @@
+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) 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..92894d90
--- /dev/null
+++ b/src/mscrypto/app.c
@@ -0,0 +1,1289 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+
+/* I don't see any other way then to use a global var to get the
+ * config info to the mscrypto keysstore :( WK
+ */
+static LPTSTR 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 != NULL) {
+ /* 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);
+ }
+
+#ifdef UNICODE
+ gXmlSecMSCryptoAppCertStoreName = xmlSecMSCryptoConvertLocaleToUnicode(config);
+ if (gXmlSecMSCryptoAppCertStoreName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoConvertLocaleToUnicode",
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "config=%s",
+ xmlSecErrorsSafeString(config));
+ return (-1);
+ }
+#else /* UNICODE */
+ gXmlSecMSCryptoAppCertStoreName = xmlStrdup(config);
+ if (gXmlSecMSCryptoAppCertStoreName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlStrdup",
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "config=%s",
+ xmlSecErrorsSafeString(config));
+ return (-1);
+ }
+#endif /* UNICODE */
+ }
+
+ 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.
+ */
+LPCTSTR
+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) {
+ 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;
+ int ret;
+
+ 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;
+ }
+
+ wcPwd = xmlSecMSCryptoConvertLocaleToUnicode(pwd);
+ if (wcPwd == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoConvertLocaleToUnicode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "wcPwd");
+ 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..90daa827
--- /dev/null
+++ b/src/mscrypto/certkeys.c
@@ -0,0 +1,2615 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+// 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
+
+
+/**************************************************************************
+ *
+ * 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;
+ const xmlSecMSCryptoProviderInfo * providers;
+ 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_SILENT_FLAG | 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;
+
+ hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, FALSE);
+ if (hProv == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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));
+}
+
+/**
+ * xmlSecMSCryptoKeyDataGetMSCryptoProvider:
+ * @data: the key data
+ *
+ * Gets crypto provider handle
+ *
+ * Returns: the crypto provider handler or 0 if there is an error.
+ */
+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));
+}
+
+/**
+ * xmlSecMSCryptoKeyDataGetMSCryptoKeySpec:
+ * @data: the key data
+ *
+ * Gets key spec info.
+ *
+ * Returns: the key spec info from key data
+ */
+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->providers = ctxSrc->providers;
+ 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; */
+};
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Rsa[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { MS_DEF_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+
+/**
+ * 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->providers = xmlSecMSCryptoProviderInfo_Rsa;
+ 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 */
+ hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Rsa, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(hProv == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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);
+
+ /* get provider */
+ hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(hProv == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ 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; */
+};
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Dss[] = {
+ { MS_DEF_DSS_PROV, PROV_DSS },
+ { NULL, 0 }
+};
+
+
+/**
+ * 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->providers = xmlSecMSCryptoProviderInfo_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 */
+
+ hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Dss, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(hProv == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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);
+
+ hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(hProv == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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; */
+};
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost[] = {
+ { MAGPRO_CSP, PROV_MAGPRO_GOST },
+ { CRYPTOPRO_CSP, PROV_CRYPTOPRO_GOST },
+ { NULL, 0 }
+};
+
+/**
+ * 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;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown);
+
+ xmlSecMSCryptoKeyDataInitialize(data);
+
+ ctx = xmlSecMSCryptoKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ctx->providers = xmlSecMSCryptoProviderInfo_Gost;
+ 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..ea2edcd5
--- /dev/null
+++ b/src/mscrypto/ciphers.c
@@ -0,0 +1,937 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+
+#include "private.h"
+
+
+/**************************************************************************
+ *
+ * Internal MSCrypto Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecMSCryptoBlockCipherCtx xmlSecMSCryptoBlockCipherCtx,
+ *xmlSecMSCryptoBlockCipherCtxPtr;
+struct _xmlSecMSCryptoBlockCipherCtx {
+ ALG_ID algorithmIdentifier;
+ const xmlSecMSCryptoProviderInfo * providers;
+ xmlSecKeyDataId keyId;
+ xmlSecSize keySize;
+
+ HCRYPTPROV cryptProvider;
+ HCRYPTKEY pubPrivKey;
+ HCRYPTKEY cryptKey;
+ int ctxInitialized;
+};
+/* 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->cryptKey != 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);
+
+
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+#ifndef XMLSEC_NO_DES
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Des[] = {
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Aes[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { NULL, 0 }
+};
+#endif /* XMLSEC_NO_AES */
+
+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;
+ int ret;
+
+ 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->providers = xmlSecMSCryptoProviderInfo_Des;
+ 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->providers = xmlSecMSCryptoProviderInfo_Aes;
+ ctx->keySize = 16;
+ } else if(transform->id == xmlSecMSCryptoTransformAes192CbcId) {
+ ctx->algorithmIdentifier = CALG_AES_192;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Aes;
+ ctx->keySize = 24;
+ } else if(transform->id == xmlSecMSCryptoTransformAes256CbcId) {
+ ctx->algorithmIdentifier = CALG_AES_256;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Aes;
+ ctx->keySize = 32;
+ } else
+#endif /* XMLSEC_NO_AES */
+
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->cryptProvider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(ctx->cryptProvider == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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);
+ }
+
+ 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->cryptKey == 0, -1);
+ xmlSecAssert2(ctx->pubPrivKey != 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,
+ TRUE,
+ &(ctx->cryptKey))) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-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 */
diff --git a/src/mscrypto/crypto.c b/src/mscrypto/crypto.c
new file mode 100644
index 00000000..82ab101d
--- /dev/null
+++ b/src/mscrypto/crypto.c
@@ -0,0 +1,889 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+#if defined(__MINGW32__)
+/* NOTE mingw.org project don't define any xxx_s function and may
+ * be never will define them.
+ *
+ * In this file is save to use non _s function as into destination
+ * buffer program code copy empty string and the size of source buffer
+ * (XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE=4096) is enough for any
+ * encoding. Also program code don't check result of _s functions.
+ */
+
+static int
+strcpy_s(char *dest, size_t n, const char *src) {
+ strcpy(dest, src);
+ return(0);
+}
+
+static int
+wcscpy_s(wchar_t *dest, size_t n, const wchar_t *src) {
+ wcscpy(dest, src);
+ return(0);
+}
+#endif
+
+#define XMLSEC_CONTAINER_NAME_A "xmlsec-key-container"
+#define XMLSEC_CONTAINER_NAME_W L"xmlsec-key-container"
+#ifdef UNICODE
+#define XMLSEC_CONTAINER_NAME XMLSEC_CONTAINER_NAME_W
+#else
+#define XMLSEC_CONTAINER_NAME XMLSEC_CONTAINER_NAME_A
+#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_HMAC
+ gXmlSecMSCryptoFunctions->keyDataHmacGetKlass = xmlSecMSCryptoKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#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
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecMSCryptoFunctions->transformAes128CbcGetKlass = xmlSecMSCryptoTransformAes128CbcGetKlass;
+ gXmlSecMSCryptoFunctions->transformAes192CbcGetKlass = xmlSecMSCryptoTransformAes192CbcGetKlass;
+ gXmlSecMSCryptoFunctions->transformAes256CbcGetKlass = xmlSecMSCryptoTransformAes256CbcGetKlass;
+ gXmlSecMSCryptoFunctions->transformKWAes128GetKlass = xmlSecMSCryptoTransformKWAes128GetKlass;
+ gXmlSecMSCryptoFunctions->transformKWAes192GetKlass = xmlSecMSCryptoTransformKWAes192GetKlass;
+ gXmlSecMSCryptoFunctions->transformKWAes256GetKlass = xmlSecMSCryptoTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecMSCryptoFunctions->transformDes3CbcGetKlass = xmlSecMSCryptoTransformDes3CbcGetKlass;
+ gXmlSecMSCryptoFunctions->transformKWDes3GetKlass = xmlSecMSCryptoTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+ gXmlSecMSCryptoFunctions->transformDsaSha1GetKlass = xmlSecMSCryptoTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* GOST ********************************/
+#ifndef XMLSEC_NO_GOST
+ gXmlSecMSCryptoFunctions->transformGost2001GostR3411_94GetKlass = xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecMSCryptoFunctions->transformGostR3411_94GetKlass = xmlSecMSCryptoTransformGostR3411_94GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecMSCryptoFunctions->transformHmacMd5GetKlass = xmlSecMSCryptoTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecMSCryptoFunctions->transformHmacSha1GetKlass = xmlSecMSCryptoTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecMSCryptoFunctions->transformHmacSha256GetKlass = xmlSecMSCryptoTransformHmacSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecMSCryptoFunctions->transformHmacSha384GetKlass = xmlSecMSCryptoTransformHmacSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecMSCryptoFunctions->transformHmacSha512GetKlass = xmlSecMSCryptoTransformHmacSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* MD5 ********************************/
+#ifndef XMLSEC_NO_MD5
+ gXmlSecMSCryptoFunctions->transformMd5GetKlass = xmlSecMSCryptoTransformMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecMSCryptoFunctions->transformRsaMd5GetKlass = xmlSecMSCryptoTransformRsaMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecMSCryptoFunctions->transformRsaSha1GetKlass = xmlSecMSCryptoTransformRsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecMSCryptoFunctions->transformRsaSha256GetKlass = xmlSecMSCryptoTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecMSCryptoFunctions->transformRsaSha384GetKlass = xmlSecMSCryptoTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecMSCryptoFunctions->transformRsaSha512GetKlass = xmlSecMSCryptoTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ gXmlSecMSCryptoFunctions->transformRsaPkcs1GetKlass = xmlSecMSCryptoTransformRsaPkcs1GetKlass;
+ gXmlSecMSCryptoFunctions->transformRsaOaepGetKlass = xmlSecMSCryptoTransformRsaOaepGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecMSCryptoFunctions->transformSha1GetKlass = xmlSecMSCryptoTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecMSCryptoFunctions->transformSha256GetKlass = xmlSecMSCryptoTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecMSCryptoFunctions->transformSha384GetKlass = xmlSecMSCryptoTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecMSCryptoFunctions->transformSha512GetKlass = xmlSecMSCryptoTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ /********************************************************************
+ *
+ * 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);
+}
+
+
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Random[] = {
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { NULL, 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);
+ }
+
+ hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Random, NULL, CRYPT_VERIFYCONTEXT, FALSE);
+ if (0 == hProv) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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);
+}
+
+#define XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE 4096
+
+/**
+ * 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;
+ TCHAR errorT[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE];
+ WCHAR errorW[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE];
+ CHAR errorUTF8[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE];
+ xmlChar buf[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE];
+ DWORD rc;
+ int ret;
+
+ dwError = GetLastError();
+ rc = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dwError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ errorT,
+ XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE,
+ NULL);
+
+#ifdef UNICODE
+ if(rc <= 0) {
+ wcscpy_s(errorT, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, L"");
+ }
+ ret = WideCharToMultiByte(CP_UTF8, 0, errorT, -1, errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, NULL, NULL);
+ if(ret <= 0) {
+ strcpy_s(errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, "");
+ }
+#else /* UNICODE */
+ if(rc <= 0) {
+ strcpy_s(errorT, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, "");
+ }
+ ret = MultiByteToWideChar(CP_ACP, 0, errorT, -1, errorW, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE);
+ if(ret <= 0) {
+ wcscpy_s(errorW, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, L"");
+ }
+ ret = WideCharToMultiByte(CP_UTF8, 0, errorW, -1, errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, NULL, NULL);
+ if(ret <= 0) {
+ strcpy_s(errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, "");
+ }
+#endif /* UNICODE */
+
+ if((msg != NULL) && ((*msg) != '\0')) {
+ xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "%s;last error=%d (0x%08x);last error msg=%s", msg, dwError, dwError, errorUTF8);
+ } else {
+ xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "last error=%d (0x%08x);last error msg=%s", dwError, dwError, errorUTF8);
+ }
+ xmlSecErrorsDefaultCallback(file, line, func,
+ errorObject, errorSubject,
+ reason, (char*)buf);
+}
+
+/**
+ * xmlSecMSCryptoConvertUtf8ToUnicode:
+ * @str: the string to convert.
+ *
+ * Converts input string from UTF8 to Unicode.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+LPWSTR
+xmlSecMSCryptoConvertUtf8ToUnicode(const xmlChar* str) {
+ LPWSTR res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* call MultiByteToWideChar first to get the buffer size */
+ ret = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ if(ret <= 0) {
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(WCHAR) * len);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = MultiByteToWideChar(CP_UTF8, 0, str, -1, res, len);
+ if(ret <= 0) {
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/**
+ * xmlSecMSCryptoConvertUnicodeToUtf8:
+ * @str: the string to convert.
+ *
+ * Converts input string from Unicode to UTF8.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecMSCryptoConvertUnicodeToUtf8(LPCWSTR str) {
+ xmlChar * res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* call WideCharToMultiByte first to get the buffer size */
+ ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
+ if(ret <= 0) {
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(xmlChar) * len);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, res, len, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/**
+ * xmlSecMSCryptoConvertLocaleToUnicode:
+ * @str: the string to convert.
+ *
+ * Converts input string from current system locale to Unicode.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+LPWSTR
+xmlSecMSCryptoConvertLocaleToUnicode(const char* str) {
+ LPWSTR res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* call MultiByteToWideChar first to get the buffer size */
+ ret = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ if(ret <= 0) {
+ return(NULL);
+ }
+ len = ret;
+
+ /* allocate buffer */
+ res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = MultiByteToWideChar(CP_ACP, 0, str, -1, res, len);
+ if(ret <= 0) {
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+/**
+ * xmlSecMSCryptoConvertLocaleToUtf8:
+ * @str: the string to convert.
+ *
+ * Converts input string from locale to UTF8.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecMSCryptoConvertLocaleToUtf8(const char * str) {
+ LPWSTR strW = NULL;
+ xmlChar * res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ strW = xmlSecMSCryptoConvertLocaleToUnicode(str);
+ if(strW == NULL) {
+ return(NULL);
+ }
+
+ /* call WideCharToMultiByte first to get the buffer size */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(xmlChar) * len);
+ xmlFree(strW);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, res, len, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(strW);
+ return(res);
+}
+
+/**
+ * xmlSecMSCryptoConvertUtf8ToLocale:
+ * @str: the string to convert.
+ *
+ * Converts input string from UTF8 to locale.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+char *
+xmlSecMSCryptoConvertUtf8ToLocale(const xmlChar* str) {
+ LPWSTR strW = NULL;
+ char * res = NULL;
+ int len;
+ int ret;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ strW = xmlSecMSCryptoConvertUtf8ToUnicode(str);
+ if(strW == NULL) {
+ return(NULL);
+ }
+
+ /* call WideCharToMultiByte first to get the buffer size */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ return(NULL);
+ }
+ len = ret + 1;
+
+ /* allocate buffer */
+ res = (char*)xmlMalloc(sizeof(char) * len);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(xmlChar) * len);
+ xmlFree(strW);
+ return(NULL);
+ }
+
+ /* convert */
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, res, len, NULL, NULL);
+ if(ret <= 0) {
+ xmlFree(strW);
+ xmlFree(res);
+ return(NULL);
+ }
+
+ /* done */
+ xmlFree(strW);
+ return(res);
+}
+
+/**
+ * xmlSecMSCryptoConvertTstrToUtf8:
+ * @str: the string to convert.
+ *
+ * Converts input string from TSTR (locale or Unicode) to UTF8.
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+xmlChar*
+xmlSecMSCryptoConvertTstrToUtf8(LPCTSTR str) {
+#ifdef UNICODE
+ return xmlSecMSCryptoConvertUnicodeToUtf8(str);
+#else /* UNICODE */
+ return xmlSecMSCryptoConvertLocaleToUtf8(str);
+#endif /* UNICODE */
+}
+
+/**
+ * xmlSecMSCryptoConvertUtf8ToTstr:
+ * @str: the string to convert.
+ *
+ * Converts input string from UTF8 to TSTR (locale or Unicode).
+ *
+ * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs.
+ */
+LPTSTR
+xmlSecMSCryptoConvertUtf8ToTstr(const xmlChar* str) {
+#ifdef UNICODE
+ return xmlSecMSCryptoConvertUtf8ToUnicode(str);
+#else /* UNICODE */
+ return xmlSecMSCryptoConvertUtf8ToLocale(str);
+#endif /* UNICODE */
+}
+
+/********************************************************************
+ *
+ * Crypto Providers
+ *
+ ********************************************************************/
+/**
+ * xmlSecMSCryptoFindProvider:
+ * @providers: the pointer to list of providers, last provider should have NULL for name.
+ * @pszContainer: the container name for CryptAcquireContext call
+ * @dwFlags: the flags for CryptAcquireContext call
+ * @bUseXmlSecContainer: the flag to indicate whether we should try to use XmlSec container if default fails
+ *
+ * Finds the first provider from the list
+ *
+ * Returns: provider handle on success or NULL for error.
+ */
+HCRYPTPROV
+xmlSecMSCryptoFindProvider(const xmlSecMSCryptoProviderInfo * providers,
+ LPCTSTR pszContainer,
+ DWORD dwFlags,
+ BOOL bUseXmlSecContainer)
+{
+ HCRYPTPROV res = 0;
+ DWORD dwLastError;
+ BOOL ret;
+ int ii;
+
+ xmlSecAssert2(providers != NULL, 0);
+
+ for(ii = 0; (res == 0) && (providers[ii].providerName != NULL) && (providers[ii].providerType != 0); ++ii) {
+ /* first try */
+ ret = CryptAcquireContext(&res,
+ pszContainer,
+ providers[ii].providerName,
+ providers[ii].providerType,
+ dwFlags);
+ if((ret == TRUE) && (res != 0)) {
+ return (res);
+ }
+
+ /* check errors */
+ dwLastError = GetLastError();
+ switch(dwLastError) {
+ case 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)
+ */
+ ret = CryptAcquireContext(&res,
+ pszContainer,
+ providers[ii].providerName,
+ providers[ii].providerType,
+ CRYPT_NEWKEYSET | dwFlags);
+ if((ret == TRUE) && (res != 0)) {
+ return (res);
+ }
+ break;
+
+ case NTE_EXISTS:
+ /* If we can, try our container */
+ if(bUseXmlSecContainer == TRUE) {
+ ret = CryptAcquireContext(&res,
+ XMLSEC_CONTAINER_NAME,
+ providers[ii].providerName,
+ providers[ii].providerType,
+ CRYPT_NEWKEYSET | dwFlags);
+ if((ret == TRUE) && (res != 0)) {
+ /* ALEKSEY TODO - NEED TO DELETE ALL THE TEMP CONTEXTS ON SHUTDOWN
+
+ CryptAcquireContext(&tmp, XMLSEC_CONTAINER_NAME,
+ providers[ii].providerName,
+ providers[ii].providerType,
+ CRYPT_DELETEKEYSET);
+
+ */
+ return (res);
+ }
+ }
+ break;
+
+ default:
+ /* ignore */
+ break;
+ }
+ }
+
+ return (0);
+}
+
+
+/********************************************************************
+ *
+ * Utils
+ *
+ ********************************************************************/
+int
+ConvertEndian(const xmlSecByte * src, xmlSecByte * dst, xmlSecSize size) {
+ xmlSecByte * p;
+
+ xmlSecAssert2(src != NULL, -1);
+ xmlSecAssert2(dst != NULL, -1);
+ xmlSecAssert2(size > 0, -1);
+
+ for(p = dst + size - 1; p >= dst; ++src, --p) {
+ (*p) = (*src);
+ }
+
+ return (0);
+}
+
+int
+ConvertEndianInPlace(xmlSecByte * buf, xmlSecSize size) {
+ xmlSecByte * p;
+ xmlSecByte ch;
+
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(size > 0, -1);
+
+ for(p = buf + size - 1; p >= buf; ++buf, --p) {
+ ch = (*p);
+ (*p) = (*buf);
+ (*buf) = ch;
+ }
+ return (0);
+}
+
+
diff --git a/src/mscrypto/csp_calg.h b/src/mscrypto/csp_calg.h
new file mode 100644
index 00000000..984fe347
--- /dev/null
+++ b/src/mscrypto/csp_calg.h
@@ -0,0 +1,105 @@
+/**
+ * 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 MAGPRO_CSP_A "MagPro CSP"
+#define MAGPRO_CSP_W L"MagPro CSP"
+#ifdef UNICODE
+#define MAGPRO_CSP MAGPRO_CSP_W
+#else
+#define MAGPRO_CSP MAGPRO_CSP_A
+#endif
+
+#define PROV_CRYPTOPRO_GOST 75
+#define CRYPTOPRO_CSP_A "CryptoPro CSP"
+#define CRYPTOPRO_CSP_W L"CryptoPro CSP"
+#ifdef UNICODE
+#define CRYPTOPRO_CSP CRYPTOPRO_CSP_W
+#else
+#define CRYPTOPRO_CSP CRYPTOPRO_CSP_A
+#endif
+
+/*! @} */
+/*! \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..e5636741
--- /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..9394afdc
--- /dev/null
+++ b/src/mscrypto/digests.c
@@ -0,0 +1,668 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+#define MSCRYPTO_MAX_HASH_SIZE 256
+
+typedef struct _xmlSecMSCryptoDigestCtx xmlSecMSCryptoDigestCtx, *xmlSecMSCryptoDigestCtxPtr;
+struct _xmlSecMSCryptoDigestCtx {
+ HCRYPTPROV provider;
+ ALG_ID alg_id;
+ const xmlSecMSCryptoProviderInfo * providers;
+ 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);
+
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Sha1[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { MS_DEF_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Sha2[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { NULL, 0 }
+};
+
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Md5[] = {
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { MS_DEF_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+
+#ifndef XMLSEC_NO_GOST
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost[] = {
+ { MAGPRO_CSP, PROV_MAGPRO_GOST },
+ { CRYPTOPRO_CSP, PROV_CRYPTOPRO_GOST },
+ { NULL, 0 }
+};
+#endif /*ndef XMLSEC_NO_GOST*/
+
+static int
+xmlSecMSCryptoDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+#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_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformMd5Id)) {
+ ctx->alg_id = CALG_MD5;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Md5;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha1Id)) {
+ ctx->alg_id = CALG_SHA1;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Sha1;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha256Id)) {
+ ctx->alg_id = CALG_SHA_256;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Sha2;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha384Id)) {
+ ctx->alg_id = CALG_SHA_384;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Sha2;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha512Id)) {
+ ctx->alg_id = CALG_SHA_512;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Sha2;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_GOST
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) {
+ ctx->alg_id = CALG_MAGPRO_HASH_R3411_94;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Gost;
+ } else
+#endif /* XMLSEC_NO_GOST*/
+
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->provider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(ctx->provider == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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);
+ }
+ if(ctx->provider != 0) {
+ 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)),
+ "CryptCreateHash",
+ 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(HP_HASHVAL)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", MSCRYPTO_MAX_HASH_SIZE);
+ 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_MD5
+/******************************************************************************
+ *
+ * MD5
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoDigestSize, /* size_t objSize */
+
+ xmlSecNameMd5, /* const xmlChar* name; */
+ xmlSecHrefMd5, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformMd5GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformMd5GetKlass(void) {
+ return(&xmlSecMSCryptoMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+#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_SHA256
+/******************************************************************************
+ *
+ * SHA256
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoDigestSize, /* size_t objSize */
+
+ xmlSecNameSha256, /* const xmlChar* name; */
+ xmlSecHrefSha256, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformSha256GetKlass:
+ *
+ * SHA-256 digest transform klass.
+ *
+ * Returns: pointer to SHA-256 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformSha256GetKlass(void) {
+ return(&xmlSecMSCryptoSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * SHA384
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoDigestSize, /* size_t objSize */
+
+ xmlSecNameSha384, /* const xmlChar* name; */
+ xmlSecHrefSha384, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformSha384GetKlass:
+ *
+ * SHA-384 digest transform klass.
+ *
+ * Returns: pointer to SHA-384 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformSha384GetKlass(void) {
+ return(&xmlSecMSCryptoSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * SHA512
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* size_t klassSize */
+ xmlSecMSCryptoDigestSize, /* size_t objSize */
+
+ xmlSecNameSha512, /* const xmlChar* name; */
+ xmlSecHrefSha512, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformSha512GetKlass:
+ *
+ * SHA-512 digest transform klass.
+ *
+ * Returns: pointer to SHA-512 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformSha512GetKlass(void) {
+ return(&xmlSecMSCryptoSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+#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..2b88d5dd
--- /dev/null
+++ b/src/mscrypto/globals.h
@@ -0,0 +1,39 @@
+/*
+ * XML Security Library
+ *
+ * THIS IS A PRIVATE XMLSEC HEADER FILE
+ * DON'T USE IT IN YOUR APPLICATION
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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
+
+/* OpenSSL 0.9.6 and 0.9.7 do not have SHA 224/256/384/512 */
+#if defined(XMLSEC_OPENSSL_096) || defined(XMLSEC_OPENSSL_097)
+#define XMLSEC_NO_SHA224 1
+#define XMLSEC_NO_SHA256 1
+#define XMLSEC_NO_SHA384 1
+#define XMLSEC_NO_SHA512 1
+#endif /* defined(XMLSEC_OPENSSL_096) || defined(XMLSEC_OPENSSL_097) */
+
+/* OpenSSL 0.9.6 does not have AES */
+#if defined(XMLSEC_OPENSSL_096)
+#define XMLSEC_NO_AES 1
+#endif /* XMLSEC_OPENSSL_096 */
+
+
+#endif /* ! __XMLSEC_GLOBALS_H__ */
diff --git a/src/mscrypto/hmac.c b/src/mscrypto/hmac.c
new file mode 100644
index 00000000..e8709838
--- /dev/null
+++ b/src/mscrypto/hmac.c
@@ -0,0 +1,963 @@
+/**
+ *
+ * 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 <windows.h>
+#include <wincrypt.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/mscrypto/crypto.h>
+#include "private.h"
+
+/* sizes in bits */
+#define XMLSEC_MSCRYPTO_MIN_HMAC_SIZE 80
+#define XMLSEC_MSCRYPTO_MAX_HMAC_SIZE 256
+
+/**************************************************************************
+ *
+ * Configuration
+ *
+ *****************************************************************************/
+static int g_xmlsec_mscrypto_hmac_min_length = XMLSEC_MSCRYPTO_MIN_HMAC_SIZE;
+
+/**
+ * xmlSecMSCryptoHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecMSCryptoHmacGetMinOutputLength(void)
+{
+ return g_xmlsec_mscrypto_hmac_min_length;
+}
+
+/**
+ * xmlSecMSCryptoHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecMSCryptoHmacSetMinOutputLength(int min_length)
+{
+ g_xmlsec_mscrypto_hmac_min_length = min_length;
+}
+
+/******************************************************************************
+ *
+ * Internal MSCrypto HMAC CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecMSCryptoHmacCtx xmlSecMSCryptoHmacCtx, *xmlSecMSCryptoHmacCtxPtr;
+struct _xmlSecMSCryptoHmacCtx {
+ HCRYPTPROV provider;
+ HCRYPTKEY cryptKey;
+ HCRYPTKEY pubPrivKey;
+ ALG_ID alg_id;
+ const xmlSecMSCryptoProviderInfo * providers;
+ HCRYPTHASH mscHash;
+ unsigned char dgst[XMLSEC_MSCRYPTO_MAX_HMAC_SIZE];
+ size_t dgstSize; /* dgst size in bytes */
+ int ctxInitialized;
+};
+
+/******************************************************************************
+ *
+ * HMAC transforms
+ *
+ * xmlSecMSCryptoHmacCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecMSCryptoHmacGetCtx(transform) \
+ ((xmlSecMSCryptoHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecMSCryptoHmacSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoHmacCtx))
+
+static int xmlSecMSCryptoHmacCheckId (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoHmacInitialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoHmacFinalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoHmacNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoHmacSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoHmacSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoHmacVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoHmacExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Hmac[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { MS_DEF_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+
+static int
+xmlSecMSCryptoHmacCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+ /* not found */
+ {
+ return(0);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoHmacInitialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
+
+ ctx = xmlSecMSCryptoHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecMSCryptoHmacCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha1Id)) {
+ ctx->alg_id = CALG_SHA1;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha256Id)) {
+ ctx->alg_id = CALG_SHA_256;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha384Id)) {
+ ctx->alg_id = CALG_SHA_384;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha512Id)) {
+ ctx->alg_id = CALG_SHA_512;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacMd5Id)) {
+ ctx->alg_id = CALG_MD5;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+ /* not found */
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->provider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(ctx->provider == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* Create dummy key to be able to import plain session keys */
+ if (!xmlSecMSCryptoCreatePrivateExponentOneKey(ctx->provider, &(ctx->pubPrivKey))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoCreatePrivateExponentOneKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecMSCryptoHmacFinalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoHmacCtxPtr ctx;
+
+ xmlSecAssert(xmlSecMSCryptoHmacCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize));
+
+ ctx = xmlSecMSCryptoHmacGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->mscHash != 0) {
+ CryptDestroyHash(ctx->mscHash);
+ }
+ if (ctx->cryptKey) {
+ CryptDestroyKey(ctx->cryptKey);
+ }
+ if (ctx->pubPrivKey) {
+ CryptDestroyKey(ctx->pubPrivKey);
+ }
+ if(ctx->provider != 0) {
+ CryptReleaseContext(ctx->provider, 0);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoHmacCtx));
+}
+
+static int
+xmlSecMSCryptoHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoHmacCtxPtr ctx;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
+ xmlSecAssert2(node!= NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) {
+ xmlChar *content;
+
+ content = xmlNodeGetContent(cur);
+ if(content != NULL) {
+ ctx->dgstSize = atoi((char*)content);
+ xmlFree(content);
+ }
+
+ /* Ensure that HMAC length is greater than min specified.
+ Otherwise, an attacker can set this length to 0 or very
+ small value
+ */
+ if((int)ctx->dgstSize < xmlSecMSCryptoHmacGetMinOutputLength()) {
+ 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
+xmlSecMSCryptoHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecMSCryptoKeyDataHmacId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoHmacCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+ HMAC_INFO hmacInfo;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecMSCryptoHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized == 0, -1);
+ xmlSecAssert2(ctx->provider != 0, -1);
+ xmlSecAssert2(ctx->pubPrivKey != 0, -1);
+ xmlSecAssert2(ctx->cryptKey == 0, -1);
+ xmlSecAssert2(ctx->mscHash == 0, -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecMSCryptoKeyDataHmacId), -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);
+
+ /* Import this key and get an HCRYPTKEY handle.
+ *
+ * HACK!!! HACK!!! HACK!!!
+ *
+ * Using CALG_RC2 instead of CALG_HMAC for the key algorithm so we don't want to check key length
+ */
+ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->provider,
+ ctx->pubPrivKey,
+ CALG_RC2,
+ xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer),
+ FALSE,
+ &(ctx->cryptKey)
+ ) || (ctx->cryptKey == 0)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* create hash */
+ ret = CryptCreateHash(ctx->provider,
+ CALG_HMAC,
+ ctx->cryptKey,
+ 0,
+ &(ctx->mscHash));
+ if((ret == 0) || (ctx->mscHash == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptCreateHash",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set parameters */
+ memset(&hmacInfo, 0, sizeof(hmacInfo));
+ hmacInfo.HashAlgid = ctx->alg_id;
+ ret = CryptSetHashParam(ctx->mscHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0);
+ if(ret == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "CryptSetHashParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* done */
+ ctx->ctxInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecMSCryptoHmacVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ static xmlSecByte last_byte_masks[] =
+ { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+
+ xmlSecMSCryptoHmacCtxPtr ctx;
+ xmlSecByte mask;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoHmacGetCtx(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
+xmlSecMSCryptoHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoHmacCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecMSCryptoHmacGetCtx(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) {
+ 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 = XMLSEC_MSCRYPTO_MAX_HMAC_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);
+ }
+ xmlSecAssert2(retLen > 0, -1);
+
+ /* check/set the result digest size */
+ if(ctx->dgstSize == 0) {
+ ctx->dgstSize = retLen * 8; /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= 8 * retLen) {
+ retLen = ((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 * retLen, ctx->dgstSize);
+ return(-1);
+ }
+
+ /* copy result to output */
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = xmlSecBufferAppend(out, ctx->dgst, retLen);
+ 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
+/******************************************************************************
+ *
+ * HMAC MD5
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacMd5, /* const xmlChar* name; */
+ xmlSecHrefHmacMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacMd5GetKlass(void) {
+ return(&xmlSecMSCryptoHmacMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_RIPEMD160
+/******************************************************************************
+ *
+ * HMAC RIPEMD160
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacRipemd160, /* const xmlChar* name; */
+ xmlSecHrefHmacRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacRipemd160GetKlass(void) {
+ return(&xmlSecMSCryptoHmacRipemd160Klass);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * HMAC SHA1
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha1, /* const xmlChar* name; */
+ xmlSecHrefHmacSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacSha1GetKlass(void) {
+ return(&xmlSecMSCryptoHmacSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+/******************************************************************************
+ *
+ * HMAC SHA224
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacSha224Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha224, /* const xmlChar* name; */
+ xmlSecHrefHmacSha224, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacSha224GetKlass:
+ *
+ * The HMAC-SHA224 transform klass.
+ *
+ * Returns: the HMAC-SHA224 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacSha224GetKlass(void) {
+ return(&xmlSecMSCryptoHmacSha224Klass);
+}
+
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * HMAC SHA256
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha256, /* const xmlChar* name; */
+ xmlSecHrefHmacSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacSha256GetKlass(void) {
+ return(&xmlSecMSCryptoHmacSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * HMAC SHA384
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha384, /* const xmlChar* name; */
+ xmlSecHrefHmacSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacSha384GetKlass(void) {
+ return(&xmlSecMSCryptoHmacSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * HMAC SHA512
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoHmacSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha512, /* const xmlChar* name; */
+ xmlSecHrefHmacSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecMSCryptoHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecMSCryptoHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecMSCryptoHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformHmacSha512GetKlass(void) {
+ return(&xmlSecMSCryptoHmacSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+
+#endif /* XMLSEC_NO_HMAC */
+
diff --git a/src/mscrypto/keysstore.c b/src/mscrypto/keysstore.c
new file mode 100644
index 00000000..33f0cd27
--- /dev/null
+++ b/src/mscrypto/keysstore.c
@@ -0,0 +1,620 @@
+/**
+ * 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.
+ *
+ * Copyright (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>
+#include "private.h"
+
+#define XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME_A "MY"
+#define XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME_W L"MY"
+#ifdef UNICODE
+#define XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME_W
+#else /* UNICODE */
+#define XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME XMLSEC_MSCRYPTO_APP_DEFAULT_CERT_STORE_NAME_A
+#endif /* UNICODE */
+
+/****************************************************************************
+ *
+ * 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) {
+ LPCTSTR storeName;
+ HCERTSTORE hStoreHandle = NULL;
+ PCCERT_CONTEXT pCertContext = NULL;
+ LPTSTR wcName = 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);
+ }
+
+ /* convert name to unicode */
+ wcName = xmlSecMSCryptoConvertUtf8ToTstr(name);
+ if(wcName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecMSCryptoConvertUtf8ToUnicode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "wcName");
+ CertCloseStore(hStoreHandle, 0);
+ return(NULL);
+ }
+
+ /* first attempt: try to find the cert with a full blown subject dn */
+ if(NULL == pCertContext) {
+ pCertContext = xmlSecMSCryptoX509FindCertBySubject(
+ hStoreHandle,
+ wcName,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING);
+ }
+
+ /*
+ * Try ro find certificate with name="Friendly Name"
+ */
+ if (NULL == pCertContext) {
+ DWORD dwPropSize;
+ PBYTE pbFriendlyName;
+ PCCERT_CONTEXT pCertCtxIter = NULL;
+
+
+ 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(wcName);
+ CertCloseStore(hStoreHandle, 0);
+ return(NULL);
+ }
+
+ if (TRUE != CertGetCertificateContextProperty(pCertCtxIter,
+ CERT_FRIENDLY_NAME_PROP_ID,
+ pbFriendlyName,
+ &dwPropSize)) {
+ xmlFree(pbFriendlyName);
+ continue;
+ }
+
+ /* Compare FriendlyName to name */
+ if (!lstrcmp(wcName, (LPCTSTR)pbFriendlyName)) {
+ pCertContext = pCertCtxIter;
+ xmlFree(pbFriendlyName);
+ break;
+ }
+ xmlFree(pbFriendlyName);
+ }
+ }
+
+ /* We don't give up easily, now try to find cert with part of the name
+ */
+ if (NULL == pCertContext) {
+ pCertContext = CertFindCertificateInStore(
+ hStoreHandle,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_STR,
+ wcName,
+ NULL);
+ }
+
+
+ /* 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? */
+ xmlFree(wcName);
+ 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..9b4908fa
--- /dev/null
+++ b/src/mscrypto/kt_rsa.c
@@ -0,0 +1,631 @@
+/**
+ *
+ * XMLSec library
+ *
+ * RSA Algorithms support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+/**************************************************************************
+ *
+ * Internal MSCRYPTO RSA PKCS1 CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecMSCryptoRsaPkcs1OaepCtx xmlSecMSCryptoRsaPkcs1OaepCtx,
+ *xmlSecMSCryptoRsaPkcs1OaepCtxPtr;
+struct _xmlSecMSCryptoRsaPkcs1OaepCtx {
+ DWORD dwFlags;
+ xmlSecKeyDataPtr data;
+ xmlSecBuffer oaepParams;
+};
+
+/*********************************************************************
+ *
+ * RSA PKCS1 key transport transform
+ *
+ * xmlSecMSCryptoRsaPkcs1OaepCtx is located after xmlSecTransform
+ *
+ ********************************************************************/
+#define xmlSecMSCryptoRsaPkcs1OaepCtx \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoRsaPkcs1OaepCtx))
+#define xmlSecMSCryptoRsaPkcs1OaepGetCtx(transform) \
+ ((xmlSecMSCryptoRsaPkcs1OaepCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecMSCryptoRsaPkcs1OaepCheckId (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoRsaPkcs1OaepInitialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoRsaPkcs1OaepFinalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoRsaPkcs1OaepSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoRsaPkcs1OaepSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoRsaPkcs1OaepExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoRsaPkcs1OaepProcess (xmlSecTransformPtr transform,
+ xmlSecTransformCtxPtr transformCtx);
+
+
+static int
+xmlSecMSCryptoRsaPkcs1OaepCheckId(xmlSecTransformPtr transform) {
+
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id)) {
+ return(1);
+ } else
+
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaOaepId)) {
+ return(1);
+ } else
+
+ /* not found */
+ {
+ return(0);
+ }
+
+ /* just in case */
+ return(0);
+}
+
+static int
+xmlSecMSCryptoRsaPkcs1OaepInitialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx), -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize */
+ memset(ctx, 0, sizeof(xmlSecMSCryptoRsaPkcs1OaepCtx));
+
+ 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);
+ }
+
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaPkcs1Id)) {
+ ctx->dwFlags = 0;
+ } else
+
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaOaepId)) {
+ ctx->dwFlags = CRYPT_OAEP;
+ } else
+
+ /* not found */
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* done */
+ return(0);
+}
+
+static void
+xmlSecMSCryptoRsaPkcs1OaepFinalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+
+ xmlSecAssert(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx));
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->data != NULL) {
+ xmlSecKeyDataDestroy(ctx->data);
+ ctx->data = NULL;
+ }
+
+ xmlSecBufferFinalize(&(ctx->oaepParams));
+ memset(ctx, 0, sizeof(xmlSecMSCryptoRsaPkcs1OaepCtx));
+}
+
+static int
+xmlSecMSCryptoRsaPkcs1OaepSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(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
+xmlSecMSCryptoRsaPkcs1OaepSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataRsaId), -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(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
+xmlSecMSCryptoRsaPkcs1OaepExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(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 = xmlSecMSCryptoRsaPkcs1OaepProcess(transform, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoRsaPkcs1OaepProcess",
+ 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
+xmlSecMSCryptoRsaPkcs1OaepProcess(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ xmlSecSize keySize;
+ int ret;
+ HCRYPTKEY hKey = 0;
+ DWORD dwInLen;
+ DWORD dwBufLen;
+ DWORD dwOutLen;
+ xmlSecByte * outBuf;
+ xmlSecByte * inBuf;
+ int i;
+
+ xmlSecAssert2(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(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) {
+ 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);
+
+ /* set OAEP parameter for the key
+ *
+ * aleksey: I don't understand how this would work in multi-threaded
+ * environment or when key can be re-used multiple times
+ */
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaOaepId) && xmlSecBufferGetSize(&(ctx->oaepParams)) > 0) {
+ CRYPT_DATA_BLOB oaepParams;
+
+ memset(&oaepParams, 0, sizeof(oaepParams));
+ oaepParams.pbData = xmlSecBufferGetData(&(ctx->oaepParams));
+ oaepParams.cbData = xmlSecBufferGetSize(&(ctx->oaepParams));
+
+ if (!CryptSetKeyParam(hKey, KP_OAEP_PARAMS, (const BYTE*)&oaepParams, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+ }
+
+ /* encrypt */
+ if (!CryptEncrypt(hKey, 0, TRUE, ctx->dwFlags, 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.
+ */
+ ConvertEndianInPlace(outBuf, outSize);
+ } 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);
+ ConvertEndian(inBuf, outBuf, inSize);
+
+ if (0 == (hKey = xmlSecMSCryptoKeyDataGetDecryptKey(ctx->data))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoKeyDataGetKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+
+ /* set OAEP parameter for the key
+ *
+ * aleksey: I don't understand how this would work in multi-threaded
+ * environment or when key can be re-used multiple times
+ */
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaOaepId) && xmlSecBufferGetSize(&(ctx->oaepParams)) > 0) {
+ CRYPT_DATA_BLOB oaepParams;
+
+ memset(&oaepParams, 0, sizeof(oaepParams));
+ oaepParams.pbData = xmlSecBufferGetData(&(ctx->oaepParams));
+ oaepParams.cbData = xmlSecBufferGetSize(&(ctx->oaepParams));
+
+ if (!CryptSetKeyParam(hKey, KP_OAEP_PARAMS, (const BYTE*)&oaepParams, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (-1);
+ }
+ }
+
+ /* decrypt */
+ if (!CryptDecrypt(hKey, 0, TRUE, ctx->dwFlags, 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);
+}
+
+
+/**********************************************************************
+ *
+ * RSA/PKCS1 transform
+ *
+ **********************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaPkcs1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoRsaPkcs1OaepCtx, /* xmlSecSize objSize */
+
+ xmlSecNameRsaPkcs1, /* const xmlChar* name; */
+ xmlSecHrefRsaPkcs1, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoRsaPkcs1OaepInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoRsaPkcs1OaepFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoRsaPkcs1OaepSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoRsaPkcs1OaepSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoRsaPkcs1OaepExecute, /* 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);
+}
+
+
+
+/**********************************************************************
+ *
+ * RSA/OAEP transform
+ *
+ **********************************************************************/
+static int xmlSecMSCryptoRsaOaepNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecMSCryptoRsaOaepKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoRsaPkcs1OaepCtx, /* xmlSecSize objSize */
+
+ xmlSecNameRsaOaep, /* const xmlChar* name; */
+ xmlSecHrefRsaOaep, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoRsaPkcs1OaepInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoRsaPkcs1OaepFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecMSCryptoRsaOaepNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoRsaPkcs1OaepSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoRsaPkcs1OaepSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoRsaPkcs1OaepExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+
+/**
+ * xmlSecMSCryptoTransformRsaOaepGetKlass:
+ *
+ * The RSA-OAEP key transport transform klass.
+ *
+ * Returns: RSA-OAEP key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaOaepGetKlass(void) {
+ return(&xmlSecMSCryptoRsaOaepKlass);
+}
+
+static int
+xmlSecMSCryptoRsaOaepNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoRsaPkcs1OaepCtxPtr ctx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoRsaPkcs1OaepCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoRsaPkcs1OaepCtx), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoRsaPkcs1OaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->oaepParams)) == 0, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ while(cur != NULL) {
+ if(xmlSecCheckNodeName(cur, xmlSecNodeRsaOAEPparams, xmlSecEncNs)) {
+ ret = xmlSecBufferBase64NodeContentRead(&(ctx->oaepParams), cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferBase64NodeContentRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs)) {
+ xmlChar* algorithm;
+
+ /* Algorithm attribute is required */
+ algorithm = xmlGetProp(cur, xmlSecAttrAlgorithm);
+ if(algorithm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ /* for now we support only sha1 */
+ if(xmlStrcmp(algorithm, xmlSecHrefSha1) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(algorithm),
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "digest algorithm is not supported for rsa/oaep");
+ xmlFree(algorithm);
+ return(-1);
+ }
+ xmlFree(algorithm);
+ } else {
+ /* not found */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* next node */
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_NO_RSA */
+
diff --git a/src/mscrypto/kw_aes.c b/src/mscrypto/kw_aes.c
new file mode 100644
index 00000000..14e96d5a
--- /dev/null
+++ b/src/mscrypto/kw_aes.c
@@ -0,0 +1,662 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+
+#include "../kw_aes_des.h"
+#include "private.h"
+
+
+#ifndef XMLSEC_NO_AES
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecMSCryptoKWAesBlockEncrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * cb_ctx);
+static int xmlSecMSCryptoKWAesBlockDecrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * cb_ctx);
+
+/* klass for KW AES operation */
+static xmlSecKWAesKlass xmlSecMSCryptoKWAesKlass = {
+ /* callbacks */
+ xmlSecMSCryptoKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */
+ xmlSecMSCryptoKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL /* void* reserved1; */
+};
+
+/**************************************************************************
+ *
+ * Internal MSCrypto KW AES cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecMSCryptoKWAesCtx xmlSecMSCryptoKWAesCtx,
+ *xmlSecMSCryptoKWAesCtxPtr;
+struct _xmlSecMSCryptoKWAesCtx {
+ ALG_ID algorithmIdentifier;
+ const xmlSecMSCryptoProviderInfo * providers;
+ xmlSecKeyDataId keyId;
+ xmlSecSize keySize;
+
+ HCRYPTPROV cryptProvider;
+ HCRYPTKEY pubPrivKey;
+ xmlSecBuffer keyBuffer;
+};
+
+/******************************************************************************
+ *
+ * KW AES transforms
+ *
+ * xmlSecMSCryptoKWAesCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecMSCryptoKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoKWAesCtx))
+#define xmlSecMSCryptoKWAesGetCtx(transform) \
+ ((xmlSecMSCryptoKWAesCtxPtr)(((unsigned char*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecMSCryptoKWAesInitialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoKWAesFinalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoKWAesSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoKWAesSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoKWAesExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecMSCryptoKWAesCheckId (xmlSecTransformPtr transform);
+
+
+
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Aes[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { NULL, 0 }
+};
+
+static int
+xmlSecMSCryptoKWAesCheckId(xmlSecTransformPtr transform) {
+
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWAes128Id) ||
+ xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWAes192Id) ||
+ xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWAes256Id)) {
+
+ return(1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKWAesInitialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoKWAesCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWAesSize), -1);
+
+ ctx = xmlSecMSCryptoKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoKWAesCtx));
+
+ if(transform->id == xmlSecMSCryptoTransformKWAes128Id) {
+ ctx->algorithmIdentifier = CALG_AES_128;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Aes;
+ ctx->keySize = XMLSEC_KW_AES128_KEY_SIZE;
+ } else if(transform->id == xmlSecMSCryptoTransformKWAes192Id) {
+ ctx->algorithmIdentifier = CALG_AES_192;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Aes;
+ ctx->keySize = XMLSEC_KW_AES192_KEY_SIZE;
+ } else if(transform->id == xmlSecMSCryptoTransformKWAes256Id) {
+ ctx->algorithmIdentifier = CALG_AES_256;
+ ctx->keyId = xmlSecMSCryptoKeyDataAesId;
+ ctx->providers = xmlSecMSCryptoProviderInfo_Aes;
+ ctx->keySize = XMLSEC_KW_AES256_KEY_SIZE;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&ctx->keyBuffer, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* find provider */
+ ctx->cryptProvider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(ctx->cryptProvider == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoFindProvider",
+ XMLSEC_ERRORS_R_XMLSEC_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);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecMSCryptoKWAesFinalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoKWAesCtxPtr ctx;
+
+ xmlSecAssert(xmlSecMSCryptoKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWAesSize));
+
+ ctx = xmlSecMSCryptoKWAesGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->pubPrivKey) {
+ CryptDestroyKey(ctx->pubPrivKey);
+ }
+ if (ctx->cryptProvider) {
+ CryptReleaseContext(ctx->cryptProvider, 0);
+ }
+
+ xmlSecBufferFinalize(&ctx->keyBuffer);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoKWAesCtx));
+}
+
+static int
+xmlSecMSCryptoKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecMSCryptoKWAesCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecMSCryptoKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecMSCryptoKWAesGetCtx(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
+xmlSecMSCryptoKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoKWAesCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWAesSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataAesId), -1);
+
+ ctx = xmlSecMSCryptoKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < ctx->keySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, ctx->keySize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer),
+ xmlSecBufferGetData(buffer),
+ ctx->keySize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d",
+ ctx->keySize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoKWAesCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecMSCryptoKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % 8) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d(not 8 bytes aligned)", inSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+ outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_KW_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWAesEncode(&xmlSecMSCryptoKWAesKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWAesDecode(&xmlSecMSCryptoKWAesKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "inSize%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ ********************************************************************/
+static int
+xmlSecMSCryptoKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ xmlSecMSCryptoKWAesCtxPtr ctx = (xmlSecMSCryptoKWAesCtxPtr)context;
+ HCRYPTKEY cryptKey = 0;
+ DWORD dwCLen;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pubPrivKey != 0, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&ctx->keyBuffer) == ctx->keySize, -1);
+
+ /* Import this key and get an HCRYPTKEY handle, we do it again and again
+ to ensure we don't go into CBC mode */
+ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->cryptProvider,
+ ctx->pubPrivKey,
+ ctx->algorithmIdentifier,
+ xmlSecBufferGetData(&ctx->keyBuffer),
+ xmlSecBufferGetSize(&ctx->keyBuffer),
+ TRUE,
+ &cryptKey)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(cryptKey != 0, -1);
+
+ /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+ * can be skipped. I hope this will work .... */
+ if(out != in) {
+ memcpy(out, in, inSize);
+ }
+ dwCLen = inSize;
+ if(!CryptEncrypt(cryptKey, 0, FALSE, 0, out, &dwCLen, outSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* cleanup */
+ CryptDestroyKey(cryptKey);
+ return(dwCLen);
+}
+
+static int
+xmlSecMSCryptoKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ xmlSecMSCryptoKWAesCtxPtr ctx = (xmlSecMSCryptoKWAesCtxPtr)context;
+ HCRYPTKEY cryptKey = 0;
+ DWORD dwCLen;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pubPrivKey != 0, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&ctx->keyBuffer) == ctx->keySize, -1);
+
+ /* Import this key and get an HCRYPTKEY handle, we do it again and again
+ to ensure we don't go into CBC mode */
+ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->cryptProvider,
+ ctx->pubPrivKey,
+ ctx->algorithmIdentifier,
+ xmlSecBufferGetData(&ctx->keyBuffer),
+ xmlSecBufferGetSize(&ctx->keyBuffer),
+ TRUE,
+ &cryptKey)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(cryptKey != 0, -1);
+
+ /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+ * can be skipped. I hope this will work .... */
+ if(out != in) {
+ memcpy(out, in, inSize);
+ }
+ dwCLen = inSize;
+ if(!CryptDecrypt(cryptKey, 0, FALSE, 0, out, &dwCLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* cleanup */
+ CryptDestroyKey(cryptKey);
+ return(dwCLen);
+}
+
+/*********************************************************************
+ *
+ * AES KW cipher transforms
+ *
+ ********************************************************************/
+
+/*
+ * The AES-128 kew wrapper transform klass.
+ */
+static xmlSecTransformKlass xmlSecMSCryptoKWAes128Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes128, /* const xmlChar* name; */
+ xmlSecHrefKWAes128, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWAes128GetKlass(void) {
+ return(&xmlSecMSCryptoKWAes128Klass);
+}
+
+
+/*
+ * The AES-192 kew wrapper transform klass.
+ */
+static xmlSecTransformKlass xmlSecMSCryptoKWAes192Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes192, /* const xmlChar* name; */
+ xmlSecHrefKWAes192, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWAes192GetKlass(void) {
+ return(&xmlSecMSCryptoKWAes192Klass);
+}
+
+/*
+ * The AES-256 kew wrapper transform klass.
+ */
+static xmlSecTransformKlass xmlSecMSCryptoKWAes256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes256, /* const xmlChar* name; */
+ xmlSecHrefKWAes256, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWAes256GetKlass(void) {
+ return(&xmlSecMSCryptoKWAes256Klass);
+}
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/mscrypto/kw_des.c b/src/mscrypto/kw_des.c
new file mode 100644
index 00000000..6ef356d4
--- /dev/null
+++ b/src/mscrypto/kw_des.c
@@ -0,0 +1,730 @@
+/**
+ *
+ * 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 <windows.h>
+#include <wincrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscrypto/crypto.h>
+
+#include "../kw_aes_des.h"
+#include "private.h"
+
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecMSCryptoKWDes3GenerateRandom (void * context,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecMSCryptoKWDes3Sha1 (void * context,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecMSCryptoKWDes3BlockEncrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecMSCryptoKWDes3BlockDecrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+
+static xmlSecKWDes3Klass xmlSecMSCryptoKWDes3ImplKlass = {
+ /* callbacks */
+ xmlSecMSCryptoKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */
+ xmlSecMSCryptoKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */
+ xmlSecMSCryptoKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */
+ xmlSecMSCryptoKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+typedef struct _xmlSecMSCryptoKWDes3Ctx xmlSecMSCryptoKWDes3Ctx,
+ *xmlSecMSCryptoKWDes3CtxPtr;
+struct _xmlSecMSCryptoKWDes3Ctx {
+ ALG_ID desAlgorithmIdentifier;
+ const xmlSecMSCryptoProviderInfo * desProviders;
+ ALG_ID sha1AlgorithmIdentifier;
+ const xmlSecMSCryptoProviderInfo * sha1Providers;
+ xmlSecKeyDataId keyId;
+ xmlSecSize keySize;
+
+ HCRYPTPROV desCryptProvider;
+ HCRYPTPROV sha1CryptProvider;
+ HCRYPTKEY pubPrivKey;
+ xmlSecBuffer keyBuffer;
+};
+#define xmlSecMSCryptoKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoKWDes3Ctx))
+#define xmlSecMSCryptoKWDes3GetCtx(transform) \
+ ((xmlSecMSCryptoKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecMSCryptoKWDes3Initialize (xmlSecTransformPtr transform);
+static void xmlSecMSCryptoKWDes3Finalize (xmlSecTransformPtr transform);
+static int xmlSecMSCryptoKWDes3SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecMSCryptoKWDes3SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecMSCryptoKWDes3Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecMSCryptoKWDes3Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoKWDes3Size, /* xmlSecSize objSize */
+
+ xmlSecNameKWDes3, /* const xmlChar* name; */
+ xmlSecHrefKWDes3, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecMSCryptoKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecMSCryptoKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecMSCryptoKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecMSCryptoKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecMSCryptoKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWDes3GetKlass(void) {
+ return(&xmlSecMSCryptoKWDes3Klass);
+}
+
+/* Ordered list of providers to search for algorithm implementation using
+ * xmlSecMSCryptoFindProvider() function
+ *
+ * MUST END with { NULL, 0 } !!!
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Des[] = {
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Sha1[] = {
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
+ { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
+ { MS_STRONG_PROV, PROV_RSA_FULL },
+ { MS_ENHANCED_PROV, PROV_RSA_FULL },
+ { MS_DEF_PROV, PROV_RSA_FULL },
+ { NULL, 0 }
+};
+
+
+static int
+xmlSecMSCryptoKWDes3Initialize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWDes3Size), -1);
+
+ ctx = xmlSecMSCryptoKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoKWDes3Ctx));
+
+ if(transform->id == xmlSecMSCryptoTransformKWDes3Id) {
+ ctx->desAlgorithmIdentifier = CALG_3DES;
+ ctx->desProviders = xmlSecMSCryptoProviderInfo_Des;
+ ctx->sha1AlgorithmIdentifier = CALG_SHA1;
+ ctx->sha1Providers = xmlSecMSCryptoProviderInfo_Sha1;
+ ctx->keyId = xmlSecMSCryptoKeyDataDesId;
+ ctx->keySize = XMLSEC_KW_DES3_KEY_LENGTH;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* find providers */
+ ctx->desCryptProvider = xmlSecMSCryptoFindProvider(ctx->desProviders, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(ctx->desCryptProvider == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoFindProvider(des)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ ctx->sha1CryptProvider = xmlSecMSCryptoFindProvider(ctx->sha1Providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+ if(ctx->sha1CryptProvider == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoFindProvider(sha1)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ /* Create dummy key to be able to import plain session keys */
+ if (!xmlSecMSCryptoCreatePrivateExponentOneKey(ctx->desCryptProvider, &(ctx->pubPrivKey))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecMSCryptoCreatePrivateExponentOneKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecMSCryptoKWDes3Finalize(xmlSecTransformPtr transform) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWDes3Size));
+
+ ctx = xmlSecMSCryptoKWDes3GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->pubPrivKey) {
+ CryptDestroyKey(ctx->pubPrivKey);
+ }
+ if (ctx->desCryptProvider) {
+ CryptReleaseContext(ctx->desCryptProvider, 0);
+ }
+ if (ctx->sha1CryptProvider) {
+ CryptReleaseContext(ctx->sha1CryptProvider, 0);
+ }
+
+ xmlSecBufferFinalize(&ctx->keyBuffer);
+
+ memset(ctx, 0, sizeof(xmlSecMSCryptoKWDes3Ctx));
+}
+
+static int
+xmlSecMSCryptoKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecMSCryptoKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecMSCryptoKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWDes3Size), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataDesId), -1);
+
+ ctx = xmlSecMSCryptoKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key length %d is not enough (%d expected)",
+ keySize, XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecMSCryptoKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoKWDes3Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecMSCryptoKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d bytes - not %d bytes aligned",
+ inSize, XMLSEC_KW_DES3_BLOCK_LENGTH);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 16 bytes longer plus one block just in case */
+ outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH;
+ } else {
+ /* just in case, add a block */
+ outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWDes3Encode(&xmlSecMSCryptoKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWDes3Decode(&xmlSecMSCryptoKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecMSCryptoKWDes3Sha1(void * context,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx = (xmlSecMSCryptoKWDes3CtxPtr)context;
+ HCRYPTHASH mscHash = 0;
+ DWORD retLen;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->sha1CryptProvider != 0, -1);
+ xmlSecAssert2(ctx->sha1AlgorithmIdentifier != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ /* create */
+ ret = CryptCreateHash(ctx->sha1CryptProvider,
+ ctx->sha1AlgorithmIdentifier,
+ 0,
+ 0,
+ &mscHash);
+ if((ret == 0) || (mscHash == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptCreateHash",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* hash */
+ ret = CryptHashData(mscHash,
+ in,
+ inSize,
+ 0);
+ if(ret == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptHashData",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", inSize);
+ CryptDestroyHash(mscHash);
+ return(-1);
+ }
+
+ /* get results */
+ retLen = outSize;
+ ret = CryptGetHashParam(mscHash,
+ HP_HASHVAL,
+ out,
+ &retLen,
+ 0);
+ if (ret == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetHashParam(HP_HASHVAL)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ CryptDestroyHash(mscHash);
+ return(-1);
+ }
+
+ /* done */
+ CryptDestroyHash(mscHash);
+ return(retLen);
+}
+
+static int
+xmlSecMSCryptoKWDes3GenerateRandom(void * context,
+ xmlSecByte * out, xmlSecSize outSize)
+{
+ xmlSecMSCryptoKWDes3CtxPtr ctx = (xmlSecMSCryptoKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->desCryptProvider != 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ if(!CryptGenRandom(ctx->desCryptProvider, outSize, out)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGenRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "len=%d", outSize);
+ return(-1);
+ }
+
+ return((int)outSize);
+}
+
+static int
+xmlSecMSCryptoKWDes3BlockEncrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx = (xmlSecMSCryptoKWDes3CtxPtr)context;
+ DWORD dwBlockLen, dwBlockLenLen, dwCLen;
+ HCRYPTKEY cryptKey = 0;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ /* Import this key and get an HCRYPTKEY handle, we do it again and again
+ to ensure we don't go into CBC mode */
+ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->desCryptProvider,
+ ctx->pubPrivKey,
+ ctx->desAlgorithmIdentifier,
+ xmlSecBufferGetData(&ctx->keyBuffer),
+ xmlSecBufferGetSize(&ctx->keyBuffer),
+ TRUE,
+ &cryptKey)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(cryptKey != 0, -1);
+
+ /* iv len == block len */
+ dwBlockLenLen = sizeof(DWORD);
+ if (!CryptGetKeyParam(cryptKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwBlockLenLen, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* set IV */
+ if((ivSize < dwBlockLen / 8) || (!CryptSetKeyParam(cryptKey, KP_IV, iv, 0))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ivSize=%d, dwBlockLen=%d",
+ ivSize, dwBlockLen / 8);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+ * can be skipped. I hope this will work .... */
+ if(out != in) {
+ memcpy(out, in, inSize);
+ }
+ dwCLen = inSize;
+ if(!CryptEncrypt(cryptKey, 0, FALSE, 0, out, &dwCLen, outSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* cleanup */
+ CryptDestroyKey(cryptKey);
+ return(dwCLen);
+}
+
+static int
+xmlSecMSCryptoKWDes3BlockDecrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecMSCryptoKWDes3CtxPtr ctx = (xmlSecMSCryptoKWDes3CtxPtr)context;
+ DWORD dwBlockLen, dwBlockLenLen, dwCLen;
+ HCRYPTKEY cryptKey = 0;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ /* Import this key and get an HCRYPTKEY handle, we do it again and again
+ to ensure we don't go into CBC mode */
+ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->desCryptProvider,
+ ctx->pubPrivKey,
+ ctx->desAlgorithmIdentifier,
+ xmlSecBufferGetData(&ctx->keyBuffer),
+ xmlSecBufferGetSize(&ctx->keyBuffer),
+ TRUE,
+ &cryptKey)) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoImportPlainSessionBlob",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(cryptKey != 0, -1);
+
+ /* iv len == block len */
+ dwBlockLenLen = sizeof(DWORD);
+ if (!CryptGetKeyParam(cryptKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwBlockLenLen, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptGetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* set IV */
+ if((ivSize < dwBlockLen / 8) || (!CryptSetKeyParam(cryptKey, KP_IV, iv, 0))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptSetKeyParam",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ivSize=%d, dwBlockLen=%d",
+ ivSize, dwBlockLen / 8);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+ * can be skipped. I hope this will work .... */
+ if(out != in) {
+ memcpy(out, in, inSize);
+ }
+ dwCLen = inSize;
+ if(!CryptDecrypt(cryptKey, 0, FALSE, 0, out, &dwCLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CryptEncrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CryptDestroyKey(cryptKey);
+ return(-1);
+ }
+
+ /* cleanup */
+ CryptDestroyKey(cryptKey);
+ return(dwCLen);
+}
+
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/mscrypto/mingw-crypt32.def b/src/mscrypto/mingw-crypt32.def
new file mode 100644
index 00000000..4ba99b2f
--- /dev/null
+++ b/src/mscrypto/mingw-crypt32.def
@@ -0,0 +1,36 @@
+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
+ CertGetNameStringW@24 = crypt32.CertGetNameStringW
+ CertGetPublicKeyLength@8 = crypt32.CertGetPublicKeyLength
+ CertNameToStrA@20 = crypt32.CertNameToStrA
+ CertNameToStrW@20 = crypt32.CertNameToStrW
+ CertOpenStore@20 = crypt32.CertOpenStore
+ CertOpenSystemStoreA@8 = crypt32.CertOpenSystemStoreA
+ CertOpenSystemStoreW@8 = crypt32.CertOpenSystemStoreW
+ CertStrToNameA@28 = crypt32.CertStrToNameA
+ CertStrToNameW@28 = crypt32.CertStrToNameW
+ 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/private.h b/src/mscrypto/private.h
new file mode 100644
index 00000000..11479bff
--- /dev/null
+++ b/src/mscrypto/private.h
@@ -0,0 +1,130 @@
+/**
+ * XMLSec library
+ *
+ * THIS IS A PRIVATE XMLSEC HEADER FILE
+ * DON'T USE IT IN YOUR APPLICATION
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin, All rights reserved.
+ */
+#ifndef __XMLSEC_MSCRYPTO_PRIVATE_H__
+#define __XMLSEC_MSCRYPTO_PRIVATE_H__
+
+#ifndef XMLSEC_PRIVATE
+#error "private.h file contains private xmlsec definitions and should not be used outside xmlsec or xmlsec-<crypto> libraries"
+#endif /* XMLSEC_PRIVATE */
+
+#if defined(__MINGW32__)
+# include "xmlsec-mingw.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/********************************************************************
+ *
+ * Utils
+ *
+ ********************************************************************/
+int ConvertEndian (const xmlSecByte * src,
+ xmlSecByte * dst,
+ xmlSecSize size);
+int ConvertEndianInPlace (xmlSecByte * buf,
+ xmlSecSize size);
+
+/********************************************************************
+ *
+ * Crypto Providers
+ *
+ ********************************************************************/
+
+/* We need to redefine both to ensure that we can pick the right one at runtime (instead of compile time) */
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_A "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_W L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
+#ifdef UNICODE
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_W
+#else
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_A
+#endif
+
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_A "Microsoft Enhanced RSA and AES Cryptographic Provider"
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_W L"Microsoft Enhanced RSA and AES Cryptographic Provider"
+#ifdef UNICODE
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_W
+#else
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_A
+#endif
+
+/**
+ * xmlSecMSCryptoProviderInfo:
+ *
+ * Contains information for looking up provider from MS Crypto.
+ */
+typedef struct _xmlSecMSCryptoProviderInfo {
+ LPCTSTR providerName;
+ DWORD providerType;
+} xmlSecMSCryptoProviderInfo;
+
+HCRYPTPROV xmlSecMSCryptoFindProvider (const xmlSecMSCryptoProviderInfo * providers,
+ LPCTSTR pszContainer,
+ DWORD dwFlags,
+ BOOL bUseXmlSecContainer);
+
+
+/******************************************************************************
+ *
+ * SymKey Util functions
+ *
+ * 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
+ * and "Base Provider Key BLOBs" article for priv key blob format.
+ *
+ ******************************************************************************/
+BOOL xmlSecMSCryptoCreatePrivateExponentOneKey (HCRYPTPROV hProv,
+ HCRYPTKEY *hPrivateKey);
+
+BOOL xmlSecMSCryptoImportPlainSessionBlob (HCRYPTPROV hProv,
+ HCRYPTKEY hPrivateKey,
+ ALG_ID dwAlgId,
+ LPBYTE pbKeyMaterial,
+ DWORD dwKeyMaterial,
+ BOOL bCheckKeyLength,
+ HCRYPTKEY *hSessionKey);
+
+/******************************************************************************
+ *
+ * X509 Util functions
+ *
+ ******************************************************************************/
+#ifndef XMLSEC_NO_X509
+PCCERT_CONTEXT xmlSecMSCryptoX509FindCertBySubject (HCERTSTORE store,
+ const LPTSTR wcSubject,
+ DWORD dwCertEncodingType);
+
+PCCERT_CONTEXT xmlSecMSCryptoX509StoreFindCert (xmlSecKeyDataStorePtr store,
+ xmlChar *subjectName,
+ xmlChar *issuerName,
+ xmlChar *issuerSerial,
+ xmlChar *ski,
+ xmlSecKeyInfoCtx* keyInfoCtx);
+
+xmlChar * xmlSecMSCryptoX509GetNameString (PCCERT_CONTEXT pCertContext,
+ DWORD dwType,
+ DWORD dwFlags,
+ void *pvTypePara);
+
+PCCERT_CONTEXT xmlSecMSCryptoX509StoreVerify (xmlSecKeyDataStorePtr store,
+ HCERTSTORE certs,
+ xmlSecKeyInfoCtx* keyInfoCtx);
+
+#endif /* XMLSEC_NO_X509 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __XMLSEC_MSCRYPTO_PRIVATE_H__ */
diff --git a/src/mscrypto/signatures.c b/src/mscrypto/signatures.c
new file mode 100644
index 00000000..2c51f09a
--- /dev/null
+++ b/src/mscrypto/signatures.c
@@ -0,0 +1,960 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+
+/**************************************************************************
+ *
+ * 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_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_GOST
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_GOST*/
+
+
+ /* not found */
+ {
+ return(0);
+ }
+
+ 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_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
+ ctx->digestAlgId = CALG_SHA1;
+ ctx->keyId = xmlSecMSCryptoKeyDataDsaId;
+ } else
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaMd5Id)) {
+ ctx->digestAlgId = CALG_MD5;
+ ctx->keyId = xmlSecMSCryptoKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ ctx->digestAlgId = CALG_SHA1;
+ ctx->keyId = xmlSecMSCryptoKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+ ctx->digestAlgId = CALG_SHA_256;
+ ctx->keyId = xmlSecMSCryptoKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+ ctx->digestAlgId = CALG_SHA_384;
+ ctx->keyId = xmlSecMSCryptoKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+ ctx->digestAlgId = CALG_SHA_512;
+ ctx->keyId = xmlSecMSCryptoKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#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*/
+
+ /* not found */
+ {
+ 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;
+ xmlSecByte *tmpBuf;
+ HCRYPTKEY hKey;
+ DWORD dwError;
+ 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 */
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaMd5Id)) {
+ ConvertEndian(data, tmpBuf, dataSize);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ ConvertEndian(data, tmpBuf, dataSize);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+ ConvertEndian(data, tmpBuf, dataSize);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+ ConvertEndian(data, tmpBuf, dataSize);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+ ConvertEndian(data, tmpBuf, dataSize);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id) && (dataSize == 40)) {
+ ConvertEndian(data, tmpBuf, 20);
+ ConvertEndian(data + 20, tmpBuf + 20, 20);
+ } else
+#endif /*endif XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_GOST
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ ConvertEndian(data, tmpBuf, dataSize);
+ } else
+#endif /* XMLSEC_NO_GOST*/
+
+ {
+ 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;
+
+ 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);
+
+ /* 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 */
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaMd5Id)) {
+ ConvertEndian(tmpBuf, outBuf, outSize);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+ ConvertEndian(tmpBuf, outBuf, outSize);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+ ConvertEndian(tmpBuf, outBuf, outSize);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+ ConvertEndian(tmpBuf, outBuf, outSize);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+ ConvertEndian(tmpBuf, outBuf, outSize);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA*/
+
+#ifndef XMLSEC_NO_DSA
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id) && (outSize == 40)) {
+ ConvertEndian(tmpBuf, outBuf, 20);
+ ConvertEndian(tmpBuf + 20, outBuf + 20, 20);
+ } else
+#endif /* XMLSEC_NO_DSA*/
+
+#ifndef XMLSEC_NO_GOST
+ if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+ ConvertEndian(tmpBuf, outBuf, outSize);
+ } else
+#endif /* XMLSEC_NO_GOST*/
+
+ {
+ /* 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
+
+#ifndef XMLSEC_NO_MD5
+/****************************************************************************
+ *
+ * RSA-MD5 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaMd5, /* const xmlChar* name; */
+ xmlSecHrefRsaMd5, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaMd5GetKlass(void) {
+ return(&xmlSecMSCryptoRsaMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * 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_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha256, /* const xmlChar* name; */
+ xmlSecHrefRsaSha256, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaSha256GetKlass(void) {
+ return(&xmlSecMSCryptoRsaSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha384, /* const xmlChar* name; */
+ xmlSecHrefRsaSha384, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaSha384GetKlass(void) {
+ return(&xmlSecMSCryptoRsaSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA2512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha512, /* const xmlChar* name; */
+ xmlSecHrefRsaSha512, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformRsaSha512GetKlass(void) {
+ return(&xmlSecMSCryptoRsaSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+#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..658a6d49
--- /dev/null
+++ b/src/mscrypto/symkeys.c
@@ -0,0 +1,824 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.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,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ unsigned char** buf,
+ xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecMSCryptoSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecMSCryptoSymKeyDataGetType(xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecMSCryptoSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecMSCryptoSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecMSCryptoSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecMSCryptoSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+/*
+ * 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, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ unsigned char** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecMSCryptoSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecMSCryptoSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize 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 xmlSecSize
+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);
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(klass == xmlSecMSCryptoKeyDataAesId) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_HMAC
+ if(klass == xmlSecMSCryptoKeyDataHmacId) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_HMAC */
+
+ {
+ return(0);
+ }
+
+ return(0);
+}
+
+
+/******************************************************************************
+ *
+ * Utils
+ *
+ * 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
+ * and "Base Provider Key BLOBs" article for priv key blob format.
+ *
+ ******************************************************************************/
+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;
+}
+
+BOOL
+xmlSecMSCryptoImportPlainSessionBlob(HCRYPTPROV hProv, HCRYPTKEY hPrivateKey,
+ ALG_ID dwAlgId, LPBYTE pbKeyMaterial,
+ DWORD dwKeyMaterial, BOOL bCheckKeyLength,
+ HCRYPTKEY *hSessionKey) {
+ ALG_ID dwPrivKeyAlg;
+ LPBYTE keyBlob = NULL;
+ DWORD keyBlobLen, rndBlobSize, dwSize, n;
+ PUBLICKEYSTRUC* pubKeyStruc;
+ ALG_ID* algId;
+ DWORD dwPublicKeySize;
+ DWORD dwProvSessionKeySize = 0;
+ 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;
+ }
+
+ if(bCheckKeyLength) {
+ /* 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;
+
+ /* yell if key is too big */
+ if ((dwKeyMaterial * 8) > dwProvSessionKeySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "dwKeyMaterial=%ld;dwProvSessionKeySize=%ld",
+ dwKeyMaterial, dwProvSessionKeySize);
+ goto done;
+ }
+ } else {
+ dwProvSessionKeySize = dwKeyMaterial * 8;
+ }
+
+ /* 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);
+}
+
+#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 */
+
+#ifndef XMLSEC_NO_HMAC
+/**************************************************************************
+ *
+ * <xmlsec:HMACKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataHmacKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameHMACKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefHMACKeyValue, /* const xmlChar* href; */
+ xmlSecNodeHMACKeyValue, /* 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; */
+};
+
+/**
+ * xmlSecMSCryptoKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecMSCryptoKeyDataHmacGetKlass(void) {
+ return(&xmlSecMSCryptoKeyDataHmacKlass);
+}
+
+/**
+ * xmlSecMSCryptoKeyDataHmacSet:
+ * @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
+xmlSecMSCryptoKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataHmacId), -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/mscrypto/x509.c b/src/mscrypto/x509.c
new file mode 100644
index 00000000..5ae025f6
--- /dev/null
+++ b/src/mscrypto/x509.c
@@ -0,0 +1,2281 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+
+/*************************************************************************
+ *
+ * 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) {
+ LPTSTR resT = NULL;
+ xmlChar *res = NULL;
+ 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);
+ if(csz <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertNameToStr",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ resT = (LPTSTR)xmlMalloc(sizeof(TCHAR) * (csz + 1));
+ if (NULL == resT) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", sizeof(WCHAR) * (csz + 1));
+ return (NULL);
+ }
+
+ csz = CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, nm, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, resT, csz + 1);
+ if (csz <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CertNameToStr",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(resT);
+ return(NULL);
+ }
+
+ res = xmlSecMSCryptoConvertTstrToUtf8(resT);
+ if (NULL == res) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoConvertTstrToUtf8",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(resT);
+ return(NULL);
+ }
+
+ 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;
+ xmlChar * subject = NULL;
+ xmlChar * issuer = NULL;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== X509 Certificate\n");
+
+ /* subject */
+ subject = xmlSecMSCryptoX509GetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoX509GetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "subject");
+ goto done;
+ }
+ fprintf(output, "==== Subject Name: %s\n", subject);
+
+ /* issuer */
+ issuer = xmlSecMSCryptoX509GetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL);
+ if(issuer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoX509GetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "issuer");
+ goto done;
+ }
+ fprintf(output, "==== Issuer Name: %s\n", issuer);
+
+ /* serial number */
+ 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");
+
+done:
+ if (subject) xmlFree(subject);
+ if (issuer) xmlFree(issuer);
+}
+
+
+static void
+xmlSecMSCryptoX509CertDebugXmlDump(PCCERT_CONTEXT cert, FILE* output) {
+ PCRYPT_INTEGER_BLOB sn;
+ unsigned int i;
+ xmlChar * subject = NULL;
+ xmlChar * issuer = NULL;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ /* subject */
+ subject = xmlSecMSCryptoX509GetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoX509GetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "subject");
+ goto done;
+ }
+ fprintf(output, "<SubjectName>");
+ xmlSecPrintXmlString(output, BAD_CAST subject);
+ fprintf(output, "</SubjectName>\n");
+
+ /* issuer */
+ issuer = xmlSecMSCryptoX509GetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL);
+ if(issuer == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoX509GetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "issuer");
+ goto done;
+ }
+ fprintf(output, "<IssuerName>");
+ xmlSecPrintXmlString(output, BAD_CAST issuer);
+ fprintf(output, "</IssuerName>\n");
+
+ /* 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");
+
+done:
+ xmlFree(subject);
+ xmlFree(issuer);
+}
+
+
+/**************************************************************************
+ *
+ * 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..cf317877
--- /dev/null
+++ b/src/mscrypto/x509vfy.c
@@ -0,0 +1,1406 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (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>
+#include "private.h"
+
+/**************************************************************************
+ *
+ * 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,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const xmlChar *issuerSerial,
+ const 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) {
+ xmlChar * subject = NULL;
+ DWORD dwSize;
+
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(flags != 0);
+
+ /* get certs subject */
+ subject = xmlSecMSCryptoX509GetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL);
+ if(subject == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoX509GetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return;
+ }
+
+ /* 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
+ *
+ *****************************************************************************/
+/**
+ * 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.
+ */
+static BYTE*
+xmlSecMSCryptoCertStrToName(DWORD dwCertEncodingType, LPTSTR 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(sizeof(TCHAR) * ((*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);
+}
+
+
+/**
+ * xmlSecMSCryptoX509FindCertBySubject:
+ * @store: the pointer to certs store
+ * @wcSubject: the cert subject (Unicode)
+ * @dwCertEncodingType: the cert encoding type
+ *
+ * Searches for a cert with given @subject in the @store
+ *
+ * Returns: cert handle on success or NULL otherwise
+ */
+PCCERT_CONTEXT
+xmlSecMSCryptoX509FindCertBySubject(HCERTSTORE store, const LPTSTR wcSubject, DWORD dwCertEncodingType) {
+ PCCERT_CONTEXT res = NULL;
+ CERT_NAME_BLOB cnb;
+ BYTE* bdata;
+ DWORD len;
+
+ xmlSecAssert2(store != NULL, NULL);
+ xmlSecAssert2(wcSubject != NULL, NULL);
+
+ /* CASE 1: UTF8, DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcSubject,
+ CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR,
+ &len);
+ if(bdata != NULL) {
+ cnb.cbData = len;
+ cnb.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* CASE 2: UTF8, REVERSE DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcSubject,
+ CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &len);
+ if(bdata != NULL) {
+ cnb.cbData = len;
+ cnb.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* CASE 3: UNICODE, DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcSubject,
+ CERT_OID_NAME_STR,
+ &len);
+ if(bdata != NULL) {
+ cnb.cbData = len;
+ cnb.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* CASE 4: UNICODE, REVERSE DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcSubject,
+ CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &len);
+ if(bdata != NULL) {
+ cnb.cbData = len;
+ cnb.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &cnb,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+
+ /* done */
+ return (res);
+}
+
+/**
+ * xmlSecMSCryptoX509FindCertByIssuer:
+ * @store: the pointer to certs store
+ * @wcIssuer: the cert issuer (Unicode)
+ * @issuerSerialBn: the cert issuer serial
+ * @dwCertEncodingType: the cert encoding type
+ *
+ * Searches for a cert with given @subject in the @store
+ *
+ * Returns: cert handle on success or NULL otherwise
+ */
+static PCCERT_CONTEXT
+xmlSecMSCryptoX509FindCertByIssuer(HCERTSTORE store, const LPTSTR wcIssuer,
+ xmlSecBnPtr issuerSerialBn, DWORD dwCertEncodingType) {
+
+ PCCERT_CONTEXT res = NULL;
+ CERT_INFO certInfo;
+ BYTE* bdata;
+ DWORD len;
+
+
+ xmlSecAssert2(store != NULL, NULL);
+ xmlSecAssert2(wcIssuer != NULL, NULL);
+ xmlSecAssert2(issuerSerialBn != NULL, NULL);
+
+ certInfo.SerialNumber.cbData = xmlSecBnGetSize(issuerSerialBn);
+ certInfo.SerialNumber.pbData = xmlSecBnGetData(issuerSerialBn);
+
+
+ /* CASE 1: UTF8, DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcIssuer,
+ CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR,
+ &len);
+ if(bdata != NULL) {
+ certInfo.Issuer.cbData = len;
+ certInfo.Issuer.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_CERT,
+ &certInfo,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* CASE 2: UTF8, REVERSE DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcIssuer,
+ CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &len);
+ if(bdata != NULL) {
+ certInfo.Issuer.cbData = len;
+ certInfo.Issuer.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_CERT,
+ &certInfo,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* CASE 3: UNICODE, DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcIssuer,
+ CERT_OID_NAME_STR,
+ &len);
+ if(bdata != NULL) {
+ certInfo.Issuer.cbData = len;
+ certInfo.Issuer.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_CERT,
+ &certInfo,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+ /* CASE 4: UNICODE, REVERSE DN */
+ if (NULL == res) {
+ bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
+ wcIssuer,
+ CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ &len);
+ if(bdata != NULL) {
+ certInfo.Issuer.cbData = len;
+ certInfo.Issuer.pbData = bdata;
+
+ res = CertFindCertificateInStore(store,
+ dwCertEncodingType,
+ 0,
+ CERT_FIND_SUBJECT_CERT,
+ &certInfo,
+ NULL);
+ xmlFree(bdata);
+ }
+ }
+
+
+ /* done */
+ return (res);
+}
+
+static LPTSTR
+xmlSecMSCryptoX509GetCertName(const xmlChar * name) {
+ xmlChar *name2 = NULL;
+ xmlChar *p = NULL;
+ LPTSTR res = NULL;
+
+ xmlSecAssert2(name != 0, NULL);
+
+ /* MSCrypto doesn't support "emailAddress" attribute (see NSS as well).
+ * 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.
+ */
+ name2 = xmlStrdup(name);
+ if(name2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "xmlStrlen(name)=%d",
+ xmlStrlen(name));
+ return(NULL);
+ }
+ while( (p = (xmlChar*)xmlStrstr(name2, BAD_CAST "emailAddress=")) != NULL) {
+ memcpy(p, " E=", 13);
+ }
+
+ /* get name */
+ res = xmlSecMSCryptoConvertUtf8ToTstr(name2);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoConvertUtf8ToTstr",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* done */
+ return(res);
+}
+
+static PCCERT_CONTEXT
+xmlSecMSCryptoX509FindCert(HCERTSTORE store,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const xmlChar *issuerSerial,
+ const xmlChar *ski) {
+ PCCERT_CONTEXT pCert = NULL;
+ int ret;
+
+ xmlSecAssert2(store != 0, NULL);
+
+ if((pCert == NULL) && (NULL != subjectName)) {
+ LPTSTR wcSubjectName = NULL;
+
+ /* get unicode subject name */
+ wcSubjectName = xmlSecMSCryptoX509GetCertName(subjectName);
+ if(wcSubjectName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509GetCertName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "wcSubjectName");
+ return(NULL);
+ }
+
+ /* search */
+ pCert = xmlSecMSCryptoX509FindCertBySubject(store,
+ wcSubjectName,
+ PKCS_7_ASN_ENCODING | X509_ASN_ENCODING);
+
+
+ /* cleanup */
+ xmlFree(wcSubjectName);
+ }
+
+ if((pCert == NULL) && (NULL != issuerName) && (NULL != issuerSerial)) {
+ xmlSecBn issuerSerialBn;
+ LPTSTR wcIssuerName = NULL;
+
+ /* 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);
+ 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);
+ 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);
+ return(NULL);
+ }
+
+ /* get issuer name */
+ wcIssuerName = xmlSecMSCryptoX509GetCertName(issuerName);
+ if(wcIssuerName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecMSCryptoX509GetCertName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "wcIssuerName");
+ xmlSecBnFinalize(&issuerSerialBn);
+ return(NULL);
+ }
+
+ /* search */
+ pCert = xmlSecMSCryptoX509FindCertByIssuer(store,
+ wcIssuerName,
+ &issuerSerialBn,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING);
+
+ xmlFree(wcIssuerName);
+
+ /* cleanup */
+ 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);
+}
+
+
+/**
+ * xmlSecMSCryptoX509GetNameString:
+ * @pCertContext: the pointer to cert
+ * @dwType: the type (see CertGetNameString description in MSDN)
+ * @dwFlags: the flags (see CertGetNameString description in MSDN)
+ * @pvTypePara: the type parameter (see CertGetNameString description in MSDN)
+ *
+ * Gets the name string for certificate (see CertGetNameString description in MSDN).
+ *
+ * Returns: name string (should be freed with xmlFree) or NULL if failed.
+ */
+xmlChar *
+xmlSecMSCryptoX509GetNameString(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara) {
+ LPTSTR name = NULL;
+ xmlChar * res = NULL;
+ DWORD dwSize;
+
+ xmlSecAssert2(pCertContext != NULL, NULL);
+
+ /* get size first */
+ dwSize = CertGetNameString(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
+ if(dwSize <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "CertGetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ /* allocate buffer */
+ name = (LPTSTR)xmlMalloc(sizeof(TCHAR) * (dwSize + 1));
+ if(name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ /* actually get the name */
+ dwSize = CertGetNameString(pCertContext, dwType, dwFlags, pvTypePara, name, dwSize);
+ if(dwSize <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "CertGetNameString",
+ NULL,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(name);
+ return (NULL);
+ }
+
+ res = xmlSecMSCryptoConvertTstrToUtf8(name);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "xmlSecMSCryptoConvertTstrToUtf8",
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(name);
+ return (NULL);
+ }
+ /* done */
+ xmlFree(name);
+ return (res);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+
diff --git a/src/mscrypto/xmlsec-mingw.h b/src/mscrypto/xmlsec-mingw.h
new file mode 100644
index 00000000..ef5d2ae4
--- /dev/null
+++ b/src/mscrypto/xmlsec-mingw.h
@@ -0,0 +1,210 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2007,2010 Roumen Petrov.
+ */
+
+#ifndef __XMLSEC_MSCRYPTO_XMLSEC_MINGW_H__
+#define __XMLSEC_MSCRYPTO_XMLSEC_MINGW_H__
+
+#ifndef XMLSEC_PRIVATE
+#error "xmlsec-mingw.h file contains private xmlsec definitions for mingw build and should not be used outside xmlsec or xmlsec-<crypto> libraries"
+#endif /* XMLSEC_PRIVATE */
+
+
+/*defines*/
+
+#ifndef ALG_SID_HMAC
+# define ALG_SID_HMAC 9
+#endif
+
+#ifndef ALG_SID_SHA_256
+# define ALG_SID_SHA_256 12
+#endif
+
+#ifndef ALG_SID_SHA_384
+# define ALG_SID_SHA_384 13
+#endif
+
+#ifndef ALG_SID_SHA_512
+# define ALG_SID_SHA_512 14
+#endif
+
+#ifndef CALG_HMAC
+# define CALG_HMAC (ALG_CLASS_HASH|ALG_TYPE_ANY|ALG_SID_HMAC)
+#endif
+
+#ifndef CALG_SHA_256
+# define CALG_SHA_256 (ALG_CLASS_HASH|ALG_TYPE_ANY|ALG_SID_SHA_256)
+#endif
+
+#ifndef CALG_SHA_384
+# define CALG_SHA_384 (ALG_CLASS_HASH|ALG_TYPE_ANY|ALG_SID_SHA_384)
+#endif
+
+#ifndef CALG_SHA_512
+# define CALG_SHA_512 (ALG_CLASS_HASH|ALG_TYPE_ANY|ALG_SID_SHA_512)
+#endif
+
+
+#ifndef KP_OAEP_PARAMS
+# define KP_OAEP_PARAMS 36
+#endif
+
+
+#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..04ae8105
--- /dev/null
+++ b/src/nodeset.c
@@ -0,0 +1,610 @@
+/**
+ * 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 freeing returned 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;
+ xmlDocPtr destroyDoc = NULL;
+
+ 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)) {
+ /* all nodesets should belong to the same doc */
+ xmlSecAssert((destroyDoc == NULL) || (tmp->doc == destroyDoc));
+ destroyDoc = tmp->doc; /* can't destroy here because other node sets can refer to it */
+ }
+ memset(tmp, 0, sizeof(xmlSecNodeSet));
+ xmlFree(tmp);
+ }
+
+ /* finally, destroy the doc if needed */
+ if(destroyDoc != NULL) {
+ xmlFreeDoc(destroyDoc);
+ }
+}
+
+/**
+ * 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);
+ }
+
+ /* all nodesets should belong to the same doc */
+ xmlSecAssert2(nset->doc == newNSet->doc, NULL);
+
+ 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..8cd85863
--- /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 = \
+ $(NSS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(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..46c8c927
--- /dev/null
+++ b/src/nss/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c
+subdir = src/nss
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__libxmlsec1_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@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-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 = \
+ $(NSS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(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..65a0f45e
--- /dev/null
+++ b/src/nss/README
@@ -0,0 +1,128 @@
+WHAT VERSION OF NSS?
+------------------------------------------------------------------------
+NSS 3.9 or greater and NSPR 4.4.1 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) 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
+
+5) 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
+
+6) 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
+
+7) RIPEMD160 Digest and RIPEMD160 HMAC is not supported by NSS
+
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118634
+
+8) 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
+
+9) 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
+
+10) "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.
+
+11) NSS doesn't support emailAddress in the cert subject. There is a hack
+that needs to be removed in xmlSecNssX509FindCert function (x509vfy.c):
+
+https://bugzilla.mozilla.org/show_bug.cgi?id=561689
+
+12) CRLs from xml document support is not working at all.
diff --git a/src/nss/app.c b/src/nss/app.c
new file mode 100644
index 00000000..dabe36d1
--- /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..261155e6
--- /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..54bd2af2
--- /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..7137f1c4
--- /dev/null
+++ b/src/nss/crypto.c
@@ -0,0 +1,444 @@
+/**
+ * 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
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#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 */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecNssFunctions->transformDes3CbcGetKlass = xmlSecNssTransformDes3CbcGetKlass;
+ gXmlSecNssFunctions->transformKWDes3GetKlass = xmlSecNssTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+ gXmlSecNssFunctions->transformDsaSha1GetKlass = xmlSecNssTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecNssFunctions->transformHmacMd5GetKlass = xmlSecNssTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecNssFunctions->transformHmacRipemd160GetKlass = xmlSecNssTransformHmacRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformHmacSha1GetKlass = xmlSecNssTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecNssFunctions->transformHmacSha256GetKlass = xmlSecNssTransformHmacSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecNssFunctions->transformHmacSha384GetKlass = xmlSecNssTransformHmacSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecNssFunctions->transformHmacSha512GetKlass = xmlSecNssTransformHmacSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecNssFunctions->transformRsaMd5GetKlass = xmlSecNssTransformRsaMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformRsaSha1GetKlass = xmlSecNssTransformRsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecNssFunctions->transformRsaSha256GetKlass = xmlSecNssTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecNssFunctions->transformRsaSha384GetKlass = xmlSecNssTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecNssFunctions->transformRsaSha512GetKlass = xmlSecNssTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ gXmlSecNssFunctions->transformRsaPkcs1GetKlass = xmlSecNssTransformRsaPkcs1GetKlass;
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+ gXmlSecNssFunctions->transformRsaOaepGetKlass = xmlSecNssTransformRsaOaepGetKlass;
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformSha1GetKlass = xmlSecNssTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecNssFunctions->transformSha256GetKlass = xmlSecNssTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecNssFunctions->transformSha384GetKlass = xmlSecNssTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecNssFunctions->transformSha512GetKlass = xmlSecNssTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ /******************************* MD5 ********************************/
+#ifndef XMLSEC_NO_MD5
+ gXmlSecNssFunctions->transformMd5GetKlass = xmlSecNssTransformMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+
+ /********************************************************************
+ *
+ * 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..8063b443
--- /dev/null
+++ b/src/nss/digests.c
@@ -0,0 +1,576 @@
+/**
+ * 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 64
+
+/**************************************************************************
+ *
+ * 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 xmlSecNssDigestCheckId (xmlSecTransformPtr transform);
+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) {
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+ 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_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformMd5Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_MD5);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha1Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha256Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA256);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha384Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA384);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha512Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA512);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+ 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) {
+ unsigned int 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);
+ ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize);
+
+ 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_MD5
+/******************************************************************************
+ *
+ * Md5 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameMd5, /* const xmlChar* name; */
+ xmlSecHrefMd5, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformMd5GetKlass:
+ *
+ * MD5 digest transform klass.
+ *
+ * Returns: pointer to MD5 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformMd5GetKlass(void) {
+ return(&xmlSecNssMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+
+#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 */
+
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * SHA256 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha256, /* const xmlChar* name; */
+ xmlSecHrefSha256, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformSha256GetKlass:
+ *
+ * SHA256 digest transform klass.
+ *
+ * Returns: pointer to SHA256 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha256GetKlass(void) {
+ return(&xmlSecNssSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * SHA384 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha384, /* const xmlChar* name; */
+ xmlSecHrefSha384, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformSha384GetKlass:
+ *
+ * SHA384 digest transform klass.
+ *
+ * Returns: pointer to SHA384 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha384GetKlass(void) {
+ return(&xmlSecNssSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * SHA512 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha512, /* const xmlChar* name; */
+ xmlSecHrefSha512, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformSha512GetKlass:
+ *
+ * SHA512 digest transform klass.
+ *
+ * Returns: pointer to SHA512 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha512GetKlass(void) {
+ return(&xmlSecNssSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
diff --git a/src/nss/globals.h b/src/nss/globals.h
new file mode 100644
index 00000000..770b6dba
--- /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..ae7e67ef
--- /dev/null
+++ b/src/nss/hmac.c
@@ -0,0 +1,855 @@
+/**
+ * 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))
+
+static int xmlSecNssHmacCheckId (xmlSecTransformPtr transform);
+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
+xmlSecNssHmacCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacRipemd160Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+ /* not found */
+ return(0);
+}
+
+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));
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacMd5Id)) {
+ ctx->digestType = CKM_MD5_HMAC;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacRipemd160Id)) {
+ ctx->digestType = CKM_RIPEMD160_HMAC;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha1Id)) {
+ ctx->digestType = CKM_SHA_1_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha256Id)) {
+ ctx->digestType = CKM_SHA256_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha384Id)) {
+ ctx->digestType = CKM_SHA384_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha512Id)) {
+ ctx->digestType = CKM_SHA512_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+ /* not found */
+ {
+ 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 length 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) {
+ unsigned int 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 = XMLSEC_SIZE_BAD_CAST(dgstSize * 8); /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= XMLSEC_SIZE_BAD_CAST(8 * dgstSize)) {
+ dgstSize = ((ctx->dgstSize + 7) / 8); /* we need to truncate result digest */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "result-bits=%d;required-bits=%d",
+ 8 * dgstSize, ctx->dgstSize);
+ return(-1);
+ }
+
+ 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);
+}
+
+
+#ifndef XMLSEC_NO_RIPEMD160
+/******************************************************************************
+ *
+ * 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);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+/******************************************************************************
+ *
+ * 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_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * 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);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * HMAC SHA256
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha256, /* const xmlChar* name; */
+ xmlSecHrefHmacSha256, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha256GetKlass(void) {
+ return(&xmlSecNssHmacSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * HMAC SHA384
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha384, /* const xmlChar* name; */
+ xmlSecHrefHmacSha384, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha384GetKlass(void) {
+ return(&xmlSecNssHmacSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * HMAC SHA512
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha512, /* const xmlChar* name; */
+ xmlSecHrefHmacSha512, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha512GetKlass(void) {
+ return(&xmlSecNssHmacSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+
diff --git a/src/nss/keysstore.c b/src/nss/keysstore.c
new file mode 100644
index 00000000..f07e44be
--- /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..d84593b9
--- /dev/null
+++ b/src/nss/keytrans.c
@@ -0,0 +1,753 @@
+/**
+ *
+ * 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 transport 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)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_RSA */
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaOaepId)) {
+ return (1);
+ }
+#endif /* XMLSEC_NO_RSA */
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
+ /* not found */
+ 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 ) ;
+
+ /* initialize context */
+ memset(context, 0, sizeof(xmlSecNssKeyTransportCtx));
+
+#ifndef XMLSEC_NO_RSA
+ if(transform->id == xmlSecNssTransformRsaPkcs1Id) {
+ context->cipher = CKM_RSA_PKCS;
+ context->keyId = xmlSecNssKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_RSA */
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+#ifndef XMLSEC_NO_RSA
+ if(transform->id == xmlSecNssTransformRsaOaepId) {
+ context->cipher = CKM_RSA_PKCS_OAEP;
+ context->keyId = xmlSecNssKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_RSA */
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
+ /* not found */
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ 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) ;
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+#endif /* XMLSEC_NO_RSA */
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+#ifndef XMLSEC_NO_RSA
+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 /* XMLSEC_NO_RSA */
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
diff --git a/src/nss/kw_aes.c b/src/nss/kw_aes.c
new file mode 100644
index 00000000..0438e306
--- /dev/null
+++ b/src/nss/kw_aes.c
@@ -0,0 +1,681 @@
+/**
+ *
+ * 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.
+ * Copyright (C) 2010 Aleksey Sanin, 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>
+
+#include "../kw_aes_des.h"
+
+/*
+ * NSS needs to implement AES KW internally and then the code
+ * needs to change to use the direct implementation instead.
+ *
+ * Follow the NSS bug system for more details on the fix
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=213795
+ */
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecNSSKWAesBlockEncrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static int xmlSecNSSKWAesBlockDecrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static xmlSecKWAesKlass xmlSecNssKWAesKlass = {
+ /* callbacks */
+ xmlSecNSSKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */
+ xmlSecNSSKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL /* void* reserved1; */
+};
+
+
+
+
+static PK11SymKey* xmlSecNssMakeAesKey (const xmlSecByte *key,
+ xmlSecSize keySize,
+ int enc);
+static int xmlSecNssAesOp (PK11SymKey *aeskey,
+ const xmlSecByte *in,
+ xmlSecByte *out,
+ int enc);
+
+
+/*********************************************************************
+ *
+ * AES KW transforms
+ *
+ ********************************************************************/
+typedef struct _xmlSecNssKWAesCtx xmlSecNssKWAesCtx,
+ *xmlSecNssKWAesCtxPtr;
+struct _xmlSecNssKWAesCtx {
+ xmlSecBuffer keyBuffer;
+ xmlSecSize keyExpectedSize;
+};
+#define xmlSecNssKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssKWAesCtx))
+#define xmlSecNssKWAesGetCtx(transform) \
+ ((xmlSecNssKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+#define xmlSecNssKWAesCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes128Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes192Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes256Id))
+
+
+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 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; */
+};
+
+/**
+ * xmlSecNssTransformKWAes128GetKlass:
+ *
+ * The AES-128 key wrapper transform klass.
+ *
+ * Returns: AES-128 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes128GetKlass(void) {
+ return(&xmlSecNssKWAes128Klass);
+}
+
+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; */
+};
+
+/**
+ * xmlSecNssTransformKWAes192GetKlass:
+ *
+ * The AES-192 key wrapper transform klass.
+ *
+ * Returns: AES-192 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes192GetKlass(void) {
+ return(&xmlSecNssKWAes192Klass);
+}
+
+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; */
+};
+
+/**
+ * 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) {
+ xmlSecNssKWAesCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes128Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes192Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes256Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKWAesFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssKWAesCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize));
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecNssKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssKWAesCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataAesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * ctx->keyExpectedSize;
+
+ return(0);
+}
+
+static int
+xmlSecNssKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssKWAesCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataAesId), -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < ctx->keyExpectedSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer),
+ xmlSecBufferGetData(buffer),
+ ctx->keyExpectedSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d",
+ ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssKWAesCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == ctx->keyExpectedSize, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % 8) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d(not 8 bytes aligned)", inSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+ outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_KW_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ PK11SymKey *aeskey = NULL;
+
+ /* create key */
+ aeskey = xmlSecNssMakeAesKey(xmlSecBufferGetData(&(ctx->keyBuffer)), keySize, 1); /* encrypt */
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+
+ /* encrypt */
+ ret = xmlSecKWAesEncode(&xmlSecNssKWAesKlass, aeskey,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSymKey(aeskey);
+ return(-1);
+ }
+
+ outSize = ret;
+ PK11_FreeSymKey(aeskey);
+ } else {
+ PK11SymKey *aeskey = NULL;
+
+ /* create key */
+ aeskey = xmlSecNssMakeAesKey(xmlSecBufferGetData(&(ctx->keyBuffer)), keySize, 0); /* decrypt */
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* decrypt */
+ ret = xmlSecKWAesDecode(&xmlSecNssKWAesKlass, aeskey,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesDecode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSymKey(aeskey);
+ return(-1);
+ }
+
+ outSize = ret;
+ PK11_FreeSymKey(aeskey);
+ }
+
+ 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);
+}
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecNSSKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ PK11SymKey *aeskey = (PK11SymKey *)context;
+ int ret;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(aeskey != NULL, -1);
+
+ /* one block */
+ ret = xmlSecNssAesOp(aeskey, in, out, 1); /* encrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(XMLSEC_KW_AES_BLOCK_SIZE);
+}
+
+static int
+xmlSecNSSKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ PK11SymKey *aeskey = (PK11SymKey *)context;
+ int ret;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(aeskey != NULL, -1);
+
+ /* one block */
+ ret = xmlSecNssAesOp(aeskey, in, out, 0); /* decrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(XMLSEC_KW_AES_BLOCK_SIZE);
+}
+
+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_KW_AES_BLOCK_SIZE), in and out can overlap */
+static int
+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;
+ int ret = -1;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ 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_KW_AES_BLOCK_SIZE, (unsigned char *)in,
+ XMLSEC_KW_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_KW_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 - success! */
+ ret = 0;
+
+done:
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ }
+ if (EncContext) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ }
+
+ return (ret);
+}
+
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/nss/kw_des.c b/src/nss/kw_des.c
new file mode 100644
index 00000000..e75f69c9
--- /dev/null
+++ b/src/nss/kw_des.c
@@ -0,0 +1,663 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES KW 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.
+ * 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 <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>
+
+#include "../kw_aes_des.h"
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecNssKWDes3GenerateRandom (void * context,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3Sha1 (void * context,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3BlockEncrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3BlockDecrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+
+static xmlSecKWDes3Klass xmlSecNssKWDes3ImplKlass = {
+ /* callbacks */
+ xmlSecNssKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */
+ xmlSecNssKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */
+ xmlSecNssKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */
+ xmlSecNssKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static int xmlSecNssKWDes3Encrypt (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *iv,
+ xmlSecSize ivSize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize,
+ int enc);
+
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+typedef struct _xmlSecNssKWDes3Ctx xmlSecNssKWDes3Ctx,
+ *xmlSecNssKWDes3CtxPtr;
+struct _xmlSecNssKWDes3Ctx {
+ xmlSecBuffer keyBuffer;
+};
+#define xmlSecNssKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssKWDes3Ctx))
+#define xmlSecNssKWDes3GetCtx(transform) \
+ ((xmlSecNssKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+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 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) {
+ xmlSecNssKWDes3CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKWDes3Finalize(xmlSecTransformPtr transform) {
+ xmlSecNssKWDes3CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size));
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecNssKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssKWDes3CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecNssKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssKWDes3CtxPtr ctx;
+ 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(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataDesId), -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key length %d is not enough (%d expected)",
+ keySize, XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssKWDes3CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ 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);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d bytes - not %d bytes aligned",
+ inSize, XMLSEC_KW_DES3_BLOCK_LENGTH);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 16 bytes longer plus one block just in case */
+ outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH;
+ } else {
+ /* just in case, add a block */
+ outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWDes3Encode(&xmlSecNssKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWDes3Decode(&xmlSecNssKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecNssKWDes3Sha1(void * context,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ PK11Context *pk11ctx = NULL;
+ unsigned int outLen = 0;
+ SECStatus status;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= SHA1_LENGTH, -1);
+
+ /* Create a pk11ctx for hashing (digesting) */
+ pk11ctx = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (pk11ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateDigestContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ status = PK11_DigestBegin(pk11ctx);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ return(-1);
+ }
+
+ status = PK11_DigestOp(pk11ctx, in, inSize);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ return(-1);
+ }
+
+ status = PK11_DigestFinal(pk11ctx, out, &outLen, outSize);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ return(-1);
+ }
+
+ /* done */
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ xmlSecAssert2(outLen == SHA1_LENGTH, -1);
+ return(outLen);
+}
+
+static int
+xmlSecNssKWDes3GenerateRandom(void * context,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ SECStatus status;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ status = PK11_GenerateRandom(out, outSize);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return((int)outSize);
+}
+
+static int
+xmlSecNssKWDes3BlockEncrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecNssKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 1); /* encrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+static int
+xmlSecNssKWDes3BlockDecrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecNssKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 0); /* decrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+
+
+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* param = NULL;
+ PK11Context* pk11ctx = NULL;
+ SECItem keyItem, ivItem;
+ SECStatus status;
+ int result_len = -1;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize == XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ 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;
+
+ param = PK11_ParamFromIV(cipherMech, &ivItem);
+ if (param == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ pk11ctx = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ symKey, param);
+ if (pk11ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ status = PK11_CipherOp(pk11ctx, out, &tmp1_outlen, outSize,
+ (unsigned char *)in, inSize);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ status = PK11_DigestFinal(pk11ctx, out+tmp1_outlen,
+ &tmp2_outlen, outSize-tmp1_outlen);
+ if (status != 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 (param) {
+ SECITEM_FreeItem(param, PR_TRUE);
+ }
+ if (pk11ctx) {
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ }
+
+ return(result_len);
+}
+
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/nss/pkikeys.c b/src/nss/pkikeys.c
new file mode 100644
index 00000000..ae9e29b4
--- /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..4f54170e
--- /dev/null
+++ b/src/nss/signatures.c
@@ -0,0 +1,841 @@
+/**
+ * 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
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+#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;
+ } else
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaMd5Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha1Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha256Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha384Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha512Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+ } 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);
+ }
+
+ 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;
+
+ if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
+ /* This creates a signature which is ASN1 encoded */
+ SECItem signatureDer;
+ SECStatus statusDer;
+
+ statusDer = DSAU_EncodeDerSig(&signatureDer, &signature);
+ if(statusDer != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "DSAU_EncodeDerSig",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d",
+ PORT_GetError());
+ return(-1);
+ }
+ status = VFY_EndWithSignature(ctx->u.vfy.vfyctx, &signatureDer);
+ SECITEM_FreeItem(&signatureDer, PR_FALSE);
+ } else {
+ status = VFY_EndWithSignature(ctx->u.vfy.vfyctx, &signature);
+ }
+
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_EndWithSignature",
+ 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_EndWithSignature",
+ 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);
+ }
+
+ if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
+ /* This creates a signature which is ASN1 encoded */
+ SECItem * signatureClr;
+
+ signatureClr = DSAU_DecodeDerSig(&signature);
+ if(signatureClr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "DSAU_EncodeDerSig",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d",
+ PORT_GetError());
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(out, signatureClr->data, signatureClr->len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ signatureClr->len);
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(signatureClr, PR_TRUE);
+ } else {
+ /* This signature is used as-is */
+ ret = xmlSecBufferSetData(out, signature.data, signature.len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ signature.len);
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ return(-1);
+ }
+ }
+
+ /* cleanup */
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ }
+ 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
+
+#ifndef XMLSEC_NO_MD5
+/****************************************************************************
+ *
+ * RSA-MD5 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaMd5, /* const xmlChar* name; */
+ xmlSecHrefRsaMd5, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaMd5GetKlass(void) {
+ return(&xmlSecNssRsaMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * 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_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha256, /* const xmlChar* name; */
+ xmlSecHrefRsaSha256, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha256GetKlass(void) {
+ return(&xmlSecNssRsaSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha384, /* const xmlChar* name; */
+ xmlSecHrefRsaSha384, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha384GetKlass(void) {
+ return(&xmlSecNssRsaSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha512, /* const xmlChar* name; */
+ xmlSecHrefRsaSha512, /* 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; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha512GetKlass(void) {
+ return(&xmlSecNssRsaSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+
diff --git a/src/nss/symkeys.c b/src/nss/symkeys.c
new file mode 100644
index 00000000..3da7a694
--- /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..887c77cf
--- /dev/null
+++ b/src/nss/x509.c
@@ -0,0 +1,2223 @@
+/**
+ * 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);
+ }
+
+ crlDst = SEC_DupCrl(crlSrc);
+ 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;
+ int resLen = 64; /* not more than 64 chars */
+ PRUint64 val = 0;
+ unsigned int ii = 0;
+ int shift = 0;
+
+ xmlSecAssert2(num != NULL, NULL);
+ xmlSecAssert2(num->type == siBuffer, NULL);
+ xmlSecAssert2(num->len <= 9, NULL);
+ xmlSecAssert2(num->data != NULL, NULL);
+
+ /* HACK : to be fixed after
+ * NSS bug http://bugzilla.mozilla.org/show_bug.cgi?id=212864 is fixed
+ */
+ for(ii = num->len; ii > 0; --ii, shift += 8) {
+ val |= ((PRUint64)num->data[ii - 1]) << shift;
+ }
+
+ res = (xmlChar*)xmlMalloc(resLen + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ PR_snprintf((char*)res, resLen, "%llu", val);
+ 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..fdb866fe
--- /dev/null
+++ b/src/nss/x509vfy.c
@@ -0,0 +1,808 @@
+/**
+ * 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 {
+ /* Two uses:
+ *
+ * 1) Just keeping a reference to destroy later.
+ *
+ * 2) NSS doesn't update it's cache correctly when new certs are added
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=211051
+ * we use this list to perform search ourselves.
+ */
+
+ 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 int xmlSecNssNumToItem (SECItem *it,
+ PRUint64 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(CERTCertList* certsList,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const 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(ctx->certsList, 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 CERTName *
+xmlSecNssGetCertName(const xmlChar * name) {
+ xmlChar *tmp, *name2;
+ xmlChar *p;
+ CERTName *res;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ /* nss doesn't support emailAddress (see https://bugzilla.mozilla.org/show_bug.cgi?id=561689)
+ * 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.
+ */
+ name2 = xmlStrdup(name);
+ if(name2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "xmlStrlen(name)=%d",
+ xmlStrlen(name));
+ return(NULL);
+ }
+ while( (p = (xmlChar*)xmlStrstr(name2, BAD_CAST "emailAddress=")) != NULL) {
+ memcpy(p, " E=", 13);
+ }
+
+ tmp = xmlSecNssX509NameRead(name2, xmlStrlen(name2));
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name2=\"%s\"",
+ xmlSecErrorsSafeString(name2));
+ xmlFree(name2);
+ return(NULL);
+ }
+
+ res = CERT_AsciiToName((char*)tmp);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_AsciiToName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ascii=\"%s\", error code=%d",
+ xmlSecErrorsSafeString((char*)tmp),
+ PORT_GetError());
+ PORT_Free(tmp);
+ xmlFree(name2);
+ return(NULL);
+ }
+
+ PORT_Free(tmp);
+ return(res);
+}
+
+static CERTCertificate*
+xmlSecNssX509FindCert(CERTCertList* certsList, const xmlChar *subjectName,
+ const xmlChar *issuerName, const xmlChar *issuerSerial,
+ xmlChar *ski) {
+ CERTCertificate *cert = NULL;
+ CERTName *name = NULL;
+ SECItem *nameitem = NULL;
+ CERTCertListNode* head;
+ SECItem tmpitem;
+ SECStatus status;
+ PRArenaPool *arena = NULL;
+ int rv;
+
+ if ((cert == NULL) && (subjectName != NULL)) {
+ name = xmlSecNssGetCertName(subjectName);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetCertName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "subject=%s",
+ xmlSecErrorsSafeString(subjectName));
+ goto done;
+ }
+
+ if(arena == NULL) {
+ 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;
+ }
+ }
+
+ 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);
+ }
+
+ if((cert == NULL) && (issuerName != NULL) && (issuerSerial != NULL)) {
+ CERTIssuerAndSN issuerAndSN;
+ PRUint64 issuerSN = 0;
+
+ name = xmlSecNssGetCertName(issuerName);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetCertName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "issuer=%s",
+ xmlSecErrorsSafeString(issuerName));
+ goto done;
+ }
+
+ if(arena == NULL) {
+ 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;
+ }
+ }
+
+ 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_CRYPTO_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 */
+ if(PR_sscanf((char *)issuerSerial, "%llu", &issuerSN) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PR_sscanf",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PR_GetError());
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ goto done;
+ }
+
+ rv = xmlSecNssNumToItem(&issuerAndSN.serialNumber, issuerSN);
+ if(rv <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssNumToItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PR_GetError());
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ goto done;
+ }
+
+ cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerAndSN);
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ }
+
+ if((cert == NULL) && (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 = len;
+ cert = CERT_FindCertBySubjectKeyID(CERT_GetDefaultCertDB(),
+ &subjKeyID);
+
+ /* try to search in our list - NSS doesn't update it's cache correctly
+ * when new certs are added https://bugzilla.mozilla.org/show_bug.cgi?id=211051
+ */
+ if((cert == NULL) && (certsList != NULL)) {
+
+ for(head = CERT_LIST_HEAD(certsList);
+ (cert == NULL) && !CERT_LIST_END(head, certsList) &&
+ (head != NULL) && (head->cert != NULL);
+ head = CERT_LIST_NEXT(head)
+ ) {
+
+ memset(&tmpitem, 0, sizeof(tmpitem));
+ status = CERT_FindSubjectKeyIDExtension(head->cert, &tmpitem);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_FindSubjectKeyIDExtension",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ski");
+ SECITEM_FreeItem(&tmpitem, PR_FALSE);
+ goto done;
+ }
+
+ if((tmpitem.len == subjKeyID.len) &&
+ (memcmp(tmpitem.data, subjKeyID.data, subjKeyID.len) == 0)
+ ) {
+ cert = CERT_DupCertificate(head->cert);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ SECITEM_FreeItem(&tmpitem, PR_FALSE);
+ goto done;
+ }
+ }
+ SECITEM_FreeItem(&tmpitem, PR_FALSE);
+ }
+ }
+ }
+
+done:
+ 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 int
+xmlSecNssNumToItem(SECItem *it, PRUint64 ui)
+{
+ unsigned char bb[9];
+ unsigned int zeros_len;
+
+ xmlSecAssert2(it != NULL, -1);
+
+ bb[0] = 0; /* important: we should have 0 at the beginning! */
+ bb[1] = (unsigned char) (ui >> 56);
+ bb[2] = (unsigned char) (ui >> 48);
+ bb[3] = (unsigned char) (ui >> 40);
+ bb[4] = (unsigned char) (ui >> 32);
+ bb[5] = (unsigned char) (ui >> 24);
+ bb[6] = (unsigned char) (ui >> 16);
+ bb[7] = (unsigned char) (ui >> 8);
+ bb[8] = (unsigned char) (ui);
+
+ /*
+ ** Small integers are encoded in a single byte. Larger integers
+ ** require progressively more space. Start from 1 because byte at
+ ** position 0 is zero
+ */
+ for(zeros_len = 1; (zeros_len < sizeof(bb)) && (bb[zeros_len] == 0); ++zeros_len);
+
+ it->len = sizeof(bb) - (zeros_len - 1);
+ it->data = (unsigned char *)PORT_Alloc(it->len);
+ if (it->data == NULL) {
+ it->len = 0;
+ return (-1);
+ }
+
+ PORT_Memcpy(it->data, bb + (zeros_len - 1), it->len);
+ return(it->len);
+}
+#endif /* XMLSEC_NO_X509 */
+
+
diff --git a/src/openssl/Makefile.am b/src/openssl/Makefile.am
new file mode 100644
index 00000000..23c225a1
--- /dev/null
+++ b/src/openssl/Makefile.am
@@ -0,0 +1,56 @@
+NULL =
+
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-openssl.la \
+ $(NULL)
+
+libxmlsec1_openssl_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(OPENSSL_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_openssl_la_SOURCES =\
+ app.c \
+ bn.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ evp.c \
+ hmac.c \
+ kw_aes.c \
+ kw_des.c \
+ kt_rsa.c \
+ signatures.c \
+ symkeys.c \
+ x509.c \
+ x509vfy.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_openssl_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_openssl_la_LIBADD = \
+ $(OPENSSL_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_openssl_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_openssl_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/openssl/Makefile.in b/src/openssl/Makefile.in
new file mode 100644
index 00000000..8f6bb8f8
--- /dev/null
+++ b/src/openssl/Makefile.in
@@ -0,0 +1,790 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c
+subdir = src/openssl
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__libxmlsec1_openssl_la_SOURCES_DIST = app.c bn.c ciphers.c crypto.c \
+ digests.c evp.c hmac.c kw_aes.c kw_des.c kt_rsa.c signatures.c \
+ symkeys.c x509.c x509vfy.c globals.h ../strings.c
+am__objects_1 =
+@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_openssl_la-strings.lo
+am_libxmlsec1_openssl_la_OBJECTS = libxmlsec1_openssl_la-app.lo \
+ libxmlsec1_openssl_la-bn.lo libxmlsec1_openssl_la-ciphers.lo \
+ libxmlsec1_openssl_la-crypto.lo \
+ libxmlsec1_openssl_la-digests.lo libxmlsec1_openssl_la-evp.lo \
+ libxmlsec1_openssl_la-hmac.lo libxmlsec1_openssl_la-kw_aes.lo \
+ libxmlsec1_openssl_la-kw_des.lo \
+ libxmlsec1_openssl_la-kt_rsa.lo \
+ libxmlsec1_openssl_la-signatures.lo \
+ libxmlsec1_openssl_la-symkeys.lo libxmlsec1_openssl_la-x509.lo \
+ libxmlsec1_openssl_la-x509vfy.lo $(am__objects_1) \
+ $(am__objects_2)
+libxmlsec1_openssl_la_OBJECTS = $(am_libxmlsec1_openssl_la_OBJECTS)
+libxmlsec1_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_openssl_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libxmlsec1_openssl_la_SOURCES)
+DIST_SOURCES = $(am__libxmlsec1_openssl_la_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CP = @CP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-openssl.la \
+ $(NULL)
+
+libxmlsec1_openssl_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(OPENSSL_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_openssl_la_SOURCES = app.c bn.c ciphers.c crypto.c \
+ digests.c evp.c hmac.c kw_aes.c kw_des.c kt_rsa.c signatures.c \
+ symkeys.c x509.c x509vfy.c globals.h $(NULL) $(am__append_1)
+libxmlsec1_openssl_la_LIBADD = \
+ $(OPENSSL_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_openssl_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_openssl_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/openssl/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/openssl/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libxmlsec1-openssl.la: $(libxmlsec1_openssl_la_OBJECTS) $(libxmlsec1_openssl_la_DEPENDENCIES)
+ $(libxmlsec1_openssl_la_LINK) -rpath $(libdir) $(libxmlsec1_openssl_la_OBJECTS) $(libxmlsec1_openssl_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-bn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-ciphers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-digests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-evp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-kw_des.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-signatures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-symkeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libxmlsec1_openssl_la-app.lo: app.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-app.Tpo -c -o libxmlsec1_openssl_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-app.Tpo $(DEPDIR)/libxmlsec1_openssl_la-app.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_openssl_la-app.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+
+libxmlsec1_openssl_la-bn.lo: bn.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-bn.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-bn.Tpo -c -o libxmlsec1_openssl_la-bn.lo `test -f 'bn.c' || echo '$(srcdir)/'`bn.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-bn.Tpo $(DEPDIR)/libxmlsec1_openssl_la-bn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bn.c' object='libxmlsec1_openssl_la-bn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-bn.lo `test -f 'bn.c' || echo '$(srcdir)/'`bn.c
+
+libxmlsec1_openssl_la-ciphers.lo: ciphers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-ciphers.Tpo -c -o libxmlsec1_openssl_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_openssl_la-ciphers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_openssl_la-ciphers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+
+libxmlsec1_openssl_la-crypto.lo: crypto.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-crypto.Tpo -c -o libxmlsec1_openssl_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-crypto.Tpo $(DEPDIR)/libxmlsec1_openssl_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_openssl_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+
+libxmlsec1_openssl_la-digests.lo: digests.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-digests.Tpo -c -o libxmlsec1_openssl_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-digests.Tpo $(DEPDIR)/libxmlsec1_openssl_la-digests.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_openssl_la-digests.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+
+libxmlsec1_openssl_la-evp.lo: evp.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-evp.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-evp.Tpo -c -o libxmlsec1_openssl_la-evp.lo `test -f 'evp.c' || echo '$(srcdir)/'`evp.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-evp.Tpo $(DEPDIR)/libxmlsec1_openssl_la-evp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='evp.c' object='libxmlsec1_openssl_la-evp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-evp.lo `test -f 'evp.c' || echo '$(srcdir)/'`evp.c
+
+libxmlsec1_openssl_la-hmac.lo: hmac.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-hmac.Tpo -c -o libxmlsec1_openssl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-hmac.Tpo $(DEPDIR)/libxmlsec1_openssl_la-hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_openssl_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+
+libxmlsec1_openssl_la-kw_aes.lo: kw_aes.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Tpo -c -o libxmlsec1_openssl_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_openssl_la-kw_aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_openssl_la-kw_aes.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+
+libxmlsec1_openssl_la-kw_des.lo: kw_des.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-kw_des.Tpo -c -o libxmlsec1_openssl_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_openssl_la-kw_des.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_openssl_la-kw_des.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+
+libxmlsec1_openssl_la-kt_rsa.lo: kt_rsa.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-kt_rsa.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Tpo -c -o libxmlsec1_openssl_la-kt_rsa.lo `test -f 'kt_rsa.c' || echo '$(srcdir)/'`kt_rsa.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Tpo $(DEPDIR)/libxmlsec1_openssl_la-kt_rsa.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kt_rsa.c' object='libxmlsec1_openssl_la-kt_rsa.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-kt_rsa.lo `test -f 'kt_rsa.c' || echo '$(srcdir)/'`kt_rsa.c
+
+libxmlsec1_openssl_la-signatures.lo: signatures.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-signatures.Tpo -c -o libxmlsec1_openssl_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-signatures.Tpo $(DEPDIR)/libxmlsec1_openssl_la-signatures.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_openssl_la-signatures.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+
+libxmlsec1_openssl_la-symkeys.lo: symkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-symkeys.Tpo -c -o libxmlsec1_openssl_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_openssl_la-symkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_openssl_la-symkeys.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+
+libxmlsec1_openssl_la-x509.lo: x509.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-x509.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-x509.Tpo -c -o libxmlsec1_openssl_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-x509.Tpo $(DEPDIR)/libxmlsec1_openssl_la-x509.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509.c' object='libxmlsec1_openssl_la-x509.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+
+libxmlsec1_openssl_la-x509vfy.lo: x509vfy.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-x509vfy.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Tpo -c -o libxmlsec1_openssl_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Tpo $(DEPDIR)/libxmlsec1_openssl_la-x509vfy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509vfy.c' object='libxmlsec1_openssl_la-x509vfy.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+
+libxmlsec1_openssl_la-strings.lo: ../strings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_openssl_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_openssl_la-strings.Tpo -c -o libxmlsec1_openssl_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_openssl_la-strings.Tpo $(DEPDIR)/libxmlsec1_openssl_la-strings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_openssl_la-strings.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_openssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_openssl_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/openssl/README b/src/openssl/README
new file mode 100644
index 00000000..0f1c625d
--- /dev/null
+++ b/src/openssl/README
@@ -0,0 +1,17 @@
+WHAT VERSION OF OPENSSL?
+------------------------------------------------------------------------
+OpenSSL 0.9.6 is supported but some functionality requires 0.9.7 or greater.
+
+KEYS MANAGER
+------------------------------------------------------------------------
+
+OpenSSL does not have a keys or certificates storage implementation. The
+default xmlsec-openssl key manager uses a simple keys store from xmlsec
+core library based on plain keys list. Trusted/untrusted certificates
+are stored in STACK_OF(X509) structures.
+
+KNOWN ISSUES.
+------------------------------------------------------------------------
+1) One day we might decide to drop OpenSSL 0.9.6 supprot and remove all
+these ifdef's to simplify the code.
+
diff --git a/src/openssl/app.c b/src/openssl/app.c
new file mode 100644
index 00000000..4f8f79e6
--- /dev/null
+++ b/src/openssl/app.c
@@ -0,0 +1,1628 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <libxml/tree.h>
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/conf.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/private.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/app.h>
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+#include <xmlsec/openssl/x509.h>
+
+static int xmlSecOpenSSLAppLoadRANDFile (const char *file);
+static int xmlSecOpenSSLAppSaveRANDFile (const char *file);
+static int xmlSecOpenSSLDefaultPasswordCallback (char *buf,
+ int bufsiz,
+ int verify,
+ void *userdata);
+static int xmlSecOpenSSLDummyPasswordCallback (char *buf,
+ int bufsize,
+ int verify,
+ void *userdata);
+
+/* conversion from ptr to func "the right way" */
+XMLSEC_PTR_TO_FUNC_IMPL(pem_password_cb)
+
+
+/**
+ * xmlSecOpenSSLAppInit:
+ * @config: the path to certs.
+ *
+ * General crypto engine initialization. This function is used
+ * by XMLSec command line utility and called before
+ * @xmlSecInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppInit(const char* config) {
+ ERR_load_crypto_strings();
+ OPENSSL_config(NULL);
+ OpenSSL_add_all_algorithms();
+
+ if((RAND_status() != 1) && (xmlSecOpenSSLAppLoadRANDFile(NULL) != 1)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppLoadRANDFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((config != NULL) && (xmlSecOpenSSLSetDefaultTrustedCertsFolder(BAD_CAST config) < 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLSetDefaultTrustedCertsFolder",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppShutdown:
+ *
+ * General crypto engine shutdown. This function is used
+ * by XMLSec command line utility and called after
+ * @xmlSecShutdown function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppShutdown(void) {
+ xmlSecOpenSSLAppSaveRANDFile(NULL);
+ RAND_cleanup();
+ EVP_cleanup();
+
+#ifndef XMLSEC_NO_X509
+ X509_TRUST_cleanup();
+#endif /* XMLSEC_NO_X509 */
+
+#ifndef XMLSEC_OPENSSL_096
+ CRYPTO_cleanup_all_ex_data();
+#endif /* XMLSEC_OPENSSL_096 */
+
+ /* finally cleanup errors */
+ ERR_remove_state(0);
+ ERR_free_strings();
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeyLoad:
+ * @filename: the key filename.
+ * @format: the key file format.
+ * @pwd: the key file password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from the a file.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback,
+ void* pwdCallbackCtx) {
+ BIO* bio;
+ xmlSecKeyPtr key;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ bio = BIO_new_file(filename, "rb");
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ return(NULL);
+ }
+
+ key = xmlSecOpenSSLAppKeyLoadBIO (bio, format, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeyLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ BIO_free(bio);
+ return(NULL);
+ }
+
+ BIO_free(bio);
+ return(key);
+}
+
+/**
+ * xmlSecOpenSSLAppKeyLoadMemory:
+ * @data: the binary key data.
+ * @dataSize: the size of binary key.
+ * @format: the key file format.
+ * @pwd: the key file password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from the memory buffer.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format, const char *pwd,
+ void* pwdCallback, void* pwdCallbackCtx) {
+ BIO* bio;
+ xmlSecKeyPtr key;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* this would be a read only BIO, cast from const is ok */
+ bio = BIO_new_mem_buf((void*)data, dataSize);
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_mem_buf",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "errno=%d",
+ errno);
+ return(NULL);
+ }
+
+ key = xmlSecOpenSSLAppKeyLoadBIO (bio, format, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeyLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free(bio);
+ return(NULL);
+ }
+
+ BIO_free(bio);
+ return(key);
+}
+
+
+/**
+ * xmlSecOpenSSLAppKeyLoadBIO:
+ * @bio: the key BIO.
+ * @format: the key file format.
+ * @pwd: the key file password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from the an OpenSSL BIO object.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppKeyLoadBIO(BIO* bio, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback,
+ void* pwdCallbackCtx) {
+
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyDataPtr data;
+ EVP_PKEY* pKey = NULL;
+ int ret;
+
+ xmlSecAssert2(bio != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+ case xmlSecKeyDataFormatPem:
+ /* try to read private key first */
+ if(pwd != NULL) {
+ pKey = PEM_read_bio_PrivateKey(bio, NULL,
+ xmlSecOpenSSLDummyPasswordCallback,
+ (void*)pwd);
+ } else {
+ pKey = PEM_read_bio_PrivateKey(bio, NULL,
+ XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback),
+ pwdCallbackCtx);
+ }
+ if(pKey == NULL) {
+ /* go to start of the file and try to read public key */
+ BIO_reset(bio);
+ pKey = PEM_read_bio_PUBKEY(bio, NULL,
+ XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback),
+ pwdCallbackCtx);
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PEM_read_bio_PrivateKey and PEM_read_bio_PUBKEY",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ }
+ break;
+ case xmlSecKeyDataFormatDer:
+ /* try to read private key first */
+ pKey = d2i_PrivateKey_bio(bio, NULL);
+ if(pKey == NULL) {
+ /* go to start of the file and try to read public key */
+ BIO_reset(bio);
+ pKey = d2i_PUBKEY_bio(bio, NULL);
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "d2i_PrivateKey_bio and d2i_PUBKEY_bio",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ }
+ break;
+ case xmlSecKeyDataFormatPkcs8Pem:
+ /* try to read private key first */
+ pKey = PEM_read_bio_PrivateKey(bio, NULL,
+ XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback),
+ pwdCallbackCtx);
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PEM_read_bio_PrivateKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ case xmlSecKeyDataFormatPkcs8Der:
+ /* try to read private key first */
+ pKey = d2i_PKCS8PrivateKey_bio(bio, NULL,
+ XMLSEC_PTR_TO_FUNC(pem_password_cb, pwdCallback),
+ pwdCallbackCtx);
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "d2i_PrivateKey_bio and d2i_PUBKEY_bio",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+#ifndef XMLSEC_NO_X509
+ case xmlSecKeyDataFormatPkcs12:
+ key = xmlSecOpenSSLAppPkcs12LoadBIO(bio, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppPkcs12LoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ return(key);
+
+ case xmlSecKeyDataFormatCertPem:
+ case xmlSecKeyDataFormatCertDer:
+ key = xmlSecOpenSSLAppKeyFromCertLoadBIO(bio, format);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeyFromCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ return(key);
+#endif /* XMLSEC_NO_X509 */
+
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ data = xmlSecOpenSSLEvpKeyAdopt(pKey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLEvpKeyAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ EVP_PKEY_free(pKey);
+ return(NULL);
+ }
+
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ xmlSecKeyDestroy(key);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+
+#ifndef XMLSEC_NO_X509
+static X509* xmlSecOpenSSLAppCertLoadBIO (BIO* bio,
+ xmlSecKeyDataFormat format);
+/**
+ * xmlSecOpenSSLAppKeyCertLoad:
+ * @key: the pointer to key.
+ * @filename: the certificate filename.
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from $@filename and adds it to key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) {
+ BIO* bio;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ bio = BIO_new_file(filename, "rb");
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLAppKeyCertLoadBIO (key, bio, format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeyCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ BIO_free(bio);
+ return(-1);
+ }
+
+ BIO_free(bio);
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeyCertLoadMemory:
+ * @key: the pointer to key.
+ * @data: the certificate binary data.
+ * @dataSize: the certificate binary data size.
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from memory buffer and adds it to key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecKeyDataFormat format) {
+ BIO* bio;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* this would be a read only BIO, cast from const is ok */
+ bio = BIO_new_mem_buf((void*)data, dataSize);
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_mem_buf",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "errno=%d",
+ errno);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLAppKeyCertLoadBIO (key, bio, format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeyCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free(bio);
+ return(-1);
+ }
+
+ BIO_free(bio);
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeyCertLoadBIO:
+ * @key: the pointer to key.
+ * @bio: the certificate bio.
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from memory buffer and adds it to key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeyCertLoadBIO(xmlSecKeyPtr key, BIO* bio, xmlSecKeyDataFormat format) {
+
+ xmlSecKeyDataFormat certFormat;
+ xmlSecKeyDataPtr data;
+ X509 *cert;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(bio != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ data = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecOpenSSLKeyDataX509Id)));
+ return(-1);
+ }
+
+ /* adjust cert format */
+ switch(format) {
+ case xmlSecKeyDataFormatPkcs8Pem:
+ certFormat = xmlSecKeyDataFormatPem;
+ break;
+ case xmlSecKeyDataFormatPkcs8Der:
+ certFormat = xmlSecKeyDataFormatDer;
+ break;
+ default:
+ certFormat = format;
+ }
+
+ cert = xmlSecOpenSSLAppCertLoadBIO(bio, certFormat);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppCertLoad",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ X509_free(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppPkcs12Load:
+ * @filename: the PKCS12 key filename.
+ * @pwd: the PKCS12 file password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 file.
+ * For uniformity, call xmlSecOpenSSLAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppPkcs12Load(const char *filename, const char *pwd,
+ void* pwdCallback, void* pwdCallbackCtx) {
+ BIO* bio;
+ xmlSecKeyPtr key;
+
+ xmlSecAssert2(filename != NULL, NULL);
+
+ bio = BIO_new_file(filename, "rb");
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ return(NULL);
+ }
+
+ key = xmlSecOpenSSLAppPkcs12LoadBIO (bio, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppPkcs12LoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ BIO_free(bio);
+ return(NULL);
+ }
+
+ BIO_free(bio);
+ return(key);
+}
+
+/**
+ * xmlSecOpenSSLAppPkcs12LoadMemory:
+ * @data: the PKCS12 binary data.
+ * @dataSize: the PKCS12 binary data size.
+ * @pwd: the PKCS12 file password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 data in memory buffer.
+ * For uniformity, call xmlSecOpenSSLAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+ const char *pwd, void* pwdCallback,
+ void* pwdCallbackCtx) {
+ BIO* bio;
+ xmlSecKeyPtr key;
+
+ xmlSecAssert2(data != NULL, NULL);
+
+ /* this would be a read only BIO, cast from const is ok */
+ bio = BIO_new_mem_buf((void*)data, dataSize);
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_mem_buf",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "errno=%d",
+ errno);
+ return(NULL);
+ }
+
+ key = xmlSecOpenSSLAppPkcs12LoadBIO (bio, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppPkcs12LoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free(bio);
+ return(NULL);
+ }
+
+ BIO_free(bio);
+ return(key);
+}
+
+/**
+ * xmlSecOpenSSLAppPkcs12LoadBIO:
+ * @bio: the PKCS12 key bio.
+ * @pwd: the PKCS12 file password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 data in an OpenSSL BIO object.
+ * For uniformity, call xmlSecOpenSSLAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppPkcs12LoadBIO(BIO* bio, const char *pwd,
+ void* pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+
+ PKCS12 *p12 = NULL;
+ EVP_PKEY *pKey = NULL;
+ STACK_OF(X509) *chain = NULL;
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ X509 *cert = NULL;
+ X509 *tmpcert = NULL;
+ int i;
+ int has_cert;
+ int ret;
+
+ xmlSecAssert2(bio != NULL, NULL);
+
+ p12 = d2i_PKCS12_bio(bio, NULL);
+ if(p12 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "d2i_PKCS12_fp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = PKCS12_verify_mac(p12, pwd, (pwd != NULL) ? strlen(pwd) : 0);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PKCS12_verify_mac",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = PKCS12_parse(p12, pwd, &pKey, &cert, &chain);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PKCS12_parse",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ data = xmlSecOpenSSLEvpKeyAdopt(pKey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLEvpKeyAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ EVP_PKEY_free(pKey);
+ goto done;
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecOpenSSLKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecOpenSSLKeyDataX509Id)));
+ goto done;
+ }
+
+ /* starting from openssl 1.0.0 the PKCS12_parse() call will not create certs
+ chain object if there is no certificates in the pkcs12 file and it will be null
+ */
+ if(chain == NULL) {
+ chain = sk_X509_new_null();
+ if(chain == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "sk_X509_new_null",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ /*
+ The documentation states (http://www.openssl.org/docs/crypto/PKCS12_parse.html):
+
+ If successful the private key will be written to "*pkey", the
+ corresponding certificate to "*cert" and any additional certificates
+ to "*ca".
+
+ In reality, the function sometime returns in the "ca" the certificates
+ including the one it is already returned in "cert".
+ */
+ has_cert = 0;
+ for(i = 0; i < sk_X509_num(chain); ++i) {
+ xmlSecAssert2(sk_X509_value(chain, i), NULL);
+
+ if(X509_cmp(sk_X509_value(chain, i), cert) == 0) {
+ has_cert = 1;
+ break;
+ }
+ }
+
+ if(has_cert == 0) {
+ tmpcert = X509_dup(cert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = sk_X509_push(chain, tmpcert);
+ if(ret < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "sk_X509_push",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ X509_free(tmpcert);
+ goto done;
+ }
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(x509Data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ cert = NULL;
+
+ for(i = 0; i < sk_X509_num(chain); ++i) {
+ xmlSecAssert2(sk_X509_value(chain, i), NULL);
+
+ tmpcert = X509_dup(sk_X509_value(chain, i));
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ X509_free(tmpcert);
+ goto done;
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ }
+
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ xmlSecKeyDestroy(key);
+ key = NULL;
+ goto done;
+ }
+ data = NULL;
+
+ ret = xmlSecKeyAdoptData(key, x509Data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyAdoptData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ xmlSecKeyDestroy(key);
+ key = NULL;
+ goto done;
+ }
+ x509Data = NULL;
+
+done:
+ if(x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if(chain != NULL) {
+ sk_X509_pop_free(chain, X509_free);
+ }
+ if(cert != NULL) {
+ X509_free(cert);
+ }
+ if(p12 != NULL) {
+ PKCS12_free(p12);
+ }
+ return(key);
+}
+
+/**
+ * xmlSecOpenSSLAppKeyFromCertLoadBIO:
+ * @bio: the BIO.
+ * @format: the cert format.
+ *
+ * Loads public key from cert.
+ *
+ * Returns: pointer to key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecOpenSSLAppKeyFromCertLoadBIO(BIO* bio, xmlSecKeyDataFormat format) {
+ xmlSecKeyPtr key;
+ xmlSecKeyDataPtr keyData;
+ xmlSecKeyDataPtr certData;
+ X509 *cert;
+ int ret;
+
+ xmlSecAssert2(bio != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* load cert */
+ cert = xmlSecOpenSSLAppCertLoadBIO(bio, format);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ /* get key value */
+ keyData = xmlSecOpenSSLX509CertGetKey(cert);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509CertGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert);
+ return(NULL);
+ }
+
+ /* create key */
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(keyData);
+ X509_free(cert);
+ return(NULL);
+ }
+
+ /* set key value */
+ ret = xmlSecKeySetValue(key, keyData);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlSecKeyDataDestroy(keyData);
+ X509_free(cert);
+ return(NULL);
+ }
+
+ /* create cert data */
+ certData = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id);
+ if(certData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ X509_free(cert);
+ return(NULL);
+ }
+
+ /* put cert in the cert data */
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(certData, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ X509_free(cert);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+
+/**
+ * xmlSecOpenSSLAppKeysMngrCertLoad:
+ * @mngr: the keys manager.
+ * @filename: the certificate file.
+ * @format: the certificate file format.
+ * @type: the flag that indicates is the certificate in @filename
+ * trusted or not.
+ *
+ * Reads cert from @filename and adds to the list of trusted or known
+ * untrusted certs in @store.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format, xmlSecKeyDataType type) {
+ BIO* bio;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ bio = BIO_new_file(filename, "rb");
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLAppKeysMngrCertLoadBIO(mngr, bio, format, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeysMngrCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename=%s;errno=%d",
+ xmlSecErrorsSafeString(filename),
+ errno);
+ BIO_free(bio);
+ return(-1);
+ }
+
+ BIO_free(bio);
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeysMngrCertLoadMemory:
+ * @mngr: the keys manager.
+ * @data: the certificate binary data.
+ * @dataSize: the certificate binary data size.
+ * @format: the certificate file format.
+ * @type: the flag that indicates is the certificate trusted or not.
+ *
+ * Reads cert from binary buffer @data and adds to the list of trusted or known
+ * untrusted certs in @store.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ BIO* bio;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* this would be a read only BIO, cast from const is ok */
+ bio = BIO_new_mem_buf((void*)data, dataSize);
+ if(bio == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new_mem_buf",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "errno=%d",
+ errno);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLAppKeysMngrCertLoadBIO(mngr, bio, format, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppKeysMngrCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free(bio);
+ return(-1);
+ }
+
+ BIO_free(bio);
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeysMngrCertLoadBIO:
+ * @mngr: the keys manager.
+ * @bio: the certificate BIO.
+ * @format: the certificate file format.
+ * @type: the flag that indicates is the certificate trusted or not.
+ *
+ * Reads cert from an OpenSSL BIO object and adds to the list of trusted or known
+ * untrusted certs in @store.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeysMngrCertLoadBIO(xmlSecKeysMngrPtr mngr, BIO* bio,
+ xmlSecKeyDataFormat format, xmlSecKeyDataType type) {
+ xmlSecKeyDataStorePtr x509Store;
+ X509* cert;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(bio != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecOpenSSLX509StoreId");
+ return(-1);
+ }
+
+ cert = xmlSecOpenSSLAppCertLoadBIO(bio, format);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLAppCertLoadBIO",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLX509StoreAdoptCert(x509Store, cert, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509StoreAdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeysMngrAddCertsPath:
+ * @mngr: the keys manager.
+ * @path: the path to trusted certificates.
+ *
+ * Reads cert from @path and adds to the list of trusted certificates.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeysMngrAddCertsPath(xmlSecKeysMngrPtr mngr, const char *path) {
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(path != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecOpenSSLX509StoreId");
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLX509StoreAddCertsPath(x509Store, path);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509StoreAddCertsPath",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "path=%s", xmlSecErrorsSafeString(path));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppKeysMngrAddCertsFile:
+ * @mngr: the keys manager.
+ * @file: the file containing trusted certificates.
+ *
+ * Reads certs from @file and adds to the list of trusted certificates.
+ * It is possible for @file to contain multiple certs.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppKeysMngrAddCertsFile(xmlSecKeysMngrPtr mngr, const char *file) {
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(file != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecOpenSSLX509StoreId");
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLX509StoreAddCertsFile(x509Store, file);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509StoreAddCertsFile",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "file=%s", xmlSecErrorsSafeString(file));
+ return(-1);
+ }
+
+ return(0);
+}
+
+static X509*
+xmlSecOpenSSLAppCertLoadBIO(BIO* bio, xmlSecKeyDataFormat format) {
+ X509 *cert;
+
+ xmlSecAssert2(bio != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+ case xmlSecKeyDataFormatPem:
+ case xmlSecKeyDataFormatCertPem:
+ cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PEM_read_bio_X509_AUX",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ case xmlSecKeyDataFormatDer:
+ case xmlSecKeyDataFormatCertDer:
+ cert = d2i_X509_bio(bio, NULL);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "d2i_X509_bio",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ return(cert);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecOpenSSLAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId
+ * and a default OpenSSL crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* create simple keys store if needed */
+ if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) {
+ xmlSecKeyStorePtr keysStore;
+
+ keysStore = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId);
+ if(keysStore == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecSimpleKeysStoreId");
+ return(-1);
+ }
+
+ ret = xmlSecKeysMngrAdoptKeysStore(mngr, keysStore);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrAdoptKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyStoreDestroy(keysStore);
+ return(-1);
+ }
+ }
+
+ ret = xmlSecOpenSSLKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* TODO */
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecOpenSSLAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecSimpleKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSimpleKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecOpenSSLAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecSimpleKeysStoreLoad(store, uri, mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSimpleKeysStoreLoad",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s", xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLAppDefaultKeysMngrSave:
+ * @mngr: the pointer to keys manager.
+ * @filename: the destination filename.
+ * @type: the type of keys to save (public/private/symmetric).
+ *
+ * Saves keys from @mngr to XML keys file.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename,
+ xmlSecKeyDataType type) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecSimpleKeysStoreSave(store, filename, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecSimpleKeysStoreSave",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename%s", xmlSecErrorsSafeString(filename));
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/*
+ * Random numbers initialization from openssl (apps/app_rand.c)
+ */
+static int seeded = 0;
+static int egdsocket = 0;
+
+static int
+xmlSecOpenSSLAppLoadRANDFile(const char *file) {
+ char buffer[1024];
+
+ if(file == NULL) {
+ file = RAND_file_name(buffer, sizeof(buffer));
+ }else if(RAND_egd(file) > 0) {
+ /* we try if the given filename is an EGD socket.
+ * if it is, we don't write anything back to the file. */
+ egdsocket = 1;
+ return 1;
+ }
+
+ if((file == NULL) || !RAND_load_file(file, -1)) {
+ if(RAND_status() == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "RAND_load_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "file=%s", xmlSecErrorsSafeString(file));
+ return 0;
+ }
+ }
+ seeded = 1;
+ return 1;
+}
+
+static int
+xmlSecOpenSSLAppSaveRANDFile(const char *file) {
+ char buffer[1024];
+
+ if(egdsocket || !seeded) {
+ /* If we did not manage to read the seed file,
+ * we should not write a low-entropy seed file back --
+ * it would suppress a crucial warning the next time
+ * we want to use it. */
+ return 0;
+ }
+
+ if(file == NULL) {
+ file = RAND_file_name(buffer, sizeof(buffer));
+ }
+ if((file == NULL) || !RAND_write_file(file)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "RAND_write_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "file=%s",
+ xmlSecErrorsSafeString(file));
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * xmlSecOpenSSLAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecOpenSSLAppGetDefaultPwdCallback(void) {
+ return XMLSEC_FUNC_TO_PTR(pem_password_cb, xmlSecOpenSSLDefaultPasswordCallback);
+}
+
+static int
+xmlSecOpenSSLDefaultPasswordCallback(char *buf, int bufsize, int verify, void *userdata) {
+ char* filename = (char*)userdata;
+ char* buf2;
+ xmlChar prompt[2048];
+ int i, ret;
+
+ xmlSecAssert2(buf != NULL, -1);
+
+ /* try 3 times */
+ for(i = 0; i < 3; i++) {
+ if(filename != NULL) {
+ xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password for \"%s\" file: ", filename);
+ } else {
+ xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password: ");
+ }
+ ret = EVP_read_pw_string(buf, bufsize, (char*)prompt, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "EVP_read_pw_string",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* if we don't need to verify password then we are done */
+ if(verify == 0) {
+ return(strlen(buf));
+ }
+
+ if(filename != NULL) {
+ xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password for \"%s\" file again: ", filename);
+ } else {
+ xmlSecStrPrintf(prompt, sizeof(prompt), BAD_CAST "Enter password again: ");
+ }
+
+ buf2 = (char*)xmlMalloc(bufsize);
+ if(buf2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "size=%d", bufsize);
+ return(-1);
+ }
+ ret = EVP_read_pw_string(buf2, bufsize, (char*)prompt, 0);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "EVP_read_pw_string",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ memset(buf2, 0, bufsize);
+ xmlFree(buf2);
+ return(-1);
+ }
+
+ /* check if passwords match */
+ if(strcmp(buf, buf2) == 0) {
+ memset(buf2, 0, bufsize);
+ xmlFree(buf2);
+ return(strlen(buf));
+ }
+
+ /* try again */
+ memset(buf2, 0, bufsize);
+ xmlFree(buf2);
+ }
+
+ return(-1);
+}
+
+static int
+xmlSecOpenSSLDummyPasswordCallback(char *buf, int bufsize,
+ int verify ATTRIBUTE_UNUSED,
+ void *userdata) {
+ char* password = (char*)userdata;
+
+ if((password == NULL) || ((int)strlen(password) + 1 > bufsize)) {
+ return(-1);
+ }
+
+ strcpy(buf, password);
+ return (strlen(buf));
+}
+
diff --git a/src/openssl/bn.c b/src/openssl/bn.c
new file mode 100644
index 00000000..dfeae6ea
--- /dev/null
+++ b/src/openssl/bn.c
@@ -0,0 +1,163 @@
+/**
+ * XMLSec library
+ *
+ * Reading/writing BIGNUM values
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/bn.h>
+
+/**
+ * xmlSecOpenSSLNodeGetBNValue:
+ * @cur: the poitner to an XML node.
+ * @a: the BIGNUM buffer.
+ *
+ * Converts the node content from CryptoBinary format
+ * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
+ * to a BIGNUM. If no BIGNUM buffer provided then a new
+ * BIGNUM is created (caller is responsible for freeing it).
+ *
+ * Returns: a pointer to BIGNUM produced from CryptoBinary string
+ * or NULL if an error occurs.
+ */
+BIGNUM*
+xmlSecOpenSSLNodeGetBNValue(const xmlNodePtr cur, BIGNUM **a) {
+ xmlSecBuffer buf;
+ int ret;
+
+ xmlSecAssert2(cur != NULL, NULL);
+
+ ret = xmlSecBufferInitialize(&buf, 128);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecBufferBase64NodeContentRead(&buf, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferBase64NodeContentRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(NULL);
+ }
+
+ (*a) = BN_bin2bn(xmlSecBufferGetData(&buf), xmlSecBufferGetSize(&buf), (*a));
+ if( (*a) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_bin2bn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(NULL);
+ }
+ xmlSecBufferFinalize(&buf);
+ return(*a);
+}
+
+/**
+ * xmlSecOpenSSLNodeSetBNValue:
+ * @cur: the pointer to an XML node.
+ * @a: the BIGNUM.
+ * @addLineBreaks: if the flag is equal to 1 then
+ * linebreaks will be added before and after
+ * new buffer content.
+ *
+ * Converts BIGNUM to CryptoBinary string
+ * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
+ * and sets it as the content of the given node. If the
+ * addLineBreaks is set then line breaks are added
+ * before and after the CryptoBinary string.
+ *
+ * Returns: 0 on success or -1 otherwise.
+ */
+int
+xmlSecOpenSSLNodeSetBNValue(xmlNodePtr cur, const BIGNUM *a, int addLineBreaks) {
+ xmlSecBuffer buf;
+ xmlSecSize size;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&buf, BN_num_bytes(a) + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", BN_num_bytes(a) + 1);
+ return(-1);
+ }
+
+ ret = BN_bn2bin(a, xmlSecBufferGetData(&buf));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_bn2bin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+ size = ret;
+
+ ret = xmlSecBufferSetSize(&buf, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ if(addLineBreaks) {
+ xmlNodeSetContent(cur, xmlSecStringCR);
+ } else {
+ xmlNodeSetContent(cur, xmlSecStringEmpty);
+ }
+
+ ret = xmlSecBufferBase64NodeContentWrite(&buf, cur, xmlSecBase64GetDefaultLineSize());
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferBase64NodeContentWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ if(addLineBreaks) {
+ xmlNodeAddContent(cur, xmlSecStringCR);
+ }
+
+ xmlSecBufferFinalize(&buf);
+ return(0);
+}
+
diff --git a/src/openssl/ciphers.c b/src/openssl/ciphers.c
new file mode 100644
index 00000000..1b600625
--- /dev/null
+++ b/src/openssl/ciphers.c
@@ -0,0 +1,856 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+
+/* this is not defined in OpenSSL 0.9.6 */
+#ifndef EVP_MAX_BLOCK_LENGTH
+#define EVP_MAX_BLOCK_LENGTH 32
+#endif /* EVP_MAX_BLOCK_LENGTH */
+
+/**************************************************************************
+ *
+ * Internal OpenSSL Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecOpenSSLEvpBlockCipherCtx xmlSecOpenSSLEvpBlockCipherCtx,
+ *xmlSecOpenSSLEvpBlockCipherCtxPtr;
+struct _xmlSecOpenSSLEvpBlockCipherCtx {
+ const EVP_CIPHER* cipher;
+ xmlSecKeyDataId keyId;
+ EVP_CIPHER_CTX cipherCtx;
+ int keyInitialized;
+ int ctxInitialized;
+ xmlSecByte key[EVP_MAX_KEY_LENGTH];
+ xmlSecByte iv[EVP_MAX_IV_LENGTH];
+ xmlSecByte pad[EVP_MAX_BLOCK_LENGTH];
+};
+static int xmlSecOpenSSLEvpBlockCipherCtxInit (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLEvpBlockCipherCtxUpdate (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLEvpBlockCipherCtxFinal (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr out,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int
+xmlSecOpenSSLEvpBlockCipherCtxInit(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ int ivLen;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized != 0, -1);
+ xmlSecAssert2(ctx->ctxInitialized == 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ivLen = EVP_CIPHER_iv_length(ctx->cipher);
+ xmlSecAssert2(ivLen > 0, -1);
+ xmlSecAssert2((xmlSecSize)ivLen <= sizeof(ctx->iv), -1);
+
+ if(encrypt) {
+ /* generate random iv */
+ ret = RAND_bytes(ctx->iv, ivLen);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "RAND_bytes",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", ivLen);
+ return(-1);
+ }
+
+ /* write iv to the output */
+ ret = xmlSecBufferAppend(out, ctx->iv, ivLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", ivLen);
+ return(-1);
+ }
+
+ } else {
+ /* if we don't have enough data, exit and hope that
+ * we'll have iv next time */
+ if(xmlSecBufferGetSize(in) < (xmlSecSize)ivLen) {
+ return(0);
+ }
+
+ /* copy iv to our buffer*/
+ xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
+ memcpy(ctx->iv, xmlSecBufferGetData(in), ivLen);
+
+ /* and remove from input */
+ ret = xmlSecBufferRemoveHead(in, ivLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", ivLen);
+ return(-1);
+ }
+ }
+
+ /* set iv */
+ ret = EVP_CipherInit(&(ctx->cipherCtx), ctx->cipher, ctx->key, ctx->iv, encrypt);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "EVP_CipherInit",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->ctxInitialized = 1;
+
+ /*
+ * The padding used in XML Enc does not follow RFC 1423
+ * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7
+ * it is possible to disable padding and do it by yourself
+ * For OpenSSL 0.9.6 you have interop problems
+ */
+#ifndef XMLSEC_OPENSSL_096
+ EVP_CIPHER_CTX_set_padding(&(ctx->cipherCtx), 0);
+#endif /* XMLSEC_OPENSSL_096 */
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherCtxUpdate(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ int blockLen, fixLength = 0, outLen = 0;
+ xmlSecSize inSize, outSize;
+ xmlSecByte* outBuf;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized != 0, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = EVP_CIPHER_block_size(ctx->cipher);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(inSize == 0) {
+ /* wait for more data */
+ return(0);
+ }
+
+ /* OpenSSL docs: The amount of data written depends on the block
+ * alignment of the encrypted data: as a result the amount of data
+ * written may be anything from zero bytes to (inl + cipher_block_size - 1).
+ */
+ ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + inSize + blockLen);
+ return(-1);
+ }
+ outBuf = xmlSecBufferGetData(out) + outSize;
+
+ /*
+ * The padding used in XML Enc does not follow RFC 1423
+ * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7
+ * it is possible to disable padding and do it by yourself
+ * For OpenSSL 0.9.6 you have interop problems.
+ *
+ * The logic below is copied from EVP_DecryptUpdate() function.
+ * This is a hack but it's the only way I can provide binary
+ * compatibility with previous versions of xmlsec.
+ * This needs to be fixed in the next XMLSEC API refresh.
+ */
+#ifndef XMLSEC_OPENSSL_096
+ if(!ctx->cipherCtx.encrypt) {
+ if(ctx->cipherCtx.final_used) {
+ memcpy(outBuf, ctx->cipherCtx.final, blockLen);
+ outBuf += blockLen;
+ fixLength = 1;
+ } else {
+ fixLength = 0;
+ }
+ }
+#endif /* XMLSEC_OPENSSL_096 */
+
+ /* encrypt/decrypt */
+ ret = EVP_CipherUpdate(&(ctx->cipherCtx), outBuf, &outLen, xmlSecBufferGetData(in), inSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "EVP_CipherUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_OPENSSL_096
+ if(!ctx->cipherCtx.encrypt) {
+ /*
+ * The logic below is copied from EVP_DecryptUpdate() function.
+ * This is a hack but it's the only way I can provide binary
+ * compatibility with previous versions of xmlsec.
+ * This needs to be fixed in the next XMLSEC API refresh.
+ */
+ if (blockLen > 1 && !ctx->cipherCtx.buf_len) {
+ outLen -= blockLen;
+ ctx->cipherCtx.final_used = 1;
+ memcpy(ctx->cipherCtx.final, &outBuf[outLen], blockLen);
+ } else {
+ ctx->cipherCtx.final_used = 0;
+ }
+ if (fixLength) {
+ outLen += blockLen;
+ }
+ }
+#endif /* XMLSEC_OPENSSL_096 */
+
+ /* set correct output buffer size */
+ ret = xmlSecBufferSetSize(out, outSize + outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen);
+ return(-1);
+ }
+
+ /* remove the processed block from input */
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherCtxFinal(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr out,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ int blockLen, outLen = 0, outLen2 = 0;
+ xmlSecSize outSize;
+ xmlSecByte* outBuf;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized != 0, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = EVP_CIPHER_block_size(ctx->cipher);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ outSize = xmlSecBufferGetSize(out);
+
+ /* OpenSSL docs: The encrypted final data is written to out which should
+ * have sufficient space for one cipher block. We might have to write
+ * one more block with padding
+ */
+ ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + 2 * blockLen);
+ return(-1);
+ }
+ outBuf = xmlSecBufferGetData(out) + outSize;
+
+ /*
+ * The padding used in XML Enc does not follow RFC 1423
+ * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7
+ * it is possible to disable padding and do it by yourself
+ * For OpenSSL 0.9.6 you have interop problems.
+ *
+ * The logic below is copied from EVP_DecryptFinal() function.
+ * This is a hack but it's the only way I can provide binary
+ * compatibility with previous versions of xmlsec.
+ * This needs to be fixed in the next XMLSEC API refresh.
+ */
+#ifndef XMLSEC_OPENSSL_096
+ if(ctx->cipherCtx.encrypt) {
+ int padLen;
+
+ xmlSecAssert2(blockLen <= EVP_MAX_BLOCK_LENGTH, -1);
+
+ padLen = blockLen - ctx->cipherCtx.buf_len;
+ xmlSecAssert2(padLen > 0, -1);
+
+ /* generate random padding */
+ if(padLen > 1) {
+ ret = RAND_bytes(ctx->pad, padLen - 1);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "RAND_bytes",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", padLen - 1);
+ return(-1);
+ }
+ }
+ ctx->pad[padLen - 1] = padLen;
+
+ /* write padding */
+ ret = EVP_CipherUpdate(&(ctx->cipherCtx), outBuf, &outLen, ctx->pad, padLen);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "EVP_CipherUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outBuf += outLen;
+ }
+#endif /* XMLSEC_OPENSSL_096 */
+
+ /* finalize transform */
+ ret = EVP_CipherFinal(&(ctx->cipherCtx), outBuf, &outLen2);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "EVP_CipherFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /*
+ * The padding used in XML Enc does not follow RFC 1423
+ * and is not supported by OpenSSL. In the case of OpenSSL 0.9.7
+ * it is possible to disable padding and do it by yourself
+ * For OpenSSL 0.9.6 you have interop problems.
+ *
+ * The logic below is copied from EVP_DecryptFinal() function.
+ * This is a hack but it's the only way I can provide binary
+ * compatibility with previous versions of xmlsec.
+ * This needs to be fixed in the next XMLSEC API refresh.
+ */
+#ifndef XMLSEC_OPENSSL_096
+ if(!ctx->cipherCtx.encrypt) {
+ /* we instructed openssl to do not use padding so there
+ * should be no final block
+ */
+ xmlSecAssert2(outLen2 == 0, -1);
+ xmlSecAssert2(ctx->cipherCtx.buf_len == 0, -1);
+ xmlSecAssert2(ctx->cipherCtx.final_used, -1);
+
+ if(blockLen > 1) {
+ outLen2 = blockLen - ctx->cipherCtx.final[blockLen - 1];
+ if(outLen2 > 0) {
+ memcpy(outBuf, ctx->cipherCtx.final, outLen2);
+ } else if(outLen2 < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "padding=%d;buffer=%d",
+ ctx->cipherCtx.final[blockLen - 1], blockLen);
+ return(-1);
+ }
+ }
+ }
+#endif /* XMLSEC_OPENSSL_096 */
+
+ /* set correct output buffer size */
+ ret = xmlSecBufferSetSize(out, outSize + outLen + outLen2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen + outLen2);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/******************************************************************************
+ *
+ * EVP Block Cipher transforms
+ *
+ * xmlSecOpenSSLEvpBlockCipherCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecOpenSSLEvpBlockCipherSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLEvpBlockCipherCtx))
+#define xmlSecOpenSSLEvpBlockCipherGetCtx(transform) \
+ ((xmlSecOpenSSLEvpBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecOpenSSLEvpBlockCipherInitialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLEvpBlockCipherFinalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLEvpBlockCipherSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLEvpBlockCipherSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLEvpBlockCipherExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLEvpBlockCipherCheckId (xmlSecTransformPtr transform);
+
+
+
+static int
+xmlSecOpenSSLEvpBlockCipherCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DES
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDes3CbcId)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformAes128CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformAes192CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformAes256CbcId)) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherInitialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLEvpBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1);
+
+ ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLEvpBlockCipherCtx));
+
+#ifndef XMLSEC_NO_DES
+ if(transform->id == xmlSecOpenSSLTransformDes3CbcId) {
+ ctx->cipher = EVP_des_ede3_cbc();
+ ctx->keyId = xmlSecOpenSSLKeyDataDesId;
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(transform->id == xmlSecOpenSSLTransformAes128CbcId) {
+ ctx->cipher = EVP_aes_128_cbc();
+ ctx->keyId = xmlSecOpenSSLKeyDataAesId;
+ } else if(transform->id == xmlSecOpenSSLTransformAes192CbcId) {
+ ctx->cipher = EVP_aes_192_cbc();
+ ctx->keyId = xmlSecOpenSSLKeyDataAesId;
+ } else if(transform->id == xmlSecOpenSSLTransformAes256CbcId) {
+ ctx->cipher = EVP_aes_256_cbc();
+ ctx->keyId = xmlSecOpenSSLKeyDataAesId;
+ } else
+#endif /* XMLSEC_NO_AES */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ EVP_CIPHER_CTX_init(&(ctx->cipherCtx));
+ return(0);
+}
+
+static void
+xmlSecOpenSSLEvpBlockCipherFinalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLEvpBlockCipherCtxPtr ctx;
+
+ xmlSecAssert(xmlSecOpenSSLEvpBlockCipherCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize));
+
+ ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ EVP_CIPHER_CTX_cleanup(&(ctx->cipherCtx));
+ memset(ctx, 0, sizeof(xmlSecOpenSSLEvpBlockCipherCtx));
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecOpenSSLEvpBlockCipherCtxPtr ctx;
+ int cipherKeyLen;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+
+ keyReq->keyId = ctx->keyId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+
+ cipherKeyLen = EVP_CIPHER_key_length(ctx->cipher);
+ xmlSecAssert2(cipherKeyLen > 0, -1);
+
+ keyReq->keyBitsSize = (xmlSecSize)(8 * cipherKeyLen);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLEvpBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ int cipherKeyLen;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized == 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ cipherKeyLen = EVP_CIPHER_key_length(ctx->cipher);
+ xmlSecAssert2(cipherKeyLen > 0, -1);
+ xmlSecAssert2((xmlSecSize)cipherKeyLen <= sizeof(ctx->key), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) < (xmlSecSize)cipherKeyLen) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "keySize=%d;expected=%d",
+ xmlSecBufferGetSize(buffer), cipherKeyLen);
+ return(-1);
+ }
+
+ xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
+ memcpy(ctx->key, xmlSecBufferGetData(buffer), cipherKeyLen);
+
+ ctx->keyInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLEvpBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpBlockCipherSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ if(ctx->ctxInitialized == 0) {
+ ret = xmlSecOpenSSLEvpBlockCipherCtxInit(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpBlockCipherCtxInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ if((ctx->ctxInitialized == 0) && (last != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "not enough data to initialize transform");
+ return(-1);
+ }
+
+ if(ctx->ctxInitialized != 0) {
+ ret = xmlSecOpenSSLEvpBlockCipherCtxUpdate(ctx, in, out,
+ xmlSecTransformGetName(transform),
+ transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpBlockCipherCtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(last != 0) {
+ /* by now there should be no input */
+ xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
+ ret = xmlSecOpenSSLEvpBlockCipherCtxFinal(ctx, out,
+ xmlSecTransformGetName(transform),
+ transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpBlockCipherCtxFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
+ } else if(transform->status == xmlSecTransformStatusNone) {
+ /* the only way we can get here is if there is no enough data in the input */
+ xmlSecAssert2(last == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+#ifndef XMLSEC_NO_AES
+/*********************************************************************
+ *
+ * AES CBC cipher transforms
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLAes128CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes128Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes128Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformAes128CbcGetKlass(void) {
+ return(&xmlSecOpenSSLAes128CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecOpenSSLAes192CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes192Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes192Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformAes192CbcGetKlass(void) {
+ return(&xmlSecOpenSSLAes192CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecOpenSSLAes256CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes256Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes256Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformAes256CbcGetKlass(void) {
+ return(&xmlSecOpenSSLAes256CbcKlass);
+}
+
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+static xmlSecTransformKlass xmlSecOpenSSLDes3CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameDes3Cbc, /* const xmlChar* name; */
+ xmlSecHrefDes3Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLEvpBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLEvpBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformDes3CbcGetKlass(void) {
+ return(&xmlSecOpenSSLDes3CbcKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/openssl/crypto.c b/src/openssl/crypto.c
new file mode 100644
index 00000000..aac8d09f
--- /dev/null
+++ b/src/openssl/crypto.c
@@ -0,0 +1,491 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/private.h>
+
+#include <xmlsec/openssl/app.h>
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/x509.h>
+
+static int xmlSecOpenSSLErrorsInit (void);
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecOpenSSLFunctions = NULL;
+static xmlChar* gXmlSecOpenSSLTrustedCertsFolder = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_openssl:
+ *
+ * Gets the pointer to xmlsec-openssl functions table.
+ *
+ * Returns: the xmlsec-openssl functions table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_openssl(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecOpenSSLFunctions != NULL) {
+ return(gXmlSecOpenSSLFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecOpenSSLFunctions = &functions;
+
+ /********************************************************************
+ *
+ * Crypto Init/shutdown
+ *
+ ********************************************************************/
+ gXmlSecOpenSSLFunctions->cryptoInit = xmlSecOpenSSLInit;
+ gXmlSecOpenSSLFunctions->cryptoShutdown = xmlSecOpenSSLShutdown;
+ gXmlSecOpenSSLFunctions->cryptoKeysMngrInit = xmlSecOpenSSLKeysMngrInit;
+
+ /********************************************************************
+ *
+ * Key data ids
+ *
+ ********************************************************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecOpenSSLFunctions->keyDataAesGetKlass = xmlSecOpenSSLKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecOpenSSLFunctions->keyDataDesGetKlass = xmlSecOpenSSLKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecOpenSSLFunctions->keyDataDsaGetKlass = xmlSecOpenSSLKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecOpenSSLFunctions->keyDataHmacGetKlass = xmlSecOpenSSLKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecOpenSSLFunctions->keyDataRsaGetKlass = xmlSecOpenSSLKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_X509
+ gXmlSecOpenSSLFunctions->keyDataX509GetKlass = xmlSecOpenSSLKeyDataX509GetKlass;
+ gXmlSecOpenSSLFunctions->keyDataRawX509CertGetKlass = xmlSecOpenSSLKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /********************************************************************
+ *
+ * Key data store ids
+ *
+ ********************************************************************/
+#ifndef XMLSEC_NO_X509
+ gXmlSecOpenSSLFunctions->x509StoreGetKlass = xmlSecOpenSSLX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /********************************************************************
+ *
+ * Crypto transforms ids
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecOpenSSLFunctions->transformAes128CbcGetKlass = xmlSecOpenSSLTransformAes128CbcGetKlass;
+ gXmlSecOpenSSLFunctions->transformAes192CbcGetKlass = xmlSecOpenSSLTransformAes192CbcGetKlass;
+ gXmlSecOpenSSLFunctions->transformAes256CbcGetKlass = xmlSecOpenSSLTransformAes256CbcGetKlass;
+ gXmlSecOpenSSLFunctions->transformKWAes128GetKlass = xmlSecOpenSSLTransformKWAes128GetKlass;
+ gXmlSecOpenSSLFunctions->transformKWAes192GetKlass = xmlSecOpenSSLTransformKWAes192GetKlass;
+ gXmlSecOpenSSLFunctions->transformKWAes256GetKlass = xmlSecOpenSSLTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecOpenSSLFunctions->transformDes3CbcGetKlass = xmlSecOpenSSLTransformDes3CbcGetKlass;
+ gXmlSecOpenSSLFunctions->transformKWDes3GetKlass = xmlSecOpenSSLTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecOpenSSLFunctions->transformDsaSha1GetKlass = xmlSecOpenSSLTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecOpenSSLFunctions->transformHmacMd5GetKlass = xmlSecOpenSSLTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecOpenSSLFunctions->transformHmacRipemd160GetKlass = xmlSecOpenSSLTransformHmacRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecOpenSSLFunctions->transformHmacSha1GetKlass = xmlSecOpenSSLTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ gXmlSecOpenSSLFunctions->transformHmacSha224GetKlass = xmlSecOpenSSLTransformHmacSha224GetKlass;
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecOpenSSLFunctions->transformHmacSha256GetKlass = xmlSecOpenSSLTransformHmacSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecOpenSSLFunctions->transformHmacSha384GetKlass = xmlSecOpenSSLTransformHmacSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecOpenSSLFunctions->transformHmacSha512GetKlass = xmlSecOpenSSLTransformHmacSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* MD5 ********************************/
+#ifndef XMLSEC_NO_MD5
+ gXmlSecOpenSSLFunctions->transformMd5GetKlass = xmlSecOpenSSLTransformMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+ /******************************* RIPEMD160 ********************************/
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecOpenSSLFunctions->transformRipemd160GetKlass = xmlSecOpenSSLTransformRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecOpenSSLFunctions->transformRsaMd5GetKlass = xmlSecOpenSSLTransformRsaMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecOpenSSLFunctions->transformRsaRipemd160GetKlass = xmlSecOpenSSLTransformRsaRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecOpenSSLFunctions->transformRsaSha1GetKlass = xmlSecOpenSSLTransformRsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ gXmlSecOpenSSLFunctions->transformRsaSha224GetKlass = xmlSecOpenSSLTransformRsaSha224GetKlass;
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecOpenSSLFunctions->transformRsaSha256GetKlass = xmlSecOpenSSLTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecOpenSSLFunctions->transformRsaSha384GetKlass = xmlSecOpenSSLTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecOpenSSLFunctions->transformRsaSha512GetKlass = xmlSecOpenSSLTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ gXmlSecOpenSSLFunctions->transformRsaPkcs1GetKlass = xmlSecOpenSSLTransformRsaPkcs1GetKlass;
+ gXmlSecOpenSSLFunctions->transformRsaOaepGetKlass = xmlSecOpenSSLTransformRsaOaepGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecOpenSSLFunctions->transformSha1GetKlass = xmlSecOpenSSLTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ gXmlSecOpenSSLFunctions->transformSha224GetKlass = xmlSecOpenSSLTransformSha224GetKlass;
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecOpenSSLFunctions->transformSha256GetKlass = xmlSecOpenSSLTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecOpenSSLFunctions->transformSha384GetKlass = xmlSecOpenSSLTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecOpenSSLFunctions->transformSha512GetKlass = xmlSecOpenSSLTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ /********************************************************************
+ *
+ * High level routines form xmlsec command line utility
+ *
+ ********************************************************************/
+ gXmlSecOpenSSLFunctions->cryptoAppInit = xmlSecOpenSSLAppInit;
+ gXmlSecOpenSSLFunctions->cryptoAppShutdown = xmlSecOpenSSLAppShutdown;
+ gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrInit = xmlSecOpenSSLAppDefaultKeysMngrInit;
+ gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecOpenSSLAppDefaultKeysMngrAdoptKey;
+ gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecOpenSSLAppDefaultKeysMngrLoad;
+ gXmlSecOpenSSLFunctions->cryptoAppDefaultKeysMngrSave = xmlSecOpenSSLAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecOpenSSLFunctions->cryptoAppKeysMngrCertLoad = xmlSecOpenSSLAppKeysMngrCertLoad;
+ gXmlSecOpenSSLFunctions->cryptoAppKeysMngrCertLoadMemory = xmlSecOpenSSLAppKeysMngrCertLoadMemory;
+ gXmlSecOpenSSLFunctions->cryptoAppPkcs12Load = xmlSecOpenSSLAppPkcs12Load;
+ gXmlSecOpenSSLFunctions->cryptoAppPkcs12LoadMemory = xmlSecOpenSSLAppPkcs12LoadMemory;
+ gXmlSecOpenSSLFunctions->cryptoAppKeyCertLoad = xmlSecOpenSSLAppKeyCertLoad;
+ gXmlSecOpenSSLFunctions->cryptoAppKeyCertLoadMemory = xmlSecOpenSSLAppKeyCertLoadMemory;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecOpenSSLFunctions->cryptoAppKeyLoad = xmlSecOpenSSLAppKeyLoad;
+ gXmlSecOpenSSLFunctions->cryptoAppKeyLoadMemory = xmlSecOpenSSLAppKeyLoadMemory;
+ gXmlSecOpenSSLFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecOpenSSLAppGetDefaultPwdCallback();
+
+ return(gXmlSecOpenSSLFunctions);
+}
+
+/**
+ * xmlSecOpenSSLInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLInit (void) {
+ /* Check loaded xmlsec library version */
+ if(xmlSecCheckVersionExact() != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCheckVersionExact",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(xmlSecOpenSSLErrorsInit() < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLErrorsInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* register our klasses */
+ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_openssl()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLShutdown(void) {
+ xmlSecOpenSSLSetDefaultTrustedCertsFolder(NULL);
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds OpenSSL specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+#ifndef XMLSEC_NO_X509
+ /* create x509 store if needed */
+ if(xmlSecKeysMngrGetDataStore(mngr, xmlSecOpenSSLX509StoreId) == NULL) {
+ xmlSecKeyDataStorePtr x509Store;
+
+ x509Store = xmlSecKeyDataStoreCreate(xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecOpenSSLX509StoreId");
+ return(-1);
+ }
+
+ ret = xmlSecKeysMngrAdoptDataStore(mngr, x509Store);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrAdoptDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataStoreDestroy(x509Store);
+ return(-1);
+ }
+ }
+#endif /* XMLSEC_NO_X509 */
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLGenerateRandom:
+ * @buffer: the destination buffer.
+ * @size: the numer of bytes to generate.
+ *
+ * Generates @size random bytes and puts result in @buffer.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLGenerateRandom(xmlSecBufferPtr buffer, xmlSecSize size) {
+ int ret;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2(size > 0, -1);
+
+ ret = xmlSecBufferSetSize(buffer, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+
+ /* get random data */
+ ret = RAND_bytes((xmlSecByte*)xmlSecBufferGetData(buffer), size);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "RAND_bytes",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLErrorsDefaultCallback:
+ * @file: the error location file name (__FILE__ macro).
+ * @line: the error location line number (__LINE__ macro).
+ * @func: the error location function name (__FUNCTION__ macro).
+ * @errorObject: the error specific error object
+ * @errorSubject: the error specific error subject.
+ * @reason: the error code.
+ * @msg: the additional error message.
+ *
+ * The default OpenSSL errors reporting callback function.
+ */
+void
+xmlSecOpenSSLErrorsDefaultCallback(const char* file, int line, const char* func,
+ const char* errorObject, const char* errorSubject,
+ int reason, const char* msg) {
+
+ ERR_put_error(XMLSEC_OPENSSL_ERRORS_LIB,
+ XMLSEC_OPENSSL_ERRORS_FUNCTION,
+ reason, file, line);
+ xmlSecErrorsDefaultCallback(file, line, func,
+ errorObject, errorSubject,
+ reason, msg);
+}
+
+static int
+xmlSecOpenSSLErrorsInit(void) {
+ static ERR_STRING_DATA xmlSecOpenSSLStrReasons[XMLSEC_ERRORS_MAX_NUMBER + 1];
+ static ERR_STRING_DATA xmlSecOpenSSLStrLib[]= {
+ { ERR_PACK(XMLSEC_OPENSSL_ERRORS_LIB,0,0), "xmlsec routines"},
+ { 0, NULL}
+ };
+ static ERR_STRING_DATA xmlSecOpenSSLStrDefReason[]= {
+ { XMLSEC_OPENSSL_ERRORS_LIB, "xmlsec lib"},
+ { 0, NULL}
+ };
+ xmlSecSize pos;
+
+ /* initialize reasons array */
+ memset(xmlSecOpenSSLStrReasons, 0, sizeof(xmlSecOpenSSLStrReasons));
+ for(pos = 0; (pos < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(pos) != NULL); ++pos) {
+ xmlSecOpenSSLStrReasons[pos].error = xmlSecErrorsGetCode(pos);
+ xmlSecOpenSSLStrReasons[pos].string = xmlSecErrorsGetMsg(pos);
+ }
+
+ /* finally load xmlsec strings in OpenSSL */
+ ERR_load_strings(XMLSEC_OPENSSL_ERRORS_LIB, xmlSecOpenSSLStrLib); /* define xmlsec lib name */
+ ERR_load_strings(XMLSEC_OPENSSL_ERRORS_LIB, xmlSecOpenSSLStrDefReason); /* define default reason */
+ ERR_load_strings(XMLSEC_OPENSSL_ERRORS_LIB, xmlSecOpenSSLStrReasons);
+
+ /* and set default errors callback for xmlsec to us */
+ xmlSecErrorsSetCallback(xmlSecOpenSSLErrorsDefaultCallback);
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLSetDefaultTrustedCertsFolder:
+ * @path: the default trusted certs path.
+ *
+ * Sets the default trusted certs folder.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLSetDefaultTrustedCertsFolder(const xmlChar* path) {
+ if(gXmlSecOpenSSLTrustedCertsFolder != NULL) {
+ xmlFree(gXmlSecOpenSSLTrustedCertsFolder);
+ gXmlSecOpenSSLTrustedCertsFolder = NULL;
+ }
+
+ if(path != NULL) {
+ gXmlSecOpenSSLTrustedCertsFolder = xmlStrdup(BAD_CAST path);
+ if(gXmlSecOpenSSLTrustedCertsFolder == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLGetDefaultTrustedCertsFolder:
+ *
+ * Gets the default trusted certs folder.
+ *
+ * Returns: the default trusted cert folder.
+ */
+const xmlChar*
+xmlSecOpenSSLGetDefaultTrustedCertsFolder(void) {
+ return(gXmlSecOpenSSLTrustedCertsFolder);
+}
+
+
+
diff --git a/src/openssl/digests.c b/src/openssl/digests.c
new file mode 100644
index 00000000..2dc32369
--- /dev/null
+++ b/src/openssl/digests.c
@@ -0,0 +1,682 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <openssl/evp.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+
+/**************************************************************************
+ *
+ * Internal OpenSSL Digest CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecOpenSSLDigestCtx xmlSecOpenSSLDigestCtx, *xmlSecOpenSSLDigestCtxPtr;
+struct _xmlSecOpenSSLDigestCtx {
+ const EVP_MD* digest;
+ EVP_MD_CTX digestCtx;
+ xmlSecByte dgst[EVP_MAX_MD_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+/******************************************************************************
+ *
+ * EVP Digest transforms
+ *
+ * xmlSecOpenSSLDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecOpenSSLEvpDigestSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLDigestCtx))
+#define xmlSecOpenSSLEvpDigestGetCtx(transform) \
+ ((xmlSecOpenSSLDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+
+static int xmlSecOpenSSLEvpDigestInitialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLEvpDigestFinalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLEvpDigestVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLEvpDigestExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLEvpDigestCheckId (xmlSecTransformPtr transform);
+
+static int
+xmlSecOpenSSLEvpDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha224Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+
+ {
+ return(0);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpDigestInitialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize), -1);
+
+ ctx = xmlSecOpenSSLEvpDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecOpenSSLDigestCtx));
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformMd5Id)) {
+ ctx->digest = EVP_md5();
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRipemd160Id)) {
+ ctx->digest = EVP_ripemd160();
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha1Id)) {
+ ctx->digest = EVP_sha1();
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha224Id)) {
+ ctx->digest = EVP_sha224();
+ } else
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha256Id)) {
+ ctx->digest = EVP_sha256();
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha384Id)) {
+ ctx->digest = EVP_sha384();
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformSha512Id)) {
+ ctx->digest = EVP_sha512();
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_OPENSSL_096
+ EVP_MD_CTX_init(&(ctx->digestCtx));
+#endif /* XMLSEC_OPENSSL_096 */
+
+ return(0);
+}
+
+static void
+xmlSecOpenSSLEvpDigestFinalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLDigestCtxPtr ctx;
+
+ xmlSecAssert(xmlSecOpenSSLEvpDigestCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize));
+
+ ctx = xmlSecOpenSSLEvpDigestGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+#ifndef XMLSEC_OPENSSL_096
+ EVP_MD_CTX_cleanup(&(ctx->digestCtx));
+#endif /* XMLSEC_OPENSSL_096 */
+ memset(ctx, 0, sizeof(xmlSecOpenSSLDigestCtx));
+}
+
+static int
+xmlSecOpenSSLEvpDigestVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ if(dataSize != ctx->dgstSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "data_size=%d;dgst_size=%d",
+ dataSize, ctx->dgstSize);
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ if(memcmp(ctx->dgst, data, ctx->dgstSize) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data and digest do not match");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLDigestCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpDigestCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpDigestSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ xmlSecAssert2(in != NULL, -1);
+
+ out = &(transform->outBuf);
+ xmlSecAssert2(out != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digest != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_DigestInit(&(ctx->digestCtx), ctx->digest);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_DigestInit",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_DigestInit(&(ctx->digestCtx), ctx->digest);
+#endif /* XMLSEC_OPENSSL_096 */
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_DigestUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_DigestUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_DigestUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize);
+#endif /* XMLSEC_OPENSSL_096 */
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ }
+ if(last) {
+ unsigned int dgstSize;
+
+ xmlSecAssert2((xmlSecSize)EVP_MD_size(ctx->digest) <= sizeof(ctx->dgst), -1);
+
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_DigestFinal(&(ctx->digestCtx), ctx->dgst, &dgstSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_DigestFinal(&(ctx->digestCtx), ctx->dgst, &dgstSize);
+#endif /* XMLSEC_OPENSSL_096 */
+ xmlSecAssert2(dgstSize > 0, -1);
+ ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize);
+
+ /* copy result to output */
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", ctx->dgstSize);
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+#ifndef XMLSEC_NO_MD5
+/******************************************************************************
+ *
+ * MD5
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameMd5, /* const xmlChar* name; */
+ xmlSecHrefMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformMd5GetKlass:
+ *
+ * MD5 digest transform klass.
+ *
+ * Returns: pointer to MD5 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformMd5GetKlass(void) {
+ return(&xmlSecOpenSSLMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+/******************************************************************************
+ *
+ * RIPEMD160
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameRipemd160, /* const xmlChar* name; */
+ xmlSecHrefRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRipemd160GetKlass:
+ *
+ * RIPEMD-160 digest transform klass.
+ *
+ * Returns: pointer to RIPEMD-160 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRipemd160GetKlass(void) {
+ return(&xmlSecOpenSSLRipemd160Klass);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * SHA1
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameSha1, /* const xmlChar* name; */
+ xmlSecHrefSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformSha1GetKlass(void) {
+ return(&xmlSecOpenSSLSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+/******************************************************************************
+ *
+ * SHA224
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLSha224Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameSha224, /* const xmlChar* name; */
+ xmlSecHrefSha224, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformSha224GetKlass:
+ *
+ * SHA-224 digest transform klass.
+ *
+ * Returns: pointer to SHA-224 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformSha224GetKlass(void) {
+ return(&xmlSecOpenSSLSha224Klass);
+}
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * SHA256
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameSha256, /* const xmlChar* name; */
+ xmlSecHrefSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformSha256GetKlass:
+ *
+ * SHA-256 digest transform klass.
+ *
+ * Returns: pointer to SHA-256 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformSha256GetKlass(void) {
+ return(&xmlSecOpenSSLSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * SHA384
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameSha384, /* const xmlChar* name; */
+ xmlSecHrefSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformSha384GetKlass:
+ *
+ * SHA-384 digest transform klass.
+ *
+ * Returns: pointer to SHA-384 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformSha384GetKlass(void) {
+ return(&xmlSecOpenSSLSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * SHA512
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpDigestSize, /* xmlSecSize objSize */
+
+ xmlSecNameSha512, /* const xmlChar* name; */
+ xmlSecHrefSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformSha512GetKlass:
+ *
+ * SHA-512 digest transform klass.
+ *
+ * Returns: pointer to SHA-512 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformSha512GetKlass(void) {
+ return(&xmlSecOpenSSLSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
diff --git a/src/openssl/evp.c b/src/openssl/evp.c
new file mode 100644
index 00000000..e48defd3
--- /dev/null
+++ b/src/openssl/evp.c
@@ -0,0 +1,1559 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/bn.h>
+#include <xmlsec/openssl/evp.h>
+
+/**************************************************************************
+ *
+ * Internal OpenSSL EVP key CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecOpenSSLEvpKeyDataCtx xmlSecOpenSSLEvpKeyDataCtx,
+ *xmlSecOpenSSLEvpKeyDataCtxPtr;
+struct _xmlSecOpenSSLEvpKeyDataCtx {
+ EVP_PKEY* pKey;
+};
+
+/******************************************************************************
+ *
+ * EVP key (dsa/rsa)
+ *
+ * xmlSecOpenSSLEvpKeyDataCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecOpenSSLEvpKeyDataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecOpenSSLEvpKeyDataCtx))
+#define xmlSecOpenSSLEvpKeyDataGetCtx(data) \
+ ((xmlSecOpenSSLEvpKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecOpenSSLEvpKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLEvpKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecOpenSSLEvpKeyDataFinalize (xmlSecKeyDataPtr data);
+
+/**
+ * xmlSecOpenSSLEvpKeyDataAdoptEvp:
+ * @data: the pointer to OpenSSL EVP key data.
+ * @pKey: the pointer to EVP key.
+ *
+ * Sets the value of key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLEvpKeyDataAdoptEvp(xmlSecKeyDataPtr data, EVP_PKEY* pKey) {
+ xmlSecOpenSSLEvpKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize), -1);
+ xmlSecAssert2(pKey != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->pKey != NULL) {
+ EVP_PKEY_free(ctx->pKey);
+ }
+ ctx->pKey = pKey;
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLEvpKeyDataGetEvp:
+ * @data: the pointer to OpenSSL EVP data.
+ *
+ * Gets the EVP_PKEY from the key data.
+ *
+ * Returns: pointer to EVP_PKEY or NULL if an error occurs.
+ */
+EVP_PKEY*
+xmlSecOpenSSLEvpKeyDataGetEvp(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLEvpKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize), NULL);
+
+ ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->pKey);
+}
+
+static int
+xmlSecOpenSSLEvpKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLEvpKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize), -1);
+
+ ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLEvpKeyDataCtx));
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecOpenSSLEvpKeyDataCtxPtr ctxDst;
+ xmlSecOpenSSLEvpKeyDataCtxPtr ctxSrc;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecOpenSSLEvpKeyDataSize), -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecOpenSSLEvpKeyDataSize), -1);
+
+ ctxDst = xmlSecOpenSSLEvpKeyDataGetCtx(dst);
+ xmlSecAssert2(ctxDst != NULL, -1);
+ xmlSecAssert2(ctxDst->pKey == NULL, -1);
+
+ ctxSrc = xmlSecOpenSSLEvpKeyDataGetCtx(src);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ if(ctxSrc->pKey != NULL) {
+ ctxDst->pKey = xmlSecOpenSSLEvpKeyDup(ctxSrc->pKey);
+ if(ctxDst->pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecOpenSSLEvpKeyDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static void
+xmlSecOpenSSLEvpKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLEvpKeyDataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecOpenSSLEvpKeyDataSize));
+
+ ctx = xmlSecOpenSSLEvpKeyDataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->pKey != NULL) {
+ EVP_PKEY_free(ctx->pKey);
+ }
+ memset(ctx, 0, sizeof(xmlSecOpenSSLEvpKeyDataCtx));
+}
+
+/******************************************************************************
+ *
+ * EVP helper functions
+ *
+ *****************************************************************************/
+/**
+ * xmlSecOpenSSLEvpKeyDup:
+ * @pKey: the pointer to EVP_PKEY.
+ *
+ * Duplicates @pKey.
+ *
+ * Returns: pointer to newly created EVP_PKEY object or NULL if an error occurs.
+ */
+EVP_PKEY*
+xmlSecOpenSSLEvpKeyDup(EVP_PKEY* pKey) {
+ int ret;
+
+ xmlSecAssert2(pKey != NULL, NULL);
+
+ ret = CRYPTO_add(&pKey->references,1,CRYPTO_LOCK_EVP_PKEY);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CRYPTO_add",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(pKey);
+}
+
+/**
+ * xmlSecOpenSSLEvpKeyAdopt:
+ * @pKey: the pointer to EVP_PKEY.
+ *
+ * Creates xmlsec key object from OpenSSL key object.
+ *
+ * Returns: pointer to newly created xmlsec key or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecOpenSSLEvpKeyAdopt(EVP_PKEY *pKey) {
+ xmlSecKeyDataPtr data = NULL;
+ int ret;
+
+ xmlSecAssert2(pKey != NULL, NULL);
+
+ switch(pKey->type) {
+#ifndef XMLSEC_NO_RSA
+ case EVP_PKEY_RSA:
+ data = xmlSecKeyDataCreate(xmlSecOpenSSLKeyDataRsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecOpenSSLKeyDataRsaId");
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_RSA */
+#ifndef XMLSEC_NO_DSA
+ case EVP_PKEY_DSA:
+ data = xmlSecKeyDataCreate(xmlSecOpenSSLKeyDataDsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecOpenSSLKeyDataDsaId");
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_DSA */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "evp key type %d not supported", pKey->type);
+ return(NULL);
+ }
+
+ xmlSecAssert2(data != NULL, NULL);
+ ret = xmlSecOpenSSLEvpKeyDataAdoptEvp(data, pKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLEvpKeyDataAdoptEvp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+ return(data);
+}
+
+#ifndef XMLSEC_NO_DSA
+/**************************************************************************
+ *
+ * <dsig:DSAKeyValue> processing
+ *
+ *
+ * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue)
+ *
+ * DSA keys and the DSA signature algorithm are specified in [DSS].
+ * DSA public key values can have the following fields:
+ *
+ * * P - a prime modulus meeting the [DSS] requirements
+ * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime
+ * divisor of P-1
+ * * G - an integer with certain properties with respect to P and Q
+ * * Y - G**X mod P (where X is part of the private key and not made
+ * public)
+ * * J - (P - 1) / Q
+ * * seed - a DSA prime generation seed
+ * * pgenCounter - a DSA prime generation counter
+ *
+ * Parameter J is available for inclusion solely for efficiency as it is
+ * calculatable from P and Q. Parameters seed and pgenCounter are used in the
+ * DSA prime number generation algorithm specified in [DSS]. As such, they are
+ * optional but must either both be present or both be absent. This prime
+ * generation algorithm is designed to provide assurance that a weak prime is
+ * not being used and it yields a P and Q value. Parameters P, Q, and G can be
+ * public and common to a group of users. They might be known from application
+ * context. As such, they are optional but P and Q must either both appear or
+ * both be absent. If all of P, Q, seed, and pgenCounter are present,
+ * implementations are not required to check if they are consistent and are
+ * free to use either P and Q or seed and pgenCounter. All parameters are
+ * encoded as base64 [MIME] values.
+ *
+ * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
+ * represented in XML as octet strings as defined by the ds:CryptoBinary type.
+ *
+ * Schema Definition:
+ *
+ * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
+ * <complexType name="DSAKeyValueType">
+ * <sequence>
+ * <sequence minOccurs="0">
+ * <element name="P" type="ds:CryptoBinary"/>
+ * <element name="Q" type="ds:CryptoBinary"/>
+ * </sequence>
+ * <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
+ * <element name="Y" type="ds:CryptoBinary"/>
+ * <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
+ * <sequence minOccurs="0">
+ * <element name="Seed" type="ds:CryptoBinary"/>
+ * <element name="PgenCounter" type="ds:CryptoBinary"/>
+ * </sequence>
+ * </sequence>
+ * </complexType>
+ *
+ * DTD Definition:
+ *
+ * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) >
+ * <!ELEMENT P (#PCDATA) >
+ * <!ELEMENT Q (#PCDATA) >
+ * <!ELEMENT G (#PCDATA) >
+ * <!ELEMENT Y (#PCDATA) >
+ * <!ELEMENT J (#PCDATA) >
+ * <!ELEMENT Seed (#PCDATA) >
+ * <!ELEMENT PgenCounter (#PCDATA) >
+ *
+ * ============================================================================
+ *
+ * To support reading/writing private keys an X element added (before Y).
+ * todo: The current implementation does not support Seed and PgenCounter!
+ * by this the P, Q and G are *required*!
+ *
+ *************************************************************************/
+static int xmlSecOpenSSLKeyDataDsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLKeyDataDsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecOpenSSLKeyDataDsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLKeyDataDsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLKeyDataDsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLKeyDataDsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecOpenSSLKeyDataDsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecOpenSSLKeyDataDsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecOpenSSLKeyDataDsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecOpenSSLKeyDataDsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataDsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecOpenSSLEvpKeyDataSize,
+
+ /* data */
+ xmlSecNameDSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecOpenSSLKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecOpenSSLKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecOpenSSLKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecOpenSSLKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecOpenSSLKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecOpenSSLKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecOpenSSLKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecOpenSSLKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecOpenSSLKeyDataDsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataDsaGetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataDsaKlass);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataDsaAdoptDsa:
+ * @data: the pointer to DSA key data.
+ * @dsa: the pointer to OpenSSL DSA key.
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLKeyDataDsaAdoptDsa(xmlSecKeyDataPtr data, DSA* dsa) {
+ EVP_PKEY* pKey = NULL;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1);
+
+ /* construct new EVP_PKEY */
+ if(dsa != NULL) {
+ pKey = EVP_PKEY_new();
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "EVP_PKEY_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = EVP_PKEY_assign_DSA(pKey, dsa);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "EVP_PKEY_assign_DSA",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ ret = xmlSecOpenSSLKeyDataDsaAdoptEvp(data, pKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataDsaAdoptEvp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ if(pKey != NULL) {
+ EVP_PKEY_free(pKey);
+ }
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataDsaGetDsa:
+ * @data: the pointer to DSA key data.
+ *
+ * Gets the OpenSSL DSA key from DSA key data.
+ *
+ * Returns: pointer to OpenSSL DSA key or NULL if an error occurs.
+ */
+DSA*
+xmlSecOpenSSLKeyDataDsaGetDsa(xmlSecKeyDataPtr data) {
+ EVP_PKEY* pKey;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), NULL);
+
+ pKey = xmlSecOpenSSLKeyDataDsaGetEvp(data);
+ xmlSecAssert2((pKey == NULL) || (pKey->type == EVP_PKEY_DSA), NULL);
+
+ return((pKey != NULL) ? pKey->pkey.dsa : (DSA*)NULL);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataDsaAdoptEvp:
+ * @data: the pointer to DSA key data.
+ * @pKey: the pointer to OpenSSL EVP key.
+ *
+ * Sets the DSA key data value to OpenSSL EVP key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLKeyDataDsaAdoptEvp(xmlSecKeyDataPtr data, EVP_PKEY* pKey) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1);
+ xmlSecAssert2(pKey != NULL, -1);
+ xmlSecAssert2(pKey->type == EVP_PKEY_DSA, -1);
+
+ return(xmlSecOpenSSLEvpKeyDataAdoptEvp(data, pKey));
+}
+
+/**
+ * xmlSecOpenSSLKeyDataDsaGetEvp:
+ * @data: the pointer to DSA key data.
+ *
+ * Gets the OpenSSL EVP key from DSA key data.
+ *
+ * Returns: pointer to OpenSSL EVP key or NULL if an error occurs.
+ */
+EVP_PKEY*
+xmlSecOpenSSLKeyDataDsaGetEvp(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), NULL);
+
+ return(xmlSecOpenSSLEvpKeyDataGetEvp(data));
+}
+
+static int
+xmlSecOpenSSLKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1);
+
+ return(xmlSecOpenSSLEvpKeyDataInitialize(data));
+}
+
+static int
+xmlSecOpenSSLKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecOpenSSLKeyDataDsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecOpenSSLKeyDataDsaId), -1);
+
+ return(xmlSecOpenSSLEvpKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecOpenSSLKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId));
+
+ xmlSecOpenSSLEvpKeyDataFinalize(data);
+}
+
+static int
+xmlSecOpenSSLKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ xmlNodePtr cur;
+ DSA *dsa;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if(xmlSecKeyGetValue(key) != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ dsa = DSA_new();
+ if(dsa == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "DSA_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ DSA_free(dsa);
+ return(-1);
+ }
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->p)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ DSA_free(dsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ DSA_free(dsa);
+ return(-1);
+ }
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->q)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ DSA_free(dsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ DSA_free(dsa);
+ return(-1);
+ }
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->g)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ DSA_free(dsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * we are not sure exactly what do we read */
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->priv_key)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAX));
+ DSA_free(dsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is Y node. */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ DSA_free(dsa);
+ return(-1);
+ }
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(dsa->pub_key)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ DSA_free(dsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* todo: add support for J */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* todo: add support for seed */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* todo: add support for pgencounter */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ DSA_free(dsa);
+ return(-1);
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ DSA_free(dsa);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataDsaAdoptDsa(data, dsa);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataDsaAdoptDsa",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ DSA_free(dsa);
+ return(-1);
+ }
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ DSA* dsa;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataDsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ dsa = xmlSecOpenSSLKeyDataDsaGetDsa(xmlSecKeyGetValue(key));
+ xmlSecAssert2(dsa != NULL, -1);
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* first is P node */
+ xmlSecAssert2(dsa->p != NULL, -1);
+ cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->p, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ return(-1);
+ }
+
+ /* next is Q node. */
+ xmlSecAssert2(dsa->q != NULL, -1);
+ cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->q, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ return(-1);
+ }
+
+ /* next is G node. */
+ xmlSecAssert2(dsa->g != NULL, -1);
+ cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->g, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ return(-1);
+ }
+
+ /* next is X node: write it ONLY for private keys and ONLY if it is requested */
+ if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (dsa->priv_key != NULL)) {
+ cur = xmlSecAddChild(node, xmlSecNodeDSAX, xmlSecNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAX));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->priv_key, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAX));
+ return(-1);
+ }
+ }
+
+ /* next is Y node. */
+ xmlSecAssert2(dsa->pub_key != NULL, -1);
+ cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, dsa->pub_key, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ DSA* dsa;
+ int counter_ret;
+ unsigned long h_ret;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ dsa = DSA_generate_parameters(sizeBits, NULL, 0, &counter_ret, &h_ret, NULL, NULL);
+ if(dsa == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "DSA_generate_parameters",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", sizeBits);
+ return(-1);
+ }
+
+ ret = DSA_generate_key(dsa);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "DSA_generate_key",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ DSA_free(dsa);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataDsaAdoptDsa(data, dsa);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataDsaAdoptDsa",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ DSA_free(dsa);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static xmlSecKeyDataType
+xmlSecOpenSSLKeyDataDsaGetType(xmlSecKeyDataPtr data) {
+ DSA* dsa;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), xmlSecKeyDataTypeUnknown);
+
+ dsa = xmlSecOpenSSLKeyDataDsaGetDsa(data);
+ if((dsa != NULL) && (dsa->p != NULL) && (dsa->q != NULL) &&
+ (dsa->g != NULL) && (dsa->pub_key != NULL)) {
+
+ if(dsa->priv_key != NULL) {
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else if(dsa->engine != NULL) {
+ /*
+ * !!! HACK !!! Also see RSA key
+ * We assume here that engine *always* has private key.
+ * This might be incorrect but it seems that there is no
+ * way to ask engine if given key is private or not.
+ */
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else {
+ return(xmlSecKeyDataTypePublic);
+ }
+ }
+
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecOpenSSLKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
+ DSA* dsa;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId), 0);
+
+ dsa = xmlSecOpenSSLKeyDataDsaGetDsa(data);
+ if((dsa != NULL) && (dsa->p != NULL)) {
+ return(BN_num_bits(dsa->p));
+ }
+ return(0);
+}
+
+static void
+xmlSecOpenSSLKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== dsa key: size = %d\n",
+ xmlSecOpenSSLKeyDataDsaGetSize(data));
+}
+
+static void
+xmlSecOpenSSLKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
+ xmlSecOpenSSLKeyDataDsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+/**************************************************************************
+ *
+ * <dsig:RSAKeyValue> processing
+ *
+ * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
+ * The RSAKeyValue Element
+ *
+ * RSA key values have two fields: Modulus and Exponent.
+ *
+ * <RSAKeyValue>
+ * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
+ * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
+ * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
+ * </Modulus>
+ * <Exponent>AQAB</Exponent>
+ * </RSAKeyValue>
+ *
+ * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
+ * represented in XML as octet strings as defined by the ds:CryptoBinary type.
+ *
+ * Schema Definition:
+ *
+ * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
+ * <complexType name="RSAKeyValueType">
+ * <sequence>
+ * <element name="Modulus" type="ds:CryptoBinary"/>
+ * <element name="Exponent" type="ds:CryptoBinary"/>
+ * </sequence>
+ * </complexType>
+ *
+ * DTD Definition:
+ *
+ * <!ELEMENT RSAKeyValue (Modulus, Exponent) >
+ * <!ELEMENT Modulus (#PCDATA) >
+ * <!ELEMENT Exponent (#PCDATA) >
+ *
+ * ============================================================================
+ *
+ * To support reading/writing private keys an PrivateExponent element is added
+ * to the end
+ *
+ *************************************************************************/
+
+static int xmlSecOpenSSLKeyDataRsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLKeyDataRsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecOpenSSLKeyDataRsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLKeyDataRsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLKeyDataRsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLKeyDataRsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecOpenSSLKeyDataRsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecOpenSSLKeyDataRsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecOpenSSLKeyDataRsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecOpenSSLKeyDataRsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataRsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecOpenSSLEvpKeyDataSize,
+
+ /* data */
+ xmlSecNameRSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecOpenSSLKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecOpenSSLKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecOpenSSLKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecOpenSSLKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecOpenSSLKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecOpenSSLKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecOpenSSLKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecOpenSSLKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecOpenSSLKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataRsaGetKlass:
+ *
+ * The OpenSSL RSA key data klass.
+ *
+ * Returns: pointer to OpenSSL RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataRsaGetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataRsaKlass);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataRsaAdoptRsa:
+ * @data: the pointer to RSA key data.
+ * @rsa: the pointer to OpenSSL RSA key.
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLKeyDataRsaAdoptRsa(xmlSecKeyDataPtr data, RSA* rsa) {
+ EVP_PKEY* pKey = NULL;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1);
+
+ /* construct new EVP_PKEY */
+ if(rsa != NULL) {
+ pKey = EVP_PKEY_new();
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "EVP_PKEY_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = EVP_PKEY_assign_RSA(pKey, rsa);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "EVP_PKEY_assign_RSA",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ ret = xmlSecOpenSSLKeyDataRsaAdoptEvp(data, pKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataRsaAdoptEvp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ if(pKey != NULL) {
+ EVP_PKEY_free(pKey);
+ }
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataRsaGetRsa:
+ * @data: the pointer to RSA key data.
+ *
+ * Gets the OpenSSL RSA key from RSA key data.
+ *
+ * Returns: pointer to OpenSSL RSA key or NULL if an error occurs.
+ */
+RSA*
+xmlSecOpenSSLKeyDataRsaGetRsa(xmlSecKeyDataPtr data) {
+ EVP_PKEY* pKey;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), NULL);
+
+ pKey = xmlSecOpenSSLKeyDataRsaGetEvp(data);
+ xmlSecAssert2((pKey == NULL) || (pKey->type == EVP_PKEY_RSA), NULL);
+
+ return((pKey != NULL) ? pKey->pkey.rsa : (RSA*)NULL);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataRsaAdoptEvp:
+ * @data: the pointer to RSA key data.
+ * @pKey: the pointer to OpenSSL EVP key.
+ *
+ * Sets the RSA key data value to OpenSSL EVP key.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLKeyDataRsaAdoptEvp(xmlSecKeyDataPtr data, EVP_PKEY* pKey) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1);
+ xmlSecAssert2(pKey != NULL, -1);
+ xmlSecAssert2(pKey->type == EVP_PKEY_RSA, -1);
+
+ return(xmlSecOpenSSLEvpKeyDataAdoptEvp(data, pKey));
+}
+
+/**
+ * xmlSecOpenSSLKeyDataRsaGetEvp:
+ * @data: the pointer to RSA key data.
+ *
+ * Gets the OpenSSL EVP key from RSA key data.
+ *
+ * Returns: pointer to OpenSSL EVP key or NULL if an error occurs.
+ */
+EVP_PKEY*
+xmlSecOpenSSLKeyDataRsaGetEvp(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), NULL);
+
+ return(xmlSecOpenSSLEvpKeyDataGetEvp(data));
+}
+
+static int
+xmlSecOpenSSLKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1);
+
+ return(xmlSecOpenSSLEvpKeyDataInitialize(data));
+}
+
+static int
+xmlSecOpenSSLKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecOpenSSLKeyDataRsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecOpenSSLKeyDataRsaId), -1);
+
+ return(xmlSecOpenSSLEvpKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecOpenSSLKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId));
+
+ xmlSecOpenSSLEvpKeyDataFinalize(data);
+}
+
+static int
+xmlSecOpenSSLKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ xmlNodePtr cur;
+ RSA *rsa;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if(xmlSecKeyGetValue(key) != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA,
+ "key already has a value");
+ return(-1);
+ }
+
+ rsa = RSA_new();
+ if(rsa == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "RSA_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* first is Modulus node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ RSA_free(rsa);
+ return(-1);
+ }
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(rsa->n)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ RSA_free(rsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is Exponent node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ RSA_free(rsa);
+ return(-1);
+ }
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(rsa->e)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ RSA_free(rsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * we are not sure exactly what do we read */
+ if(xmlSecOpenSSLNodeGetBNValue(cur, &(rsa->d)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeGetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent));
+ RSA_free(rsa);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "no nodes expected");
+ RSA_free(rsa);
+ return(-1);
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ RSA_free(rsa);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataRsaAdoptRsa(data, rsa);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLKeyDataRsaAdoptRsa",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ RSA_free(rsa);
+ return(-1);
+ }
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ RSA* rsa;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataRsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ rsa = xmlSecOpenSSLKeyDataRsaGetRsa(xmlSecKeyGetValue(key));
+ xmlSecAssert2(rsa != NULL, -1);
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* first is Modulus node */
+ cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, rsa->n, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ return(-1);
+ }
+
+ /* next is Exponent node. */
+ cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, rsa->e, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ return(-1);
+ }
+
+ /* next is PrivateExponent node: write it ONLY for private keys and ONLY if it is requested */
+ if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (rsa->d != NULL)) {
+ cur = xmlSecAddChild(node, xmlSecNodeRSAPrivateExponent, xmlSecNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent));
+ return(-1);
+ }
+ ret = xmlSecOpenSSLNodeSetBNValue(cur, rsa->d, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLNodeSetBNValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent));
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ RSA* rsa;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ rsa = RSA_generate_key(sizeBits, 3, NULL, NULL);
+ if(rsa == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "RSA_generate_key",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "sizeBits=%d", sizeBits);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataRsaAdoptRsa(data, rsa);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataRsaAdoptRsa",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ RSA_free(rsa);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static xmlSecKeyDataType
+xmlSecOpenSSLKeyDataRsaGetType(xmlSecKeyDataPtr data) {
+ RSA* rsa;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), xmlSecKeyDataTypeUnknown);
+
+ rsa = xmlSecOpenSSLKeyDataRsaGetRsa(data);
+ if((rsa != NULL) && (rsa->n != NULL) && (rsa->e != NULL)) {
+ if(rsa->d != NULL) {
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else if(rsa->engine != NULL) {
+ /*
+ * !!! HACK !!! Also see DSA key
+ * We assume here that engine *always* has private key.
+ * This might be incorrect but it seems that there is no
+ * way to ask engine if given key is private or not.
+ */
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else {
+ return(xmlSecKeyDataTypePublic);
+ }
+ }
+
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecOpenSSLKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
+ RSA* rsa;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId), 0);
+
+ rsa = xmlSecOpenSSLKeyDataRsaGetRsa(data);
+ if((rsa != NULL) && (rsa->n != NULL)) {
+ return(BN_num_bits(rsa->n));
+ }
+ return(0);
+}
+
+static void
+xmlSecOpenSSLKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== rsa key: size = %d\n",
+ xmlSecOpenSSLKeyDataRsaGetSize(data));
+}
+
+static void
+xmlSecOpenSSLKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
+ xmlSecOpenSSLKeyDataRsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_RSA */
+
+
+
diff --git a/src/openssl/globals.h b/src/openssl/globals.h
new file mode 100644
index 00000000..770b6dba
--- /dev/null
+++ b/src/openssl/globals.h
@@ -0,0 +1,24 @@
+/*
+ * XML Security Library
+ *
+ * globals.h: internal header only used during the compilation
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef __XMLSEC_GLOBALS_H__
+#define __XMLSEC_GLOBALS_H__
+
+/**
+ * Use autoconf defines if present.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#define IN_XMLSEC_CRYPTO
+#define XMLSEC_PRIVATE
+
+#endif /* ! __XMLSEC_GLOBALS_H__ */
diff --git a/src/openssl/hmac.c b/src/openssl/hmac.c
new file mode 100644
index 00000000..bad1ac03
--- /dev/null
+++ b/src/openssl/hmac.c
@@ -0,0 +1,857 @@
+/**
+ *
+ * XMLSec library
+ *
+ * HMAC Algorithm support (http://www.w3.org/TR/xmldsig-core/#sec-HMAC):
+ * The HMAC algorithm (RFC2104 [HMAC]) takes the truncation length in bits
+ * as a parameter; if the parameter is not specified then all the bits of the
+ * hash are output. An example of an HMAC SignatureMethod element:
+ * <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+ * <HMACOutputLength>128</HMACOutputLength>
+ * </SignatureMethod>
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_HMAC
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/hmac.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+
+/* sizes in bits */
+#define XMLSEC_OPENSSL_MIN_HMAC_SIZE 80
+#define XMLSEC_OPENSSL_MAX_HMAC_SIZE (EVP_MAX_MD_SIZE * 8)
+
+/**************************************************************************
+ *
+ * Configuration
+ *
+ *****************************************************************************/
+static int g_xmlsec_openssl_hmac_min_length = XMLSEC_OPENSSL_MIN_HMAC_SIZE;
+
+/**
+ * xmlSecOpenSSLHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecOpenSSLHmacGetMinOutputLength(void)
+{
+ return g_xmlsec_openssl_hmac_min_length;
+}
+
+/**
+ * xmlSecOpenSSLHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecOpenSSLHmacSetMinOutputLength(int min_length)
+{
+ g_xmlsec_openssl_hmac_min_length = min_length;
+}
+
+/**************************************************************************
+ *
+ * Internal OpenSSL HMAC CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecOpenSSLHmacCtx xmlSecOpenSSLHmacCtx, *xmlSecOpenSSLHmacCtxPtr;
+struct _xmlSecOpenSSLHmacCtx {
+ const EVP_MD* hmacDgst;
+ HMAC_CTX hmacCtx;
+ int ctxInitialized;
+ xmlSecByte dgst[XMLSEC_OPENSSL_MAX_HMAC_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bits */
+};
+
+/**************************************************************************
+ *
+ * HMAC transforms
+ *
+ * xmlSecOpenSSLHmacCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecOpenSSLHmacGetCtx(transform) \
+ ((xmlSecOpenSSLHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecOpenSSLHmacSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLHmacCtx))
+
+static int xmlSecOpenSSLHmacCheckId (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLHmacInitialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLHmacFinalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLHmacNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLHmacSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLHmacSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLHmacVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLHmacExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+
+static int
+xmlSecOpenSSLHmacCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha224Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+ /* not found */
+ {
+ return(0);
+ }
+
+ /* just in case */
+ return(0);
+}
+
+
+
+static int
+xmlSecOpenSSLHmacInitialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1);
+
+ ctx = xmlSecOpenSSLHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecOpenSSLHmacCtx));
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha1Id)) {
+ ctx->hmacDgst = EVP_sha1();
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha224Id)) {
+ ctx->hmacDgst = EVP_sha224();
+ } else
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha256Id)) {
+ ctx->hmacDgst = EVP_sha256();
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha384Id)) {
+ ctx->hmacDgst = EVP_sha384();
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacSha512Id)) {
+ ctx->hmacDgst = EVP_sha512();
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacRipemd160Id)) {
+ ctx->hmacDgst = EVP_ripemd160();
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHmacMd5Id)) {
+ ctx->hmacDgst = EVP_md5();
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_OPENSSL_096
+ HMAC_CTX_init(&(ctx->hmacCtx));
+#endif /* XMLSEC_OPENSSL_096 */
+ return(0);
+}
+
+static void
+xmlSecOpenSSLHmacFinalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLHmacCtxPtr ctx;
+
+ xmlSecAssert(xmlSecOpenSSLHmacCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize));
+
+ ctx = xmlSecOpenSSLHmacGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+#ifndef XMLSEC_OPENSSL_096
+ HMAC_CTX_cleanup(&(ctx->hmacCtx));
+#endif /* XMLSEC_OPENSSL_096 */
+ memset(ctx, 0, sizeof(xmlSecOpenSSLHmacCtx));
+}
+
+static int
+xmlSecOpenSSLHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLHmacCtxPtr ctx;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1);
+ xmlSecAssert2(node!= NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) {
+ xmlChar *content;
+
+ content = xmlNodeGetContent(cur);
+ if(content != NULL) {
+ ctx->dgstSize = atoi((char*)content);
+ xmlFree(content);
+ }
+
+ /* Ensure that HMAC length is greater than min specified.
+ Otherwise, an attacker can set this length to 0 or very
+ small value
+ */
+ if((int)ctx->dgstSize < xmlSecOpenSSLHmacGetMinOutputLength()) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "HMAC output length is too small");
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataHmacId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLHmacCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecOpenSSLHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecOpenSSLHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->hmacDgst != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized == 0, -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecOpenSSLKeyDataHmacId), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(value);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "keySize=0");
+ return(-1);
+ }
+
+ xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
+ HMAC_Init(&(ctx->hmacCtx),
+ xmlSecBufferGetData(buffer),
+ xmlSecBufferGetSize(buffer),
+ ctx->hmacDgst);
+ ctx->ctxInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLHmacVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ static xmlSecByte last_byte_masks[] =
+ { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+
+ xmlSecOpenSSLHmacCtxPtr ctx;
+ xmlSecByte mask;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ /* compare the digest size in bytes */
+ if(dataSize != ((ctx->dgstSize + 7) / 8)){
+ /* NO COMMIT */
+ xmlChar* a;
+ mask = last_byte_masks[ctx->dgstSize % 8];
+ ctx->dgst[dataSize - 1] &= mask;
+ a = xmlSecBase64Encode(ctx->dgst, (ctx->dgstSize + 7) / 8, -1);
+ fprintf(stderr, "%s\n", a);
+ xmlFree(a);
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "data=%d;dgst=%d",
+ dataSize, ((ctx->dgstSize + 7) / 8));
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ /* we check the last byte separatelly */
+ xmlSecAssert2(dataSize > 0, -1);
+ mask = last_byte_masks[ctx->dgstSize % 8];
+ if((ctx->dgst[dataSize - 1] & mask) != (data[dataSize - 1] & mask)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "data and digest do not match (last byte)");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ /* now check the rest of the digest */
+ if((dataSize > 1) && (memcmp(ctx->dgst, data, dataSize - 1) != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "data and digest do not match");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLHmacCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLHmacSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecOpenSSLHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ /* we should be already initialized when we set key */
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ HMAC_Update(&(ctx->hmacCtx), xmlSecBufferGetData(in), inSize);
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ }
+
+ if(last) {
+ unsigned int dgstSize;
+
+ HMAC_Final(&(ctx->hmacCtx), ctx->dgst, &dgstSize);
+ xmlSecAssert2(dgstSize > 0, -1);
+
+ /* check/set the result digest size */
+ if(ctx->dgstSize == 0) {
+ ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize * 8); /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= XMLSEC_SIZE_BAD_CAST(8 * dgstSize)) {
+ dgstSize = ((ctx->dgstSize + 7) / 8); /* we need to truncate result digest */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "result-bits=%d;required-bits=%d",
+ 8 * dgstSize, ctx->dgstSize);
+ return(-1);
+ }
+
+ /* finally write result to output */
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = xmlSecBufferAppend(out, ctx->dgst, dgstSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", dgstSize);
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_MD5
+
+/********************************************************************
+ *
+ * HMAC MD5
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacMd5, /* const xmlChar* name; */
+ xmlSecHrefHmacMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacMd5GetKlass(void) {
+ return(&xmlSecOpenSSLHmacMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_RIPEMD160
+/********************************************************************
+ *
+ * HMAC RIPEMD160
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacRipemd160, /* const xmlChar* name; */
+ xmlSecHrefHmacRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacRipemd160GetKlass(void) {
+ return(&xmlSecOpenSSLHmacRipemd160Klass);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+/********************************************************************
+ *
+ * HMAC SHA1
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha1, /* const xmlChar* name; */
+ xmlSecHrefHmacSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacSha1GetKlass(void) {
+ return(&xmlSecOpenSSLHmacSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+/********************************************************************
+ *
+ * HMAC SHA224
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacSha224Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha224, /* const xmlChar* name; */
+ xmlSecHrefHmacSha224, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacSha224GetKlass:
+ *
+ * The HMAC-SHA224 transform klass.
+ *
+ * Returns: the HMAC-SHA224 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacSha224GetKlass(void) {
+ return(&xmlSecOpenSSLHmacSha224Klass);
+}
+
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+/********************************************************************
+ *
+ * HMAC SHA256
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha256, /* const xmlChar* name; */
+ xmlSecHrefHmacSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacSha256GetKlass(void) {
+ return(&xmlSecOpenSSLHmacSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/********************************************************************
+ *
+ * HMAC SHA384
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha384, /* const xmlChar* name; */
+ xmlSecHrefHmacSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacSha384GetKlass(void) {
+ return(&xmlSecOpenSSLHmacSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/********************************************************************
+ *
+ * HMAC SHA512
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLHmacSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha512, /* const xmlChar* name; */
+ xmlSecHrefHmacSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformHmacSha512GetKlass(void) {
+ return(&xmlSecOpenSSLHmacSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+
+#endif /* XMLSEC_NO_HMAC */
+
diff --git a/src/openssl/kt_rsa.c b/src/openssl/kt_rsa.c
new file mode 100644
index 00000000..1cf1aba1
--- /dev/null
+++ b/src/openssl/kt_rsa.c
@@ -0,0 +1,876 @@
+/**
+ *
+ * XMLSec library
+ *
+ * RSA Algorithms support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_RSA
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+#include <openssl/objects.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/strings.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+#include <xmlsec/openssl/bn.h>
+
+/**************************************************************************
+ *
+ * Internal OpenSSL RSA PKCS1 CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecOpenSSLRsaPkcs1Ctx xmlSecOpenSSLRsaPkcs1Ctx,
+ *xmlSecOpenSSLRsaPkcs1CtxPtr;
+struct _xmlSecOpenSSLRsaPkcs1Ctx {
+ EVP_PKEY* pKey;
+};
+
+/*********************************************************************
+ *
+ * RSA PKCS1 key transport transform
+ *
+ * xmlSecOpenSSLRsaPkcs1Ctx is located after xmlSecTransform
+ *
+ ********************************************************************/
+#define xmlSecOpenSSLRsaPkcs1Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLRsaPkcs1Ctx))
+#define xmlSecOpenSSLRsaPkcs1GetCtx(transform) \
+ ((xmlSecOpenSSLRsaPkcs1CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecOpenSSLRsaPkcs1Initialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLRsaPkcs1Finalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLRsaPkcs1SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLRsaPkcs1SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLRsaPkcs1Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLRsaPkcs1Process (xmlSecTransformPtr transform,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecOpenSSLRsaPkcs1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLRsaPkcs1Size, /* xmlSecSize objSize */
+
+ xmlSecNameRsaPkcs1, /* const xmlChar* name; */
+ xmlSecHrefRsaPkcs1, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLRsaPkcs1Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLRsaPkcs1Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLRsaPkcs1SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLRsaPkcs1SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLRsaPkcs1Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaPkcs1GetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaPkcs1GetKlass(void) {
+ return(&xmlSecOpenSSLRsaPkcs1Klass);
+}
+
+static int
+xmlSecOpenSSLRsaPkcs1Initialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1);
+
+ ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLRsaPkcs1Ctx));
+ return(0);
+}
+
+static void
+xmlSecOpenSSLRsaPkcs1Finalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size));
+
+ ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->pKey != NULL) {
+ EVP_PKEY_free(ctx->pKey);
+ }
+ memset(ctx, 0, sizeof(xmlSecOpenSSLRsaPkcs1Ctx));
+}
+
+static int
+xmlSecOpenSSLRsaPkcs1SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataRsaId;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaPkcs1SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
+ EVP_PKEY* pKey;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataRsaId), -1);
+
+ ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pKey == NULL, -1);
+
+ pKey = xmlSecOpenSSLKeyDataRsaGetEvp(xmlSecKeyGetValue(key));
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKeyDataRsaGetEvp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(pKey->type == EVP_PKEY_RSA, -1);
+ xmlSecAssert2(pKey->pkey.rsa != NULL, -1);
+
+ ctx->pKey = xmlSecOpenSSLEvpKeyDup(pKey);
+ if(ctx->pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpKeyDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaPkcs1Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pKey != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ ret = xmlSecOpenSSLRsaPkcs1Process(transform, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLRsaPkcs1Process",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaPkcs1Process(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLRsaPkcs1CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaPkcs1Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaPkcs1Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaPkcs1GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pKey != NULL, -1);
+ xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1);
+ xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1);
+
+ keySize = RSA_size(ctx->pKey->pkey.rsa);
+ xmlSecAssert2(keySize > 0, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ /* the encoded size is equal to the keys size so we could not
+ * process more than that */
+ if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d when expected less than %d", inSize, keySize);
+ return(-1);
+ } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d when expected %d", inSize, keySize);
+ return(-1);
+ }
+
+ outSize = keySize;
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in),
+ xmlSecBufferGetData(out),
+ ctx->pKey->pkey.rsa, RSA_PKCS1_PADDING);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_public_encrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in),
+ xmlSecBufferGetData(out),
+ ctx->pKey->pkey.rsa, RSA_PKCS1_PADDING);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_private_decrypt",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**************************************************************************
+ *
+ * Internal OpenSSL RSA OAEP CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecOpenSSLRsaOaepCtx xmlSecOpenSSLRsaOaepCtx,
+ *xmlSecOpenSSLRsaOaepCtxPtr;
+struct _xmlSecOpenSSLRsaOaepCtx {
+ EVP_PKEY* pKey;
+ xmlSecBuffer oaepParams;
+};
+
+/*********************************************************************
+ *
+ * RSA OAEP key transport transform
+ *
+ * xmlSecOpenSSLRsaOaepCtx is located after xmlSecTransform
+ *
+ ********************************************************************/
+#define xmlSecOpenSSLRsaOaepSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLRsaOaepCtx))
+#define xmlSecOpenSSLRsaOaepGetCtx(transform) \
+ ((xmlSecOpenSSLRsaOaepCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecOpenSSLRsaOaepInitialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLRsaOaepFinalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLRsaOaepNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLRsaOaepSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLRsaOaepSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLRsaOaepExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLRsaOaepProcess (xmlSecTransformPtr transform,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecOpenSSLRsaOaepKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLRsaOaepSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaOaep, /* const xmlChar* name; */
+ xmlSecHrefRsaOaep, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLRsaOaepInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLRsaOaepFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecOpenSSLRsaOaepNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLRsaOaepSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLRsaOaepSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLRsaOaepExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaOaepGetKlass:
+ *
+ * The RSA-OAEP key transport transform klass.
+ *
+ * Returns: RSA-OAEP key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaOaepGetKlass(void) {
+ return(&xmlSecOpenSSLRsaOaepKlass);
+}
+
+static int
+xmlSecOpenSSLRsaOaepInitialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLRsaOaepCtx));
+
+ ret = xmlSecBufferInitialize(&(ctx->oaepParams), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecOpenSSLRsaOaepFinalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize));
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->pKey != NULL) {
+ EVP_PKEY_free(ctx->pKey);
+ }
+ xmlSecBufferFinalize(&(ctx->oaepParams));
+ memset(ctx, 0, sizeof(xmlSecOpenSSLRsaOaepCtx));
+}
+
+static int
+xmlSecOpenSSLRsaOaepNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->oaepParams)) == 0, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ while(cur != NULL) {
+ if(xmlSecCheckNodeName(cur, xmlSecNodeRsaOAEPparams, xmlSecEncNs)) {
+ ret = xmlSecBufferBase64NodeContentRead(&(ctx->oaepParams), cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferBase64NodeContentRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs)) {
+ xmlChar* algorithm;
+
+ /* Algorithm attribute is required */
+ algorithm = xmlGetProp(cur, xmlSecAttrAlgorithm);
+ if(algorithm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecAttrAlgorithm),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+
+ /* for now we support only sha1 */
+ if(xmlStrcmp(algorithm, xmlSecHrefSha1) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(algorithm),
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ "digest algorithm is not supported for rsa/oaep");
+ xmlFree(algorithm);
+ return(-1);
+ }
+ xmlFree(algorithm);
+ } else {
+ /* not found */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* next node */
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaOaepSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataRsaId;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaOaepSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+ EVP_PKEY* pKey;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataRsaId), -1);
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pKey == NULL, -1);
+
+ pKey = xmlSecOpenSSLKeyDataRsaGetEvp(xmlSecKeyGetValue(key));
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKeyDataRsaGetEvp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2(pKey->type == EVP_PKEY_RSA, -1);
+ xmlSecAssert2(pKey->pkey.rsa != NULL, -1);
+
+ ctx->pKey = xmlSecOpenSSLEvpKeyDup(pKey);
+ if(ctx->pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpKeyDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaOaepExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pKey != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ ret = xmlSecOpenSSLRsaOaepProcess(transform, transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLRsaOaepProcess",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLRsaOaepProcess(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLRsaOaepCtxPtr ctx;
+ xmlSecSize paramsSize;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLRsaOaepGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pKey != NULL, -1);
+ xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1);
+ xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1);
+
+ keySize = RSA_size(ctx->pKey->pkey.rsa);
+ xmlSecAssert2(keySize > 0, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ /* the encoded size is equal to the keys size so we could not
+ * process more than that */
+ if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d when expected less than %d", inSize, keySize);
+ return(-1);
+ } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d when expected %d", inSize, keySize);
+ return(-1);
+ }
+
+ outSize = keySize;
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ paramsSize = xmlSecBufferGetSize(&(ctx->oaepParams));
+ if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize == 0)) {
+ /* encode w/o OAEPParams --> simple */
+ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in),
+ xmlSecBufferGetData(out),
+ ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_public_encrypt(RSA_PKCS1_OAEP_PADDING)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize > 0)) {
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->oaepParams)) != NULL, -1);
+
+ /* add space for padding */
+ ret = xmlSecBufferSetMaxSize(in, keySize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", keySize);
+ return(-1);
+ }
+
+ /* add padding */
+ ret = RSA_padding_add_PKCS1_OAEP(xmlSecBufferGetData(in), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(&(ctx->oaepParams)),
+ paramsSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_padding_add_PKCS1_OAEP",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ inSize = keySize;
+
+ /* encode with OAEPParams */
+ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in),
+ xmlSecBufferGetData(out),
+ ctx->pKey->pkey.rsa, RSA_NO_PADDING);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_public_encrypt(RSA_NO_PADDING)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize == 0)) {
+ ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in),
+ xmlSecBufferGetData(out),
+ ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_private_decrypt(RSA_PKCS1_OAEP_PADDING)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize != 0)) {
+ BIGNUM bn;
+
+ ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in),
+ xmlSecBufferGetData(out),
+ ctx->pKey->pkey.rsa, RSA_NO_PADDING);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_private_decrypt(RSA_NO_PADDING)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+
+ /*
+ * the private decrypt w/o padding adds '0's at the begginning.
+ * it's not clear for me can I simply skip all '0's from the
+ * beggining so I have to do decode it back to BIGNUM and dump
+ * buffer again
+ */
+ BN_init(&bn);
+ if(BN_bin2bn(xmlSecBufferGetData(out), outSize, &bn) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "BN_bin2bn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", outSize);
+ BN_clear_free(&bn);
+ return(-1);
+ }
+
+ ret = BN_bn2bin(&bn, xmlSecBufferGetData(out));
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "BN_bn2bin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BN_clear_free(&bn);
+ return(-1);
+ }
+ BN_clear_free(&bn);
+ outSize = ret;
+
+ ret = RSA_padding_check_PKCS1_OAEP(xmlSecBufferGetData(out), outSize,
+ xmlSecBufferGetData(out), outSize,
+ keySize,
+ xmlSecBufferGetData(&(ctx->oaepParams)),
+ paramsSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "RSA_padding_check_PKCS1_OAEP",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ xmlSecAssert2("we could not be here" == NULL, -1);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_NO_RSA */
+
diff --git a/src/openssl/kw_aes.c b/src/openssl/kw_aes.c
new file mode 100644
index 00000000..573fb985
--- /dev/null
+++ b/src/openssl/kw_aes.c
@@ -0,0 +1,513 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_AES
+#ifndef XMLSEC_OPENSSL_096
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/aes.h>
+#include <openssl/rand.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+
+#include "../kw_aes_des.h"
+
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecOpenSSLKWAesBlockEncrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static int xmlSecOpenSSLKWAesBlockDecrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static xmlSecKWAesKlass xmlSecOpenSSLKWAesKlass = {
+ /* callbacks */
+ xmlSecOpenSSLKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */
+ xmlSecOpenSSLKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL /* void* reserved1; */
+};
+
+
+/*********************************************************************
+ *
+ * AES KW transforms
+ *
+ ********************************************************************/
+typedef struct _xmlSecOpenSSLKWAesCtx xmlSecOpenSSLKWAesCtx,
+ *xmlSecOpenSSLKWAesCtxPtr;
+struct _xmlSecOpenSSLKWAesCtx {
+ xmlSecBuffer keyBuffer;
+ xmlSecSize keyExpectedSize;
+};
+#define xmlSecOpenSSLKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLKWAesCtx))
+#define xmlSecOpenSSLKWAesGetCtx(transform) \
+ ((xmlSecOpenSSLKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecOpenSSLKWAesCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes128Id) || \
+ xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes192Id) || \
+ xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes256Id))
+
+static int xmlSecOpenSSLKWAesInitialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLKWAesFinalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLKWAesSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLKWAesSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLKWAesExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecOpenSSLKWAesInitialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLKWAesCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+
+ ctx = xmlSecOpenSSLKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes128Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes192Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes256Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLKWAesGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecOpenSSLKWAesFinalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLKWAesCtxPtr ctx;
+
+ xmlSecAssert(xmlSecOpenSSLKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize));
+
+ ctx = xmlSecOpenSSLKWAesGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecOpenSSLKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecOpenSSLKWAesCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecOpenSSLKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataAesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * ctx->keyExpectedSize;
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLKWAesCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataAesId), -1);
+
+ ctx = xmlSecOpenSSLKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < ctx->keyExpectedSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer),
+ xmlSecBufferGetData(buffer),
+ ctx->keyExpectedSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d",
+ ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLKWAesCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ AES_KEY aesKey;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == ctx->keyExpectedSize, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % 8) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d(not 8 bytes aligned)", inSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+ outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_KW_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* prepare key */
+ ret = AES_set_encrypt_key(xmlSecBufferGetData(&(ctx->keyBuffer)),
+ 8 * keySize,
+ &aesKey);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "AES_set_decrypt_key",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKWAesEncode(&xmlSecOpenSSLKWAesKlass, &aesKey,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ /* prepare key */
+ ret = AES_set_decrypt_key(xmlSecBufferGetData(&(ctx->keyBuffer)),
+ 8 * keySize,
+ &aesKey);
+ if(ret != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "AES_set_decrypt_key",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecKWAesDecode(&xmlSecOpenSSLKWAesKlass, &aesKey,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "inSize%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+static xmlSecTransformKlass xmlSecOpenSSLKWAes128Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes128, /* const xmlChar* name; */
+ xmlSecHrefKWAes128, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWAes128GetKlass(void) {
+ return(&xmlSecOpenSSLKWAes128Klass);
+}
+
+static xmlSecTransformKlass xmlSecOpenSSLKWAes192Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes192, /* const xmlChar* name; */
+ xmlSecHrefKWAes192, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+
+/**
+ * xmlSecOpenSSLTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWAes192GetKlass(void) {
+ return(&xmlSecOpenSSLKWAes192Klass);
+}
+
+static xmlSecTransformKlass xmlSecOpenSSLKWAes256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes256, /* const xmlChar* name; */
+ xmlSecHrefKWAes256, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWAes256GetKlass(void) {
+ return(&xmlSecOpenSSLKWAes256Klass);
+}
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecOpenSSLKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(context != NULL, -1);
+
+ AES_encrypt(in, out, (AES_KEY*)context);
+ return(AES_BLOCK_SIZE);
+}
+
+static int
+xmlSecOpenSSLKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(context != NULL, -1);
+
+ AES_decrypt(in, out, (AES_KEY*)context);
+ return(AES_BLOCK_SIZE);
+}
+
+
+#endif /* XMLSEC_OPENSSL_096 */
+#endif /* XMLSEC_NO_AES */
diff --git a/src/openssl/kw_des.c b/src/openssl/kw_des.c
new file mode 100644
index 00000000..9d55e107
--- /dev/null
+++ b/src/openssl/kw_des.c
@@ -0,0 +1,563 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_DES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/des.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+
+#include "../kw_aes_des.h"
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecOpenSSLKWDes3GenerateRandom (void * context,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecOpenSSLKWDes3Sha1 (void * context,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecOpenSSLKWDes3BlockEncrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecOpenSSLKWDes3BlockDecrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+
+static xmlSecKWDes3Klass xmlSecOpenSSLKWDes3ImplKlass = {
+ /* callbacks */
+ xmlSecOpenSSLKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */
+ xmlSecOpenSSLKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */
+ xmlSecOpenSSLKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */
+ xmlSecOpenSSLKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static int xmlSecOpenSSLKWDes3Encrypt (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *iv,
+ xmlSecSize ivSize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize,
+ int enc);
+
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+typedef struct _xmlSecOpenSSLKWDes3Ctx xmlSecOpenSSLKWDes3Ctx,
+ *xmlSecOpenSSLKWDes3CtxPtr;
+struct _xmlSecOpenSSLKWDes3Ctx {
+ xmlSecBuffer keyBuffer;
+};
+#define xmlSecOpenSSLKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLKWDes3Ctx))
+#define xmlSecOpenSSLKWDes3GetCtx(transform) \
+ ((xmlSecOpenSSLKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecOpenSSLKWDes3Initialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLKWDes3Finalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLKWDes3SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLKWDes3SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLKWDes3Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecOpenSSLKWDes3Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLKWDes3Size, /* xmlSecSize objSize */
+
+ xmlSecNameKWDes3, /* const xmlChar* name; */
+ xmlSecHrefKWDes3, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecOpenSSLKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecOpenSSLKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformKWDes3GetKlass(void) {
+ return(&xmlSecOpenSSLKWDes3Klass);
+}
+
+static int
+xmlSecOpenSSLKWDes3Initialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1);
+
+ ctx = xmlSecOpenSSLKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecOpenSSLKWDes3Finalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size));
+
+ ctx = xmlSecOpenSSLKWDes3GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecOpenSSLKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecOpenSSLKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecOpenSSLKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataDesId), -1);
+
+ ctx = xmlSecOpenSSLKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key length %d is not enough (%d expected)",
+ keySize, XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWDes3Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d bytes - not %d bytes aligned",
+ inSize, XMLSEC_KW_DES3_BLOCK_LENGTH);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 16 bytes longer plus one block just in case */
+ outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH;
+ } else {
+ /* just in case, add a block */
+ outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWDes3Encode(&xmlSecOpenSSLKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWDes3Decode(&xmlSecOpenSSLKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecOpenSSLKWDes3Sha1(void * context,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= SHA_DIGEST_LENGTH, -1);
+
+ if(SHA1(in, inSize, out) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SHA1",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(SHA_DIGEST_LENGTH);
+}
+
+static int
+xmlSecOpenSSLKWDes3GenerateRandom(void * context,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ ret = RAND_bytes(out, outSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "RAND_bytes",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ret=%d", ret);
+ return(-1);
+ }
+
+ return((int)outSize);
+}
+
+static int
+xmlSecOpenSSLKWDes3BlockEncrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecOpenSSLKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 1); /* encrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+static int
+xmlSecOpenSSLKWDes3BlockDecrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecOpenSSLKWDes3CtxPtr ctx = (xmlSecOpenSSLKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecOpenSSLKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 0); /* decrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+
+
+static int
+xmlSecOpenSSLKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *iv, xmlSecSize ivSize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize,
+ int enc) {
+ EVP_CIPHER_CTX cipherCtx;
+ int updateLen;
+ int finalLen;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == (xmlSecSize)EVP_CIPHER_key_length(EVP_des_ede3_cbc()), -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize == (xmlSecSize)EVP_CIPHER_iv_length(EVP_des_ede3_cbc()), -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ EVP_CIPHER_CTX_init(&cipherCtx);
+ ret = EVP_CipherInit(&cipherCtx, EVP_des_ede3_cbc(), key, iv, enc);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "EVP_CipherInit",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_OPENSSL_096
+ EVP_CIPHER_CTX_set_padding(&cipherCtx, 0);
+#endif /* XMLSEC_OPENSSL_096 */
+
+ ret = EVP_CipherUpdate(&cipherCtx, out, &updateLen, in, inSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "EVP_CipherUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = EVP_CipherFinal(&cipherCtx, out + updateLen, &finalLen);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "EVP_CipherFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ EVP_CIPHER_CTX_cleanup(&cipherCtx);
+
+ return(updateLen + finalLen);
+}
+
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/openssl/signatures.c b/src/openssl/signatures.c
new file mode 100644
index 00000000..38f42b34
--- /dev/null
+++ b/src/openssl/signatures.c
@@ -0,0 +1,1065 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+
+#ifndef XMLSEC_NO_DSA
+#define XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE 40
+static const EVP_MD *xmlSecOpenSSLDsaSha1Evp (void);
+#endif /* XMLSEC_NO_DSA */
+
+
+/**************************************************************************
+ *
+ * Internal OpenSSL evp signatures ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecOpenSSLEvpSignatureCtx xmlSecOpenSSLEvpSignatureCtx,
+ *xmlSecOpenSSLEvpSignatureCtxPtr;
+struct _xmlSecOpenSSLEvpSignatureCtx {
+ const EVP_MD* digest;
+ EVP_MD_CTX digestCtx;
+ xmlSecKeyDataId keyId;
+ EVP_PKEY* pKey;
+};
+
+/******************************************************************************
+ *
+ * EVP Signature transforms
+ *
+ * xmlSecOpenSSLEvpSignatureCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecOpenSSLEvpSignatureSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecOpenSSLEvpSignatureCtx))
+#define xmlSecOpenSSLEvpSignatureGetCtx(transform) \
+ ((xmlSecOpenSSLEvpSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecOpenSSLEvpSignatureCheckId (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLEvpSignatureInitialize (xmlSecTransformPtr transform);
+static void xmlSecOpenSSLEvpSignatureFinalize (xmlSecTransformPtr transform);
+static int xmlSecOpenSSLEvpSignatureSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecOpenSSLEvpSignatureSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecOpenSSLEvpSignatureVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecOpenSSLEvpSignatureExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecOpenSSLEvpSignatureCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha224Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ {
+ return(0);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpSignatureInitialize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLEvpSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1);
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLEvpSignatureCtx));
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDsaSha1Id)) {
+ ctx->digest = xmlSecOpenSSLDsaSha1Evp();
+ ctx->keyId = xmlSecOpenSSLKeyDataDsaId;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaMd5Id)) {
+ ctx->digest = EVP_md5();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaRipemd160Id)) {
+ ctx->digest = EVP_ripemd160();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha1Id)) {
+ ctx->digest = EVP_sha1();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha224Id)) {
+ ctx->digest = EVP_sha224();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha256Id)) {
+ ctx->digest = EVP_sha256();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha384Id)) {
+ ctx->digest = EVP_sha384();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaSha512Id)) {
+ ctx->digest = EVP_sha512();
+ ctx->keyId = xmlSecOpenSSLKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#ifndef XMLSEC_OPENSSL_096
+ EVP_MD_CTX_init(&(ctx->digestCtx));
+#endif /* XMLSEC_OPENSSL_096 */
+ return(0);
+}
+
+static void
+xmlSecOpenSSLEvpSignatureFinalize(xmlSecTransformPtr transform) {
+ xmlSecOpenSSLEvpSignatureCtxPtr ctx;
+
+ xmlSecAssert(xmlSecOpenSSLEvpSignatureCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize));
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->pKey != NULL) {
+ EVP_PKEY_free(ctx->pKey);
+ }
+
+#ifndef XMLSEC_OPENSSL_096
+ EVP_MD_CTX_cleanup(&(ctx->digestCtx));
+#endif /* XMLSEC_OPENSSL_096 */
+ memset(ctx, 0, sizeof(xmlSecOpenSSLEvpSignatureCtx));
+}
+
+static int
+xmlSecOpenSSLEvpSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecOpenSSLEvpSignatureCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ EVP_PKEY* pKey;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digest != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(value != NULL, -1);
+
+ pKey = xmlSecOpenSSLEvpKeyDataGetEvp(value);
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpKeyDataGetEvp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(ctx->pKey != NULL) {
+ EVP_PKEY_free(ctx->pKey);
+ }
+
+ ctx->pKey = xmlSecOpenSSLEvpKeyDup(pKey);
+ if(ctx->pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecOpenSSLEvpKeyDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecOpenSSLEvpSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+
+ keyReq->keyId = ctx->keyId;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+ return(0);
+}
+
+
+static int
+xmlSecOpenSSLEvpSignatureVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLEvpSignatureCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = EVP_VerifyFinal(&(ctx->digestCtx), (xmlSecByte*)data, dataSize, ctx->pKey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_VerifyFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ } else if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_VerifyFinal",
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "signature do not match");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecOpenSSLEvpSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecOpenSSLEvpSignatureCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize;
+ xmlSecSize outSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLEvpSignatureSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ ctx = xmlSecOpenSSLEvpSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digest != NULL, -1);
+ xmlSecAssert2(ctx->pKey != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_SignInit(&(ctx->digestCtx), ctx->digest);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_SignInit",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_SignInit(&(ctx->digestCtx), ctx->digest);
+#endif /* XMLSEC_OPENSSL_096 */
+ } else {
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_VerifyInit(&(ctx->digestCtx), ctx->digest);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_VerifyInit",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_VerifyInit(&(ctx->digestCtx), ctx->digest);
+#endif /* XMLSEC_OPENSSL_096 */
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (inSize > 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_SignUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_SignUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_SignUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize);
+#endif /* XMLSEC_OPENSSL_096 */
+ } else {
+#ifndef XMLSEC_OPENSSL_096
+ ret = EVP_VerifyUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_VerifyUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#else /* XMLSEC_OPENSSL_096 */
+ EVP_VerifyUpdate(&(ctx->digestCtx), xmlSecBufferGetData(in), inSize);
+#endif /* XMLSEC_OPENSSL_096 */
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+ if(transform->operation == xmlSecTransformOperationSign) {
+ unsigned int signSize;
+
+ /* this is a hack: for rsa signatures
+ * we get size from EVP_PKEY_size(),
+ * for dsa signature we use a fixed constant */
+ signSize = EVP_PKEY_size(ctx->pKey);
+#ifndef XMLSEC_NO_DSA
+ if(signSize < XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE) {
+ signSize = XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE;
+ }
+#endif /* XMLSEC_NO_DSA */
+
+ ret = xmlSecBufferSetMaxSize(out, signSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%u", signSize);
+ return(-1);
+ }
+
+ ret = EVP_SignFinal(&(ctx->digestCtx), xmlSecBufferGetData(out), &signSize, ctx->pKey);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "EVP_SignFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetSize(out, signSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%u", signSize);
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) || (transform->status == xmlSecTransformStatusFinished)) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * DSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+
+static xmlSecTransformKlass xmlSecOpenSSLDsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameDsaSha1, /* const xmlChar* name; */
+ xmlSecHrefDsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformDsaSha1GetKlass(void) {
+ return(&xmlSecOpenSSLDsaSha1Klass);
+}
+
+/****************************************************************************
+ *
+ * DSA-SHA1 EVP
+ *
+ * XMLDSig specifies dsa signature packing not supported by OpenSSL so
+ * we created our own EVP_MD.
+ *
+ * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg:
+ *
+ * The output of the DSA algorithm consists of a pair of integers
+ * usually referred by the pair (r, s). The signature value consists of
+ * the base64 encoding of the concatenation of two octet-streams that
+ * respectively result from the octet-encoding of the values r and s in
+ * that order. Integer to octet-stream conversion must be done according
+ * to the I2OSP operation defined in the RFC 2437 [PKCS1] specification
+ * with a l parameter equal to 20. For example, the SignatureValue element
+ * for a DSA signature (r, s) with values specified in hexadecimal:
+ *
+ * r = 8BAC1AB6 6410435C B7181F95 B16AB97C 92B341C0
+ * s = 41E2345F 1F56DF24 58F426D1 55B4BA2D B6DCD8C8
+ *
+ * from the example in Appendix 5 of the DSS standard would be
+ *
+ * <SignatureValue>i6watmQQQ1y3GB+VsWq5fJKzQcBB4jRfH1bfJFj0JtFVtLotttzYyA==</SignatureValue>
+ *
+ ***************************************************************************/
+#ifndef XMLSEC_OPENSSL_096
+static int
+xmlSecOpenSSLDsaSha1EvpInit(EVP_MD_CTX *ctx)
+{
+ return SHA1_Init(ctx->md_data);
+}
+
+static int
+xmlSecOpenSSLDsaSha1EvpUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+ return SHA1_Update(ctx->md_data,data,count);
+}
+
+static int
+xmlSecOpenSSLDsaSha1EvpFinal(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ return SHA1_Final(md,ctx->md_data);
+}
+#endif /* XMLSEC_OPENSSL_096 */
+
+static int
+xmlSecOpenSSLDsaSha1EvpSign(int type ATTRIBUTE_UNUSED,
+ const unsigned char *dgst, unsigned int dlen,
+ unsigned char *sig, unsigned int *siglen, void *dsa) {
+ DSA_SIG *s;
+ int rSize, sSize;
+
+ s = DSA_do_sign(dgst, dlen, dsa);
+ if(s == NULL) {
+ *siglen=0;
+ return(0);
+ }
+
+ rSize = BN_num_bytes(s->r);
+ sSize = BN_num_bytes(s->s);
+ if((rSize > (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2)) ||
+ (sSize > (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2))) {
+
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size(r)=%d or size(s)=%d > %d",
+ rSize, sSize, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2);
+ DSA_SIG_free(s);
+ return(0);
+ }
+
+ memset(sig, 0, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE);
+ BN_bn2bin(s->r, sig + (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2) - rSize);
+ BN_bn2bin(s->s, sig + XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE - sSize);
+ *siglen = XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE;
+
+ DSA_SIG_free(s);
+ return(1);
+}
+
+static int
+xmlSecOpenSSLDsaSha1EvpVerify(int type ATTRIBUTE_UNUSED,
+ const unsigned char *dgst, unsigned int dgst_len,
+ const unsigned char *sigbuf, unsigned int siglen,
+ void *dsa) {
+ DSA_SIG *s;
+ int ret = -1;
+
+ s = DSA_SIG_new();
+ if (s == NULL) {
+ return(ret);
+ }
+
+ if(siglen != XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "invalid length %d (%d expected)",
+ siglen, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE);
+ goto err;
+ }
+
+ s->r = BN_bin2bn(sigbuf, XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2, NULL);
+ s->s = BN_bin2bn(sigbuf + (XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2),
+ XMLSEC_OPENSSL_DSA_SIGNATURE_SIZE / 2, NULL);
+ if((s->r == NULL) || (s->s == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_bin2bn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto err;
+ }
+
+ ret = DSA_do_verify(dgst, dgst_len, s, dsa);
+
+err:
+ DSA_SIG_free(s);
+ return(ret);
+}
+
+static const EVP_MD xmlSecOpenSSLDsaMdEvp = {
+ NID_dsaWithSHA,
+ NID_dsaWithSHA,
+ SHA_DIGEST_LENGTH,
+#ifndef XMLSEC_OPENSSL_096
+ 0,
+ xmlSecOpenSSLDsaSha1EvpInit,
+ xmlSecOpenSSLDsaSha1EvpUpdate,
+ xmlSecOpenSSLDsaSha1EvpFinal,
+ NULL,
+ NULL,
+#else /* XMLSEC_OPENSSL_096 */
+ SHA1_Init,
+ SHA1_Update,
+ SHA1_Final,
+#endif /* XMLSEC_OPENSSL_096 */
+ xmlSecOpenSSLDsaSha1EvpSign,
+ xmlSecOpenSSLDsaSha1EvpVerify,
+ {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3,EVP_PKEY_DSA4,0},
+ SHA_CBLOCK,
+ sizeof(EVP_MD *)+sizeof(SHA_CTX),
+};
+
+static const EVP_MD *xmlSecOpenSSLDsaSha1Evp(void)
+{
+ return(&xmlSecOpenSSLDsaMdEvp);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+/****************************************************************************
+ *
+ * RSA-MD5 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaMd5, /* const xmlChar* name; */
+ xmlSecHrefRsaMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaMd5GetKlass(void) {
+ return(&xmlSecOpenSSLRsaMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+/****************************************************************************
+ *
+ * RSA-RIPEMD160 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaRipemd160, /* const xmlChar* name; */
+ xmlSecHrefRsaRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaRipemd160GetKlass:
+ *
+ * The RSA-RIPEMD160 signature transform klass.
+ *
+ * Returns: RSA-RIPEMD160 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaRipemd160GetKlass(void) {
+ return(&xmlSecOpenSSLRsaRipemd160Klass);
+}
+
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha1, /* const xmlChar* name; */
+ xmlSecHrefRsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaSha1GetKlass(void) {
+ return(&xmlSecOpenSSLRsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA224
+/****************************************************************************
+ *
+ * RSA-SHA224 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaSha224Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha224, /* const xmlChar* name; */
+ xmlSecHrefRsaSha224, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaSha224GetKlass:
+ *
+ * The RSA-SHA224 signature transform klass.
+ *
+ * Returns: RSA-SHA224 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaSha224GetKlass(void) {
+ return(&xmlSecOpenSSLRsaSha224Klass);
+}
+
+#endif /* XMLSEC_NO_SHA224 */
+
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha256, /* const xmlChar* name; */
+ xmlSecHrefRsaSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaSha256GetKlass(void) {
+ return(&xmlSecOpenSSLRsaSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha384, /* const xmlChar* name; */
+ xmlSecHrefRsaSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaSha384GetKlass(void) {
+ return(&xmlSecOpenSSLRsaSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecOpenSSLRsaSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecOpenSSLEvpSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha512, /* const xmlChar* name; */
+ xmlSecHrefRsaSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecOpenSSLEvpSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecOpenSSLEvpSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecOpenSSLEvpSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecOpenSSLEvpSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecOpenSSLEvpSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecOpenSSLEvpSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecOpenSSLTransformRsaSha512GetKlass(void) {
+ return(&xmlSecOpenSSLRsaSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+
+
diff --git a/src/openssl/symkeys.c b/src/openssl/symkeys.c
new file mode 100644
index 00000000..6195ed6d
--- /dev/null
+++ b/src/openssl/symkeys.c
@@ -0,0 +1,447 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/rand.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+
+/*****************************************************************************
+ *
+ * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary
+ *
+ ****************************************************************************/
+static int xmlSecOpenSSLSymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLSymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecOpenSSLSymKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLSymKeyDataXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLSymKeyDataXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLSymKeyDataBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlSecByte** buf,
+ xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecOpenSSLSymKeyDataGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecOpenSSLSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecOpenSSLSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecOpenSSLSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecOpenSSLSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+#define xmlSecOpenSSLSymKeyDataCheckId(data) \
+ (xmlSecKeyDataIsValid((data)) && \
+ xmlSecOpenSSLSymKeyDataKlassCheck((data)->id))
+
+static int
+xmlSecOpenSSLSymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), -1);
+
+ return(xmlSecKeyDataBinaryValueInitialize(data));
+}
+
+static int
+xmlSecOpenSSLSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(dst), -1);
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ return(xmlSecKeyDataBinaryValueDuplicate(dst, src));
+}
+
+static void
+xmlSecOpenSSLSymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecOpenSSLSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueFinalize(data);
+}
+
+static int
+xmlSecOpenSSLSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecOpenSSLSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecOpenSSLSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecOpenSSLSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecOpenSSLSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecOpenSSLGenerateRandom(buffer, (sizeBits + 7) / 8));
+}
+
+static xmlSecKeyDataType
+xmlSecOpenSSLSymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown);
+
+ return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecOpenSSLSymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecOpenSSLSymKeyDataCheckId(data), 0);
+
+ return(xmlSecKeyDataBinaryValueGetSize(data));
+}
+
+static void
+xmlSecOpenSSLSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecOpenSSLSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugDump(data, output);
+}
+
+static void
+xmlSecOpenSSLSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecOpenSSLSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugXmlDump(data, output);
+}
+
+static int
+xmlSecOpenSSLSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) {
+#ifndef XMLSEC_NO_DES
+ if(klass == xmlSecOpenSSLKeyDataDesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+#ifndef XMLSEC_OPENSSL_096
+ if(klass == xmlSecOpenSSLKeyDataAesId) {
+ return(1);
+ }
+#endif /* XMLSEC_OPENSSL_096 */
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_HMAC
+ if(klass == xmlSecOpenSSLKeyDataHmacId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_HMAC */
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_AES
+#ifndef XMLSEC_OPENSSL_096
+/**************************************************************************
+ *
+ * <xmlsec:AESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataAesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameAESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefAESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecOpenSSLSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecOpenSSLSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecOpenSSLSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecOpenSSLSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecOpenSSLSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecOpenSSLSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecOpenSSLSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecOpenSSLSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecOpenSSLSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecOpenSSLSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecOpenSSLSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataAesGetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataAesKlass);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataAesSet:
+ * @data: the pointer to AES key data.
+ * @buf: the pointer to key value.
+ * @bufSize: the key value size (in bytes).
+ *
+ * Sets the value of AES key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataAesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+#endif /* XMLSEC_OPENSSL_096 */
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**************************************************************************
+ *
+ * <xmlsec:DESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataDesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameDESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecOpenSSLSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecOpenSSLSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecOpenSSLSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecOpenSSLSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecOpenSSLSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecOpenSSLSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecOpenSSLSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecOpenSSLSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecOpenSSLSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecOpenSSLSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecOpenSSLSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataDesGetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataDesKlass);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataDesSet:
+ * @data: the pointer to DES key data.
+ * @buf: the pointer to key value.
+ * @bufSize: the key value size (in bytes).
+ *
+ * Sets the value of DES key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataDesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_HMAC
+/**************************************************************************
+ *
+ * <xmlsec:HMACKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataHmacKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameHMACKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefHMACKeyValue, /* const xmlChar* href; */
+ xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecOpenSSLSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecOpenSSLSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecOpenSSLSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecOpenSSLSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecOpenSSLSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecOpenSSLSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecOpenSSLSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecOpenSSLSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecOpenSSLSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecOpenSSLSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecOpenSSLSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataHmacGetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataHmacKlass);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataHmacSet:
+ * @data: the pointer to HMAC key data.
+ * @buf: the pointer to key value.
+ * @bufSize: the key value size (in bytes).
+ *
+ * Sets the value of HMAC key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataHmacId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+#endif /* XMLSEC_NO_HMAC */
+
diff --git a/src/openssl/x509.c b/src/openssl/x509.c
new file mode 100644
index 00000000..459a312d
--- /dev/null
+++ b/src/openssl/x509.c
@@ -0,0 +1,2414 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+#include <libxml/tree.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+#include <openssl/asn1.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/x509.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+#include <xmlsec/openssl/x509.h>
+
+/*************************************************************************
+ *
+ * X509 utility functions
+ *
+ ************************************************************************/
+static int xmlSecOpenSSLX509DataNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509CertificateNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509CertificateNodeWrite (X509* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509SubjectNameNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509SubjectNameNodeWrite (X509* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509IssuerSerialNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509IssuerSerialNodeWrite (X509* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509SKINodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509SKINodeWrite (X509* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509CRLNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLX509CRLNodeWrite (X509_CRL* crl,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data,
+ xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static X509* xmlSecOpenSSLX509CertDerRead (const xmlSecByte* buf,
+ xmlSecSize size);
+static X509* xmlSecOpenSSLX509CertBase64DerRead (xmlChar* buf);
+static xmlChar* xmlSecOpenSSLX509CertBase64DerWrite (X509* cert,
+ int base64LineWrap);
+static X509_CRL* xmlSecOpenSSLX509CrlDerRead (xmlSecByte* buf,
+ xmlSecSize size);
+static X509_CRL* xmlSecOpenSSLX509CrlBase64DerRead (xmlChar* buf);
+static xmlChar* xmlSecOpenSSLX509CrlBase64DerWrite (X509_CRL* crl,
+ int base64LineWrap);
+static xmlChar* xmlSecOpenSSLX509NameWrite (X509_NAME* nm);
+static xmlChar* xmlSecOpenSSLASN1IntegerWrite (ASN1_INTEGER *asni);
+static xmlChar* xmlSecOpenSSLX509SKIWrite (X509* cert);
+static void xmlSecOpenSSLX509CertDebugDump (X509* cert,
+ FILE* output);
+static void xmlSecOpenSSLX509CertDebugXmlDump (X509* cert,
+ FILE* output);
+static int xmlSecOpenSSLX509CertGetTime (ASN1_TIME* t,
+ time_t* res);
+
+/*************************************************************************
+ *
+ * Internal OpenSSL X509 data CTX
+ *
+ ************************************************************************/
+typedef struct _xmlSecOpenSSLX509DataCtx xmlSecOpenSSLX509DataCtx,
+ *xmlSecOpenSSLX509DataCtxPtr;
+struct _xmlSecOpenSSLX509DataCtx {
+ X509* keyCert;
+ STACK_OF(X509)* certsList;
+ STACK_OF(X509_CRL)* crlsList;
+};
+
+/**************************************************************************
+ *
+ * <dsig:X509Data> processing
+ *
+ *
+ * The X509Data Element (http://www.w3.org/TR/xmldsig-core/#sec-X509Data)
+ *
+ * An X509Data element within KeyInfo contains one or more identifiers of keys
+ * or X509 certificates (or certificates' identifiers or a revocation list).
+ * The content of X509Data is:
+ *
+ * 1. At least one element, from the following set of element types; any of these may appear together or more than once iff (if and only if) each instance describes or is related to the same certificate:
+ * 2.
+ * * The X509IssuerSerial element, which contains an X.509 issuer
+ * distinguished name/serial number pair that SHOULD be compliant
+ * with RFC2253 [LDAP-DN],
+ * * The X509SubjectName element, which contains an X.509 subject
+ * distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN],
+ * * The X509SKI element, which contains the base64 encoded plain (i.e.
+ * non-DER-encoded) value of a X509 V.3 SubjectKeyIdentifier extension.
+ * * The X509Certificate element, which contains a base64-encoded [X509v3]
+ * certificate, and
+ * * Elements from an external namespace which accompanies/complements any
+ * of the elements above.
+ * * The X509CRL element, which contains a base64-encoded certificate
+ * revocation list (CRL) [X509v3].
+ *
+ * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear
+ * MUST refer to the certificate or certificates containing the validation key.
+ * All such elements that refer to a particular individual certificate MUST be
+ * grouped inside a single X509Data element and if the certificate to which
+ * they refer appears, it MUST also be in that X509Data element.
+ *
+ * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that relate to
+ * the same key but different certificates MUST be grouped within a single
+ * KeyInfo but MAY occur in multiple X509Data elements.
+ *
+ * All certificates appearing in an X509Data element MUST relate to the
+ * validation key by either containing it or being part of a certification
+ * chain that terminates in a certificate containing the validation key.
+ *
+ * No ordering is implied by the above constraints.
+ *
+ * Note, there is no direct provision for a PKCS#7 encoded "bag" of
+ * certificates or CRLs. However, a set of certificates and CRLs can occur
+ * within an X509Data element and multiple X509Data elements can occur in a
+ * KeyInfo. Whenever multiple certificates occur in an X509Data element, at
+ * least one such certificate must contain the public key which verifies the
+ * signature.
+ *
+ * Schema Definition
+ *
+ * <element name="X509Data" type="ds:X509DataType"/>
+ * <complexType name="X509DataType">
+ * <sequence maxOccurs="unbounded">
+ * <choice>
+ * <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+ * <element name="X509SKI" type="base64Binary"/>
+ * <element name="X509SubjectName" type="string"/>
+ * <element name="X509Certificate" type="base64Binary"/>
+ * <element name="X509CRL" type="base64Binary"/>
+ * <any namespace="##other" processContents="lax"/>
+ * </choice>
+ * </sequence>
+ * </complexType>
+ * <complexType name="X509IssuerSerialType">
+ * <sequence>
+ * <element name="X509IssuerName" type="string"/>
+ * <element name="X509SerialNumber" type="integer"/>
+ * </sequence>
+ * </complexType>
+ *
+ * DTD
+ *
+ * <!ELEMENT X509Data ((X509IssuerSerial | X509SKI | X509SubjectName |
+ * X509Certificate | X509CRL)+ %X509.ANY;)>
+ * <!ELEMENT X509IssuerSerial (X509IssuerName, X509SerialNumber) >
+ * <!ELEMENT X509IssuerName (#PCDATA) >
+ * <!ELEMENT X509SubjectName (#PCDATA) >
+ * <!ELEMENT X509SerialNumber (#PCDATA) >
+ * <!ELEMENT X509SKI (#PCDATA) >
+ * <!ELEMENT X509Certificate (#PCDATA) >
+ * <!ELEMENT X509CRL (#PCDATA) >
+ *
+ * -----------------------------------------------------------------------
+ *
+ * xmlSecOpenSSLX509DataCtx is located after xmlSecTransform
+ *
+ *************************************************************************/
+#define xmlSecOpenSSLX509DataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecOpenSSLX509DataCtx))
+#define xmlSecOpenSSLX509DataGetCtx(data) \
+ ((xmlSecOpenSSLX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecOpenSSLKeyDataX509Initialize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLKeyDataX509Duplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecOpenSSLKeyDataX509Finalize (xmlSecKeyDataPtr data);
+static int xmlSecOpenSSLKeyDataX509XmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecOpenSSLKeyDataX509XmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyDataType xmlSecOpenSSLKeyDataX509GetType (xmlSecKeyDataPtr data);
+static const xmlChar* xmlSecOpenSSLKeyDataX509GetIdentifier (xmlSecKeyDataPtr data);
+
+static void xmlSecOpenSSLKeyDataX509DebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecOpenSSLKeyDataX509DebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+
+
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataX509Klass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecOpenSSLX509DataSize,
+
+ /* data */
+ xmlSecNameX509Data,
+ xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefX509Data, /* const xmlChar* href; */
+ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecOpenSSLKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecOpenSSLKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecOpenSSLKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ xmlSecOpenSSLKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecOpenSSLKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecOpenSSLKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecOpenSSLKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecOpenSSLKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataX509GetKlass:
+ *
+ * The OpenSSL X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data).
+ *
+ * Returns: the X509 data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataX509GetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataX509Klass);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509GetKeyCert:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the certificate from which the key was extracted.
+ *
+ * Returns: the key's certificate or NULL if key data was not used for key
+ * extraction or an error occurs.
+ */
+X509*
+xmlSecOpenSSLKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->keyCert);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509AdoptKeyCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to OpenSSL X509 certificate.
+ *
+ * Sets the key's certificate in @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, X509* cert) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->keyCert != NULL) {
+ X509_free(ctx->keyCert);
+ }
+ ctx->keyCert = cert;
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509AdoptCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to OpenSSL X509 certificate.
+ *
+ * Adds certificate to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLKeyDataX509AdoptCert(xmlSecKeyDataPtr data, X509* cert) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->certsList == NULL) {
+ ctx->certsList = sk_X509_new_null();
+ if(ctx->certsList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "sk_X509_new_null",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ ret = sk_X509_push(ctx->certsList, cert);
+ if(ret < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "sk_X509_push",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509GetCert:
+ * @data: the pointer to X509 key data.
+ * @pos: the desired certificate position.
+ *
+ * Gets a certificate from X509 key data.
+ *
+ * Returns: the pointer to certificate or NULL if @pos is larger than the
+ * number of certificates in @data or an error occurs.
+ */
+X509*
+xmlSecOpenSSLKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->certsList != NULL, NULL);
+ xmlSecAssert2((int)pos < sk_X509_num(ctx->certsList), NULL);
+
+ return(sk_X509_value(ctx->certsList, pos));
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509GetCertsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of certificates in @data.
+ *
+ * Returns: te number of certificates in @data.
+ */
+xmlSecSize
+xmlSecOpenSSLKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), 0);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return((ctx->certsList != NULL) ? sk_X509_num(ctx->certsList) : 0);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509AdoptCrl:
+ * @data: the pointer to X509 key data.
+ * @crl: the pointer to OpenSSL X509 CRL.
+ *
+ * Adds CRL to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, X509_CRL* crl) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(crl != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->crlsList == NULL) {
+ ctx->crlsList = sk_X509_CRL_new_null();
+ if(ctx->crlsList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "sk_X509_CRL_new_null",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ ret = sk_X509_CRL_push(ctx->crlsList, crl);
+ if(ret < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "sk_X509_CRL_push",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509GetCrl:
+ * @data: the pointer to X509 key data.
+ * @pos: the desired CRL position.
+ *
+ * Gets a CRL from X509 key data.
+ *
+ * Returns: the pointer to CRL or NULL if @pos is larger than the
+ * number of CRLs in @data or an error occurs.
+ */
+X509_CRL*
+xmlSecOpenSSLKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ xmlSecAssert2(ctx->crlsList != NULL, NULL);
+ xmlSecAssert2((int)pos < sk_X509_CRL_num(ctx->crlsList), NULL);
+
+ return(sk_X509_CRL_value(ctx->crlsList, pos));
+}
+
+/**
+ * xmlSecOpenSSLKeyDataX509GetCrlsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of CRLs in @data.
+ *
+ * Returns: te number of CRLs in @data.
+ */
+xmlSecSize
+xmlSecOpenSSLKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), 0);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return((ctx->crlsList != NULL) ? sk_X509_CRL_num(ctx->crlsList) : 0);
+}
+
+static int
+xmlSecOpenSSLKeyDataX509Initialize(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLX509DataCtx));
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ X509* certSrc;
+ X509* certDst;
+ X509_CRL* crlSrc;
+ X509_CRL* crlDst;
+ xmlSecSize size, pos;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecOpenSSLKeyDataX509Id), -1);
+
+ /* copy certsList */
+ size = xmlSecOpenSSLKeyDataX509GetCertsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ certSrc = xmlSecOpenSSLKeyDataX509GetCert(src, pos);
+ if(certSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecOpenSSLKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ certDst = X509_dup(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(certDst);
+ return(-1);
+ }
+ }
+
+ /* copy crls */
+ size = xmlSecOpenSSLKeyDataX509GetCrlsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ crlSrc = xmlSecOpenSSLKeyDataX509GetCrl(src, pos);
+ if(crlSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecOpenSSLKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ crlDst = X509_CRL_dup(crlSrc);
+ if(crlDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "X509_CRL_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCrl(dst, crlDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecOpenSSLKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_CRL_free(crlDst);
+ return(-1);
+ }
+ }
+
+ /* copy key cert if exist */
+ certSrc = xmlSecOpenSSLKeyDataX509GetKeyCert(src);
+ if(certSrc != NULL) {
+ certDst = X509_dup(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecOpenSSLKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(certDst);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static void
+xmlSecOpenSSLKeyDataX509Finalize(xmlSecKeyDataPtr data) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id));
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->certsList != NULL) {
+ sk_X509_pop_free(ctx->certsList, X509_free);
+ }
+ if(ctx->crlsList != NULL) {
+ sk_X509_CRL_pop_free(ctx->crlsList, X509_CRL_free);
+ }
+ if(ctx->keyCert != NULL) {
+ X509_free(ctx->keyCert);
+ }
+ memset(ctx, 0, sizeof(xmlSecOpenSSLX509DataCtx));
+}
+
+static int
+xmlSecOpenSSLKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataX509Id, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ data = xmlSecKeyEnsureData(key, id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLX509DataNodeRead(data, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLX509DataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
+ ret = xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ X509* cert;
+ X509_CRL* crl;
+ xmlSecSize size, pos;
+ int content;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataX509Id, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ content = xmlSecX509DataGetNodeContent (node, 1, keyInfoCtx);
+ if (content < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecX509DataGetNodeContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "content=%d", content);
+ return(-1);
+ } else if(content == 0) {
+ /* by default we are writing certificates and crls */
+ content = XMLSEC_X509DATA_DEFAULT;
+ }
+
+ /* get x509 data */
+ data = xmlSecKeyGetData(key, id);
+ if(data == NULL) {
+ /* no x509 data in the key */
+ return(0);
+ }
+
+ /* write certs */
+ size = xmlSecOpenSSLKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecOpenSSLKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) {
+ ret = xmlSecOpenSSLX509CertificateNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLX509CertificateNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) {
+ ret = xmlSecOpenSSLX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLX509SubjectNameNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) {
+ ret = xmlSecOpenSSLX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLX509IssuerSerialNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SKI_NODE) != 0) {
+ ret = xmlSecOpenSSLX509SKINodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLX509SKINodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ /* write crls if needed */
+ if((content & XMLSEC_X509DATA_CRL_NODE) != 0) {
+ size = xmlSecOpenSSLKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ crl = xmlSecOpenSSLKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLX509CRLNodeWrite(crl, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLX509CRLNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+
+static xmlSecKeyDataType
+xmlSecOpenSSLKeyDataX509GetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), xmlSecKeyDataTypeUnknown);
+
+ /* TODO: return verified/not verified status */
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static const xmlChar*
+xmlSecOpenSSLKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), NULL);
+
+ /* TODO */
+ return(NULL);
+}
+
+static void
+xmlSecOpenSSLKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ X509* cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== X509 Data:\n");
+ cert = xmlSecOpenSSLKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "==== Key Certificate:\n");
+ xmlSecOpenSSLX509CertDebugDump(cert, output);
+ }
+
+ size = xmlSecOpenSSLKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecOpenSSLKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "==== Certificate:\n");
+ xmlSecOpenSSLX509CertDebugDump(cert, output);
+ }
+
+ /* we don't print out crls */
+}
+
+static void
+xmlSecOpenSSLKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ X509* cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<X509Data>\n");
+ cert = xmlSecOpenSSLKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "<KeyCertificate>\n");
+ xmlSecOpenSSLX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</KeyCertificate>\n");
+ }
+
+ size = xmlSecOpenSSLKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecOpenSSLKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "<Certificate>\n");
+ xmlSecOpenSSLX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</Certificate>\n");
+ }
+
+ /* we don't print out crls */
+ fprintf(output, "</X509Data>\n");
+}
+
+static int
+xmlSecOpenSSLX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ for(cur = xmlSecGetNextElementNode(node->children);
+ cur != NULL;
+ cur = xmlSecGetNextElementNode(cur->next)) {
+
+ ret = 0;
+ if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) {
+ ret = xmlSecOpenSSLX509CertificateNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+ ret = xmlSecOpenSSLX509SubjectNameNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+ ret = xmlSecOpenSSLX509IssuerSerialNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+ ret = xmlSecOpenSSLX509SKINodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+ ret = xmlSecOpenSSLX509CRLNodeRead(data, cur, keyInfoCtx);
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CHILD) != 0) {
+ /* laxi schema validation: ignore unknown nodes */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "read node failed");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ X509* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ content = xmlNodeGetContent(node);
+ if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+ if(content != NULL) {
+ xmlFree(content);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert = xmlSecOpenSSLX509CertBase64DerRead(content);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLX509CertBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509CertificateNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar* buf;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ /* set base64 lines size from context */
+ buf = xmlSecOpenSSLX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509CertBase64DerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509Certificate));
+ xmlFree(buf);
+ return(-1);
+ }
+
+ /* todo: add \n around base64 data - from context */
+ /* todo: add errors check */
+ xmlNodeSetContent(cur, xmlSecStringCR);
+ xmlNodeSetContent(cur, buf);
+ xmlFree(buf);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* subject;
+ X509* cert;
+ X509* cert2;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ subject = xmlNodeGetContent(node);
+ if((subject == NULL) || (xmlSecIsEmptyString(subject) == 1)) {
+ if(subject != NULL) {
+ xmlFree(subject);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert = xmlSecOpenSSLX509StoreFindCert(x509Store, subject, NULL, NULL, NULL, keyInfoCtx);
+ if(cert == NULL){
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ "subject=%s",
+ xmlSecErrorsSafeString(subject));
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+ }
+
+ cert2 = X509_dup(cert);
+ if(cert2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ xmlFree(subject);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert2);
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509SubjectNameNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecOpenSSLX509NameWrite(X509_get_subject_name(cert));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameWrite(X509_get_subject_name)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SubjectName));
+ xmlFree(buf);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(cur, buf);
+ xmlFree(buf);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlNodePtr cur;
+ xmlChar *issuerName;
+ xmlChar *issuerSerial;
+ X509* cert;
+ X509* cert2;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if(cur == NULL) {
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ return(0);
+ }
+
+ /* the first is required node X509IssuerName */
+ if(!xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ issuerName = xmlNodeGetContent(cur);
+ if(issuerName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is required node X509SerialNumber */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+ xmlFree(issuerName);
+ return(-1);
+ }
+ issuerSerial = xmlNodeGetContent(cur);
+ if(issuerSerial == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ xmlFree(issuerName);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ cert = xmlSecOpenSSLX509StoreFindCert(x509Store, NULL, issuerName, issuerSerial, NULL, keyInfoCtx);
+ if(cert == NULL){
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ "issuerName=%s;issuerSerial=%s",
+ xmlSecErrorsSafeString(issuerName),
+ xmlSecErrorsSafeString(issuerSerial));
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+ }
+
+ cert2 = X509_dup(cert);
+ if(cert2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert2);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509IssuerSerialNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlNodePtr cur;
+ xmlNodePtr issuerNameNode;
+ xmlNodePtr issuerNumberNode;
+ xmlChar* buf;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* create xml nodes */
+ cur = xmlSecAddChild(node, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial));
+ return(-1);
+ }
+
+ issuerNameNode = xmlSecAddChild(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs);
+ if(issuerNameNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+ return(-1);
+ }
+
+ issuerNumberNode = xmlSecAddChild(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs);
+ if(issuerNumberNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+ return(-1);
+ }
+
+ /* write data */
+ buf = xmlSecOpenSSLX509NameWrite(X509_get_issuer_name(cert));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameWrite(X509_get_issuer_name)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNameNode, buf);
+ xmlFree(buf);
+
+ buf = xmlSecOpenSSLASN1IntegerWrite(X509_get_serialNumber(cert));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLASN1IntegerWrite(X509_get_serialNumber)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNumberNode, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+
+static int
+xmlSecOpenSSLX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* ski;
+ X509* cert;
+ X509* cert2;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ski = xmlNodeGetContent(node);
+ if((ski == NULL) || (xmlSecIsEmptyString(ski) == 1)) {
+ if(ski != NULL) {
+ xmlFree(ski);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert = xmlSecOpenSSLX509StoreFindCert(x509Store, NULL, NULL, NULL, ski, keyInfoCtx);
+ if(cert == NULL){
+ xmlFree(ski);
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ "ski=%s",
+ xmlSecErrorsSafeString(ski));
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert2 = X509_dup(cert);
+ if(cert2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert2);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert2);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ xmlFree(ski);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509SKINodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar *buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecOpenSSLX509SKIWrite(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509SKIWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "new_node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+ xmlFree(buf);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(cur, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ X509_CRL* crl;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ content = xmlNodeGetContent(node);
+ if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+ if(content != NULL) {
+ xmlFree(content);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ crl = xmlSecOpenSSLX509CrlBase64DerRead(content);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLX509CrlBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCrl(data, crl);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_CRL_free(crl);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509CRLNodeWrite(X509_CRL* crl, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(crl != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ /* set base64 lines size from context */
+ buf = xmlSecOpenSSLX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509CrlBase64DerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509CRL, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "new_node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509CRL));
+ xmlFree(buf);
+ return(-1);
+ }
+ /* todo: add \n around base64 data - from context */
+ /* todo: add errors check */
+ xmlNodeSetContent(cur, xmlSecStringCR);
+ xmlNodeSetContent(cur, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+static int
+xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecOpenSSLX509DataCtxPtr ctx;
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecOpenSSLX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((ctx->keyCert == NULL) && (ctx->certsList != NULL) && (xmlSecKeyGetValue(key) == NULL)) {
+ X509* cert;
+
+ cert = xmlSecOpenSSLX509StoreVerify(x509Store, ctx->certsList, ctx->crlsList, keyInfoCtx);
+ if(cert != NULL) {
+ xmlSecKeyDataPtr keyValue;
+
+ ctx->keyCert = X509_dup(cert);
+ if(ctx->keyCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ keyValue = xmlSecOpenSSLX509CertGetKey(ctx->keyCert);
+ if(keyValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLX509CertGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* verify that the key matches our expectations */
+ if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), keyValue) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeyReqMatchKeyValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(keyValue);
+ return(-1);
+ }
+
+ ret = xmlSecKeySetValue(key, keyValue);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(keyValue);
+ return(-1);
+ }
+
+ if((X509_get_notBefore(ctx->keyCert) != NULL) && (X509_get_notAfter(ctx->keyCert) != NULL)) {
+ ret = xmlSecOpenSSLX509CertGetTime(X509_get_notBefore(ctx->keyCert), &(key->notValidBefore));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidBefore");
+ return(-1);
+ }
+ ret = xmlSecOpenSSLX509CertGetTime(X509_get_notAfter(ctx->keyCert), &(key->notValidAfter));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecOpenSSLX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidAfter");
+ return(-1);
+ }
+ } else {
+ key->notValidBefore = key->notValidAfter = 0;
+ }
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_INVALID_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+#ifdef HAVE_TIMEGM
+extern time_t timegm (struct tm *tm);
+#else /* HAVE_TIMEGM */
+#ifdef WIN32
+#define timegm(tm) (mktime(tm) - _timezone)
+#else /* WIN32 */
+/* Absolutely not the best way but it's the only ANSI compatible way I know.
+ * If you system has a native struct tm --> GMT time_t conversion function
+ * (like timegm) use it instead.
+ */
+static time_t
+my_timegm(struct tm *t) {
+ time_t tl, tb;
+ struct tm *tg;
+
+ tl = mktime (t);
+ if(tl == -1) {
+ t->tm_hour--;
+ tl = mktime (t);
+ if (tl == -1) {
+ return -1;
+ }
+ tl += 3600;
+ }
+ tg = gmtime (&tl);
+ tg->tm_isdst = 0;
+ tb = mktime (tg);
+ if (tb == -1) {
+ tg->tm_hour--;
+ tb = mktime (tg);
+ if (tb == -1) {
+ return -1;
+ }
+ tb += 3600;
+ }
+ return (tl - (tb - tl));
+}
+
+#define timegm(tm) my_timegm(tm)
+#endif /* WIN32 */
+#endif /* HAVE_TIMEGM */
+
+static int
+xmlSecOpenSSLX509CertGetTime(ASN1_TIME* t, time_t* res) {
+ struct tm tm;
+ int offset;
+
+ xmlSecAssert2(t != NULL, -1);
+ xmlSecAssert2(res != NULL, -1);
+
+ (*res) = 0;
+#ifndef XMLSEC_OPENSSL_096
+ if(!ASN1_TIME_check(t)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "ASN1_TIME_check",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+#endif /* XMLSEC_OPENSSL_096 */
+
+ memset(&tm, 0, sizeof(tm));
+
+#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
+ if(t->type == V_ASN1_UTCTIME) {
+ xmlSecAssert2(t->length > 12, -1);
+
+
+ /* this code is copied from OpenSSL asn1/a_utctm.c file */
+ tm.tm_year = g2(t->data);
+ if(tm.tm_year < 50) {
+ tm.tm_year += 100;
+ }
+ tm.tm_mon = g2(t->data + 2) - 1;
+ tm.tm_mday = g2(t->data + 4);
+ tm.tm_hour = g2(t->data + 6);
+ tm.tm_min = g2(t->data + 8);
+ tm.tm_sec = g2(t->data + 10);
+ if(t->data[12] == 'Z') {
+ offset = 0;
+ } else {
+ xmlSecAssert2(t->length > 16, -1);
+
+ offset = g2(t->data + 13) * 60 + g2(t->data + 15);
+ if(t->data[12] == '-') {
+ offset = -offset;
+ }
+ }
+ tm.tm_isdst = -1;
+ } else {
+ xmlSecAssert2(t->length > 14, -1);
+
+ tm.tm_year = g2(t->data) * 100 + g2(t->data + 2);
+ tm.tm_mon = g2(t->data + 4) - 1;
+ tm.tm_mday = g2(t->data + 6);
+ tm.tm_hour = g2(t->data + 8);
+ tm.tm_min = g2(t->data + 10);
+ tm.tm_sec = g2(t->data + 12);
+ if(t->data[14] == 'Z') {
+ offset = 0;
+ } else {
+ xmlSecAssert2(t->length > 18, -1);
+
+ offset = g2(t->data + 15) * 60 + g2(t->data + 17);
+ if(t->data[14] == '-') {
+ offset = -offset;
+ }
+ }
+ tm.tm_isdst = -1;
+ }
+#undef g2
+ (*res) = timegm(&tm) - offset * 60;
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLX509CertGetKey:
+ * @cert: the certificate.
+ *
+ * Extracts public key from the @cert.
+ *
+ * Returns: public key value or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecOpenSSLX509CertGetKey(X509* cert) {
+ xmlSecKeyDataPtr data;
+ EVP_PKEY *pKey = NULL;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ pKey = X509_get_pubkey(cert);
+ if(pKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_get_pubkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ data = xmlSecOpenSSLEvpKeyAdopt(pKey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLEvpKeyAdopt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ EVP_PKEY_free(pKey);
+ return(NULL);
+ }
+
+ return(data);
+}
+
+static X509*
+xmlSecOpenSSLX509CertBase64DerRead(xmlChar* buf) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+
+ /* usual trick with base64 decoding "in-place" */
+ ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecOpenSSLX509CertDerRead((xmlSecByte*)buf, ret));
+}
+
+static X509*
+xmlSecOpenSSLX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
+ X509 *cert = NULL;
+ BIO *mem = NULL;
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ mem = BIO_new(BIO_s_mem());
+ if(mem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "BIO_s_mem");
+ return(NULL);
+ }
+
+ ret = BIO_write(mem, buf, size);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_write",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", size);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ cert = d2i_X509_bio(mem, NULL);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "d2i_X509_bio",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ BIO_free_all(mem);
+ return(cert);
+}
+
+static xmlChar*
+xmlSecOpenSSLX509CertBase64DerWrite(X509* cert, int base64LineWrap) {
+ xmlChar *res = NULL;
+ BIO *mem = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ mem = BIO_new(BIO_s_mem());
+ if(mem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "BIO_s_mem");
+ return(NULL);
+ }
+
+ /* todo: add error checks */
+ i2d_X509_bio(mem, cert);
+ BIO_flush(mem);
+
+ size = BIO_get_mem_data(mem, &p);
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_get_mem_data",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(p, size, base64LineWrap);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ BIO_free_all(mem);
+ return(res);
+}
+
+static X509_CRL*
+xmlSecOpenSSLX509CrlBase64DerRead(xmlChar* buf) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+
+ /* usual trick with base64 decoding "in-place" */
+ ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecOpenSSLX509CrlDerRead((xmlSecByte*)buf, ret));
+}
+
+static X509_CRL*
+xmlSecOpenSSLX509CrlDerRead(xmlSecByte* buf, xmlSecSize size) {
+ X509_CRL *crl = NULL;
+ BIO *mem = NULL;
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ mem = BIO_new(BIO_s_mem());
+ if(mem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "BIO_s_mem");
+ return(NULL);
+ }
+
+ ret = BIO_write(mem, buf, size);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_write",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", size);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ crl = d2i_X509_CRL_bio(mem, NULL);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "d2i_X509_CRL_bio",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ BIO_free_all(mem);
+ return(crl);
+}
+
+static xmlChar*
+xmlSecOpenSSLX509CrlBase64DerWrite(X509_CRL* crl, int base64LineWrap) {
+ xmlChar *res = NULL;
+ BIO *mem = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(crl != NULL, NULL);
+
+ mem = BIO_new(BIO_s_mem());
+ if(mem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "BIO_s_mem");
+ return(NULL);
+ }
+
+ /* todo: add error checks */
+ i2d_X509_CRL_bio(mem, crl);
+ BIO_flush(mem);
+
+ size = BIO_get_mem_data(mem, &p);
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_get_mem_data",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(p, size, base64LineWrap);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ BIO_free_all(mem);
+ return(res);
+}
+
+static xmlChar*
+xmlSecOpenSSLX509NameWrite(X509_NAME* nm) {
+ xmlChar *res = NULL;
+ BIO *mem = NULL;
+ long size;
+
+ xmlSecAssert2(nm != NULL, NULL);
+
+ mem = BIO_new(BIO_s_mem());
+ if(mem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BIO_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "BIO_s_mem");
+ return(NULL);
+ }
+
+ if (X509_NAME_print_ex(mem, nm, 0, XN_FLAG_RFC2253) <=0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_NAME_print_ex",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ BIO_flush(mem); /* should call flush ? */
+
+ size = BIO_pending(mem);
+ res = xmlMalloc(size + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BIO_free_all(mem);
+ return(NULL);
+ }
+
+ size = BIO_read(mem, res, size);
+ res[size] = '\0';
+
+ BIO_free_all(mem);
+ return(res);
+}
+
+static xmlChar*
+xmlSecOpenSSLASN1IntegerWrite(ASN1_INTEGER *asni) {
+ xmlChar *res = NULL;
+ BIGNUM *bn;
+ char *p;
+
+ xmlSecAssert2(asni != NULL, NULL);
+
+ bn = ASN1_INTEGER_to_BN(asni, NULL);
+ if(bn == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "ASN1_INTEGER_to_BN",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ p = BN_bn2dec(bn);
+ if (p == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_bn2dec",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BN_free(bn);
+ return(NULL);
+ }
+ BN_free(bn);
+ bn = NULL;
+
+ /* OpenSSL and LibXML2 can have different memory callbacks, i.e.
+ when data is allocated in OpenSSL should be freed with OpenSSL
+ method, not with LibXML2 method.
+ */
+ res = xmlCharStrdup(p);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlCharStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ OPENSSL_free(p);
+ return(NULL);
+ }
+ OPENSSL_free(p);
+ p = NULL;
+ return(res);
+}
+
+static xmlChar*
+xmlSecOpenSSLX509SKIWrite(X509* cert) {
+ xmlChar *res = NULL;
+ int index;
+ X509_EXTENSION *ext;
+ ASN1_OCTET_STRING *keyId;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
+ if (index < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "Certificate without SubjectKeyIdentifier extension",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ext = X509_get_ext(cert, index);
+ if (ext == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_get_ext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ keyId = X509V3_EXT_d2i(ext);
+ if (keyId == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509V3_EXT_d2i",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ M_ASN1_OCTET_STRING_free(keyId);
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(M_ASN1_STRING_data(keyId), M_ASN1_STRING_length(keyId), 0);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ M_ASN1_OCTET_STRING_free(keyId);
+ return(NULL);
+ }
+ M_ASN1_OCTET_STRING_free(keyId);
+
+ return(res);
+}
+
+static void
+xmlSecOpenSSLX509CertDebugDump(X509* cert, FILE* output) {
+ char buf[1024];
+ BIGNUM *bn = NULL;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "==== Subject Name: %s\n",
+ X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)));
+ fprintf(output, "==== Issuer Name: %s\n",
+ X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)));
+ fprintf(output, "==== Issuer Serial: ");
+ bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert),NULL);
+ if(bn != NULL) {
+ BN_print_fp(output, bn);
+ BN_free(bn);
+ fprintf(output, "\n");
+ } else {
+ fprintf(output, "unknown\n");
+ }
+}
+
+
+static void
+xmlSecOpenSSLX509CertDebugXmlDump(X509* cert, FILE* output) {
+ char buf[1024];
+ BIGNUM *bn = NULL;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<SubjectName>");
+ xmlSecPrintXmlString(output,
+ BAD_CAST X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf))
+ );
+ fprintf(output, "</SubjectName>\n");
+
+
+ fprintf(output, "<IssuerName>");
+ xmlSecPrintXmlString(output,
+ BAD_CAST X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)));
+ fprintf(output, "</IssuerName>\n");
+
+ fprintf(output, "<SerialNumber>");
+ bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert),NULL);
+ if(bn != NULL) {
+ BN_print_fp(output, bn);
+ BN_free(bn);
+ }
+ fprintf(output, "</SerialNumber>\n");
+}
+
+
+/**************************************************************************
+ *
+ * Raw X509 Certificate processing
+ *
+ *
+ *************************************************************************/
+static int xmlSecOpenSSLKeyDataRawX509CertBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecOpenSSLKeyDataRawX509CertKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ sizeof(xmlSecKeyData),
+
+ /* data */
+ xmlSecNameRawX509Cert,
+ xmlSecKeyDataUsageRetrievalMethodNodeBin,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRawX509Cert, /* const xmlChar* href; */
+ NULL, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ NULL, /* xmlSecKeyDataInitializeMethod initialize; */
+ NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ NULL, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ NULL, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecOpenSSLKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecOpenSSLKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 certificates key data klass.
+ *
+ * Returns: raw X509 certificates key data klass.
+ */
+xmlSecKeyDataId
+xmlSecOpenSSLKeyDataRawX509CertGetKlass(void) {
+ return(&xmlSecOpenSSLKeyDataRawX509CertKlass);
+}
+
+static int
+xmlSecOpenSSLKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ X509* cert;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecOpenSSLKeyDataRawX509CertId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ cert = xmlSecOpenSSLX509CertDerRead(buf, bufSize);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509CertDerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ data = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_free(cert);
+ return(-1);
+ }
+
+ ret = xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecOpenSSLKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/openssl/x509vfy.c b/src/openssl/x509vfy.c
new file mode 100644
index 00000000..fe51da4e
--- /dev/null
+++ b/src/openssl/x509vfy.c
@@ -0,0 +1,1284 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <libxml/tree.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
+#include <xmlsec/openssl/x509.h>
+
+/**************************************************************************
+ *
+ * Internal OpenSSL X509 store CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecOpenSSLX509StoreCtx xmlSecOpenSSLX509StoreCtx,
+ *xmlSecOpenSSLX509StoreCtxPtr;
+struct _xmlSecOpenSSLX509StoreCtx {
+ X509_STORE* xst;
+ STACK_OF(X509)* untrusted;
+ STACK_OF(X509_CRL)* crls;
+
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+ X509_VERIFY_PARAM * vpm;
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+};
+
+/****************************************************************************
+ *
+ * xmlSecOpenSSLKeyDataStoreX509Id:
+ *
+ * xmlSecOpenSSLX509StoreCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecOpenSSLX509StoreGetCtx(store) \
+ ((xmlSecOpenSSLX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
+ sizeof(xmlSecKeyDataStoreKlass)))
+#define xmlSecOpenSSLX509StoreSize \
+ (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecOpenSSLX509StoreCtx))
+
+static int xmlSecOpenSSLX509StoreInitialize (xmlSecKeyDataStorePtr store);
+static void xmlSecOpenSSLX509StoreFinalize (xmlSecKeyDataStorePtr store);
+
+static xmlSecKeyDataStoreKlass xmlSecOpenSSLX509StoreKlass = {
+ sizeof(xmlSecKeyDataStoreKlass),
+ xmlSecOpenSSLX509StoreSize,
+
+ /* data */
+ xmlSecNameX509Store, /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecOpenSSLX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
+ xmlSecOpenSSLX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static int xmlSecOpenSSLX509VerifyCRL (X509_STORE* xst,
+ X509_CRL *crl );
+static X509* xmlSecOpenSSLX509FindCert (STACK_OF(X509) *certs,
+ xmlChar *subjectName,
+ xmlChar *issuerName,
+ xmlChar *issuerSerial,
+ xmlChar *ski);
+static X509* xmlSecOpenSSLX509FindNextChainCert (STACK_OF(X509) *chain,
+ X509 *cert);
+static int xmlSecOpenSSLX509VerifyCertAgainstCrls (STACK_OF(X509_CRL) *crls,
+ X509* cert);
+static X509_NAME* xmlSecOpenSSLX509NameRead (xmlSecByte *str,
+ int len);
+static int xmlSecOpenSSLX509NameStringRead (xmlSecByte **str,
+ int *strLen,
+ xmlSecByte *res,
+ int resLen,
+ xmlSecByte delim,
+ int ingoreTrailingSpaces);
+static int xmlSecOpenSSLX509NamesCompare (X509_NAME *a,
+ X509_NAME *b);
+static int xmlSecOpenSSLX509_NAME_cmp (const X509_NAME * a,
+ const X509_NAME * b);
+static int xmlSecOpenSSLX509_NAME_ENTRY_cmp (const X509_NAME_ENTRY * const *a,
+ const X509_NAME_ENTRY * const *b);
+
+/**
+ * xmlSecOpenSSLX509StoreGetKlass:
+ *
+ * The OpenSSL X509 certificates key data store klass.
+ *
+ * Returns: pointer to OpenSSL X509 certificates key data store klass.
+ */
+xmlSecKeyDataStoreId
+xmlSecOpenSSLX509StoreGetKlass(void) {
+ return(&xmlSecOpenSSLX509StoreKlass);
+}
+
+/**
+ * xmlSecOpenSSLX509StoreFindCert:
+ * @store: the pointer to X509 key data store klass.
+ * @subjectName: the desired certificate name.
+ * @issuerName: the desired certificate issuer name.
+ * @issuerSerial: the desired certificate issuer serial number.
+ * @ski: the desired certificate SKI.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Searches @store for a certificate that matches given criteria.
+ *
+ * Returns: pointer to found certificate or NULL if certificate is not found
+ * or an error occurs.
+ */
+X509*
+xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
+ xmlChar *issuerName, xmlChar *issuerSerial,
+ xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ X509* res = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ if((res == NULL) && (ctx->untrusted != NULL)) {
+ res = xmlSecOpenSSLX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecOpenSSLX509StoreVerify:
+ * @store: the pointer to X509 key data store klass.
+ * @certs: the untrusted certificates stack.
+ * @crls: the crls stack.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Verifies @certs list.
+ *
+ * Returns: pointer to the first verified certificate from @certs.
+ */
+X509*
+xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs,
+ XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ STACK_OF(X509)* certs2 = NULL;
+ STACK_OF(X509_CRL)* crls2 = NULL;
+ X509 * res = NULL;
+ X509 * cert;
+ X509 * err_cert = NULL;
+ char buf[256];
+ int err = 0, depth;
+ int i;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->xst != NULL, NULL);
+
+ /* dup certs */
+ certs2 = sk_X509_dup(certs);
+ if(certs2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* add untrusted certs from the store */
+ if(ctx->untrusted != NULL) {
+ for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) {
+ ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i));
+ if(ret < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_push",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ }
+
+ /* dup crls but remove all non-verified */
+ if(crls != NULL) {
+ crls2 = sk_X509_CRL_dup(crls);
+ if(crls2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_CRL_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ for(i = 0; i < sk_X509_CRL_num(crls2); ) {
+ ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i));
+ if(ret == 1) {
+ ++i;
+ } else if(ret == 0) {
+ (void)sk_X509_CRL_delete(crls2, i);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecOpenSSLX509VerifyCRL",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ }
+
+ /* remove all revoked certs */
+ for(i = 0; i < sk_X509_num(certs2);) {
+ cert = sk_X509_value(certs2, i);
+
+ if(crls2 != NULL) {
+ ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert);
+ if(ret == 0) {
+ (void)sk_X509_delete(certs2, i);
+ continue;
+ } else if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecOpenSSLX509VerifyCertAgainstCrls",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ if(ctx->crls != NULL) {
+ ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert);
+ if(ret == 0) {
+ (void)sk_X509_delete(certs2, i);
+ continue;
+ } else if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "xmlSecOpenSSLX509VerifyCertAgainstCrls",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+ ++i;
+ }
+
+ /* get one cert after another and try to verify */
+ for(i = 0; i < sk_X509_num(certs2); ++i) {
+ cert = sk_X509_value(certs2, i);
+ if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) {
+ X509_STORE_CTX xsc;
+
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+ X509_VERIFY_PARAM * vpm = NULL;
+ unsigned long vpm_flags = 0;
+
+ vpm = X509_VERIFY_PARAM_new();
+ if(vpm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_VERIFY_PARAM_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ vpm_flags = vpm->flags;
+/*
+ vpm_flags &= (~X509_V_FLAG_X509_STRICT);
+*/
+ vpm_flags &= (~X509_V_FLAG_CRL_CHECK);
+
+ X509_VERIFY_PARAM_set_depth(vpm, 9);
+ X509_VERIFY_PARAM_set_flags(vpm, vpm_flags);
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+
+
+ X509_STORE_CTX_init (&xsc, ctx->xst, cert, certs2);
+
+ if(keyInfoCtx->certsVerificationTime > 0) {
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+ vpm_flags |= X509_V_FLAG_USE_CHECK_TIME;
+ X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime);
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+ X509_STORE_CTX_set_time(&xsc, 0, keyInfoCtx->certsVerificationTime);
+ }
+
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+ X509_STORE_CTX_set0_param(&xsc, vpm);
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+
+
+ ret = X509_verify_cert(&xsc);
+ err_cert = X509_STORE_CTX_get_current_cert(&xsc);
+ err = X509_STORE_CTX_get_error(&xsc);
+ depth = X509_STORE_CTX_get_error_depth(&xsc);
+
+ X509_STORE_CTX_cleanup (&xsc);
+
+ if(ret == 1) {
+ res = cert;
+ goto done;
+ } else if(ret < 0) {
+ const char* err_msg;
+
+ buf[0] = '\0';
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
+ err_msg = X509_verify_cert_error_string(err);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_verify_cert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "subj=%s;err=%d;msg=%s",
+ xmlSecErrorsSafeString(buf),
+ err,
+ xmlSecErrorsSafeString(err_msg));
+ goto done;
+ } else if(ret == 0) {
+ const char* err_msg;
+
+ buf[0] = '\0';
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
+ err_msg = X509_verify_cert_error_string(err);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_verify_cert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "subj=%s;err=%d;msg=%s",
+ xmlSecErrorsSafeString(buf),
+ err,
+ xmlSecErrorsSafeString(err_msg));
+ }
+ }
+ }
+
+ /* if we came here then we found nothing. do we have any error? */
+ if((err != 0) && (err_cert != NULL)) {
+ const char* err_msg;
+
+ err_msg = X509_verify_cert_error_string(err);
+ switch (err) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
+ "err=%d;msg=%s;issuer=%s",
+ err,
+ xmlSecErrorsSafeString(err_msg),
+ xmlSecErrorsSafeString(buf));
+ break;
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
+ "err=%d;msg=%s", err,
+ xmlSecErrorsSafeString(err_msg));
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
+ "err=%d;msg=%s", err,
+ xmlSecErrorsSafeString(err_msg));
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+ "err=%d;msg=%s", err,
+ xmlSecErrorsSafeString(err_msg));
+ }
+ }
+
+done:
+ if(certs2 != NULL) {
+ sk_X509_free(certs2);
+ }
+ if(crls2 != NULL) {
+ sk_X509_CRL_free(crls2);
+ }
+ return(res);
+}
+
+/**
+ * xmlSecOpenSSLX509StoreAdoptCert:
+ * @store: the pointer to X509 key data store klass.
+ * @cert: the pointer to OpenSSL X509 certificate.
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Adds trusted (root) or untrusted certificate to the store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store, X509* cert, xmlSecKeyDataType type) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if((type & xmlSecKeyDataTypeTrusted) != 0) {
+ xmlSecAssert2(ctx->xst != NULL, -1);
+
+ ret = X509_STORE_add_cert(ctx->xst, cert);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_STORE_add_cert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ /* add cert increments the reference */
+ X509_free(cert);
+ } else {
+ xmlSecAssert2(ctx->untrusted != NULL, -1);
+
+ ret = sk_X509_push(ctx->untrusted, cert);
+ if(ret < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_push",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLX509StoreAdoptCrl:
+ * @store: the pointer to X509 key data store klass.
+ * @crl: the pointer to OpenSSL X509_CRL.
+ *
+ * Adds X509 CRL to the store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store, X509_CRL* crl) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
+ xmlSecAssert2(crl != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->crls != NULL, -1);
+
+ ret = sk_X509_CRL_push(ctx->crls, crl);
+ if(ret < 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_CRL_push",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return (0);
+}
+
+/**
+ * xmlSecOpenSSLX509StoreAddCertsPath:
+ * @store: the pointer to OpenSSL x509 store.
+ * @path: the path to the certs dir.
+ *
+ * Adds all certs in the @path to the list of trusted certs
+ * in @store.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store, const char *path) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ X509_LOOKUP *lookup = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
+ xmlSecAssert2(path != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->xst != NULL, -1);
+
+ lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
+ if(lookup == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_STORE_add_lookup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_LOOKUP_add_dir",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "path='%s'",
+ xmlSecErrorsSafeString(path)
+ );
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecOpenSSLX509StoreAddCertsFile:
+ * @store: the pointer to OpenSSL x509 store.
+ * @file: the certs file.
+ *
+ * Adds all certs in @file to the list of trusted certs
+ * in @store. It is possible for @file to contain multiple certs.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store, const char *file) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ X509_LOOKUP *lookup = NULL;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
+ xmlSecAssert2(file != NULL, -1);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->xst != NULL, -1);
+
+ lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_file());
+ if(lookup == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_STORE_add_lookup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_LOOKUP_load_file",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "file='%s'",
+ xmlSecErrorsSafeString(file)
+ );
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store) {
+ const xmlChar* path;
+ X509_LOOKUP *lookup = NULL;
+
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
+
+ ctx->xst = X509_STORE_new();
+ if(ctx->xst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_STORE_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(!X509_STORE_set_default_paths(ctx->xst)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_STORE_set_default_paths",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+
+ lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
+ if(lookup == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_STORE_add_lookup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ path = xmlSecOpenSSLGetDefaultTrustedCertsFolder();
+ if(path != NULL) {
+ if(!X509_LOOKUP_add_dir(lookup, (char*)path, X509_FILETYPE_PEM)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_LOOKUP_add_dir",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "path='%s'",
+ xmlSecErrorsSafeString(path)
+ );
+ return(-1);
+ }
+ } else {
+ if(!X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_LOOKUP_add_dir",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE
+ );
+ return(-1);
+ }
+ }
+
+ ctx->untrusted = sk_X509_new_null();
+ if(ctx->untrusted == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_new_null",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->crls = sk_X509_CRL_new_null();
+ if(ctx->crls == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "sk_X509_CRL_new_null",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+ ctx->vpm = X509_VERIFY_PARAM_new();
+ if(ctx->vpm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "X509_VERIFY_PARAM_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ X509_VERIFY_PARAM_set_depth(ctx->vpm, 9); /* the default cert verification path in openssl */
+ X509_STORE_set1_param(ctx->xst, ctx->vpm);
+
+#else /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+ ctx->xst->depth = 9; /* the default cert verification path in openssl */
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+
+ return(0);
+}
+
+static void
+xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store) {
+ xmlSecOpenSSLX509StoreCtxPtr ctx;
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId));
+
+ ctx = xmlSecOpenSSLX509StoreGetCtx(store);
+ xmlSecAssert(ctx != NULL);
+
+
+ if(ctx->xst != NULL) {
+ X509_STORE_free(ctx->xst);
+ }
+ if(ctx->untrusted != NULL) {
+ sk_X509_pop_free(ctx->untrusted, X509_free);
+ }
+ if(ctx->crls != NULL) {
+ sk_X509_CRL_pop_free(ctx->crls, X509_CRL_free);
+ }
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+ if(ctx->vpm != NULL) {
+ X509_VERIFY_PARAM_free(ctx->vpm);
+ }
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+
+ memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
+}
+
+
+/*****************************************************************************
+ *
+ * Low-level x509 functions
+ *
+ *****************************************************************************/
+static int
+xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) {
+ X509_STORE_CTX xsc;
+ X509_OBJECT xobj;
+ EVP_PKEY *pkey;
+ int ret;
+
+ xmlSecAssert2(xst != NULL, -1);
+ xmlSecAssert2(crl != NULL, -1);
+
+ X509_STORE_CTX_init(&xsc, xst, NULL, NULL);
+ ret = X509_STORE_get_by_subject(&xsc, X509_LU_X509,
+ X509_CRL_get_issuer(crl), &xobj);
+ if(ret <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_STORE_get_by_subject",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ pkey = X509_get_pubkey(xobj.data.x509);
+ X509_OBJECT_free_contents(&xobj);
+ if(pkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_get_pubkey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ ret = X509_CRL_verify(crl, pkey);
+ EVP_PKEY_free(pkey);
+ if(ret != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_CRL_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+ X509_STORE_CTX_cleanup (&xsc);
+ return((ret == 1) ? 1 : 0);
+}
+
+static X509*
+xmlSecOpenSSLX509FindCert(STACK_OF(X509) *certs, xmlChar *subjectName,
+ xmlChar *issuerName, xmlChar *issuerSerial,
+ xmlChar *ski) {
+ X509 *cert = NULL;
+ int i;
+
+ xmlSecAssert2(certs != NULL, NULL);
+
+ /* todo: may be this is not the fastest way to search certs */
+ if(subjectName != NULL) {
+ X509_NAME *nm;
+ X509_NAME *subj;
+
+ nm = xmlSecOpenSSLX509NameRead(subjectName, xmlStrlen(subjectName));
+ if(nm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "subject=%s",
+ xmlSecErrorsSafeString(subjectName));
+ return(NULL);
+ }
+
+ for(i = 0; i < sk_X509_num(certs); ++i) {
+ cert = sk_X509_value(certs, i);
+ subj = X509_get_subject_name(cert);
+ if(xmlSecOpenSSLX509NamesCompare(nm, subj) == 0) {
+ X509_NAME_free(nm);
+ return(cert);
+ }
+ }
+ X509_NAME_free(nm);
+ } else if((issuerName != NULL) && (issuerSerial != NULL)) {
+ X509_NAME *nm;
+ X509_NAME *issuer;
+ BIGNUM *bn;
+ ASN1_INTEGER *serial;
+
+ nm = xmlSecOpenSSLX509NameRead(issuerName, xmlStrlen(issuerName));
+ if(nm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "issuer=%s",
+ xmlSecErrorsSafeString(issuerName));
+ return(NULL);
+ }
+
+ bn = BN_new();
+ if(bn == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+ if(BN_dec2bn(&bn, (char*)issuerSerial) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_dec2bn",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BN_free(bn);
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+
+ serial = BN_to_ASN1_INTEGER(bn, NULL);
+ if(serial == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "BN_to_ASN1_INTEGER",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ BN_free(bn);
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+ BN_free(bn);
+
+
+ for(i = 0; i < sk_X509_num(certs); ++i) {
+ cert = sk_X509_value(certs, i);
+ if(ASN1_INTEGER_cmp(X509_get_serialNumber(cert), serial) != 0) {
+ continue;
+ }
+ issuer = X509_get_issuer_name(cert);
+ if(xmlSecOpenSSLX509NamesCompare(nm, issuer) == 0) {
+ ASN1_INTEGER_free(serial);
+ X509_NAME_free(nm);
+ return(cert);
+ }
+ }
+
+ X509_NAME_free(nm);
+ ASN1_INTEGER_free(serial);
+ } else if(ski != NULL) {
+ int len;
+ int index;
+ X509_EXTENSION *ext;
+ ASN1_OCTET_STRING *keyId;
+
+ /* our usual trick with base64 decode */
+ len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski));
+ if(len < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ski=%s",
+ xmlSecErrorsSafeString(ski));
+ return(NULL);
+ }
+ for(i = 0; i < sk_X509_num(certs); ++i) {
+ cert = sk_X509_value(certs, i);
+ index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
+ if((index >= 0) && (ext = X509_get_ext(cert, index))) {
+ keyId = X509V3_EXT_d2i(ext);
+ if((keyId != NULL) && (keyId->length == len) &&
+ (memcmp(keyId->data, ski, len) == 0)) {
+ M_ASN1_OCTET_STRING_free(keyId);
+ return(cert);
+ }
+ M_ASN1_OCTET_STRING_free(keyId);
+ }
+ }
+ }
+
+ return(NULL);
+}
+
+static X509*
+xmlSecOpenSSLX509FindNextChainCert(STACK_OF(X509) *chain, X509 *cert) {
+ unsigned long certSubjHash;
+ int i;
+
+ xmlSecAssert2(chain != NULL, NULL);
+ xmlSecAssert2(cert != NULL, NULL);
+
+ certSubjHash = X509_subject_name_hash(cert);
+ for(i = 0; i < sk_X509_num(chain); ++i) {
+ if((sk_X509_value(chain, i) != cert) &&
+ (X509_issuer_name_hash(sk_X509_value(chain, i)) == certSubjHash)) {
+
+ return(sk_X509_value(chain, i));
+ }
+ }
+ return(NULL);
+}
+
+static int
+xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF(X509_CRL) *crls, X509* cert) {
+ X509_NAME *issuer;
+ X509_CRL *crl = NULL;
+ X509_REVOKED *revoked;
+ int i, n;
+ int ret;
+
+ xmlSecAssert2(crls != NULL, -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ /*
+ * Try to retrieve a CRL corresponding to the issuer of
+ * the current certificate
+ */
+ n = sk_X509_CRL_num(crls);
+ for(i = 0; i < n; i++) {
+ crl = sk_X509_CRL_value(crls, i);
+ if(crl == NULL) {
+ continue;
+ }
+
+ issuer = X509_CRL_get_issuer(crl);
+ if(xmlSecOpenSSLX509NamesCompare(X509_CRL_get_issuer(crl), issuer) == 0) {
+ break;
+ }
+ }
+ if((i >= n) || (crl == NULL)){
+ /* no crls for this issuer */
+ return(1);
+ }
+
+ /*
+ * Check date of CRL to make sure it's not expired
+ */
+ ret = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
+ if (ret == 0) {
+ /* crl expired */
+ return(1);
+ }
+
+ /*
+ * Check if the current certificate is revoked by this CRL
+ */
+ n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
+ for (i = 0; i < n; i++) {
+ revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
+ if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(cert)) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_CERT_REVOKED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(0);
+ }
+ }
+ return(1);
+}
+
+static X509_NAME *
+xmlSecOpenSSLX509NameRead(xmlSecByte *str, int len) {
+ xmlSecByte name[256];
+ xmlSecByte value[256];
+ int nameLen, valueLen;
+ X509_NAME *nm;
+ int type = MBSTRING_ASC;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ nm = X509_NAME_new();
+ if(nm == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_NAME_new",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ while(len > 0) {
+ /* skip spaces after comma or semicolon */
+ while((len > 0) && isspace(*str)) {
+ ++str; --len;
+ }
+
+ nameLen = xmlSecOpenSSLX509NameStringRead(&str, &len, name, sizeof(name), '=', 0);
+ if(nameLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+ name[nameLen] = '\0';
+ if(len > 0) {
+ ++str; --len;
+ if((*str) == '\"') {
+ ++str; --len;
+ valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
+ value, sizeof(value), '"', 1);
+ if(valueLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+
+ /* skip quote */
+ if((len <= 0) || ((*str) != '\"')) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "quote is expected:%s",
+ xmlSecErrorsSafeString(str));
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+ ++str; --len;
+
+ /* skip spaces before comma or semicolon */
+ while((len > 0) && isspace(*str)) {
+ ++str; --len;
+ }
+ if((len > 0) && ((*str) != ',')) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "comma is expected:%s",
+ xmlSecErrorsSafeString(str));
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+ if(len > 0) {
+ ++str; --len;
+ }
+ type = MBSTRING_ASC;
+ } else if((*str) == '#') {
+ /* TODO: read octect values */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "reading octect values is not implemented yet");
+ X509_NAME_free(nm);
+ return(NULL);
+ } else {
+ valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
+ value, sizeof(value), ',', 1);
+ if(valueLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecOpenSSLX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ X509_NAME_free(nm);
+ return(NULL);
+ }
+ type = MBSTRING_ASC;
+ }
+ } else {
+ valueLen = 0;
+ }
+ value[valueLen] = '\0';
+ if(len > 0) {
+ ++str; --len;
+ }
+ X509_NAME_add_entry_by_txt(nm, (char*)name, type, value, valueLen, -1, 0);
+ }
+
+ return(nm);
+}
+
+static int
+xmlSecOpenSSLX509NameStringRead(xmlSecByte **str, int *strLen,
+ xmlSecByte *res, int resLen,
+ xmlSecByte delim, int ingoreTrailingSpaces) {
+ xmlSecByte *p, *q, *nonSpace;
+
+ xmlSecAssert2(str != NULL, -1);
+ xmlSecAssert2(strLen != NULL, -1);
+ xmlSecAssert2(res != NULL, -1);
+
+ p = (*str);
+ nonSpace = q = res;
+ while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) {
+ if((*p) != '\\') {
+ if(ingoreTrailingSpaces && !isspace(*p)) nonSpace = q;
+ *(q++) = *(p++);
+ } else {
+ ++p;
+ nonSpace = q;
+ if(xmlSecIsHex((*p))) {
+ if((p - (*str) + 1) >= (*strLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "two hex digits expected");
+ return(-1);
+ }
+ *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]);
+ p += 2;
+ } else {
+ if(((++p) - (*str)) >= (*strLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "escaped symbol missed");
+ return(-1);
+ }
+ *(q++) = *(p++);
+ }
+ }
+ }
+ if(((p - (*str)) < (*strLen)) && ((*p) != delim)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "buffer is too small");
+ return(-1);
+ }
+ (*strLen) -= (p - (*str));
+ (*str) = p;
+ return((ingoreTrailingSpaces) ? nonSpace - res + 1 : q - res);
+}
+
+static
+int xmlSecOpenSSLX509_NAME_cmp(const X509_NAME * a, const X509_NAME * b) {
+ int i,ret;
+ const X509_NAME_ENTRY *na,*nb;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(b != NULL, 1);
+
+ if (sk_X509_NAME_ENTRY_num(a->entries) != sk_X509_NAME_ENTRY_num(b->entries)) {
+ return sk_X509_NAME_ENTRY_num(a->entries) - sk_X509_NAME_ENTRY_num(b->entries);
+ }
+
+ for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) {
+ na=sk_X509_NAME_ENTRY_value(a->entries,i);
+ nb=sk_X509_NAME_ENTRY_value(b->entries,i);
+
+ ret = xmlSecOpenSSLX509_NAME_ENTRY_cmp(&na, &nb);
+ if(ret != 0) {
+ return(ret);
+ }
+ }
+
+ return(0);
+}
+
+
+/**
+ * xmlSecOpenSSLX509NamesCompare:
+ *
+ * We have to sort X509_NAME entries to get correct results.
+ * This is ugly but OpenSSL does not support it
+ */
+static int
+xmlSecOpenSSLX509NamesCompare(X509_NAME *a, X509_NAME *b) {
+ X509_NAME *a1 = NULL;
+ X509_NAME *b1 = NULL;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(b != NULL, 1);
+
+ a1 = X509_NAME_dup(a);
+ if(a1 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_NAME_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ b1 = X509_NAME_dup(b);
+ if(b1 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "X509_NAME_dup",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(1);
+ }
+
+ /* sort both */
+ (void)sk_X509_NAME_ENTRY_set_cmp_func(a1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
+ sk_X509_NAME_ENTRY_sort(a1->entries);
+ (void)sk_X509_NAME_ENTRY_set_cmp_func(b1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
+ sk_X509_NAME_ENTRY_sort(b1->entries);
+
+ /* actually compare */
+ ret = xmlSecOpenSSLX509_NAME_cmp(a1, b1);
+
+ /* cleanup */
+ X509_NAME_free(a1);
+ X509_NAME_free(b1);
+ return(ret);
+}
+
+static int
+xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY * const *a, const X509_NAME_ENTRY * const *b) {
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(b != NULL, 1);
+ xmlSecAssert2((*a) != NULL, -1);
+ xmlSecAssert2((*b) != NULL, 1);
+
+ /* first compare values */
+ if(((*a)->value == NULL) && ((*b)->value != NULL)) {
+ return(-1);
+ } else if(((*a)->value != NULL) && ((*b)->value == NULL)) {
+ return(1);
+ } else if(((*a)->value == NULL) && ((*b)->value == NULL)) {
+ return(0);
+ }
+
+ ret = (*a)->value->length - (*b)->value->length;
+ if(ret != 0) {
+ return(ret);
+ }
+
+ ret = memcmp((*a)->value->data, (*b)->value->data, (*a)->value->length);
+ if(ret != 0) {
+ return(ret);
+ }
+
+ /* next compare names */
+ return(OBJ_cmp((*a)->object, (*b)->object));
+}
+
+
+#endif /* XMLSEC_NO_X509 */
+
+
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 00000000..fdb99c51
--- /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..2f54f9de
--- /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 = \
+ $(SKELETON_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(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..15ba3cf7
--- /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..f52d4ac0
--- /dev/null
+++ b/src/skeleton/crypto.c
@@ -0,0 +1,260 @@
+/**
+ * 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
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#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 */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecSkeletonFunctions->transformDes3CbcGetKlass = xmlSecSkeletonTransformDes3CbcGetKlass;
+ gXmlSecSkeletonFunctions->transformKWDes3GetKlass = xmlSecSkeletonTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecSkeletonFunctions->transformDsaSha1GetKlass = xmlSecSkeletonTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* GOST ********************************/
+#ifndef XMLSEC_NO_GOST
+ gXmlSecSkeletonFunctions->transformGost2001GostR3411_94GetKlass = xmlSecSkeletonTransformGost2001GostR3411_94GetKlass;
+#endif /* XMLSEC_GOST */
+
+#ifndef XMLSEC_NO_GOST
+ gXmlSecSkeletonFunctions->transformGostR3411_94GetKlass = xmlSecSkeletonTransformGostR3411_94GetKlass;
+#endif /* XMLSEC_NO_GOST */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecSkeletonFunctions->transformHmacSha1GetKlass = xmlSecSkeletonTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecSkeletonFunctions->transformHmacRipemd160GetKlass = xmlSecSkeletonTransformHmacRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecSkeletonFunctions->transformHmacMd5GetKlass = xmlSecSkeletonTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* RIPEMD160 ********************************/
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecSkeletonFunctions->transformRipemd160GetKlass = xmlSecSkeletonTransformRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+ gXmlSecSkeletonFunctions->transformRsaSha1GetKlass = xmlSecSkeletonTransformRsaSha1GetKlass;
+ gXmlSecSkeletonFunctions->transformRsaPkcs1GetKlass = xmlSecSkeletonTransformRsaPkcs1GetKlass;
+ gXmlSecSkeletonFunctions->transformRsaOaepGetKlass = xmlSecSkeletonTransformRsaOaepGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA1 ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecSkeletonFunctions->transformSha1GetKlass = xmlSecSkeletonTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+ /********************************************************************
+ *
+ * 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..770b6dba
--- /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..3757e1ad
--- /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..99ee316c
--- /dev/null
+++ b/src/strings.c
@@ -0,0 +1,597 @@
+/**
+ * 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..2270db67
--- /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..8a2ded23
--- /dev/null
+++ b/src/transforms.c
@@ -0,0 +1,2902 @@
+/**
+ * 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>
+
+#include <xmlsec/private/xslt.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);
+ }
+
+#ifndef XMLSEC_NO_XSLT
+ xmlSecTransformXsltInitialize();
+#endif /* XMLSEC_NO_XSLT */
+
+ 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) {
+#ifndef XMLSEC_NO_XSLT
+ xmlSecTransformXsltShutdown();
+#endif /* XMLSEC_NO_XSLT */
+
+ 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 returned 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 cleaning up returned 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 destroying */
+ 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..028030ef
--- /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..d10099bb
--- /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 returned 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 cleaning up returned 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..cec9ca6b
--- /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 returned 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 cleaning up returned 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..44c98779
--- /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 returned 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 cleaning up returned 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..2f7e7f69
--- /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..27ad09e2
--- /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..afa7c52c
--- /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..0353a251
--- /dev/null
+++ b/src/xslt.c
@@ -0,0 +1,617 @@
+/**
+ * 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>
+#include <xmlsec/private/xslt.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 (xmlSecXsltCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out);
+static xmlDocPtr xmlSecXsApplyStylesheet (xmlSecXsltCtxPtr ctx,
+ xmlDocPtr doc);
+
+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; */
+};
+
+
+#define XMLSEC_XSLT_COPY_SEC_PREF(src, dst, pref) \
+ xsltSetSecurityPrefs((dst), (pref), xsltGetSecurityPrefs((src), (pref)))
+
+static xsltSecurityPrefsPtr g_xslt_default_security_prefs = NULL;
+
+void xmlSecTransformXsltInitialize(void) {
+ xmlSecAssert(g_xslt_default_security_prefs == NULL);
+
+ g_xslt_default_security_prefs = xsltNewSecurityPrefs();
+ xmlSecAssert(g_xslt_default_security_prefs != NULL);
+ xsltSetSecurityPrefs(g_xslt_default_security_prefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(g_xslt_default_security_prefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(g_xslt_default_security_prefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(g_xslt_default_security_prefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(g_xslt_default_security_prefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+}
+
+void xmlSecTransformXsltShutdown(void) {
+ if(g_xslt_default_security_prefs != NULL) {
+ xsltFreeSecurityPrefs(g_xslt_default_security_prefs);
+ g_xslt_default_security_prefs = NULL;
+ }
+}
+
+/**
+ * xmlSecTransformXsltSetDefaultSecurityPrefs:
+ * @sec: the new security preferences
+ *
+ * Sets the new default security preferences. The xmlsec default security policy is
+ * to disable everything.
+ */
+XMLSEC_EXPORT void
+xmlSecTransformXsltSetDefaultSecurityPrefs(xsltSecurityPrefsPtr sec) {
+ xmlSecAssert(sec != NULL);
+ xmlSecAssert(g_xslt_default_security_prefs != NULL);
+
+ /* copy prefs */
+ XMLSEC_XSLT_COPY_SEC_PREF(sec, g_xslt_default_security_prefs, XSLT_SECPREF_READ_FILE);
+ XMLSEC_XSLT_COPY_SEC_PREF(sec, g_xslt_default_security_prefs, XSLT_SECPREF_WRITE_FILE);
+ XMLSEC_XSLT_COPY_SEC_PREF(sec, g_xslt_default_security_prefs, XSLT_SECPREF_CREATE_DIRECTORY);
+ XMLSEC_XSLT_COPY_SEC_PREF(sec, g_xslt_default_security_prefs, XSLT_SECPREF_READ_NETWORK);
+ XMLSEC_XSLT_COPY_SEC_PREF(sec, g_xslt_default_security_prefs, XSLT_SECPREF_WRITE_NETWORK);
+}
+
+/**
+ * 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));
+
+ /* done */
+ 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 = xmlSecXsApplyStylesheet(ctx, docIn);
+ if(docOut == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecXsApplyStylesheet",
+ XMLSEC_ERRORS_R_XMLSEC_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(ctx, in, out);
+ 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(xmlSecXsltCtxPtr ctx, xmlSecBufferPtr in, xmlSecBufferPtr out) {
+ xmlDocPtr docIn = NULL;
+ xmlDocPtr docOut = NULL;
+ xmlOutputBufferPtr output = NULL;
+ int res = -1;
+ int ret;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(ctx != 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 = xmlSecXsApplyStylesheet(ctx, docIn);
+ if(docOut == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecXsApplyStylesheet",
+ XMLSEC_ERRORS_R_XMLSEC_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, ctx->xslt);
+ 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);
+}
+
+
+static xmlDocPtr
+xmlSecXsApplyStylesheet(xmlSecXsltCtxPtr ctx, xmlDocPtr doc) {
+ xsltTransformContextPtr xsltCtx = NULL;
+ xmlDocPtr res = NULL;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->xslt != NULL, NULL);
+ xmlSecAssert2(doc != NULL, NULL);
+
+ xsltCtx = xsltNewTransformContext(ctx->xslt, doc);
+ if(xsltCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xsltNewTransformContext",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* set security prefs */
+ ret = xsltSetCtxtSecurityPrefs(g_xslt_default_security_prefs, xsltCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xsltSetCtxtSecurityPrefs",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ res = xsltApplyStylesheetUser(ctx->xslt, doc, NULL, NULL, NULL, xsltCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xsltApplyStylesheetUser",
+ XMLSEC_ERRORS_R_XSLT_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+done:
+ if(xsltCtx != NULL) xsltFreeTransformContext(xsltCtx);
+ return res;
+}
+
+
+#endif /* XMLSEC_NO_XSLT */
+