summaryrefslogtreecommitdiff
path: root/src/mscrypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscrypto')
-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
23 files changed, 17009 insertions, 0 deletions
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__*/