summaryrefslogtreecommitdiff
path: root/src/nss
diff options
context:
space:
mode:
Diffstat (limited to 'src/nss')
-rw-r--r--src/nss/Makefile.am57
-rw-r--r--src/nss/Makefile.in798
-rw-r--r--src/nss/README128
-rw-r--r--src/nss/app.c1598
-rw-r--r--src/nss/bignum.c163
-rw-r--r--src/nss/ciphers.c838
-rw-r--r--src/nss/crypto.c444
-rw-r--r--src/nss/digests.c576
-rw-r--r--src/nss/globals.h24
-rw-r--r--src/nss/hmac.c855
-rw-r--r--src/nss/keysstore.c485
-rw-r--r--src/nss/keytrans.c753
-rw-r--r--src/nss/kw_aes.c681
-rw-r--r--src/nss/kw_des.c663
-rw-r--r--src/nss/pkikeys.c1554
-rw-r--r--src/nss/signatures.c841
-rw-r--r--src/nss/symkeys.c440
-rw-r--r--src/nss/x509.c2223
-rw-r--r--src/nss/x509vfy.c808
19 files changed, 13929 insertions, 0 deletions
diff --git a/src/nss/Makefile.am b/src/nss/Makefile.am
new file mode 100644
index 00000000..8cd85863
--- /dev/null
+++ b/src/nss/Makefile.am
@@ -0,0 +1,57 @@
+NULL =
+
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-nss.la \
+ $(NULL)
+
+libxmlsec1_nss_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(NSS_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_nss_la_SOURCES =\
+ app.c \
+ bignum.c \
+ ciphers.c \
+ crypto.c \
+ digests.c \
+ hmac.c \
+ pkikeys.c \
+ signatures.c \
+ symkeys.c \
+ x509.c \
+ x509vfy.c \
+ keysstore.c \
+ keytrans.c \
+ kw_des.c \
+ kw_aes.c \
+ globals.h \
+ $(NULL)
+
+if SHAREDLIB_HACK
+libxmlsec1_nss_la_SOURCES += ../strings.c
+endif
+
+libxmlsec1_nss_la_LIBADD = \
+ $(NSS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_nss_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_nss_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
diff --git a/src/nss/Makefile.in b/src/nss/Makefile.in
new file mode 100644
index 00000000..46c8c927
--- /dev/null
+++ b/src/nss/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c
+subdir = src/nss
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__libxmlsec1_nss_la_SOURCES_DIST = app.c bignum.c ciphers.c crypto.c \
+ digests.c hmac.c pkikeys.c signatures.c symkeys.c x509.c \
+ x509vfy.c keysstore.c keytrans.c kw_des.c kw_aes.c globals.h \
+ ../strings.c
+am__objects_1 =
+@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_nss_la-strings.lo
+am_libxmlsec1_nss_la_OBJECTS = libxmlsec1_nss_la-app.lo \
+ libxmlsec1_nss_la-bignum.lo libxmlsec1_nss_la-ciphers.lo \
+ libxmlsec1_nss_la-crypto.lo libxmlsec1_nss_la-digests.lo \
+ libxmlsec1_nss_la-hmac.lo libxmlsec1_nss_la-pkikeys.lo \
+ libxmlsec1_nss_la-signatures.lo libxmlsec1_nss_la-symkeys.lo \
+ libxmlsec1_nss_la-x509.lo libxmlsec1_nss_la-x509vfy.lo \
+ libxmlsec1_nss_la-keysstore.lo libxmlsec1_nss_la-keytrans.lo \
+ libxmlsec1_nss_la-kw_des.lo libxmlsec1_nss_la-kw_aes.lo \
+ $(am__objects_1) $(am__objects_2)
+libxmlsec1_nss_la_OBJECTS = $(am_libxmlsec1_nss_la_OBJECTS)
+libxmlsec1_nss_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libxmlsec1_nss_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libxmlsec1_nss_la_SOURCES)
+DIST_SOURCES = $(am__libxmlsec1_nss_la_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CP = @CP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GCRYPT_CFLAGS = @GCRYPT_CFLAGS@
+GCRYPT_CRYPTO_LIB = @GCRYPT_CRYPTO_LIB@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GCRYPT_MIN_VERSION = @GCRYPT_MIN_VERSION@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_CRYPTO_LIB = @GNUTLS_CRYPTO_LIB@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GNUTLS_MIN_VERSION = @GNUTLS_MIN_VERSION@
+GREP = @GREP@
+HELP2MAN = @HELP2MAN@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_CONFIG = @LIBXML_CONFIG@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_MIN_VERSION = @LIBXML_MIN_VERSION@
+LIBXSLT_CFLAGS = @LIBXSLT_CFLAGS@
+LIBXSLT_CONFIG = @LIBXSLT_CONFIG@
+LIBXSLT_LIBS = @LIBXSLT_LIBS@
+LIBXSLT_MIN_VERSION = @LIBXSLT_MIN_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MOZILLA_MIN_VERSION = @MOZILLA_MIN_VERSION@
+MSCRYPTO_CFLAGS = @MSCRYPTO_CFLAGS@
+MSCRYPTO_CRYPTO_LIB = @MSCRYPTO_CRYPTO_LIB@
+MSCRYPTO_LIBS = @MSCRYPTO_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSPR_MIN_VERSION = @NSPR_MIN_VERSION@
+NSPR_PACKAGE = @NSPR_PACKAGE@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_CRYPTO_LIB = @NSS_CRYPTO_LIB@
+NSS_LIBS = @NSS_LIBS@
+NSS_MIN_VERSION = @NSS_MIN_VERSION@
+NSS_PACKAGE = @NSS_PACKAGE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_CRYPTO_LIB = @OPENSSL_CRYPTO_LIB@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OPENSSL_MIN_VERSION = @OPENSSL_MIN_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PRESENT = @PKGCONFIG_PRESENT@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TAR = @TAR@
+U = @U@
+VERSION = @VERSION@
+XMLSEC_APP_DEFINES = @XMLSEC_APP_DEFINES@
+XMLSEC_CFLAGS = @XMLSEC_CFLAGS@
+XMLSEC_CORE_CFLAGS = @XMLSEC_CORE_CFLAGS@
+XMLSEC_CORE_LIBS = @XMLSEC_CORE_LIBS@
+XMLSEC_CRYPTO = @XMLSEC_CRYPTO@
+XMLSEC_CRYPTO_CFLAGS = @XMLSEC_CRYPTO_CFLAGS@
+XMLSEC_CRYPTO_DISABLED_LIST = @XMLSEC_CRYPTO_DISABLED_LIST@
+XMLSEC_CRYPTO_EXTRA_LDFLAGS = @XMLSEC_CRYPTO_EXTRA_LDFLAGS@
+XMLSEC_CRYPTO_LIB = @XMLSEC_CRYPTO_LIB@
+XMLSEC_CRYPTO_LIBS = @XMLSEC_CRYPTO_LIBS@
+XMLSEC_CRYPTO_LIST = @XMLSEC_CRYPTO_LIST@
+XMLSEC_CRYPTO_PC_FILES_LIST = @XMLSEC_CRYPTO_PC_FILES_LIST@
+XMLSEC_DEFINES = @XMLSEC_DEFINES@
+XMLSEC_DL_INCLUDES = @XMLSEC_DL_INCLUDES@
+XMLSEC_DL_LIBS = @XMLSEC_DL_LIBS@
+XMLSEC_DOCDIR = @XMLSEC_DOCDIR@
+XMLSEC_EXTRA_LDFLAGS = @XMLSEC_EXTRA_LDFLAGS@
+XMLSEC_GCRYPT_CFLAGS = @XMLSEC_GCRYPT_CFLAGS@
+XMLSEC_GCRYPT_LIBS = @XMLSEC_GCRYPT_LIBS@
+XMLSEC_GNUTLS_CFLAGS = @XMLSEC_GNUTLS_CFLAGS@
+XMLSEC_GNUTLS_LIBS = @XMLSEC_GNUTLS_LIBS@
+XMLSEC_LIBDIR = @XMLSEC_LIBDIR@
+XMLSEC_LIBS = @XMLSEC_LIBS@
+XMLSEC_NO_AES = @XMLSEC_NO_AES@
+XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_APPS_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_CRYPTO_DYNAMIC_LOADING = @XMLSEC_NO_CRYPTO_DYNAMIC_LOADING@
+XMLSEC_NO_DES = @XMLSEC_NO_DES@
+XMLSEC_NO_DSA = @XMLSEC_NO_DSA@
+XMLSEC_NO_GCRYPT = @XMLSEC_NO_GCRYPT@
+XMLSEC_NO_GNUTLS = @XMLSEC_NO_GNUTLS@
+XMLSEC_NO_GOST = @XMLSEC_NO_GOST@
+XMLSEC_NO_HMAC = @XMLSEC_NO_HMAC@
+XMLSEC_NO_LIBXSLT = @XMLSEC_NO_LIBXSLT@
+XMLSEC_NO_MD5 = @XMLSEC_NO_MD5@
+XMLSEC_NO_MSCRYPTO = @XMLSEC_NO_MSCRYPTO@
+XMLSEC_NO_NSS = @XMLSEC_NO_NSS@
+XMLSEC_NO_OPENSSL = @XMLSEC_NO_OPENSSL@
+XMLSEC_NO_RIPEMD160 = @XMLSEC_NO_RIPEMD160@
+XMLSEC_NO_RSA = @XMLSEC_NO_RSA@
+XMLSEC_NO_SHA1 = @XMLSEC_NO_SHA1@
+XMLSEC_NO_SHA224 = @XMLSEC_NO_SHA224@
+XMLSEC_NO_SHA256 = @XMLSEC_NO_SHA256@
+XMLSEC_NO_SHA384 = @XMLSEC_NO_SHA384@
+XMLSEC_NO_SHA512 = @XMLSEC_NO_SHA512@
+XMLSEC_NO_X509 = @XMLSEC_NO_X509@
+XMLSEC_NO_XKMS = @XMLSEC_NO_XKMS@
+XMLSEC_NO_XMLDSIG = @XMLSEC_NO_XMLDSIG@
+XMLSEC_NO_XMLENC = @XMLSEC_NO_XMLENC@
+XMLSEC_NSS_CFLAGS = @XMLSEC_NSS_CFLAGS@
+XMLSEC_NSS_LIBS = @XMLSEC_NSS_LIBS@
+XMLSEC_OPENSSL_CFLAGS = @XMLSEC_OPENSSL_CFLAGS@
+XMLSEC_OPENSSL_LIBS = @XMLSEC_OPENSSL_LIBS@
+XMLSEC_PACKAGE = @XMLSEC_PACKAGE@
+XMLSEC_STATIC_BINARIES = @XMLSEC_STATIC_BINARIES@
+XMLSEC_VERSION = @XMLSEC_VERSION@
+XMLSEC_VERSION_INFO = @XMLSEC_VERSION_INFO@
+XMLSEC_VERSION_MAJOR = @XMLSEC_VERSION_MAJOR@
+XMLSEC_VERSION_MINOR = @XMLSEC_VERSION_MINOR@
+XMLSEC_VERSION_SAFE = @XMLSEC_VERSION_SAFE@
+XMLSEC_VERSION_SUBMINOR = @XMLSEC_VERSION_SUBMINOR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+EXTRA_DIST = \
+ README \
+ $(NULL)
+
+lib_LTLIBRARIES = \
+ libxmlsec1-nss.la \
+ $(NULL)
+
+libxmlsec1_nss_la_CPPFLAGS = \
+ -DPACKAGE=\"@PACKAGE@\" \
+ -I../../include \
+ -I$(top_srcdir)/include \
+ $(XMLSEC_DEFINES) \
+ $(NSS_CFLAGS) \
+ $(LIBXSLT_CFLAGS) \
+ $(LIBXML_CFLAGS) \
+ $(NULL)
+
+libxmlsec1_nss_la_SOURCES = app.c bignum.c ciphers.c crypto.c \
+ digests.c hmac.c pkikeys.c signatures.c symkeys.c x509.c \
+ x509vfy.c keysstore.c keytrans.c kw_des.c kw_aes.c globals.h \
+ $(NULL) $(am__append_1)
+libxmlsec1_nss_la_LIBADD = \
+ $(NSS_LIBS) \
+ $(LIBXSLT_LIBS) \
+ $(LIBXML_LIBS) \
+ ../libxmlsec1.la \
+ $(NULL)
+
+libxmlsec1_nss_la_DEPENDENCIES = \
+ $(NULL)
+
+libxmlsec1_nss_la_LDFLAGS = \
+ @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \
+ -version-info @XMLSEC_VERSION_INFO@ \
+ $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/nss/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/nss/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libxmlsec1-nss.la: $(libxmlsec1_nss_la_OBJECTS) $(libxmlsec1_nss_la_DEPENDENCIES)
+ $(libxmlsec1_nss_la_LINK) -rpath $(libdir) $(libxmlsec1_nss_la_OBJECTS) $(libxmlsec1_nss_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-app.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-bignum.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-ciphers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-digests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-keysstore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-keytrans.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-kw_aes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-kw_des.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-pkikeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-signatures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-strings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-symkeys.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_nss_la-x509vfy.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libxmlsec1_nss_la-app.lo: app.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-app.Tpo -c -o libxmlsec1_nss_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-app.Tpo $(DEPDIR)/libxmlsec1_nss_la-app.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='app.c' object='libxmlsec1_nss_la-app.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c
+
+libxmlsec1_nss_la-bignum.lo: bignum.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-bignum.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-bignum.Tpo -c -o libxmlsec1_nss_la-bignum.lo `test -f 'bignum.c' || echo '$(srcdir)/'`bignum.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-bignum.Tpo $(DEPDIR)/libxmlsec1_nss_la-bignum.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bignum.c' object='libxmlsec1_nss_la-bignum.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-bignum.lo `test -f 'bignum.c' || echo '$(srcdir)/'`bignum.c
+
+libxmlsec1_nss_la-ciphers.lo: ciphers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-ciphers.Tpo -c -o libxmlsec1_nss_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_nss_la-ciphers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ciphers.c' object='libxmlsec1_nss_la-ciphers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c
+
+libxmlsec1_nss_la-crypto.lo: crypto.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-crypto.Tpo -c -o libxmlsec1_nss_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-crypto.Tpo $(DEPDIR)/libxmlsec1_nss_la-crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libxmlsec1_nss_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
+
+libxmlsec1_nss_la-digests.lo: digests.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-digests.Tpo -c -o libxmlsec1_nss_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-digests.Tpo $(DEPDIR)/libxmlsec1_nss_la-digests.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='digests.c' object='libxmlsec1_nss_la-digests.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c
+
+libxmlsec1_nss_la-hmac.lo: hmac.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-hmac.Tpo -c -o libxmlsec1_nss_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-hmac.Tpo $(DEPDIR)/libxmlsec1_nss_la-hmac.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hmac.c' object='libxmlsec1_nss_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
+
+libxmlsec1_nss_la-pkikeys.lo: pkikeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-pkikeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-pkikeys.Tpo -c -o libxmlsec1_nss_la-pkikeys.lo `test -f 'pkikeys.c' || echo '$(srcdir)/'`pkikeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-pkikeys.Tpo $(DEPDIR)/libxmlsec1_nss_la-pkikeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pkikeys.c' object='libxmlsec1_nss_la-pkikeys.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-pkikeys.lo `test -f 'pkikeys.c' || echo '$(srcdir)/'`pkikeys.c
+
+libxmlsec1_nss_la-signatures.lo: signatures.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-signatures.Tpo -c -o libxmlsec1_nss_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-signatures.Tpo $(DEPDIR)/libxmlsec1_nss_la-signatures.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='signatures.c' object='libxmlsec1_nss_la-signatures.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c
+
+libxmlsec1_nss_la-symkeys.lo: symkeys.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-symkeys.Tpo -c -o libxmlsec1_nss_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_nss_la-symkeys.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='symkeys.c' object='libxmlsec1_nss_la-symkeys.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c
+
+libxmlsec1_nss_la-x509.lo: x509.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-x509.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-x509.Tpo -c -o libxmlsec1_nss_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-x509.Tpo $(DEPDIR)/libxmlsec1_nss_la-x509.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509.c' object='libxmlsec1_nss_la-x509.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-x509.lo `test -f 'x509.c' || echo '$(srcdir)/'`x509.c
+
+libxmlsec1_nss_la-x509vfy.lo: x509vfy.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-x509vfy.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-x509vfy.Tpo -c -o libxmlsec1_nss_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-x509vfy.Tpo $(DEPDIR)/libxmlsec1_nss_la-x509vfy.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='x509vfy.c' object='libxmlsec1_nss_la-x509vfy.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-x509vfy.lo `test -f 'x509vfy.c' || echo '$(srcdir)/'`x509vfy.c
+
+libxmlsec1_nss_la-keysstore.lo: keysstore.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-keysstore.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-keysstore.Tpo -c -o libxmlsec1_nss_la-keysstore.lo `test -f 'keysstore.c' || echo '$(srcdir)/'`keysstore.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-keysstore.Tpo $(DEPDIR)/libxmlsec1_nss_la-keysstore.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='keysstore.c' object='libxmlsec1_nss_la-keysstore.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-keysstore.lo `test -f 'keysstore.c' || echo '$(srcdir)/'`keysstore.c
+
+libxmlsec1_nss_la-keytrans.lo: keytrans.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-keytrans.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-keytrans.Tpo -c -o libxmlsec1_nss_la-keytrans.lo `test -f 'keytrans.c' || echo '$(srcdir)/'`keytrans.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-keytrans.Tpo $(DEPDIR)/libxmlsec1_nss_la-keytrans.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='keytrans.c' object='libxmlsec1_nss_la-keytrans.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-keytrans.lo `test -f 'keytrans.c' || echo '$(srcdir)/'`keytrans.c
+
+libxmlsec1_nss_la-kw_des.lo: kw_des.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-kw_des.Tpo -c -o libxmlsec1_nss_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_nss_la-kw_des.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_des.c' object='libxmlsec1_nss_la-kw_des.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c
+
+libxmlsec1_nss_la-kw_aes.lo: kw_aes.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-kw_aes.Tpo -c -o libxmlsec1_nss_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_nss_la-kw_aes.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kw_aes.c' object='libxmlsec1_nss_la-kw_aes.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c
+
+libxmlsec1_nss_la-strings.lo: ../strings.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_nss_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_nss_la-strings.Tpo -c -o libxmlsec1_nss_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxmlsec1_nss_la-strings.Tpo $(DEPDIR)/libxmlsec1_nss_la-strings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../strings.c' object='libxmlsec1_nss_la-strings.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_nss_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_nss_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/nss/README b/src/nss/README
new file mode 100644
index 00000000..65a0f45e
--- /dev/null
+++ b/src/nss/README
@@ -0,0 +1,128 @@
+WHAT VERSION OF NSS?
+------------------------------------------------------------------------
+NSS 3.9 or greater and NSPR 4.4.1 or greater are required.
+
+KEYS MANAGER
+------------------------------------------------------------------------
+
+xmlsec-nss key manager uses a custom Keys Store, and a custom X509 Store.
+The custom Keys Store and the X509 Store use the NSS database as the underlying
+store for public/private keys, Certs and CRLs.
+
+The NSS Keys store uses the Simple Keys Store on top of the NSS repository.
+The reason for this is that XMLSEC's generic adoptkey/getKey functions use a
+XMLSEC key object that contains more attributes than the raw NSS key object,
+and the getkey function may use a combination of one or more of these attributes
+(name, type, usage, Id) to find a key. There is no straightforward 1-1 mapping
+between XMLSEC's adoptkey/getkey and NSS's APIs.
+
+For example, the store may be asked to adopt a symmetric key, and later asked
+to find it just by name. Or the store may be asked to adopt a private key
+just by its type, and later asked to find it just by type. The key returned
+by getKey is expected to contain all the attributes that were present at the
+time of adoptkey - NSS store does not provide a way to store app-specific
+attributes.
+
+When a key is adopted by the NSS Keys Store, it is simply saved in the
+Simple Keys Store. It is not saved into the NSS database. The only
+way to load keys into the NSS database is with a load operation through
+the XMLSEC API or via an administrator operation.
+
+When a getKey is done on the NSS Keys Store, it first checks the Simple
+Keys Store. If the key is found there, it is returned. If not, the key
+is searched in the NSS database. If found, the key is stored in the
+Simple Keys Store before it is returned.
+
+
+Thus, the various sources for keys/certs/crls for an XMLSEC-NSS application
+are:
+- elements in XML documents
+- PKCS12 and DER files
+- NSS Database
+
+
+KNOWN ISSUES
+------------------------------------------------------------------------
+1) NSS needs to provide a way to convert a DER integer string to an ASCII
+decimal string. Once NSS is fixed, the function xmlSecNssASN1IntegerWrite
+in src/nss/x509.c needs to be implemented.
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=212864
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118633
+
+2) RSA Encryption/Decryption using PKCS#1 v1.5 padding not currently exposed
+in NSS. This causes some tests to fail.
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=214236
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118628
+
+3) RSA-OAEP is not yet implemented in NSS. This is the only REQUIRED algorithm
+that is missing from xmlsec-nss.
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=158747
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118629
+
+4) CERT_FindCertByNameString does not work in all cases
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=210709
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118631
+
+5) CERT_FindCertBySubjectKeyID does not work in all cases
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=211051
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118632
+
+6) Finding a cert by Issuer & Serial Number needs the ability to
+convert an ASCII decimal string to a DER integer string. Filed
+an RFE against NSS. Once fixed, xmlSecNumToItem in x509vfy.c
+needs to be changed to use the new function(s) provided
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=212864
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118633
+
+7) RIPEMD160 Digest and RIPEMD160 HMAC is not supported by NSS
+
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118634
+
+8) AES Key wrap algorithm is implemented in NSS but not exposed due to
+some bug src/nss/kw_aes.c uses a workaround which should be removed
+when the bug is fixed
+
+ NSS bug: http://bugzilla.mozilla.org/show_bug.cgi?id=213795
+ xmlsec bug: http://bugzilla.gnome.org/show_bug.cgi?id=118635
+
+9) Not all file formats are supported
+
+- xmlSecNssAppKeyLoad(): This function loads a PKI key from a file.
+ The following formats are supported:
+ . xmlSecKeyDataFormatDer: This expects the private key to be in
+ PrivateKeyInfo format. Note that the DER files containing
+ private keys in the xmlsec test suite aren't in that format
+ . xmlsecKeyDataFormatPkcs12
+
+ The following formats are not supported:
+ . xmlSecKeyDataFormatPkcs8Pem
+ . xmlSecKeyDataFormatPkcs8Der
+
+
+- xmlSecNssAppCertLoad(): This function loads a cert from a file.
+ The following formats are supported:
+ xmlSecKeyDataFormatDer
+
+ The following formats are not supported:
+ xmlSecKeyDataFormatPem
+
+10) "Trusted" vs "Untrusted" certificates:
+The distinction between "trusted" and "untrusted" certificates in
+xmlsec-openssl is maintained because the OPENSSL application (and
+not the OPENSSL library) has to maintain a cert store and verify
+certificates. With NSS, no such distinction is necessary in the
+application.
+
+Aleksey: Not sure that I understand this point but thats what Tej wrote.
+
+11) NSS doesn't support emailAddress in the cert subject. There is a hack
+that needs to be removed in xmlSecNssX509FindCert function (x509vfy.c):
+
+https://bugzilla.mozilla.org/show_bug.cgi?id=561689
+
+12) CRLs from xml document support is not working at all.
diff --git a/src/nss/app.c b/src/nss/app.c
new file mode 100644
index 00000000..dabe36d1
--- /dev/null
+++ b/src/nss/app.c
@@ -0,0 +1,1598 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <pk11func.h>
+#include <cert.h>
+#include <keyhi.h>
+#include <pkcs12.h>
+#include <p12plcy.h>
+/*
+#include <ssl.h>
+*/
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+#include <xmlsec/nss/pkikeys.h>
+#include <xmlsec/nss/keysstore.h>
+
+/* workaround - NSS exports this but doesn't declare it */
+extern CERTCertificate * __CERT_NewTempCertificate (CERTCertDBHandle *handle,
+ SECItem *derCert,
+ char *nickname,
+ PRBool isperm,
+ PRBool copyDER);
+static int xmlSecNssAppCreateSECItem (SECItem *contents,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+static int xmlSecNssAppReadSECItem (SECItem *contents,
+ const char *fn);
+static PRBool xmlSecNssAppAscii2UCS2Conv (PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen,
+ PRBool swapBytes);
+static SECItem *xmlSecNssAppNicknameCollisionCallback (SECItem *old_nick,
+ PRBool *cancel,
+ void *wincx);
+static xmlSecKeyPtr xmlSecNssAppDerKeyLoadSECItem (SECItem* secItem);
+
+/**
+ * xmlSecNssAppInit:
+ * @config: the path to NSS database files.
+ *
+ * General crypto engine initialization. This function is used
+ * by XMLSec command line utility and called before
+ * @xmlSecInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppInit(const char* config) {
+ SECStatus rv;
+
+ if(config) {
+ rv = NSS_InitReadWrite(config);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "NSS_InitReadWrite",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "config=%s",
+ xmlSecErrorsSafeString(config));
+ return(-1);
+ }
+ } else {
+ rv = NSS_NoDB_Init(NULL);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "NSS_NoDB_Init",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* configure PKCS11 */
+ PK11_ConfigurePKCS11("manufacturesID", "libraryDescription",
+ "tokenDescription", "privateTokenDescription",
+ "slotDescription", "privateSlotDescription",
+ "fipsSlotDescription", "fipsPrivateSlotDescription",
+ 0, 0);
+
+ /* setup for PKCS12 */
+ PORT_SetUCS2_ASCIIConversionFunction(xmlSecNssAppAscii2UCS2Conv);
+ SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+ SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppShutdown:
+ *
+ * General crypto engine shutdown. This function is used
+ * by XMLSec command line utility and called after
+ * @xmlSecShutdown function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppShutdown(void) {
+ SECStatus rv;
+/*
+ SSL_ClearSessionCache();
+*/
+ PK11_LogoutAll();
+ rv = NSS_Shutdown();
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "NSS_Shutdown",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecNssAppCreateSECItem(SECItem *contents, const xmlSecByte* data, xmlSecSize dataSize) {
+ xmlSecAssert2(contents != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+
+ contents->data = 0;
+ if (!SECITEM_AllocItem(NULL, contents, dataSize)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECITEM_AllocItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(dataSize > 0) {
+ xmlSecAssert2(contents->data != NULL, -1);
+ memcpy(contents->data, data, dataSize);
+ }
+
+ return (0);
+}
+
+static int
+xmlSecNssAppReadSECItem(SECItem *contents, const char *fn) {
+ PRFileInfo info;
+ PRFileDesc *file = NULL;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ int ret = -1;
+
+ xmlSecAssert2(contents != NULL, -1);
+ xmlSecAssert2(fn != NULL, -1);
+
+ file = PR_Open(fn, PR_RDONLY, 00660);
+ if (file == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PR_Open",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(fn));
+ goto done;
+ }
+
+ prStatus = PR_GetOpenFileInfo(file, &info);
+ if (prStatus != PR_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PR_GetOpenFileInfo",
+ XMLSEC_ERRORS_R_IO_FAILED,
+ "filename=%s",
+ xmlSecErrorsSafeString(fn));
+ goto done;
+ }
+
+ contents->data = 0;
+ if (!SECITEM_AllocItem(NULL, contents, info.size)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECITEM_AllocItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ numBytes = PR_Read(file, contents->data, info.size);
+ if (numBytes != info.size) {
+ SECITEM_FreeItem(contents, PR_FALSE);
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (file) {
+ PR_Close(file);
+ }
+
+ return (ret);
+}
+
+static PRBool
+xmlSecNssAppAscii2UCS2Conv(PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen,
+ PRBool swapBytes ATTRIBUTE_UNUSED)
+{
+ SECItem it;
+
+ if (toUnicode == PR_FALSE) {
+ return (PR_FALSE);
+ }
+
+ memset(&it, 0, sizeof(it));
+ it.data = inBuf;
+ it.len = inBufLen;
+
+ return(PORT_UCS2_UTF8Conversion(toUnicode, it.data, it.len,
+ outBuf, maxOutBufLen, outBufLen));
+}
+
+static SECItem *
+xmlSecNssAppNicknameCollisionCallback(SECItem *old_nick ATTRIBUTE_UNUSED,
+ PRBool *cancel,
+ void *wincx ATTRIBUTE_UNUSED)
+{
+ if (cancel == NULL) {
+ return (NULL);
+ }
+
+ /* XXX not handled yet */
+ *cancel = PR_TRUE;
+ return (NULL);
+}
+
+/**
+ * xmlSecNssAppKeyLoad:
+ * @filename: the key filename.
+ * @format: the key file format.
+ * @pwd: the key file password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from a file
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+/**
+ * xmlSecNssAppKeyLoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the key data format.
+ * @pwd: the key data2 password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from a binary @data.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ const char *pwd, void* pwdCallback, void* pwdCallbackCtx) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+/**
+ * xmlSecNssAppKeyLoadSECItem:
+ * @secItem: the pointer to sec item.
+ * @format: the key format.
+ * @pwd: the key password.
+ * @pwdCallback: the key password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key from a file
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format,
+ const char *pwd,
+ void* pwdCallback,
+ void* pwdCallbackCtx) {
+ xmlSecKeyPtr key = NULL;
+
+ xmlSecAssert2(secItem != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ switch(format) {
+#ifndef XMLSEC_NO_X509
+ case xmlSecKeyDataFormatPkcs12:
+ key = xmlSecNssAppPkcs12LoadSECItem(secItem, pwd, pwdCallback, pwdCallbackCtx);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12LoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ case xmlSecKeyDataFormatCertDer:
+ key = xmlSecNssAppKeyFromCertLoadSECItem(secItem, format);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyFromCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_X509 */
+ case xmlSecKeyDataFormatDer:
+ key = xmlSecNssAppDerKeyLoadSECItem(secItem);
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppDerKeyLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyLoad",
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+static xmlSecKeyPtr
+xmlSecNssAppDerKeyLoadSECItem(SECItem* secItem) {
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyPtr retval = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ int ret;
+ SECKEYPublicKey *pubkey = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ CERTSubjectPublicKeyInfo *spki = NULL;
+ SECItem nickname;
+ PK11SlotInfo *slot = NULL;
+ SECStatus status;
+
+ xmlSecAssert2(secItem != NULL, NULL);
+
+ /* we're importing a key about which we know nothing yet, just use the
+ * internal slot
+ */
+ slot = xmlSecNssGetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetInternalKeySlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ nickname.len = 0;
+ nickname.data = NULL;
+
+
+ /* TRY PRIVATE KEY FIRST
+ * Note: This expects the key to be in PrivateKeyInfo format. The
+ * DER files created from PEM via openssl utilities aren't in that
+ * format
+ */
+ status = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secItem,
+ &nickname, NULL, PR_FALSE,
+ PR_TRUE, KU_ALL, &privkey, NULL);
+ if (status != SECSuccess) {
+ /* TRY PUBLIC KEY */
+ spki = SECKEY_DecodeDERSubjectPublicKeyInfo(secItem);
+ if (spki == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_DecodeDERSubjectPublicKeyInfo",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ }
+
+ pubkey = SECKEY_ExtractPublicKey(spki);
+ if (pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ data = xmlSecNssPKIAdoptKey(privkey, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ privkey = NULL;
+ pubkey = NULL;
+
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ goto done;
+ }
+ retval = key;
+ key = NULL;
+ data = NULL;
+
+
+done:
+ if(slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if(privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if(pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if(key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if(spki != NULL) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+ return (retval);
+}
+
+#ifndef XMLSEC_NO_X509
+/**
+ * xmlSecNssAppKeyCertLoad:
+ * @key: the pointer to key.
+ * @filename: the certificate filename.
+ * @format: the certificate file format.
+ *
+ * Reads the certificate from $@filename and adds it to key
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeyCertLoadMemory:
+ * @key: the pointer to key.
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the certificate format.
+ *
+ * Reads the certificate from @data and adds it to key
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeyCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeyCertLoadSECItem:
+ * @key: the pointer to key.
+ * @secItem: the pointer to SECItem.
+ * @format: the certificate format.
+ *
+ * Reads the certificate from @secItem and adds it to key
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyDataFormat format) {
+ CERTCertificate *cert=NULL;
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(secItem != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
+ return(-1);
+ }
+
+ switch(format) {
+ case xmlSecKeyDataFormatPkcs8Der:
+ case xmlSecKeyDataFormatDer:
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ secItem, NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "format=%d", format);
+ return(-1);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(-1);
+ }
+
+ xmlSecAssert2(cert != NULL, -1);
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppPkcs12Load:
+ * @filename: the PKCS12 key filename.
+ * @pwd: the PKCS12 file password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 file.
+ * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppPkcs12Load(const char *filename, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(filename != NULL, NULL);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12LoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+/**
+ * xmlSecNssAppPkcs12LoadMemory:
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @pwd: the PKCS12 password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 binary data.
+ * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ SECItem secItem;
+ xmlSecKeyPtr res;
+ int ret;
+
+ xmlSecAssert2(data != NULL, NULL);
+
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12LoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(NULL);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(res);
+}
+
+
+/**
+ * xmlSecNssAppPkcs12LoadSECItem:
+ * @secItem: the @SECItem object.
+ * @pwd: the PKCS12 file password.
+ * @pwdCallback: the password callback.
+ * @pwdCallbackCtx: the user context for password callback.
+ *
+ * Reads key and all associated certificates from the PKCS12 SECItem.
+ * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass
+ * in format=xmlSecKeyDataFormatPkcs12.
+ *
+ * Returns: pointer to the key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppPkcs12LoadSECItem(SECItem* secItem, const char *pwd,
+ void *pwdCallback ATTRIBUTE_UNUSED,
+ void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ int ret;
+ PK11SlotInfo *slot = NULL;
+ SECItem pwditem;
+ SECItem uc2_pwditem;
+ SECStatus rv;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ CERTCertList *certlist = NULL;
+ CERTCertListNode *head = NULL;
+ CERTCertificate *cert = NULL;
+ CERTCertificate *tmpcert = NULL;
+ SEC_PKCS12DecoderContext *p12ctx = NULL;
+
+
+ xmlSecAssert2((secItem != NULL), NULL);
+
+ if (pwd == NULL) {
+ pwd = "";
+ }
+ memset(&uc2_pwditem, 0, sizeof(uc2_pwditem));
+
+ /* we're importing a key about which we know nothing yet, just use the
+ * internal slot. We have no criteria to choose a slot.
+ */
+ slot = xmlSecNssGetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetInternalKeySlot",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ pwditem.data = (unsigned char *)pwd;
+ pwditem.len = strlen(pwd)+1;
+ if (!SECITEM_AllocItem(NULL, &uc2_pwditem, 2*pwditem.len)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECITEM_AllocItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ if (PORT_UCS2_ASCIIConversion(PR_TRUE, pwditem.data, pwditem.len,
+ uc2_pwditem.data, 2*pwditem.len,
+ &(uc2_pwditem.len), 0) == PR_FALSE) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_UCS2_ASCIIConversion",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ p12ctx = SEC_PKCS12DecoderStart(&uc2_pwditem, slot, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (p12ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderStart",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderUpdate(p12ctx, secItem->data, secItem->len);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderUpdate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderVerify(p12ctx);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderVerify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderValidateBags(p12ctx, xmlSecNssAppNicknameCollisionCallback);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderValidateBags",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = SEC_PKCS12DecoderImportBags(p12ctx);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderImportBags",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ certlist = SEC_PKCS12DecoderGetCerts(p12ctx);
+ if (certlist == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_PKCS12DecoderGetCerts",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
+ goto done;
+ }
+
+ for (head = CERT_LIST_HEAD(certlist);
+ !CERT_LIST_END(head, certlist);
+ head = CERT_LIST_NEXT(head)) {
+ cert = head->cert;
+ privkey = PK11_FindKeyByAnyCert(cert, NULL);
+
+ if (privkey != NULL) {
+ if (data != NULL) {
+ /* we already found a private key.
+ * assume the first private key we find is THE ONE
+ */
+ SECKEY_DestroyPrivateKey(privkey);
+ privkey = NULL;
+ } else {
+ pubkey = CERT_ExtractPublicKey(cert);
+ if (pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ data = xmlSecNssPKIAdoptKey(privkey, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ pubkey = NULL;
+ privkey = NULL;
+
+ tmpcert = CERT_DupCertificate(cert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ CERT_DestroyCertificate(tmpcert);
+ goto done;
+ }
+
+ }
+ }
+
+ tmpcert = CERT_DupCertificate(cert);
+ if(tmpcert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ ret = xmlSecNssKeyDataX509AdoptCert(x509Data, tmpcert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ CERT_DestroyCertificate(tmpcert);
+ goto done;
+ }
+
+ } /* end for loop */
+
+ if (data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppPkcs12Load",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "private key not found in PKCS12 file");
+ goto done;
+ }
+
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ xmlSecKeyDestroy(key);
+ key = NULL;
+ goto done;
+ }
+ data = NULL;
+
+ ret = xmlSecKeyAdoptData(key, x509Data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyAdoptData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ xmlSecKeyDestroy(key);
+ key = NULL;
+ goto done;
+ }
+ x509Data = NULL;
+
+done:
+ if (p12ctx) {
+ SEC_PKCS12DecoderFinish(p12ctx);
+ }
+ SECITEM_FreeItem(&uc2_pwditem, PR_FALSE);
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (certlist) {
+ CERT_DestroyCertList(certlist);
+ }
+ if(x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if(data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if (privkey) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (pubkey) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+
+ return(key);
+}
+
+/**
+ * xmlSecNssAppKeyFromCertLoadSECItem:
+ * @secItem: the @SECItem object.
+ * @format: the cert format.
+ *
+ * Loads public key from cert.
+ *
+ * Returns: pointer to key or NULL if an error occurs.
+ */
+xmlSecKeyPtr
+xmlSecNssAppKeyFromCertLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format) {
+ xmlSecKeyPtr key;
+ xmlSecKeyDataPtr keyData;
+ xmlSecKeyDataPtr certData;
+ CERTCertificate *cert=NULL;
+ int ret;
+
+ xmlSecAssert2(secItem != NULL, NULL);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
+
+ /* load cert */
+ switch(format) {
+ case xmlSecKeyDataFormatCertDer:
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ secItem, NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "format=%d", format);
+ return(NULL);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(NULL);
+ }
+
+ /* get key value */
+ keyData = xmlSecNssX509CertGetKey(cert);
+ if(keyData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CertGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ /* create key */
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(keyData);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ /* set key value */
+ ret = xmlSecKeySetValue(key, keyData);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlSecKeyDataDestroy(keyData);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ /* create cert data */
+ certData = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id);
+ if(certData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ /* put cert in the cert data */
+ ret = xmlSecNssKeyDataX509AdoptCert(certData, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ CERT_DestroyCertificate(cert);
+ return(NULL);
+ }
+
+ return(key);
+}
+
+
+/**
+ * xmlSecNssAppKeysMngrCertLoad:
+ * @mngr: the pointer to keys manager.
+ * @filename: the certificate file.
+ * @format: the certificate file format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Reads cert from @filename and adds to the list of trusted or known
+ * untrusted certs in @store
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ /* read the file contents */
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppReadSECItem(&secItem, filename);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppReadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeysMngrCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeysMngrCertLoadMemory:
+ * @mngr: the pointer to keys manager.
+ * @data: the key binary data.
+ * @dataSize: the key binary data size.
+ * @format: the certificate format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Reads cert from @data and adds to the list of trusted or known
+ * untrusted certs in @store
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data,
+ xmlSecSize dataSize, xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ SECItem secItem;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ memset(&secItem, 0, sizeof(secItem));
+ ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppCreateSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAppKeysMngrCertLoadSECItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(&secItem, PR_FALSE);
+ return(0);
+}
+
+/**
+ * xmlSecNssAppKeysMngrCertLoadSECItem:
+ * @mngr: the pointer to keys manager.
+ * @secItem: the pointer to SECItem.
+ * @format: the certificate format (PEM or DER).
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Reads cert from @secItem and adds to the list of trusted or known
+ * untrusted certs in @store
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppKeysMngrCertLoadSECItem(xmlSecKeysMngrPtr mngr, SECItem* secItem,
+ xmlSecKeyDataFormat format,
+ xmlSecKeyDataType type) {
+ xmlSecKeyDataStorePtr x509Store;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(secItem != NULL, -1);
+ xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssX509StoreId");
+ return(-1);
+ }
+
+ switch(format) {
+ case xmlSecKeyDataFormatDer:
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+ secItem, NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "format=%d", format);
+ return(-1);
+ }
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_FORMAT,
+ "format=%d", format);
+ return(-1);
+ }
+
+ ret = xmlSecNssX509StoreAdoptCert(x509Store, cert, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509StoreAdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+/**
+ * xmlSecNssAppDefaultKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Initializes @mngr with NSS keys store #xmlSecNssKeysStoreId
+ * and a default NSS crypto key data stores.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+ /* create NSS keys store if needed */
+ if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) {
+ xmlSecKeyStorePtr keysStore;
+
+ keysStore = xmlSecKeyStoreCreate(xmlSecNssKeysStoreId);
+ if(keysStore == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssKeysStoreId");
+ return(-1);
+ }
+
+ ret = xmlSecKeysMngrAdoptKeysStore(mngr, keysStore);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrAdoptKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyStoreDestroy(keysStore);
+ return(-1);
+ }
+ }
+
+ ret = xmlSecNssKeysMngrInit(mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(0);
+}
+
+/**
+ * xmlSecNssAppDefaultKeysMngrAdoptKey:
+ * @mngr: the pointer to keys manager.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the keys manager @mngr created with #xmlSecNssAppDefaultKeysMngrInit
+ * function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppDefaultKeysMngrLoad:
+ * @mngr: the pointer to keys manager.
+ * @uri: the uri.
+ *
+ * Loads XML keys file from @uri to the keys manager @mngr created
+ * with #xmlSecNssAppDefaultKeysMngrInit function.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(uri != NULL, -1);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeysStoreLoad(store, uri, mngr);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysStoreLoad",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "uri=%s", xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppDefaultKeysMngrSave:
+ * @mngr: the pointer to keys manager.
+ * @filename: the destination filename.
+ * @type: the type of keys to save (public/private/symmetric).
+ *
+ * Saves keys from @mngr to XML keys file.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename, xmlSecKeyDataType type) {
+ xmlSecKeyStorePtr store;
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+ xmlSecAssert2(filename != NULL, -1);
+
+ store = xmlSecKeysMngrGetKeysStore(mngr);
+ if(store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrGetKeysStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeysStoreSave(store, filename, type);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeysStoreSave",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "filename%s", xmlSecErrorsSafeString(filename));
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssAppGetDefaultPwdCallback:
+ *
+ * Gets default password callback.
+ *
+ * Returns: default password callback.
+ */
+void*
+xmlSecNssAppGetDefaultPwdCallback(void) {
+ return(NULL);
+}
+
diff --git a/src/nss/bignum.c b/src/nss/bignum.c
new file mode 100644
index 00000000..261155e6
--- /dev/null
+++ b/src/nss/bignum.c
@@ -0,0 +1,163 @@
+/**
+ * XMLSec library
+ *
+ * Reading/writing bignum values
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for precise wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <nss.h>
+#include <secitem.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/bignum.h>
+
+/**
+ * xmlSecNssNodeGetBigNumValue:
+ * @arena: the arena from which to allocate memory
+ * @cur: the poitner to an XML node.
+ * @a: a SECItem object to hold the BigNum value
+ *
+ * Converts the node content from CryptoBinary format
+ * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
+ * to a SECItem. If no SECItem object provided then a new
+ * one is created (caller is responsible for freeing it).
+ *
+ * Returns: a pointer to SECItem produced from CryptoBinary string
+ * or NULL if an error occurs.
+ */
+SECItem *
+xmlSecNssNodeGetBigNumValue(PRArenaPool *arena, const xmlNodePtr cur,
+ SECItem *a) {
+ xmlSecBuffer buf;
+ int ret;
+ SECItem *rv;
+ int len;
+
+ xmlSecAssert2(arena != NULL, NULL);
+ xmlSecAssert2(cur != NULL, NULL);
+
+ ret = xmlSecBufferInitialize(&buf, 128);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecBufferBase64NodeContentRead(&buf, cur);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferBase64NodeContentRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(NULL);
+ }
+
+ len = xmlSecBufferGetSize(&buf);
+
+ if (a == NULL) {
+ rv = SECITEM_AllocItem(arena, NULL, len);
+ } else {
+ rv = a;
+ xmlSecAssert2(rv->data == NULL, NULL);
+ rv->len = len;
+ rv->data = PORT_ArenaZAlloc(arena, len);
+ }
+
+ PORT_Memcpy(rv->data, xmlSecBufferGetData(&buf), len);
+
+ xmlSecBufferFinalize(&buf);
+ return(rv);
+}
+
+/**
+ * xmlSecNssNodeSetBigNumValue:
+ * @cur: the pointer to an XML node.
+ * @a: a SECItem containing the BigNum value.
+ * @addLineBreaks: if the flag is equal to 1 then
+ * linebreaks will be added before and after
+ * new buffer content.
+ *
+ * Converts SECItem to CryptoBinary string
+ * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
+ * and sets it as the content of the given node. If the
+ * addLineBreaks is set then line breaks are added
+ * before and after the CryptoBinary string.
+ *
+ * Returns: 0 on success or -1 otherwise.
+ */
+int
+xmlSecNssNodeSetBigNumValue(xmlNodePtr cur, const SECItem *a, int addLineBreaks) {
+ xmlSecBuffer buf;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(cur != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&buf, a->len + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", a->len + 1);
+ return(-1);
+ }
+
+ PORT_Memcpy(xmlSecBufferGetData(&buf), a->data, a->len);
+
+ ret = xmlSecBufferSetSize(&buf, a->len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", a->len);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ if(addLineBreaks) {
+ xmlNodeSetContent(cur, xmlSecStringCR);
+ } else {
+ xmlNodeSetContent(cur, xmlSecStringEmpty);
+ }
+
+ ret = xmlSecBufferBase64NodeContentWrite(&buf, cur, xmlSecBase64GetDefaultLineSize());
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferBase64NodeContentWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecBufferFinalize(&buf);
+ return(-1);
+ }
+
+ if(addLineBreaks) {
+ xmlNodeAddContent(cur, xmlSecStringCR);
+ }
+
+ xmlSecBufferFinalize(&buf);
+ return(0);
+}
+
diff --git a/src/nss/ciphers.c b/src/nss/ciphers.c
new file mode 100644
index 00000000..54bd2af2
--- /dev/null
+++ b/src/nss/ciphers.c
@@ -0,0 +1,838 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <secoid.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+#define XMLSEC_NSS_MAX_KEY_SIZE 32
+#define XMLSEC_NSS_MAX_IV_SIZE 32
+#define XMLSEC_NSS_MAX_BLOCK_SIZE 32
+
+/**************************************************************************
+ *
+ * Internal Nss Block cipher CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssBlockCipherCtx xmlSecNssBlockCipherCtx,
+ *xmlSecNssBlockCipherCtxPtr;
+struct _xmlSecNssBlockCipherCtx {
+ CK_MECHANISM_TYPE cipher;
+ PK11Context* cipherCtx;
+ xmlSecKeyDataId keyId;
+ int keyInitialized;
+ int ctxInitialized;
+ xmlSecByte key[XMLSEC_NSS_MAX_KEY_SIZE];
+ xmlSecSize keySize;
+ xmlSecByte iv[XMLSEC_NSS_MAX_IV_SIZE];
+ xmlSecSize ivSize;
+};
+static int xmlSecNssBlockCipherCtxInit (xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssBlockCipherCtxUpdate (xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssBlockCipherCtxFinal (xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx);
+static int
+xmlSecNssBlockCipherCtxInit(xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ SECItem keyItem;
+ SECItem ivItem;
+ PK11SlotInfo* slot;
+ PK11SymKey* symKey;
+ int ivLen;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx == NULL, -1);
+ xmlSecAssert2(ctx->keyInitialized != 0, -1);
+ xmlSecAssert2(ctx->ctxInitialized == 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ivLen = PK11_GetIVLength(ctx->cipher);
+ xmlSecAssert2(ivLen > 0, -1);
+ xmlSecAssert2((xmlSecSize)ivLen <= sizeof(ctx->iv), -1);
+
+ if(encrypt) {
+ /* generate random iv */
+ rv = PK11_GenerateRandom(ctx->iv, ivLen);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", ivLen);
+ return(-1);
+ }
+
+ /* write iv to the output */
+ ret = xmlSecBufferAppend(out, ctx->iv, ivLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", ivLen);
+ return(-1);
+ }
+
+ } else {
+ /* if we don't have enough data, exit and hope that
+ * we'll have iv next time */
+ if(xmlSecBufferGetSize(in) < (xmlSecSize)ivLen) {
+ return(0);
+ }
+
+ /* copy iv to our buffer*/
+ xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
+ memcpy(ctx->iv, xmlSecBufferGetData(in), ivLen);
+
+ /* and remove from input */
+ ret = xmlSecBufferRemoveHead(in, ivLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", ivLen);
+ return(-1);
+ }
+ }
+
+ memset(&keyItem, 0, sizeof(keyItem));
+ keyItem.data = ctx->key;
+ keyItem.len = ctx->keySize;
+ memset(&ivItem, 0, sizeof(ivItem));
+ ivItem.data = ctx->iv;
+ ivItem.len = ctx->ivSize;
+
+ slot = PK11_GetBestSlot(ctx->cipher, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ symKey = PK11_ImportSymKey(slot, ctx->cipher, PK11_OriginDerive,
+ CKA_SIGN, &keyItem, NULL);
+ if(symKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ ctx->cipherCtx = PK11_CreateContextBySymKey(ctx->cipher,
+ (encrypt) ? CKA_ENCRYPT : CKA_DECRYPT,
+ symKey, &ivItem);
+ if(ctx->cipherCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ ctx->ctxInitialized = 1;
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherCtxUpdate(xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, inBlocks, outSize;
+ int blockLen;
+ int outLen = 0;
+ xmlSecByte* outBuf;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = PK11_GetBlockSize(ctx->cipher, NULL);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(inSize < (xmlSecSize)blockLen) {
+ return(0);
+ }
+
+ if(encrypt) {
+ inBlocks = inSize / ((xmlSecSize)blockLen);
+ } else {
+ /* we want to have the last block in the input buffer
+ * for padding check */
+ inBlocks = (inSize - 1) / ((xmlSecSize)blockLen);
+ }
+ inSize = inBlocks * ((xmlSecSize)blockLen);
+
+ /* we write out the input size plus may be one block */
+ ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + inSize + blockLen);
+ return(-1);
+ }
+ outBuf = xmlSecBufferGetData(out) + outSize;
+
+ rv = PK11_CipherOp(ctx->cipherCtx, outBuf, &outLen, inSize + blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2((xmlSecSize)outLen == inSize, -1);
+
+ /* set correct output buffer size */
+ ret = xmlSecBufferSetSize(out, outSize + outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen);
+ return(-1);
+ }
+
+ /* remove the processed block from input */
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherCtxFinal(xmlSecNssBlockCipherCtxPtr ctx,
+ xmlSecBufferPtr in,
+ xmlSecBufferPtr out,
+ int encrypt,
+ const xmlChar* cipherName,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecSize inSize, outSize;
+ int blockLen, outLen = 0;
+ xmlSecByte* inBuf;
+ xmlSecByte* outBuf;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+ xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ blockLen = PK11_GetBlockSize(ctx->cipher, NULL);
+ xmlSecAssert2(blockLen > 0, -1);
+
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ if(encrypt != 0) {
+ xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1);
+
+ /* create padding */
+ ret = xmlSecBufferSetMaxSize(in, blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", blockLen);
+ return(-1);
+ }
+ inBuf = xmlSecBufferGetData(in);
+
+ /* generate random padding */
+ if((xmlSecSize)blockLen > (inSize + 1)) {
+ rv = PK11_GenerateRandom(inBuf + inSize, blockLen - inSize - 1);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", blockLen - inSize - 1);
+ return(-1);
+ }
+ }
+ inBuf[blockLen - 1] = blockLen - inSize;
+ inSize = blockLen;
+ } else {
+ if(inSize != (xmlSecSize)blockLen) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data=%d;block=%d", inSize, blockLen);
+ return(-1);
+ }
+ }
+
+ /* process last block */
+ ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + 2 * blockLen);
+ return(-1);
+ }
+ outBuf = xmlSecBufferGetData(out) + outSize;
+
+ rv = PK11_CipherOp(ctx->cipherCtx, outBuf, &outLen, 2 * blockLen,
+ xmlSecBufferGetData(in), inSize);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecAssert2((xmlSecSize)outLen == inSize, -1);
+
+ if(encrypt == 0) {
+ /* check padding */
+ if(outLen < outBuf[blockLen - 1]) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "padding=%d;buffer=%d",
+ outBuf[blockLen - 1], outLen);
+ return(-1);
+ }
+ outLen -= outBuf[blockLen - 1];
+ }
+
+ /* set correct output buffer size */
+ ret = xmlSecBufferSetSize(out, outSize + outLen);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize + outLen);
+ return(-1);
+ }
+
+ /* remove the processed block from input */
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(cipherName),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/******************************************************************************
+ *
+ * EVP Block Cipher transforms
+ *
+ * xmlSecNssBlockCipherCtx block is located after xmlSecTransform structure
+ *
+ *****************************************************************************/
+#define xmlSecNssBlockCipherSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssBlockCipherCtx))
+#define xmlSecNssBlockCipherGetCtx(transform) \
+ ((xmlSecNssBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssBlockCipherInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssBlockCipherFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssBlockCipherSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssBlockCipherSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssBlockCipherExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssBlockCipherCheckId (xmlSecTransformPtr transform);
+
+
+
+static int
+xmlSecNssBlockCipherCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DES
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformDes3CbcId)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformAes128CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecNssTransformAes192CbcId) ||
+ xmlSecTransformCheckId(transform, xmlSecNssTransformAes256CbcId)) {
+
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssBlockCipherCtx));
+
+#ifndef XMLSEC_NO_DES
+ if(transform->id == xmlSecNssTransformDes3CbcId) {
+ ctx->cipher = CKM_DES3_CBC;
+ ctx->keyId = xmlSecNssKeyDataDesId;
+ ctx->keySize = 24;
+ } else
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(transform->id == xmlSecNssTransformAes128CbcId) {
+ ctx->cipher = CKM_AES_CBC;
+ ctx->keyId = xmlSecNssKeyDataAesId;
+ ctx->keySize = 16;
+ } else if(transform->id == xmlSecNssTransformAes192CbcId) {
+ ctx->cipher = CKM_AES_CBC;
+ ctx->keyId = xmlSecNssKeyDataAesId;
+ ctx->keySize = 24;
+ } else if(transform->id == xmlSecNssTransformAes256CbcId) {
+ ctx->cipher = CKM_AES_CBC;
+ ctx->keyId = xmlSecNssKeyDataAesId;
+ ctx->keySize = 32;
+ } else
+#endif /* XMLSEC_NO_AES */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssBlockCipherFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssBlockCipherCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize));
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->cipherCtx != NULL) {
+ PK11_DestroyContext(ctx->cipherCtx, PR_TRUE);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssBlockCipherCtx));
+}
+
+static int
+xmlSecNssBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+
+ keyReq->keyId = ctx->keyId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * ctx->keySize;
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->cipher != 0, -1);
+ xmlSecAssert2(ctx->keyInitialized == 0, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ xmlSecAssert2(ctx->keySize > 0, -1);
+ xmlSecAssert2(ctx->keySize <= sizeof(ctx->key), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) < ctx->keySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "keySize=%d;expected=%d",
+ xmlSecBufferGetSize(buffer), ctx->keySize);
+ return(-1);
+ }
+
+ xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
+ memcpy(ctx->key, xmlSecBufferGetData(buffer), ctx->keySize);
+
+ ctx->keyInitialized = 1;
+ return(0);
+}
+
+static int
+xmlSecNssBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssBlockCipherCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ ctx = xmlSecNssBlockCipherGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ if(ctx->ctxInitialized == 0) {
+ ret = xmlSecNssBlockCipherCtxInit(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssBlockCipherCtxInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ if((ctx->ctxInitialized == 0) && (last != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "not enough data to initialize transform");
+ return(-1);
+ }
+
+ if(ctx->ctxInitialized != 0) {
+ ret = xmlSecNssBlockCipherCtxUpdate(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssBlockCipherCtxUpdate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if(last) {
+ ret = xmlSecNssBlockCipherCtxFinal(ctx, in, out,
+ (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0,
+ xmlSecTransformGetName(transform), transformCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssBlockCipherCtxFinal",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
+ } else if(transform->status == xmlSecTransformStatusNone) {
+ /* the only way we can get here is if there is no enough data in the input */
+ xmlSecAssert2(last == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+#ifndef XMLSEC_NO_AES
+/*********************************************************************
+ *
+ * AES CBC cipher transforms
+ *
+ ********************************************************************/
+static xmlSecTransformKlass xmlSecNssAes128CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes128Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes128Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformAes128CbcGetKlass:
+ *
+ * AES 128 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 128 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformAes128CbcGetKlass(void) {
+ return(&xmlSecNssAes128CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecNssAes192CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes192Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes192Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformAes192CbcGetKlass:
+ *
+ * AES 192 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 192 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformAes192CbcGetKlass(void) {
+ return(&xmlSecNssAes192CbcKlass);
+}
+
+static xmlSecTransformKlass xmlSecNssAes256CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameAes256Cbc, /* const xmlChar* name; */
+ xmlSecHrefAes256Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformAes256CbcGetKlass:
+ *
+ * AES 256 CBC encryption transform klass.
+ *
+ * Returns: pointer to AES 256 CBC encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformAes256CbcGetKlass(void) {
+ return(&xmlSecNssAes256CbcKlass);
+}
+
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+static xmlSecTransformKlass xmlSecNssDes3CbcKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssBlockCipherSize, /* xmlSecSize objSize */
+
+ xmlSecNameDes3Cbc, /* const xmlChar* name; */
+ xmlSecHrefDes3Cbc, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformDes3CbcGetKlass:
+ *
+ * Triple DES CBC encryption transform klass.
+ *
+ * Returns: pointer to Triple DES encryption transform.
+ */
+xmlSecTransformId
+xmlSecNssTransformDes3CbcGetKlass(void) {
+ return(&xmlSecNssDes3CbcKlass);
+}
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/nss/crypto.c b/src/nss/crypto.c
new file mode 100644
index 00000000..7137f1c4
--- /dev/null
+++ b/src/nss/crypto.c
@@ -0,0 +1,444 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+#include <prinit.h>
+
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/private.h>
+#include <xmlsec/xmltree.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+
+static xmlSecCryptoDLFunctionsPtr gXmlSecNssFunctions = NULL;
+
+/**
+ * xmlSecCryptoGetFunctions_nss:
+ *
+ * Gets the pointer to xmlsec-nss functions table.
+ *
+ * Returns: the xmlsec-nss functions table or NULL if an error occurs.
+ */
+xmlSecCryptoDLFunctionsPtr
+xmlSecCryptoGetFunctions_nss(void) {
+ static xmlSecCryptoDLFunctions functions;
+
+ if(gXmlSecNssFunctions != NULL) {
+ return(gXmlSecNssFunctions);
+ }
+
+ memset(&functions, 0, sizeof(functions));
+ gXmlSecNssFunctions = &functions;
+
+ /********************************************************************
+ *
+ * Crypto Init/shutdown
+ *
+ ********************************************************************/
+ gXmlSecNssFunctions->cryptoInit = xmlSecNssInit;
+ gXmlSecNssFunctions->cryptoShutdown = xmlSecNssShutdown;
+ gXmlSecNssFunctions->cryptoKeysMngrInit = xmlSecNssKeysMngrInit;
+
+ /********************************************************************
+ *
+ * Key data ids
+ *
+ ********************************************************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecNssFunctions->keyDataAesGetKlass = xmlSecNssKeyDataAesGetKlass;
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+ gXmlSecNssFunctions->keyDataDesGetKlass = xmlSecNssKeyDataDesGetKlass;
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_DSA
+ gXmlSecNssFunctions->keyDataDsaGetKlass = xmlSecNssKeyDataDsaGetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_HMAC
+ gXmlSecNssFunctions->keyDataHmacGetKlass = xmlSecNssKeyDataHmacGetKlass;
+#endif /* XMLSEC_NO_HMAC */
+
+#ifndef XMLSEC_NO_RSA
+ gXmlSecNssFunctions->keyDataRsaGetKlass = xmlSecNssKeyDataRsaGetKlass;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_X509
+ gXmlSecNssFunctions->keyDataX509GetKlass = xmlSecNssKeyDataX509GetKlass;
+ gXmlSecNssFunctions->keyDataRawX509CertGetKlass = xmlSecNssKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /********************************************************************
+ *
+ * Key data store ids
+ *
+ ********************************************************************/
+#ifndef XMLSEC_NO_X509
+ gXmlSecNssFunctions->x509StoreGetKlass = xmlSecNssX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
+ /********************************************************************
+ *
+ * Crypto transforms ids
+ *
+ ********************************************************************/
+
+ /******************************* AES ********************************/
+#ifndef XMLSEC_NO_AES
+ gXmlSecNssFunctions->transformAes128CbcGetKlass = xmlSecNssTransformAes128CbcGetKlass;
+ gXmlSecNssFunctions->transformAes192CbcGetKlass = xmlSecNssTransformAes192CbcGetKlass;
+ gXmlSecNssFunctions->transformAes256CbcGetKlass = xmlSecNssTransformAes256CbcGetKlass;
+ gXmlSecNssFunctions->transformKWAes128GetKlass = xmlSecNssTransformKWAes128GetKlass;
+ gXmlSecNssFunctions->transformKWAes192GetKlass = xmlSecNssTransformKWAes192GetKlass;
+ gXmlSecNssFunctions->transformKWAes256GetKlass = xmlSecNssTransformKWAes256GetKlass;
+#endif /* XMLSEC_NO_AES */
+
+ /******************************* DES ********************************/
+#ifndef XMLSEC_NO_DES
+ gXmlSecNssFunctions->transformDes3CbcGetKlass = xmlSecNssTransformDes3CbcGetKlass;
+ gXmlSecNssFunctions->transformKWDes3GetKlass = xmlSecNssTransformKWDes3GetKlass;
+#endif /* XMLSEC_NO_DES */
+
+ /******************************* DSA ********************************/
+#ifndef XMLSEC_NO_DSA
+ gXmlSecNssFunctions->transformDsaSha1GetKlass = xmlSecNssTransformDsaSha1GetKlass;
+#endif /* XMLSEC_NO_DSA */
+
+ /******************************* HMAC ********************************/
+#ifndef XMLSEC_NO_HMAC
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecNssFunctions->transformHmacMd5GetKlass = xmlSecNssTransformHmacMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ gXmlSecNssFunctions->transformHmacRipemd160GetKlass = xmlSecNssTransformHmacRipemd160GetKlass;
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformHmacSha1GetKlass = xmlSecNssTransformHmacSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecNssFunctions->transformHmacSha256GetKlass = xmlSecNssTransformHmacSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecNssFunctions->transformHmacSha384GetKlass = xmlSecNssTransformHmacSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecNssFunctions->transformHmacSha512GetKlass = xmlSecNssTransformHmacSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+ /******************************* RSA ********************************/
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ gXmlSecNssFunctions->transformRsaMd5GetKlass = xmlSecNssTransformRsaMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformRsaSha1GetKlass = xmlSecNssTransformRsaSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecNssFunctions->transformRsaSha256GetKlass = xmlSecNssTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecNssFunctions->transformRsaSha384GetKlass = xmlSecNssTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecNssFunctions->transformRsaSha512GetKlass = xmlSecNssTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ gXmlSecNssFunctions->transformRsaPkcs1GetKlass = xmlSecNssTransformRsaPkcs1GetKlass;
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+ gXmlSecNssFunctions->transformRsaOaepGetKlass = xmlSecNssTransformRsaOaepGetKlass;
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
+#endif /* XMLSEC_NO_RSA */
+
+ /******************************* SHA ********************************/
+#ifndef XMLSEC_NO_SHA1
+ gXmlSecNssFunctions->transformSha1GetKlass = xmlSecNssTransformSha1GetKlass;
+#endif /* XMLSEC_NO_SHA1 */
+#ifndef XMLSEC_NO_SHA256
+ gXmlSecNssFunctions->transformSha256GetKlass = xmlSecNssTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+#ifndef XMLSEC_NO_SHA384
+ gXmlSecNssFunctions->transformSha384GetKlass = xmlSecNssTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+#ifndef XMLSEC_NO_SHA512
+ gXmlSecNssFunctions->transformSha512GetKlass = xmlSecNssTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
+ /******************************* MD5 ********************************/
+#ifndef XMLSEC_NO_MD5
+ gXmlSecNssFunctions->transformMd5GetKlass = xmlSecNssTransformMd5GetKlass;
+#endif /* XMLSEC_NO_MD5 */
+
+
+ /********************************************************************
+ *
+ * High level routines form xmlsec command line utility
+ *
+ ********************************************************************/
+ gXmlSecNssFunctions->cryptoAppInit = xmlSecNssAppInit;
+ gXmlSecNssFunctions->cryptoAppShutdown = xmlSecNssAppShutdown;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrInit = xmlSecNssAppDefaultKeysMngrInit;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecNssAppDefaultKeysMngrAdoptKey;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecNssAppDefaultKeysMngrLoad;
+ gXmlSecNssFunctions->cryptoAppDefaultKeysMngrSave = xmlSecNssAppDefaultKeysMngrSave;
+#ifndef XMLSEC_NO_X509
+ gXmlSecNssFunctions->cryptoAppKeysMngrCertLoad = xmlSecNssAppKeysMngrCertLoad;
+ gXmlSecNssFunctions->cryptoAppKeysMngrCertLoadMemory= xmlSecNssAppKeysMngrCertLoadMemory;
+ gXmlSecNssFunctions->cryptoAppPkcs12Load = xmlSecNssAppPkcs12Load;
+ gXmlSecNssFunctions->cryptoAppPkcs12LoadMemory = xmlSecNssAppPkcs12LoadMemory;
+ gXmlSecNssFunctions->cryptoAppKeyCertLoad = xmlSecNssAppKeyCertLoad;
+ gXmlSecNssFunctions->cryptoAppKeyCertLoadMemory = xmlSecNssAppKeyCertLoadMemory;
+#endif /* XMLSEC_NO_X509 */
+ gXmlSecNssFunctions->cryptoAppKeyLoad = xmlSecNssAppKeyLoad;
+ gXmlSecNssFunctions->cryptoAppKeyLoadMemory = xmlSecNssAppKeyLoadMemory;
+ gXmlSecNssFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecNssAppGetDefaultPwdCallback();
+
+ return(gXmlSecNssFunctions);
+}
+
+/**
+ * xmlSecNssInit:
+ *
+ * XMLSec library specific crypto engine initialization.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssInit (void) {
+ /* Check loaded xmlsec library version */
+ if(xmlSecCheckVersionExact() != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCheckVersionExact",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* set default errors callback for xmlsec to us */
+ xmlSecErrorsSetCallback(xmlSecNssErrorsDefaultCallback);
+
+ /* register our klasses */
+ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_nss()) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecNssShutdown:
+ *
+ * XMLSec library specific crypto engine shutdown.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssShutdown(void) {
+ return(0);
+}
+
+/**
+ * xmlSecNssKeysMngrInit:
+ * @mngr: the pointer to keys manager.
+ *
+ * Adds NSS specific key data stores in keys manager.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+ int ret;
+
+ xmlSecAssert2(mngr != NULL, -1);
+
+#ifndef XMLSEC_NO_X509
+ /* create x509 store if needed */
+ if(xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId) == NULL) {
+ xmlSecKeyDataStorePtr x509Store;
+
+ x509Store = xmlSecKeyDataStoreCreate(xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssX509StoreId");
+ return(-1);
+ }
+
+ ret = xmlSecKeysMngrAdoptDataStore(mngr, x509Store);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeysMngrAdoptDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataStoreDestroy(x509Store);
+ return(-1);
+ }
+ }
+#endif /* XMLSEC_NO_X509 */
+
+ return(0);
+}
+
+/**
+ * xmlSecNssGetInternalKeySlot:
+ *
+ * Gets internal NSS key slot.
+ *
+ * Returns: internal key slot and initializes it if needed.
+ */
+PK11SlotInfo *
+xmlSecNssGetInternalKeySlot()
+{
+ PK11SlotInfo *slot = NULL;
+ SECStatus rv;
+
+ slot = PK11_GetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetInternalKeySlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return NULL;
+ }
+
+ if (PK11_NeedUserInit(slot)) {
+ rv = PK11_InitPin(slot, NULL, NULL);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_Authenticate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return NULL;
+ }
+ }
+
+ if(PK11_IsLoggedIn(slot, NULL) != PR_TRUE) {
+ rv = PK11_Authenticate(slot, PR_TRUE, NULL);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_Authenticate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return NULL;
+ }
+ }
+
+ return(slot);
+}
+
+/**
+ * xmlSecNssGenerateRandom:
+ * @buffer: the destination buffer.
+ * @size: the numer of bytes to generate.
+ *
+ * Generates @size random bytes and puts result in @buffer.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecNssGenerateRandom(xmlSecBufferPtr buffer, xmlSecSize size) {
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(buffer != NULL, -1);
+ xmlSecAssert2(size > 0, -1);
+
+ ret = xmlSecBufferSetSize(buffer, size);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+
+ /* get random data */
+ rv = PK11_GenerateRandom((xmlSecByte*)xmlSecBufferGetData(buffer), size);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", size);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSecNssErrorsDefaultCallback:
+ * @file: the error location file name (__FILE__ macro).
+ * @line: the error location line number (__LINE__ macro).
+ * @func: the error location function name (__FUNCTION__ macro).
+ * @errorObject: the error specific error object
+ * @errorSubject: the error specific error subject.
+ * @reason: the error code.
+ * @msg: the additional error message.
+ *
+ * The default errors reporting callback function.
+ */
+void
+xmlSecNssErrorsDefaultCallback(const char* file, int line, const char* func,
+ const char* errorObject, const char* errorSubject,
+ int reason, const char* msg) {
+ xmlChar buf[500];
+ int err;
+
+ err = PORT_GetError();
+ xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "%s;last nss error=%d (0x%08X)", msg, err, err);
+ xmlSecErrorsDefaultCallback(file, line, func,
+ errorObject, errorSubject,
+ reason, (char*)buf);
+}
diff --git a/src/nss/digests.c b/src/nss/digests.c
new file mode 100644
index 00000000..8063b443
--- /dev/null
+++ b/src/nss/digests.c
@@ -0,0 +1,576 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <secoid.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+
+#define XMLSEC_NSS_MAX_DIGEST_SIZE 64
+
+/**************************************************************************
+ *
+ * Internal NSS Digest CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssDigestCtx xmlSecNssDigestCtx, *xmlSecNssDigestCtxPtr;
+struct _xmlSecNssDigestCtx {
+ SECOidData* digest;
+ PK11Context* digestCtx;
+ xmlSecByte dgst[XMLSEC_NSS_MAX_DIGEST_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+/******************************************************************************
+ *
+ * Digest transforms
+ *
+ * xmlSecNssDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssDigestSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssDigestCtx))
+#define xmlSecNssDigestGetCtx(transform) \
+ ((xmlSecNssDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssDigestCheckId (xmlSecTransformPtr transform);
+static int xmlSecNssDigestInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssDigestFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssDigestVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssDigestExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecNssDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+ return(0);
+}
+
+static int
+xmlSecNssDigestInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1);
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ /* initialize context */
+ memset(ctx, 0, sizeof(xmlSecNssDigestCtx));
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformMd5Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_MD5);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha1Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha256Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA256);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha384Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA384);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformSha512Id)) {
+ ctx->digest = SECOID_FindOIDByTag(SEC_OID_SHA512);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if(ctx->digest == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SECOID_FindOIDByTag",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ctx->digestCtx = PK11_CreateDigestContext(ctx->digest->offset);
+ if(ctx->digestCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_CreateDigestContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssDigestFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssDigestCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssDigestCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize));
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ PK11_DestroyContext(ctx->digestCtx, PR_TRUE);
+ }
+ memset(ctx, 0, sizeof(xmlSecNssDigestCtx));
+}
+
+static int
+xmlSecNssDigestVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssDigestCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ if(dataSize != ctx->dgstSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data and digest sizes are different (data=%d, dgst=%d)",
+ dataSize, ctx->dgstSize);
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ if(memcmp(ctx->dgst, data, dataSize) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "data and digest do not match");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecNssDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssDigestCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1);
+
+ ctx = xmlSecNssDigestGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ rv = PK11_DigestBegin(ctx->digestCtx);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ rv = PK11_DigestOp(ctx->digestCtx, xmlSecBufferGetData(in), inSize);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ }
+ if(last) {
+ unsigned int dgstSize;
+
+ rv = PK11_DigestFinal(ctx->digestCtx, ctx->dgst, &dgstSize, sizeof(ctx->dgst));
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ xmlSecAssert2(dgstSize > 0, -1);
+ ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", ctx->dgstSize);
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_MD5
+/******************************************************************************
+ *
+ * Md5 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameMd5, /* const xmlChar* name; */
+ xmlSecHrefMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecNssDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformMd5GetKlass:
+ *
+ * MD5 digest transform klass.
+ *
+ * Returns: pointer to MD5 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformMd5GetKlass(void) {
+ return(&xmlSecNssMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * SHA1 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha1, /* const xmlChar* name; */
+ xmlSecHrefSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecNssDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns: pointer to SHA-1 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha1GetKlass(void) {
+ return(&xmlSecNssSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * SHA256 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha256, /* const xmlChar* name; */
+ xmlSecHrefSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecNssDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformSha256GetKlass:
+ *
+ * SHA256 digest transform klass.
+ *
+ * Returns: pointer to SHA256 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha256GetKlass(void) {
+ return(&xmlSecNssSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * SHA384 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha384, /* const xmlChar* name; */
+ xmlSecHrefSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecNssDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformSha384GetKlass:
+ *
+ * SHA384 digest transform klass.
+ *
+ * Returns: pointer to SHA384 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha384GetKlass(void) {
+ return(&xmlSecNssSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * SHA512 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecNssSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssDigestSize, /* xmlSecSize objSize */
+
+ /* data */
+ xmlSecNameSha512, /* const xmlChar* name; */
+ xmlSecHrefSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
+
+ /* methods */
+ xmlSecNssDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ NULL, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssDigestVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssDigestExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformSha512GetKlass:
+ *
+ * SHA512 digest transform klass.
+ *
+ * Returns: pointer to SHA512 digest transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformSha512GetKlass(void) {
+ return(&xmlSecNssSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
diff --git a/src/nss/globals.h b/src/nss/globals.h
new file mode 100644
index 00000000..770b6dba
--- /dev/null
+++ b/src/nss/globals.h
@@ -0,0 +1,24 @@
+/*
+ * XML Security Library
+ *
+ * globals.h: internal header only used during the compilation
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef __XMLSEC_GLOBALS_H__
+#define __XMLSEC_GLOBALS_H__
+
+/**
+ * Use autoconf defines if present.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#define IN_XMLSEC_CRYPTO
+#define XMLSEC_PRIVATE
+
+#endif /* ! __XMLSEC_GLOBALS_H__ */
diff --git a/src/nss/hmac.c b/src/nss/hmac.c
new file mode 100644
index 00000000..ae7e67ef
--- /dev/null
+++ b/src/nss/hmac.c
@@ -0,0 +1,855 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#ifndef XMLSEC_NO_HMAC
+#include "globals.h"
+
+#include <string.h>
+
+#include <nspr.h>
+#include <nss.h>
+#include <secoid.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+
+/* sizes in bits */
+#define XMLSEC_NSS_MIN_HMAC_SIZE 80
+#define XMLSEC_NSS_MAX_HMAC_SIZE (128 * 8)
+
+/**************************************************************************
+ *
+ * Configuration
+ *
+ *****************************************************************************/
+static int g_xmlsec_nss_hmac_min_length = XMLSEC_NSS_MIN_HMAC_SIZE;
+
+/**
+ * xmlSecNssHmacGetMinOutputLength:
+ *
+ * Gets the value of min HMAC length.
+ *
+ * Returns: the min HMAC output length
+ */
+int xmlSecNssHmacGetMinOutputLength(void)
+{
+ return g_xmlsec_nss_hmac_min_length;
+}
+
+/**
+ * xmlSecNssHmacSetMinOutputLength:
+ * @min_length: the new min length
+ *
+ * Sets the min HMAC output length
+ */
+void xmlSecNssHmacSetMinOutputLength(int min_length)
+{
+ g_xmlsec_nss_hmac_min_length = min_length;
+}
+
+/**************************************************************************
+ *
+ * Internal NSS HMAC CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssHmacCtx xmlSecNssHmacCtx, *xmlSecNssHmacCtxPtr;
+struct _xmlSecNssHmacCtx {
+ CK_MECHANISM_TYPE digestType;
+ PK11Context* digestCtx;
+ xmlSecByte dgst[XMLSEC_NSS_MAX_HMAC_SIZE / 8];
+ xmlSecSize dgstSize; /* dgst size in bits */
+};
+
+/******************************************************************************
+ *
+ * HMAC transforms
+ *
+ * xmlSecNssHmacCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssHmacGetCtx(transform) \
+ ((xmlSecNssHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecNssHmacSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssHmacCtx))
+
+static int xmlSecNssHmacCheckId (xmlSecTransformPtr transform);
+static int xmlSecNssHmacInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssHmacFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssHmacNodeRead (xmlSecTransformPtr transform,
+ xmlNodePtr node,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssHmacSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssHmacSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssHmacVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssHmacExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+
+static int
+xmlSecNssHmacCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacRipemd160Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+ /* not found */
+ return(0);
+}
+
+static int
+xmlSecNssHmacInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ memset(ctx, 0, sizeof(xmlSecNssHmacCtx));
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacMd5Id)) {
+ ctx->digestType = CKM_MD5_HMAC;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacRipemd160Id)) {
+ ctx->digestType = CKM_RIPEMD160_HMAC;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha1Id)) {
+ ctx->digestType = CKM_SHA_1_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha256Id)) {
+ ctx->digestType = CKM_SHA256_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha384Id)) {
+ ctx->digestType = CKM_SHA384_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformHmacSha512Id)) {
+ ctx->digestType = CKM_SHA512_HMAC;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+ /* not found */
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+static void
+xmlSecNssHmacFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssHmacCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssHmacCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize));
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->digestCtx != NULL) {
+ PK11_DestroyContext(ctx->digestCtx, PR_TRUE);
+ }
+ memset(ctx, 0, sizeof(xmlSecNssHmacCtx));
+}
+
+/**
+ * xmlSecNssHmacNodeRead:
+ *
+ * HMAC (http://www.w3.org/TR/xmldsig-core/#sec-HMAC):
+ *
+ * The HMAC algorithm (RFC2104 [HMAC]) takes the truncation length in bits
+ * as a parameter; if the parameter is not specified then all the bits of the
+ * hash are output. An example of an HMAC SignatureMethod element:
+ * <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+ * <HMACOutputLength>128</HMACOutputLength>
+ * </SignatureMethod>
+ *
+ * Schema Definition:
+ *
+ * <simpleType name="HMACOutputLengthType">
+ * <restriction base="integer"/>
+ * </simpleType>
+ *
+ * DTD:
+ *
+ * <!ELEMENT HMACOutputLength (#PCDATA)>
+ */
+static int
+xmlSecNssHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssHmacCtxPtr ctx;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(node!= NULL, -1);
+ xmlSecAssert2(transformCtx!= NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) {
+ xmlChar *content;
+
+ content = xmlNodeGetContent(cur);
+ if(content != NULL) {
+ ctx->dgstSize = atoi((char*)content);
+ xmlFree(content);
+ }
+
+ /* Ensure that HMAC length is greater than min specified.
+ Otherwise, an attacker can set this length to 0 or very
+ small value
+ */
+ if((int)ctx->dgstSize < xmlSecNssHmacGetMinOutputLength()) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
+ "HMAC output length is too small");
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "no nodes expected");
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+xmlSecNssHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssHmacCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataHmacId;
+ keyReq->keyType= xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssHmacCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+ xmlSecBufferPtr buffer;
+ SECItem keyItem;
+ SECItem ignore;
+ PK11SlotInfo* slot;
+ PK11SymKey* symKey;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestType != 0, -1);
+ xmlSecAssert2(ctx->digestCtx == NULL, -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecNssKeyDataHmacId), -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(value);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ if(xmlSecBufferGetSize(buffer) == 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key is empty");
+ return(-1);
+ }
+
+ memset(&ignore, 0, sizeof(ignore));
+ memset(&keyItem, 0, sizeof(keyItem));
+ keyItem.data = xmlSecBufferGetData(buffer);
+ keyItem.len = xmlSecBufferGetSize(buffer);
+
+ slot = PK11_GetBestSlot(ctx->digestType, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ symKey = PK11_ImportSymKey(slot, ctx->digestType, PK11_OriginDerive,
+ CKA_SIGN, &keyItem, NULL);
+ if(symKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ ctx->digestCtx = PK11_CreateContextBySymKey(ctx->digestType, CKA_SIGN, symKey, &ignore);
+ if(ctx->digestCtx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(-1);
+ }
+
+ PK11_FreeSymKey(symKey);
+ PK11_FreeSlot(slot);
+ return(0);
+}
+
+static int
+xmlSecNssHmacVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ static xmlSecByte last_byte_masks[] =
+ { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
+
+ xmlSecNssHmacCtxPtr ctx;
+ xmlSecByte mask;
+
+ xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+
+ /* compare the digest size in bytes */
+ if(dataSize != ((ctx->dgstSize + 7) / 8)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "data=%d;dgst=%d",
+ dataSize, ((ctx->dgstSize + 7) / 8));
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ /* we check the last byte separatelly */
+ xmlSecAssert2(dataSize > 0, -1);
+ mask = last_byte_masks[ctx->dgstSize % 8];
+ if((ctx->dgst[dataSize - 1] & mask) != (data[dataSize - 1] & mask)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "data and digest do not match (last byte)");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ /* now check the rest of the digest */
+ if((dataSize > 1) && (memcmp(ctx->dgst, data, dataSize - 1) != 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "data and digest do not match");
+ transform->status = xmlSecTransformStatusFail;
+ return(0);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecNssHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssHmacCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ SECStatus rv;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssHmacCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssHmacSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssHmacGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->digestCtx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ rv = PK11_DigestBegin(ctx->digestCtx);
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecSize inSize;
+
+ inSize = xmlSecBufferGetSize(in);
+ if(inSize > 0) {
+ rv = PK11_DigestOp(ctx->digestCtx, xmlSecBufferGetData(in), inSize);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+ }
+ if(last) {
+ unsigned int dgstSize;
+
+ rv = PK11_DigestFinal(ctx->digestCtx, ctx->dgst, &dgstSize, sizeof(ctx->dgst));
+ if(rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ xmlSecAssert2(dgstSize > 0, -1);
+
+ /* check/set the result digest size */
+ if(ctx->dgstSize == 0) {
+ ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize * 8); /* no dgst size specified, use all we have */
+ } else if(ctx->dgstSize <= XMLSEC_SIZE_BAD_CAST(8 * dgstSize)) {
+ dgstSize = ((ctx->dgstSize + 7) / 8); /* we need to truncate result digest */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "result-bits=%d;required-bits=%d",
+ 8 * dgstSize, ctx->dgstSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = xmlSecBufferAppend(out, ctx->dgst, dgstSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferAppend",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", dgstSize);
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "size=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+#ifndef XMLSEC_NO_RIPEMD160
+/******************************************************************************
+ *
+ * HMAC Ripemd160
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacRipemd160, /* const xmlChar* name; */
+ xmlSecHrefHmacRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacRipemd160GetKlass:
+ *
+ * The HMAC-RIPEMD160 transform klass.
+ *
+ * Returns: the HMAC-RIPEMD160 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacRipemd160GetKlass(void) {
+ return(&xmlSecNssHmacRipemd160Klass);
+}
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_MD5
+/******************************************************************************
+ *
+ * HMAC MD5
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacMd5, /* const xmlChar* name; */
+ xmlSecHrefHmacMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacMd5GetKlass:
+ *
+ * The HMAC-MD5 transform klass.
+ *
+ * Returns: the HMAC-MD5 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacMd5GetKlass(void) {
+ return(&xmlSecNssHmacMd5Klass);
+}
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * HMAC SHA1
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha1, /* const xmlChar* name; */
+ xmlSecHrefHmacSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha1GetKlass:
+ *
+ * The HMAC-SHA1 transform klass.
+ *
+ * Returns: the HMAC-SHA1 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha1GetKlass(void) {
+ return(&xmlSecNssHmacSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * HMAC SHA256
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha256, /* const xmlChar* name; */
+ xmlSecHrefHmacSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha256GetKlass:
+ *
+ * The HMAC-SHA256 transform klass.
+ *
+ * Returns: the HMAC-SHA256 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha256GetKlass(void) {
+ return(&xmlSecNssHmacSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * HMAC SHA384
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha384, /* const xmlChar* name; */
+ xmlSecHrefHmacSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha384GetKlass:
+ *
+ * The HMAC-SHA384 transform klass.
+ *
+ * Returns: the HMAC-SHA384 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha384GetKlass(void) {
+ return(&xmlSecNssHmacSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * HMAC SHA512
+ *
+ ******************************************************************************/
+static xmlSecTransformKlass xmlSecNssHmacSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssHmacSize, /* xmlSecSize objSize */
+
+ xmlSecNameHmacSha512, /* const xmlChar* name; */
+ xmlSecHrefHmacSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ xmlSecNssHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssHmacVerify, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssHmacExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformHmacSha512GetKlass:
+ *
+ * The HMAC-SHA512 transform klass.
+ *
+ * Returns: the HMAC-SHA512 transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformHmacSha512GetKlass(void) {
+ return(&xmlSecNssHmacSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_HMAC */
+
+
diff --git a/src/nss/keysstore.c b/src/nss/keysstore.c
new file mode 100644
index 00000000..f07e44be
--- /dev/null
+++ b/src/nss/keysstore.c
@@ -0,0 +1,485 @@
+/**
+ * XMLSec library
+ *
+ * Nss keys store that uses Simple Keys Store under the hood. Uses the
+ * Nss DB as a backing store for the finding keys, but the NSS DB is
+ * not written to by the keys store.
+ * So, if store->findkey is done and the key is not found in the simple
+ * keys store, the NSS DB is looked up.
+ * If store is called to adopt a key, that key is not written to the NSS
+ * DB.
+ * Thus, the NSS DB can be used to pre-load keys and becomes an alternate
+ * source of keys for xmlsec
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for precise wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <nss.h>
+#include <cert.h>
+#include <pk11func.h>
+#include <keyhi.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/xmltree.h>
+
+#include <xmlsec/keysmngr.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/keysstore.h>
+#include <xmlsec/nss/x509.h>
+#include <xmlsec/nss/pkikeys.h>
+
+/****************************************************************************
+ *
+ * Nss Keys Store. Uses Simple Keys Store under the hood
+ *
+ * Simple Keys Store ptr is located after xmlSecKeyStore
+ *
+ ***************************************************************************/
+#define xmlSecNssKeysStoreSize \
+ (sizeof(xmlSecKeyStore) + sizeof(xmlSecKeyStorePtr))
+
+#define xmlSecNssKeysStoreGetSS(store) \
+ ((xmlSecKeyStoreCheckSize((store), xmlSecNssKeysStoreSize)) ? \
+ (xmlSecKeyStorePtr*)(((xmlSecByte*)(store)) + sizeof(xmlSecKeyStore)) : \
+ (xmlSecKeyStorePtr*)NULL)
+
+static int xmlSecNssKeysStoreInitialize (xmlSecKeyStorePtr store);
+static void xmlSecNssKeysStoreFinalize (xmlSecKeyStorePtr store);
+static xmlSecKeyPtr xmlSecNssKeysStoreFindKey (xmlSecKeyStorePtr store,
+ const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyStoreKlass xmlSecNssKeysStoreKlass = {
+ sizeof(xmlSecKeyStoreKlass),
+ xmlSecNssKeysStoreSize,
+
+ /* data */
+ BAD_CAST "NSS-keys-store", /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecNssKeysStoreInitialize, /* xmlSecKeyStoreInitializeMethod initialize; */
+ xmlSecNssKeysStoreFinalize, /* xmlSecKeyStoreFinalizeMethod finalize; */
+ xmlSecNssKeysStoreFindKey, /* xmlSecKeyStoreFindKeyMethod findKey; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeysStoreGetKlass:
+ *
+ * The Nss list based keys store klass.
+ *
+ * Returns: Nss list based keys store klass.
+ */
+xmlSecKeyStoreId
+xmlSecNssKeysStoreGetKlass(void) {
+ return(&xmlSecNssKeysStoreKlass);
+}
+
+/**
+ * xmlSecNssKeysStoreAdoptKey:
+ * @store: the pointer to Nss keys store.
+ * @key: the pointer to key.
+ *
+ * Adds @key to the @store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeysStoreAdoptKey(xmlSecKeyStorePtr store, xmlSecKeyPtr key) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+ xmlSecAssert2((key != NULL), -1);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
+ (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
+
+ return (xmlSecSimpleKeysStoreAdoptKey(*ss, key));
+}
+
+/**
+ * xmlSecNssKeysStoreLoad:
+ * @store: the pointer to Nss keys store.
+ * @uri: the filename.
+ * @keysMngr: the pointer to associated keys manager.
+ *
+ * Reads keys from an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeysStoreLoad(xmlSecKeyStorePtr store, const char *uri,
+ xmlSecKeysMngrPtr keysMngr) {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr cur;
+ xmlSecKeyPtr key;
+ xmlSecKeyInfoCtx keyInfoCtx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+ xmlSecAssert2((uri != NULL), -1);
+
+ doc = xmlParseFile(uri);
+ if(doc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlParseFile",
+ XMLSEC_ERRORS_R_XML_FAILED,
+ "uri=%s",
+ xmlSecErrorsSafeString(uri));
+ return(-1);
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if(!xmlSecCheckNodeName(root, BAD_CAST "Keys", xmlSecNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(root)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=<xmlsec:Keys>");
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(root->children);
+ while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
+ key = xmlSecKeyCreate();
+ if(key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "expected-node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoCtxInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ keyInfoCtx.mode = xmlSecKeyInfoModeRead;
+ keyInfoCtx.keysMngr = keysMngr;
+ keyInfoCtx.flags = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
+ XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+ keyInfoCtx.keyReq.keyId = xmlSecKeyDataIdUnknown;
+ keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
+ keyInfoCtx.keyReq.keyUsage= xmlSecKeyDataUsageAny;
+
+ ret = xmlSecKeyInfoNodeRead(cur, key, &keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyInfoNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
+
+ if(xmlSecKeyIsValid(key)) {
+ ret = xmlSecNssKeysStoreAdoptKey(store, key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecNssKeysStoreAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDestroy(key);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ } else {
+ /* we have an unknown key in our file, just ignore it */
+ xmlSecKeyDestroy(key);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ xmlFreeDoc(doc);
+ return(0);
+}
+
+/**
+ * xmlSecNssKeysStoreSave:
+ * @store: the pointer to Nss keys store.
+ * @filename: the filename.
+ * @type: the saved keys type (public, private, ...).
+ *
+ * Writes keys from @store to an XML file.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeysStoreSave(xmlSecKeyStorePtr store, const char *filename, xmlSecKeyDataType type) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+ xmlSecAssert2((filename != NULL), -1);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL) &&
+ (xmlSecKeyStoreCheckId(*ss, xmlSecSimpleKeysStoreId))), -1);
+
+ return (xmlSecSimpleKeysStoreSave(*ss, filename, type));
+}
+
+static int
+xmlSecNssKeysStoreInitialize(xmlSecKeyStorePtr store) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), -1);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2((*ss == NULL), -1);
+
+ *ss = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId);
+ if(*ss == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecSimpleKeysStoreId");
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKeysStoreFinalize(xmlSecKeyStorePtr store) {
+ xmlSecKeyStorePtr *ss;
+
+ xmlSecAssert(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId));
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert((ss != NULL) && (*ss != NULL));
+
+ xmlSecKeyStoreDestroy(*ss);
+}
+
+static xmlSecKeyPtr
+xmlSecNssKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyStorePtr* ss;
+ xmlSecKeyPtr key = NULL;
+ xmlSecKeyPtr retval = NULL;
+ xmlSecKeyReqPtr keyReq = NULL;
+ CERTCertificate *cert = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ xmlSecKeyDataPtr data = NULL;
+ xmlSecKeyDataPtr x509Data = NULL;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ss = xmlSecNssKeysStoreGetSS(store);
+ xmlSecAssert2(((ss != NULL) && (*ss != NULL)), NULL);
+
+ key = xmlSecKeyStoreFindKey(*ss, name, keyInfoCtx);
+ if (key != NULL) {
+ return (key);
+ }
+
+ /* Try to find the key in the NSS DB, and construct an xmlSecKey.
+ * we must have a name to lookup keys in NSS DB.
+ */
+ if (name == NULL) {
+ goto done;
+ }
+
+ /* what type of key are we looking for?
+ * TBD: For now, we'll look only for public/private keys using the
+ * name as a cert nickname. Later on, we can attempt to find
+ * symmetric keys using PK11_FindFixedKey
+ */
+ keyReq = &(keyInfoCtx->keyReq);
+ if (keyReq->keyType &
+ (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) {
+ cert = CERT_FindCertByNickname (CERT_GetDefaultCertDB(), (char *)name);
+ if (cert == NULL) {
+ goto done;
+ }
+
+ if (keyReq->keyType & xmlSecKeyDataTypePublic) {
+ pubkey = CERT_ExtractPublicKey(cert);
+ if (pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ if (keyReq->keyType & xmlSecKeyDataTypePrivate) {
+ privkey = PK11_FindKeyByAnyCert(cert, NULL);
+ if (privkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_FindKeyByAnyCert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ data = xmlSecNssPKIAdoptKey(privkey, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ privkey = NULL;
+ pubkey = NULL;
+
+ key = xmlSecKeyCreate();
+ if (key == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id);
+ if(x509Data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "transform=%s",
+ xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
+ goto done;
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, cert);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ cert = CERT_DupCertificate(cert);
+ if (cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(x509Data, cert);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ cert = NULL;
+
+ ret = xmlSecKeySetValue(key, data);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
+ goto done;
+ }
+ data = NULL;
+
+ ret = xmlSecKeyAdoptData(key, x509Data);
+ if (ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyAdoptData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "data=%s",
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+ goto done;
+ }
+ x509Data = NULL;
+
+ retval = key;
+ key = NULL;
+ }
+
+done:
+ if (cert != NULL) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ if (x509Data != NULL) {
+ xmlSecKeyDataDestroy(x509Data);
+ }
+ if (key != NULL) {
+ xmlSecKeyDestroy(key);
+ }
+
+ return (retval);
+}
diff --git a/src/nss/keytrans.c b/src/nss/keytrans.c
new file mode 100644
index 00000000..d84593b9
--- /dev/null
+++ b/src/nss/keytrans.c
@@ -0,0 +1,753 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright .................................
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+#include <keyhi.h>
+#include <key.h>
+#include <hasht.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/pkikeys.h>
+
+/*********************************************************************
+ *
+ * Key transport transforms
+ *
+ ********************************************************************/
+typedef struct _xmlSecNssKeyTransportCtx xmlSecNssKeyTransportCtx;
+typedef struct _xmlSecNssKeyTransportCtx* xmlSecNssKeyTransportCtxPtr;
+
+#define xmlSecNssKeyTransportSize \
+ ( sizeof( xmlSecTransform ) + sizeof( xmlSecNssKeyTransportCtx ) )
+#define xmlSecNssKeyTransportGetCtx( transform ) \
+ ( ( xmlSecNssKeyTransportCtxPtr )( ( ( xmlSecByte* )( transform ) ) + sizeof( xmlSecTransform ) ) )
+
+struct _xmlSecNssKeyTransportCtx {
+ CK_MECHANISM_TYPE cipher ;
+ SECKEYPublicKey* pubkey ;
+ SECKEYPrivateKey* prikey ;
+ xmlSecKeyDataId keyId ;
+ xmlSecBufferPtr material ; /* to be encrypted/decrypted material */
+} ;
+
+static int xmlSecNssKeyTransportInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssKeyTransportFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssKeyTransportSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKeyTransportSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKeyTransportExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecNssKeyTransportCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaPkcs1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_RSA */
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+#ifndef XMLSEC_NO_RSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaOaepId)) {
+ return (1);
+ }
+#endif /* XMLSEC_NO_RSA */
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
+ /* not found */
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssKeyTransportCtxPtr context ;
+ xmlSecAssert2(xmlSecNssKeyTransportCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize), -1);
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ xmlSecAssert2( context != NULL , -1 ) ;
+
+ /* initialize context */
+ memset(context, 0, sizeof(xmlSecNssKeyTransportCtx));
+
+#ifndef XMLSEC_NO_RSA
+ if(transform->id == xmlSecNssTransformRsaPkcs1Id) {
+ context->cipher = CKM_RSA_PKCS;
+ context->keyId = xmlSecNssKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_RSA */
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+#ifndef XMLSEC_NO_RSA
+ if(transform->id == xmlSecNssTransformRsaOaepId) {
+ context->cipher = CKM_RSA_PKCS_OAEP;
+ context->keyId = xmlSecNssKeyDataRsaId;
+ } else
+#endif /* XMLSEC_NO_RSA */
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
+ /* not found */
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKeyTransportFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssKeyTransportCtxPtr context ;
+
+ xmlSecAssert(xmlSecNssKeyTransportCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize));
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ xmlSecAssert( context != NULL ) ;
+
+ if( context->pubkey != NULL ) {
+ SECKEY_DestroyPublicKey( context->pubkey ) ;
+ context->pubkey = NULL ;
+ }
+
+ if( context->prikey != NULL ) {
+ SECKEY_DestroyPrivateKey( context->prikey ) ;
+ context->prikey = NULL ;
+ }
+
+ if( context->material != NULL ) {
+ xmlSecBufferDestroy(context->material);
+ context->material = NULL ;
+ }
+}
+
+static int
+xmlSecNssKeyTransportSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssKeyTransportCtxPtr context ;
+
+ xmlSecAssert2(xmlSecNssKeyTransportCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ xmlSecAssert2( context != NULL , -1 ) ;
+
+ keyReq->keyId = context->keyId;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssKeyTransportCtxPtr context = NULL ;
+ xmlSecKeyDataPtr keyData = NULL ;
+ SECKEYPublicKey* pubkey = NULL ;
+ SECKEYPrivateKey* prikey = NULL ;
+
+ xmlSecAssert2(xmlSecNssKeyTransportCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKeyTransportSize), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ if( (context == NULL) || (context->keyId == NULL) || (context->pubkey != NULL) ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportGetCtx" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ xmlSecAssert2( xmlSecKeyCheckId( key, context->keyId ), -1 ) ;
+
+ keyData = xmlSecKeyGetValue( key ) ;
+ if( keyData == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyGetName( key ) ) ,
+ "xmlSecKeyGetValue" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ if( ( pubkey = xmlSecNssPKIKeyDataGetPubKey( keyData ) ) == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataGetName( keyData ) ) ,
+ "xmlSecNssPKIKeyDataGetPubKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ context->pubkey = pubkey ;
+ } else {
+ if( ( prikey = xmlSecNssPKIKeyDataGetPrivKey( keyData ) ) == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecKeyDataGetName( keyData ) ) ,
+ "xmlSecNssPKIKeyDataGetPrivKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ context->prikey = prikey ;
+ }
+
+ return(0) ;
+}
+
+static int
+xmlSecNssKeyTransportCtxInit(
+ xmlSecNssKeyTransportCtxPtr ctx ,
+ xmlSecBufferPtr in ,
+ xmlSecBufferPtr out ,
+ int encrypt ,
+ xmlSecTransformCtxPtr transformCtx
+) {
+ int blockSize ;
+
+ xmlSecAssert2( ctx != NULL , -1 ) ;
+ xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ;
+ xmlSecAssert2( ( ctx->pubkey != NULL && encrypt ) || ( ctx->prikey != NULL && !encrypt ), -1 ) ;
+ xmlSecAssert2( ctx->keyId != NULL , -1 ) ;
+ xmlSecAssert2( in != NULL , -1 ) ;
+ xmlSecAssert2( out != NULL , -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ if( ctx->material != NULL ) {
+ xmlSecBufferDestroy( ctx->material ) ;
+ ctx->material = NULL ;
+ }
+
+ if( ctx->pubkey != NULL ) {
+ blockSize = SECKEY_PublicKeyStrength( ctx->pubkey ) ;
+ } else if( ctx->prikey != NULL ) {
+ blockSize = PK11_SignatureLen( ctx->prikey ) ;
+ } else {
+ blockSize = -1 ;
+ }
+
+ if( blockSize < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ ctx->material = xmlSecBufferCreate( blockSize ) ;
+ if( ctx->material == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferCreate" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ /* read raw key material into context */
+ if( xmlSecBufferSetData( ctx->material, xmlSecBufferGetData(in), xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferSetData" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferRemoveHead( in , xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferRemoveHead" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportCtxUpdate(
+ xmlSecNssKeyTransportCtxPtr ctx ,
+ xmlSecBufferPtr in ,
+ xmlSecBufferPtr out ,
+ int encrypt ,
+ xmlSecTransformCtxPtr transformCtx
+) {
+ xmlSecAssert2( ctx != NULL , -1 ) ;
+ xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ;
+ xmlSecAssert2( ( ctx->pubkey != NULL && encrypt ) || ( ctx->prikey != NULL && !encrypt ), -1 ) ;
+ xmlSecAssert2( ctx->keyId != NULL , -1 ) ;
+ xmlSecAssert2( ctx->material != NULL , -1 ) ;
+ xmlSecAssert2( in != NULL , -1 ) ;
+ xmlSecAssert2( out != NULL , -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ /* read raw key material and append into context */
+ if( xmlSecBufferAppend( ctx->material, xmlSecBufferGetData(in), xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferAppend" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferRemoveHead( in , xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferRemoveHead" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportCtxFinal(xmlSecNssKeyTransportCtxPtr ctx, xmlSecBufferPtr in, xmlSecBufferPtr out,
+ int encrypt, xmlSecTransformCtxPtr transformCtx) {
+ PK11SymKey* symKey ;
+ PK11SlotInfo* slot ;
+ SECItem oriskv ;
+ int blockSize ;
+ xmlSecBufferPtr result ;
+
+ xmlSecAssert2( ctx != NULL , -1 ) ;
+ xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ;
+ xmlSecAssert2( ( ctx->pubkey != NULL && encrypt ) || ( ctx->prikey != NULL && !encrypt ), -1 ) ;
+ xmlSecAssert2( ctx->keyId != NULL , -1 ) ;
+ xmlSecAssert2( ctx->material != NULL , -1 ) ;
+ xmlSecAssert2( in != NULL , -1 ) ;
+ xmlSecAssert2( out != NULL , -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ /* read raw key material and append into context */
+ if( xmlSecBufferAppend( ctx->material, xmlSecBufferGetData(in), xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferAppend" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferRemoveHead( in , xmlSecBufferGetSize(in) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferRemoveHead" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ /* Now we get all of the key materail */
+ /* from now on we will wrap or unwrap the key */
+ if( ctx->pubkey != NULL ) {
+ blockSize = SECKEY_PublicKeyStrength( ctx->pubkey ) ;
+ } else if( ctx->prikey != NULL ) {
+ blockSize = PK11_SignatureLen( ctx->prikey ) ;
+ } else {
+ blockSize = -1 ;
+ }
+
+ if( blockSize < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_GetBlockSize" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ result = xmlSecBufferCreate( blockSize * 2 ) ;
+ if( result == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL,
+ "xmlSecBufferCreate" ,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return(-1);
+ }
+
+ oriskv.type = siBuffer ;
+ oriskv.data = xmlSecBufferGetData( ctx->material ) ;
+ oriskv.len = xmlSecBufferGetSize( ctx->material ) ;
+
+ if( encrypt != 0 ) {
+ CK_OBJECT_HANDLE id ;
+ SECItem wrpskv ;
+
+ /* Create template symmetric key from material */
+ slot = ctx->pubkey->pkcs11Slot;
+ if( slot == NULL ) {
+ slot = PK11_GetBestSlot( ctx->cipher, NULL ) ;
+ if( slot == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecNssSlotGet" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ id = PK11_ImportPublicKey( slot, ctx->pubkey, PR_FALSE ) ;
+ if( id == CK_INVALID_HANDLE ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_ImportPublicKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+ }
+
+ /* pay attention to mechanism */
+ symKey = PK11_ImportSymKey( slot, ctx->cipher, PK11_OriginUnwrap, CKA_WRAP, &oriskv, NULL ) ;
+ if( symKey == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_ImportSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+
+ wrpskv.type = siBuffer ;
+ wrpskv.data = xmlSecBufferGetData( result ) ;
+ wrpskv.len = xmlSecBufferGetMaxSize( result ) ;
+
+ if( PK11_PubWrapSymKey( ctx->cipher, ctx->pubkey, symKey, &wrpskv ) != SECSuccess ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_PubWrapSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+
+ if( xmlSecBufferSetSize( result , wrpskv.len ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferSetSize" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ PK11_FreeSlot( slot ) ;
+ return(-1);
+ }
+ PK11_FreeSymKey( symKey ) ;
+ PK11_FreeSlot( slot ) ;
+ } else {
+ SECItem* keyItem ;
+
+ /* pay attention to mechanism */
+ symKey = PK11_PubUnwrapSymKey( ctx->prikey, &oriskv, ctx->cipher, CKA_UNWRAP, 0 );
+ if( symKey == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_PubUnwrapSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ /* Extract raw data from symmetric key */
+ if( PK11_ExtractKeyValue( symKey ) != SECSuccess ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_ExtractKeyValue" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ keyItem = PK11_GetKeyData( symKey );
+ if( keyItem == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_GetKeyData" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+
+ if( xmlSecBufferSetData( result, keyItem->data, keyItem->len ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "PK11_PubUnwrapSymKey" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ PK11_FreeSymKey( symKey ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+ PK11_FreeSymKey( symKey ) ;
+ }
+
+ /* Write output */
+ if( xmlSecBufferAppend( out, xmlSecBufferGetData(result), xmlSecBufferGetSize(result) ) < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ "xmlSecBufferAppend" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ xmlSecBufferDestroy(result);
+ return(-1);
+ }
+ xmlSecBufferDestroy(result);
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyTransportExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssKeyTransportCtxPtr context = NULL ;
+ xmlSecBufferPtr inBuf, outBuf ;
+ int operation ;
+ int rtv ;
+
+ xmlSecAssert2( xmlSecNssKeyTransportCheckId( transform ), -1 ) ;
+ xmlSecAssert2( xmlSecTransformCheckSize( transform, xmlSecNssKeyTransportSize ), -1 ) ;
+ xmlSecAssert2( ( transform->operation == xmlSecTransformOperationEncrypt ) || ( transform->operation == xmlSecTransformOperationDecrypt ), -1 ) ;
+ xmlSecAssert2( transformCtx != NULL , -1 ) ;
+
+ context = xmlSecNssKeyTransportGetCtx( transform ) ;
+ if( context == NULL ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportGetCtx" ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+
+ inBuf = &( transform->inBuf ) ;
+ outBuf = &( transform->outBuf ) ;
+
+ if( transform->status == xmlSecTransformStatusNone ) {
+ transform->status = xmlSecTransformStatusWorking ;
+ }
+
+ operation = ( transform->operation == xmlSecTransformOperationEncrypt ) ? 1 : 0 ;
+ if( transform->status == xmlSecTransformStatusWorking ) {
+ if( context->material == NULL ) {
+ rtv = xmlSecNssKeyTransportCtxInit( context, inBuf , outBuf , operation , transformCtx ) ;
+ if( rtv < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportCtxInit" ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ }
+
+ if( (context->material == NULL) && (last != 0) ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ NULL ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ "No enough data to intialize transform" ) ;
+ return(-1);
+ }
+
+ if( context->material != NULL ) {
+ rtv = xmlSecNssKeyTransportCtxUpdate( context, inBuf , outBuf , operation , transformCtx ) ;
+ if( rtv < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportCtxUpdate" ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ }
+
+ if( last ) {
+ rtv = xmlSecNssKeyTransportCtxFinal( context, inBuf , outBuf , operation , transformCtx ) ;
+ if( rtv < 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ "xmlSecNssKeyTransportCtxFinal" ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ XMLSEC_ERRORS_NO_MESSAGE ) ;
+ return(-1);
+ }
+ transform->status = xmlSecTransformStatusFinished ;
+ }
+ } else if( transform->status == xmlSecTransformStatusFinished ) {
+ if( xmlSecBufferGetSize( inBuf ) != 0 ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ NULL ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ "status=%d", transform->status ) ;
+ return(-1);
+ }
+ } else {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) ,
+ NULL ,
+ XMLSEC_ERRORS_R_INVALID_STATUS ,
+ "status=%d", transform->status ) ;
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+#ifndef XMLSEC_NO_RSA
+static xmlSecTransformKlass xmlSecNssRsaPkcs1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKeyTransportSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaPkcs1, /* const xmlChar* name; */
+ xmlSecHrefRsaPkcs1, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKeyTransportInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKeyTransportFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKeyTransportSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKeyTransportSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKeyTransportExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaPkcs1GetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaPkcs1GetKlass(void) {
+ return(&xmlSecNssRsaPkcs1Klass);
+}
+#endif /* XMLSEC_NO_RSA */
+
+/* aleksey, April 2010: NSS 3.12.6 has CKM_RSA_PKCS_OAEP algorithm but
+ it doesn't implement the SHA1 OAEP PKCS we need
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=158747
+*/
+#ifdef XMLSEC_NSS_RSA_OAEP_TODO
+#ifndef XMLSEC_NO_RSA
+static xmlSecTransformKlass xmlSecNssRsaOaepKlass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKeyTransportSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaOaep, /* const xmlChar* name; */
+ xmlSecHrefRsaOaep, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKeyTransportInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKeyTransportFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKeyTransportSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKeyTransportSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKeyTransportExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaOaepGetKlass:
+ *
+ * The RSA-PKCS1 key transport transform klass.
+ *
+ * Returns: RSA-PKCS1 key transport transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaOaepGetKlass(void) {
+ return(&xmlSecNssRsaOaepKlass);
+}
+#endif /* XMLSEC_NO_RSA */
+#endif /* XMLSEC_NSS_RSA_OAEP_TODO */
+
diff --git a/src/nss/kw_aes.c b/src/nss/kw_aes.c
new file mode 100644
index 00000000..0438e306
--- /dev/null
+++ b/src/nss/kw_aes.c
@@ -0,0 +1,681 @@
+/**
+ *
+ * XMLSec library
+ *
+ * AES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ * Copyright (C) 2010 Aleksey Sanin, All rights reserved.
+ */
+#ifndef XMLSEC_NO_AES
+
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+#include "../kw_aes_des.h"
+
+/*
+ * NSS needs to implement AES KW internally and then the code
+ * needs to change to use the direct implementation instead.
+ *
+ * Follow the NSS bug system for more details on the fix
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=213795
+ */
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecNSSKWAesBlockEncrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static int xmlSecNSSKWAesBlockDecrypt (const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize,
+ void * context);
+static xmlSecKWAesKlass xmlSecNssKWAesKlass = {
+ /* callbacks */
+ xmlSecNSSKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */
+ xmlSecNSSKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL /* void* reserved1; */
+};
+
+
+
+
+static PK11SymKey* xmlSecNssMakeAesKey (const xmlSecByte *key,
+ xmlSecSize keySize,
+ int enc);
+static int xmlSecNssAesOp (PK11SymKey *aeskey,
+ const xmlSecByte *in,
+ xmlSecByte *out,
+ int enc);
+
+
+/*********************************************************************
+ *
+ * AES KW transforms
+ *
+ ********************************************************************/
+typedef struct _xmlSecNssKWAesCtx xmlSecNssKWAesCtx,
+ *xmlSecNssKWAesCtxPtr;
+struct _xmlSecNssKWAesCtx {
+ xmlSecBuffer keyBuffer;
+ xmlSecSize keyExpectedSize;
+};
+#define xmlSecNssKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssKWAesCtx))
+#define xmlSecNssKWAesGetCtx(transform) \
+ ((xmlSecNssKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+#define xmlSecNssKWAesCheckId(transform) \
+ (xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes128Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes192Id) || \
+ xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes256Id))
+
+
+static int xmlSecNssKWAesInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssKWAesFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssKWAesSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKWAesSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKWAesExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static xmlSecTransformKlass xmlSecNssKWAes128Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes128, /* const xmlChar* name; */
+ xmlSecHrefKWAes128, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformKWAes128GetKlass:
+ *
+ * The AES-128 key wrapper transform klass.
+ *
+ * Returns: AES-128 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes128GetKlass(void) {
+ return(&xmlSecNssKWAes128Klass);
+}
+
+static xmlSecTransformKlass xmlSecNssKWAes192Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes192, /* const xmlChar* name; */
+ xmlSecHrefKWAes192, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformKWAes192GetKlass:
+ *
+ * The AES-192 key wrapper transform klass.
+ *
+ * Returns: AES-192 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes192GetKlass(void) {
+ return(&xmlSecNssKWAes192Klass);
+}
+
+static xmlSecTransformKlass xmlSecNssKWAes256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes256, /* const xmlChar* name; */
+ xmlSecHrefKWAes256, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformKWAes256GetKlass:
+ *
+ * The AES-256 key wrapper transform klass.
+ *
+ * Returns: AES-256 key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWAes256GetKlass(void) {
+ return(&xmlSecNssKWAes256Klass);
+}
+
+static int
+xmlSecNssKWAesInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssKWAesCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes128Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes192Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE;
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes256Id)) {
+ ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKWAesFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssKWAesCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssKWAesCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize));
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecNssKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssKWAesCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataAesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * ctx->keyExpectedSize;
+
+ return(0);
+}
+
+static int
+xmlSecNssKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssKWAesCtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataAesId), -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < ctx->keyExpectedSize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer),
+ xmlSecBufferGetData(buffer),
+ ctx->keyExpectedSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d",
+ ctx->keyExpectedSize);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssKWAesCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssKWAesGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == ctx->keyExpectedSize, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % 8) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d(not 8 bytes aligned)", inSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+ outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_KW_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ PK11SymKey *aeskey = NULL;
+
+ /* create key */
+ aeskey = xmlSecNssMakeAesKey(xmlSecBufferGetData(&(ctx->keyBuffer)), keySize, 1); /* encrypt */
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+
+ /* encrypt */
+ ret = xmlSecKWAesEncode(&xmlSecNssKWAesKlass, aeskey,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesEncode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSymKey(aeskey);
+ return(-1);
+ }
+
+ outSize = ret;
+ PK11_FreeSymKey(aeskey);
+ } else {
+ PK11SymKey *aeskey = NULL;
+
+ /* create key */
+ aeskey = xmlSecNssMakeAesKey(xmlSecBufferGetData(&(ctx->keyBuffer)), keySize, 0); /* decrypt */
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* decrypt */
+ ret = xmlSecKWAesDecode(&xmlSecNssKWAesKlass, aeskey,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWAesDecode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_FreeSymKey(aeskey);
+ return(-1);
+ }
+
+ outSize = ret;
+ PK11_FreeSymKey(aeskey);
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "inSize%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+/*********************************************************************
+ *
+ * AES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecNSSKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ PK11SymKey *aeskey = (PK11SymKey *)context;
+ int ret;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(aeskey != NULL, -1);
+
+ /* one block */
+ ret = xmlSecNssAesOp(aeskey, in, out, 1); /* encrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(XMLSEC_KW_AES_BLOCK_SIZE);
+}
+
+static int
+xmlSecNSSKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize,
+ void * context) {
+ PK11SymKey *aeskey = (PK11SymKey *)context;
+ int ret;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(aeskey != NULL, -1);
+
+ /* one block */
+ ret = xmlSecNssAesOp(aeskey, in, out, 0); /* decrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(XMLSEC_KW_AES_BLOCK_SIZE);
+}
+
+static PK11SymKey *
+xmlSecNssMakeAesKey(const xmlSecByte *key, xmlSecSize keySize, int enc) {
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* aeskey = NULL;
+ SECItem keyItem;
+
+ xmlSecAssert2(key != NULL, NULL);
+ xmlSecAssert2(keySize > 0, NULL);
+
+ cipherMech = CKM_AES_ECB;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyItem.data = (unsigned char *)key;
+ keyItem.len = keySize;
+ aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ if (aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+done:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+
+ return(aeskey);
+}
+
+/* encrypt a block (XMLSEC_KW_AES_BLOCK_SIZE), in and out can overlap */
+static int
+xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out, int enc) {
+
+ CK_MECHANISM_TYPE cipherMech;
+ SECItem* SecParam = NULL;
+ PK11Context* EncContext = NULL;
+ SECStatus rv;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+ int ret = -1;
+
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ cipherMech = CKM_AES_ECB;
+ SecParam = PK11_ParamFromIV(cipherMech, NULL);
+ if (SecParam == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ EncContext = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ aeskey, SecParam);
+ if (EncContext == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ rv = PK11_CipherOp(EncContext, out, &tmp1_outlen,
+ XMLSEC_KW_AES_BLOCK_SIZE, (unsigned char *)in,
+ XMLSEC_KW_AES_BLOCK_SIZE);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
+ &tmp2_outlen, XMLSEC_KW_AES_BLOCK_SIZE-tmp1_outlen);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* done - success! */
+ ret = 0;
+
+done:
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ }
+ if (EncContext) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ }
+
+ return (ret);
+}
+
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/nss/kw_des.c b/src/nss/kw_des.c
new file mode 100644
index 00000000..e75f69c9
--- /dev/null
+++ b/src/nss/kw_des.c
@@ -0,0 +1,663 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES KW Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#ifndef XMLSEC_NO_DES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11func.h>
+#include <hasht.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+#include "../kw_aes_des.h"
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int xmlSecNssKWDes3GenerateRandom (void * context,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3Sha1 (void * context,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3BlockEncrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+static int xmlSecNssKWDes3BlockDecrypt (void * context,
+ const xmlSecByte * iv,
+ xmlSecSize ivSize,
+ const xmlSecByte * in,
+ xmlSecSize inSize,
+ xmlSecByte * out,
+ xmlSecSize outSize);
+
+static xmlSecKWDes3Klass xmlSecNssKWDes3ImplKlass = {
+ /* callbacks */
+ xmlSecNssKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */
+ xmlSecNssKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */
+ xmlSecNssKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */
+ xmlSecNssKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */
+
+ /* for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static int xmlSecNssKWDes3Encrypt (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte *iv,
+ xmlSecSize ivSize,
+ const xmlSecByte *in,
+ xmlSecSize inSize,
+ xmlSecByte *out,
+ xmlSecSize outSize,
+ int enc);
+
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+typedef struct _xmlSecNssKWDes3Ctx xmlSecNssKWDes3Ctx,
+ *xmlSecNssKWDes3CtxPtr;
+struct _xmlSecNssKWDes3Ctx {
+ xmlSecBuffer keyBuffer;
+};
+#define xmlSecNssKWDes3Size \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssKWDes3Ctx))
+#define xmlSecNssKWDes3GetCtx(transform) \
+ ((xmlSecNssKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssKWDes3Initialize (xmlSecTransformPtr transform);
+static void xmlSecNssKWDes3Finalize (xmlSecTransformPtr transform);
+static int xmlSecNssKWDes3SetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKWDes3SetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKWDes3Execute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecNssKWDes3Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWDes3Size, /* xmlSecSize objSize */
+
+ xmlSecNameKWDes3, /* const xmlChar* name; */
+ xmlSecHrefKWDes3, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformKWDes3GetKlass(void) {
+ return(&xmlSecNssKWDes3Klass);
+}
+
+static int
+xmlSecNssKWDes3Initialize(xmlSecTransformPtr transform) {
+ xmlSecNssKWDes3CtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssKWDes3Finalize(xmlSecTransformPtr transform) {
+ xmlSecNssKWDes3CtxPtr ctx;
+
+ xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size));
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecNssKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssKWDes3CtxPtr ctx;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keyReq->keyId = xmlSecNssKeyDataDesId;
+ keyReq->keyType = xmlSecKeyDataTypeSymmetric;
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+ } else {
+ keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+ }
+ keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH;
+ return(0);
+}
+
+static int
+xmlSecNssKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssKWDes3CtxPtr ctx;
+ xmlSecBufferPtr buffer;
+ xmlSecSize keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataDesId), -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+ xmlSecAssert2(buffer != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(buffer);
+ if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key length %d is not enough (%d expected)",
+ keySize, XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", XMLSEC_KW_DES3_KEY_LENGTH);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssKWDes3CtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize, keySize;
+ int ret;
+
+ xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecNssTransformKWDes3Id), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWDes3Size), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssKWDes3GetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+ /* just do nothing */
+ } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "%d bytes - not %d bytes aligned",
+ inSize, XMLSEC_KW_DES3_BLOCK_LENGTH);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 16 bytes longer plus one block just in case */
+ outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH +
+ XMLSEC_KW_DES3_BLOCK_LENGTH;
+ } else {
+ /* just in case, add a block */
+ outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecKWDes3Encode(&xmlSecNssKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecKWDes3Decode(&xmlSecNssKWDes3ImplKlass, ctx,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKWDes3Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "key=%d,in=%d,out=%d",
+ keySize, inSize, outSize);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
+ } else if(transform->status == xmlSecTransformStatusFinished) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+ return(0);
+}
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecNssKWDes3Sha1(void * context,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ PK11Context *pk11ctx = NULL;
+ unsigned int outLen = 0;
+ SECStatus status;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= SHA1_LENGTH, -1);
+
+ /* Create a pk11ctx for hashing (digesting) */
+ pk11ctx = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (pk11ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateDigestContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ status = PK11_DigestBegin(pk11ctx);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestBegin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ return(-1);
+ }
+
+ status = PK11_DigestOp(pk11ctx, in, inSize);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ return(-1);
+ }
+
+ status = PK11_DigestFinal(pk11ctx, out, &outLen, outSize);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ return(-1);
+ }
+
+ /* done */
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ xmlSecAssert2(outLen == SHA1_LENGTH, -1);
+ return(outLen);
+}
+
+static int
+xmlSecNssKWDes3GenerateRandom(void * context,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ SECStatus status;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize > 0, -1);
+
+ status = PK11_GenerateRandom(out, outSize);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GenerateRandom",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return((int)outSize);
+}
+
+static int
+xmlSecNssKWDes3BlockEncrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecNssKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 1); /* encrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+static int
+xmlSecNssKWDes3BlockDecrypt(void * context,
+ const xmlSecByte * iv, xmlSecSize ivSize,
+ const xmlSecByte * in, xmlSecSize inSize,
+ xmlSecByte * out, xmlSecSize outSize) {
+ xmlSecNssKWDes3CtxPtr ctx = (xmlSecNssKWDes3CtxPtr)context;
+ int ret;
+
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+ xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ ret = xmlSecNssKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), XMLSEC_KW_DES3_KEY_LENGTH,
+ iv, XMLSEC_KW_DES3_IV_LENGTH,
+ in, inSize,
+ out, outSize,
+ 0); /* decrypt */
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssKWDes3Encrypt",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(ret);
+}
+
+
+
+static int
+xmlSecNssKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *iv, xmlSecSize ivSize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize,
+ int enc) {
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* symKey = NULL;
+ SECItem* param = NULL;
+ PK11Context* pk11ctx = NULL;
+ SECItem keyItem, ivItem;
+ SECStatus status;
+ int result_len = -1;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+ xmlSecAssert2(iv != NULL, -1);
+ xmlSecAssert2(ivSize == XMLSEC_KW_DES3_IV_LENGTH, -1);
+ xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize, -1);
+
+ cipherMech = CKM_DES3_CBC;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyItem.data = (unsigned char *)key;
+ keyItem.len = keySize;
+ symKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ if (symKey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ivItem.data = (unsigned char *)iv;
+ ivItem.len = ivSize;
+
+ param = PK11_ParamFromIV(cipherMech, &ivItem);
+ if (param == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ pk11ctx = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ symKey, param);
+ if (pk11ctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ status = PK11_CipherOp(pk11ctx, out, &tmp1_outlen, outSize,
+ (unsigned char *)in, inSize);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ status = PK11_DigestFinal(pk11ctx, out+tmp1_outlen,
+ &tmp2_outlen, outSize-tmp1_outlen);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ result_len = tmp1_outlen + tmp2_outlen;
+
+done:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (symKey) {
+ PK11_FreeSymKey(symKey);
+ }
+ if (param) {
+ SECITEM_FreeItem(param, PR_TRUE);
+ }
+ if (pk11ctx) {
+ PK11_DestroyContext(pk11ctx, PR_TRUE);
+ }
+
+ return(result_len);
+}
+
+
+#endif /* XMLSEC_NO_DES */
+
diff --git a/src/nss/pkikeys.c b/src/nss/pkikeys.c
new file mode 100644
index 00000000..ae9e29b4
--- /dev/null
+++ b/src/nss/pkikeys.c
@@ -0,0 +1,1554 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <pk11func.h>
+#include <keyhi.h>
+#include <pk11pqg.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/bignum.h>
+#include <xmlsec/nss/pkikeys.h>
+
+/**************************************************************************
+ *
+ * Internal NSS PKI key CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecNssPKIKeyDataCtx xmlSecNssPKIKeyDataCtx,
+ *xmlSecNssPKIKeyDataCtxPtr;
+struct _xmlSecNssPKIKeyDataCtx {
+ SECKEYPublicKey *pubkey;
+ SECKEYPrivateKey *privkey;
+};
+
+/******************************************************************************
+ *
+ * PKI key (dsa/rsa)
+ *
+ * xmlSecNssPKIKeyDataCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssPKIKeyDataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecNssPKIKeyDataCtx))
+#define xmlSecNssPKIKeyDataGetCtx(data) \
+ ((xmlSecNssPKIKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+
+static int xmlSecNssPKIKeyDataInitialize (xmlSecKeyDataPtr data);
+static void xmlSecNssPKIKeyDataFinalize (xmlSecKeyDataPtr data);
+
+
+static void xmlSecNSSPKIKeyDataCtxFree (xmlSecNssPKIKeyDataCtxPtr ctx);
+static int xmlSecNSSPKIKeyDataCtxDup (xmlSecNssPKIKeyDataCtxPtr ctxDst,
+ xmlSecNssPKIKeyDataCtxPtr ctxSrc);
+static int xmlSecNssPKIKeyDataAdoptKey (xmlSecKeyDataPtr data,
+ SECKEYPrivateKey *privkey,
+ SECKEYPublicKey *pubkey);
+
+
+static int
+xmlSecNssPKIKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), -1);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssPKIKeyDataCtx));
+
+ return(0);
+}
+
+
+static void
+xmlSecNssPKIKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataIsValid(data));
+ xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize));
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ xmlSecNSSPKIKeyDataCtxFree(ctx);
+ memset(ctx, 0, sizeof(xmlSecNssPKIKeyDataCtx));
+}
+
+
+static void
+xmlSecNSSPKIKeyDataCtxFree(xmlSecNssPKIKeyDataCtxPtr ctx)
+{
+ xmlSecAssert(ctx != NULL);
+ if (ctx->privkey != NULL) {
+ SECKEY_DestroyPrivateKey(ctx->privkey);
+ ctx->privkey = NULL;
+ }
+
+ if (ctx->pubkey)
+ {
+ SECKEY_DestroyPublicKey(ctx->pubkey);
+ ctx->pubkey = NULL;
+ }
+
+}
+
+static int
+xmlSecNSSPKIKeyDataCtxDup(xmlSecNssPKIKeyDataCtxPtr ctxDst,
+ xmlSecNssPKIKeyDataCtxPtr ctxSrc)
+{
+ xmlSecNSSPKIKeyDataCtxFree(ctxDst);
+ if (ctxSrc->privkey != NULL) {
+ ctxDst->privkey = SECKEY_CopyPrivateKey(ctxSrc->privkey);
+ if(ctxDst->privkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_CopyPrivateKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ if (ctxSrc->pubkey != NULL) {
+ ctxDst->pubkey = SECKEY_CopyPublicKey(ctxSrc->pubkey);
+ if(ctxDst->pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SECKEY_CopyPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+ return (0);
+}
+
+static int
+xmlSecNssPKIKeyDataAdoptKey(xmlSecKeyDataPtr data,
+ SECKEYPrivateKey *privkey,
+ SECKEYPublicKey *pubkey)
+{
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ KeyType pubType = nullKey ;
+ KeyType priType = nullKey ;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), -1);
+
+ if( privkey != NULL ) {
+ priType = SECKEY_GetPrivateKeyType( privkey ) ;
+ }
+
+ if( pubkey != NULL ) {
+ pubType = SECKEY_GetPublicKeyType( pubkey ) ;
+ }
+
+ if( priType != nullKey && pubType != nullKey ) {
+ if( pubType != priType ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ "different type of private and public key" ) ;
+ return -1 ;
+ }
+ }
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if (ctx->privkey) {
+ SECKEY_DestroyPrivateKey(ctx->privkey);
+ }
+ ctx->privkey = privkey;
+
+ if (ctx->pubkey) {
+ SECKEY_DestroyPublicKey(ctx->pubkey);
+ }
+ ctx->pubkey = pubkey;
+
+ return(0);
+}
+
+/**
+ * xmlSecNssPKIAdoptKey:
+ * @privkey: the NSS Private Key handle
+ * @pubkey: the NSS Public Key handle
+ *
+ * Build a KeyData object from the given Private Key and Public
+ * Key handles.
+ *
+ * Returns: pointer to KeyData object or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecNssPKIAdoptKey(SECKEYPrivateKey *privkey,
+ SECKEYPublicKey *pubkey)
+{
+ xmlSecKeyDataPtr data = NULL;
+ int ret;
+ KeyType pubType = nullKey ;
+ KeyType priType = nullKey ;
+
+ if( privkey != NULL ) {
+ priType = SECKEY_GetPrivateKeyType( privkey ) ;
+ }
+
+ if( pubkey != NULL ) {
+ pubType = SECKEY_GetPublicKeyType( pubkey ) ;
+ }
+
+ if( priType != nullKey && pubType != nullKey ) {
+ if( pubType != priType ) {
+ xmlSecError( XMLSEC_ERRORS_HERE ,
+ NULL ,
+ NULL ,
+ XMLSEC_ERRORS_R_CRYPTO_FAILED ,
+ "different type of private and public key" ) ;
+ return( NULL ) ;
+ }
+ }
+
+ pubType = priType != nullKey ? priType : pubType ;
+ switch(pubType) {
+#ifndef XMLSEC_NO_RSA
+ case rsaKey:
+ data = xmlSecKeyDataCreate(xmlSecNssKeyDataRsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssKeyDataRsaId");
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_RSA */
+#ifndef XMLSEC_NO_DSA
+ case dsaKey:
+ data = xmlSecKeyDataCreate(xmlSecNssKeyDataDsaId);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "xmlSecNssKeyDataDsaId");
+ return(NULL);
+ }
+ break;
+#endif /* XMLSEC_NO_DSA */
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TYPE,
+ "PKI key type %d not supported", pubType);
+ return(NULL);
+ }
+
+ xmlSecAssert2(data != NULL, NULL);
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ return(NULL);
+ }
+ return(data);
+}
+
+/**
+ * xmlSecNssPKIKeyDataGetPubKey:
+ * @data: the pointer to NSS Key data.
+ *
+ * Gets the Public Key from the key data.
+ *
+ * Returns: pointer to SECKEYPublicKey or NULL if an error occurs.
+ * Caller is responsible for freeing the key when done
+ */
+SECKEYPublicKey *
+xmlSecNssPKIKeyDataGetPubKey(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ SECKEYPublicKey *ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), NULL);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->pubkey != NULL, NULL);
+
+ ret = SECKEY_CopyPublicKey(ctx->pubkey);
+ return(ret);
+}
+
+/**
+ * xmlSecNssPKIKeyDataGetPrivKey:
+ * @data: the pointer to NSS Key data.
+ *
+ * Gets the Private Key from the key data.
+ *
+ * Returns: pointer to SECKEYPrivateKey or NULL if an error occurs.
+ * Caller is responsible for freeing the key when done
+ */
+SECKEYPrivateKey*
+xmlSecNssPKIKeyDataGetPrivKey(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ SECKEYPrivateKey* ret;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), NULL);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->privkey != NULL, NULL);
+
+ ret = SECKEY_CopyPrivateKey(ctx->privkey);
+ return(ret);
+}
+
+/**
+ * xmlSecNssPKIKeyDataGetKeyType:
+ * @data: the pointer to NSS Key data.
+ *
+ * Gets the Key Type from the key data.
+ *
+ * Returns: Key Type
+ */
+KeyType
+xmlSecNssPKIKeyDataGetKeyType(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ KeyType kt;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(data), nullKey);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), nullKey);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, nullKey);
+
+ if (ctx->pubkey != NULL) {
+ kt = SECKEY_GetPublicKeyType(ctx->pubkey);
+ } else {
+ kt = SECKEY_GetPrivateKeyType(ctx->privkey);
+ }
+ return(kt);
+}
+
+/**
+ * xmlSecNssPKIKeyDataDuplicate
+ * @dst: the pointer to NSS Key data to copy to.
+ * @src: the pointer to NSS Key data to copy from.
+ *
+ * Duplicates the keydata from src to dst
+ *
+ * Returns: -1 on error, 0 on success
+ */
+int
+xmlSecNssPKIKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecNssPKIKeyDataCtxPtr ctxDst;
+ xmlSecNssPKIKeyDataCtxPtr ctxSrc;
+
+ xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecNssPKIKeyDataSize), -1);
+ xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecNssPKIKeyDataSize), -1);
+
+ ctxDst = xmlSecNssPKIKeyDataGetCtx(dst);
+ xmlSecAssert2(ctxDst != NULL, -1);
+
+ ctxSrc = xmlSecNssPKIKeyDataGetCtx(src);
+ xmlSecAssert2(ctxSrc != NULL, -1);
+
+ if (xmlSecNSSPKIKeyDataCtxDup(ctxDst, ctxSrc) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssPKIKeydataCtxDup",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+/**************************************************************************
+ *
+ * <dsig:DSAKeyValue> processing
+ *
+ *
+ * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue)
+ *
+ * DSA keys and the DSA signature algorithm are specified in [DSS].
+ * DSA public key values can have the following fields:
+ *
+ * * P - a prime modulus meeting the [DSS] requirements
+ * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime
+ * divisor of P-1
+ * * G - an integer with certain properties with respect to P and Q
+ * * Y - G**X mod P (where X is part of the private key and not made
+ * public)
+ * * J - (P - 1) / Q
+ * * seed - a DSA prime generation seed
+ * * pgenCounter - a DSA prime generation counter
+ *
+ * Parameter J is available for inclusion solely for efficiency as it is
+ * calculatable from P and Q. Parameters seed and pgenCounter are used in the
+ * DSA prime number generation algorithm specified in [DSS]. As such, they are
+ * optional but must either both be present or both be absent. This prime
+ * generation algorithm is designed to provide assurance that a weak prime is
+ * not being used and it yields a P and Q value. Parameters P, Q, and G can be
+ * public and common to a group of users. They might be known from application
+ * context. As such, they are optional but P and Q must either both appear or
+ * both be absent. If all of P, Q, seed, and pgenCounter are present,
+ * implementations are not required to check if they are consistent and are
+ * free to use either P and Q or seed and pgenCounter. All parameters are
+ * encoded as base64 [MIME] values.
+ *
+ * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
+ * represented in XML as octet strings as defined by the ds:CryptoBinary type.
+ *
+ * Schema Definition:
+ *
+ * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
+ * <complexType name="DSAKeyValueType">
+ * <sequence>
+ * <sequence minOccurs="0">
+ * <element name="P" type="ds:CryptoBinary"/>
+ * <element name="Q" type="ds:CryptoBinary"/>
+ * </sequence>
+ * <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
+ * <element name="Y" type="ds:CryptoBinary"/>
+ * <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
+ * <sequence minOccurs="0">
+ * <element name="Seed" type="ds:CryptoBinary"/>
+ * <element name="PgenCounter" type="ds:CryptoBinary"/>
+ * </sequence>
+ * </sequence>
+ * </complexType>
+ *
+ * DTD Definition:
+ *
+ * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) >
+ * <!ELEMENT P (#PCDATA) >
+ * <!ELEMENT Q (#PCDATA) >
+ * <!ELEMENT G (#PCDATA) >
+ * <!ELEMENT Y (#PCDATA) >
+ * <!ELEMENT J (#PCDATA) >
+ * <!ELEMENT Seed (#PCDATA) >
+ * <!ELEMENT PgenCounter (#PCDATA) >
+ *
+ * ============================================================================
+ *
+ * To support reading/writing private keys an X element added (before Y).
+ * todo: The current implementation does not support Seed and PgenCounter!
+ * by this the P, Q and G are *required*!
+ *
+ *************************************************************************/
+static int xmlSecNssKeyDataDsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataDsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssKeyDataDsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataDsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataDsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataDsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecNssKeyDataDsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecNssKeyDataDsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecNssKeyDataDsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssKeyDataDsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataDsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecNssPKIKeyDataSize,
+
+ /* data */
+ xmlSecNameDSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssKeyDataDsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataDsaGetKlass(void) {
+ return(&xmlSecNssKeyDataDsaKlass);
+}
+
+
+static int
+xmlSecNssKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), -1);
+
+ return(xmlSecNssPKIKeyDataInitialize(data));
+}
+
+static int
+xmlSecNssKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataDsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataDsaId), -1);
+
+ return(xmlSecNssPKIKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecNssKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId));
+
+ xmlSecNssPKIKeyDataFinalize(data);
+}
+
+static int
+xmlSecNssKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data = NULL;
+ xmlNodePtr cur;
+ int ret;
+ PK11SlotInfo *slot = NULL;
+ CK_OBJECT_HANDLE handle;
+ SECKEYPublicKey *pubkey=NULL;
+ PRArenaPool *arena = NULL;
+
+
+ xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if(xmlSecKeyGetValue(key) != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ slot = PK11_GetBestSlot(CKM_DSA, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if(arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ ret = -1;
+ goto done;
+ }
+
+ pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(SECKEYPublicKey));
+ if(pubkey == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_ArenaZAlloc",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PORT_FreeArena(arena, PR_FALSE);
+ ret = -1;
+ goto done;
+ }
+ pubkey->arena = arena;
+ pubkey->u.dsa.params.arena = arena;
+ pubkey->keyType = dsaKey;
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.params.prime)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.params.subPrime)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.params.base)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * NSS does not support it, we just ignore it */
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* next is Y node. */
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.dsa.publicValue)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* todo: add support for J */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* todo: add support for seed */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ /* todo: add support for pgencounter */
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) {
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ handle = PK11_ImportPublicKey(slot, pubkey, PR_FALSE);
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ pubkey = NULL;
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ data = NULL;
+
+ ret = 0;
+
+done:
+ if (slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if (ret != 0) {
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (data != NULL) {
+ xmlSecKeyDataDestroy(data);
+ }
+ }
+ return(ret);
+}
+
+static int
+xmlSecNssKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataDsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(xmlSecKeyGetValue(key));
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1);
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* first is P node */
+ cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ return(-1);
+ }
+ ret = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.params.prime), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAP));
+ return(-1);
+ }
+
+ /* next is Q node. */
+ cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ return(-1);
+ }
+ ret = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.params.subPrime), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAQ));
+ return(-1);
+ }
+
+ /* next is G node. */
+ cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ return(-1);
+ }
+ ret = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.params.base), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAG));
+ return(-1);
+ }
+
+ /* next is X node: not supported in NSS */
+
+ /* next is Y node. */
+ cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ return(-1);
+ }
+ ret = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.dsa.publicValue), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeDSAY));
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ PQGParams *pqgParams = NULL;
+ PQGVerify *pqgVerify = NULL;
+ SECStatus rv;
+ SECStatus res;
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ int ret = -1;
+ int j;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ j = PQG_PBITS_TO_INDEX(sizeBits);
+ rv = PK11_PQG_ParamGen(j, &pqgParams, &pqgVerify);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_PQG_ParamGen",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", sizeBits);
+ goto done;
+ }
+
+ rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &res);
+ if (rv != SECSuccess || res != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_PQG_VerifyParams",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "size=%d", sizeBits);
+ goto done;
+ }
+
+ slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
+ PK11_Authenticate(slot, PR_TRUE, NULL /* default pwd callback */);
+ privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, pqgParams,
+ &pubkey, PR_FALSE, PR_TRUE, NULL);
+
+ if((privkey == NULL) || (pubkey == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_GenerateKeyPair",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if (pqgParams != NULL) {
+ PK11_PQG_DestroyParams(pqgParams);
+ }
+ if (pqgVerify != NULL) {
+ PK11_PQG_DestroyVerify(pqgVerify);
+ }
+ if (ret == 0) {
+ return (0);
+ }
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ return(-1);
+}
+
+static xmlSecKeyDataType
+xmlSecNssKeyDataDsaGetType(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), xmlSecKeyDataTypeUnknown);
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1);
+ if (ctx->privkey != NULL) {
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else {
+ return(xmlSecKeyDataTypePublic);
+ }
+
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecNssKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), 0);
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1);
+
+ return(8 * SECKEY_PublicKeyStrength(ctx->pubkey));
+}
+
+static void
+xmlSecNssKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== dsa key: size = %d\n",
+ xmlSecNssKeyDataDsaGetSize(data));
+}
+
+static void
+xmlSecNssKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
+ xmlSecNssKeyDataDsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+/**************************************************************************
+ *
+ * <dsig:RSAKeyValue> processing
+ *
+ * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
+ * The RSAKeyValue Element
+ *
+ * RSA key values have two fields: Modulus and Exponent.
+ *
+ * <RSAKeyValue>
+ * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
+ * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
+ * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
+ * </Modulus>
+ * <Exponent>AQAB</Exponent>
+ * </RSAKeyValue>
+ *
+ * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
+ * represented in XML as octet strings as defined by the ds:CryptoBinary type.
+ *
+ * Schema Definition:
+ *
+ * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
+ * <complexType name="RSAKeyValueType">
+ * <sequence>
+ * <element name="Modulus" type="ds:CryptoBinary"/>
+ * <element name="Exponent" type="ds:CryptoBinary"/>
+ * </sequence>
+ * </complexType>
+ *
+ * DTD Definition:
+ *
+ * <!ELEMENT RSAKeyValue (Modulus, Exponent) >
+ * <!ELEMENT Modulus (#PCDATA) >
+ * <!ELEMENT Exponent (#PCDATA) >
+ *
+ * ============================================================================
+ *
+ * To support reading/writing private keys an PrivateExponent element is added
+ * to the end
+ *
+ *************************************************************************/
+
+static int xmlSecNssKeyDataRsaInitialize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataRsaDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssKeyDataRsaFinalize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataRsaXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataRsaXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataRsaGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecNssKeyDataRsaGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecNssKeyDataRsaGetSize (xmlSecKeyDataPtr data);
+static void xmlSecNssKeyDataRsaDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssKeyDataRsaDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataRsaKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecNssPKIKeyDataSize,
+
+ /* data */
+ xmlSecNameRSAKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
+ xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataRsaGetKlass:
+ *
+ * The RSA key data klass.
+ *
+ * Returns: pointer to RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataRsaGetKlass(void) {
+ return(&xmlSecNssKeyDataRsaKlass);
+}
+
+static int
+xmlSecNssKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), -1);
+
+ return(xmlSecNssPKIKeyDataInitialize(data));
+}
+
+static int
+xmlSecNssKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataRsaId), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataRsaId), -1);
+
+ return(xmlSecNssPKIKeyDataDuplicate(dst, src));
+}
+
+static void
+xmlSecNssKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId));
+
+ xmlSecNssPKIKeyDataFinalize(data);
+}
+
+static int
+xmlSecNssKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data = NULL;
+ xmlNodePtr cur;
+ int ret;
+ PK11SlotInfo *slot = NULL;
+ SECKEYPublicKey *pubkey=NULL;
+ PRArenaPool *arena = NULL;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ if(xmlSecKeyGetValue(key) != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA,
+ "key already has a value");
+ ret = -1;
+ goto done;
+ }
+
+ slot = PK11_GetBestSlot(CKM_RSA_PKCS, NULL);
+ if(slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if(arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ ret = -1;
+ goto done;
+ }
+
+ pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(SECKEYPublicKey));
+ if(pubkey == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "PORT_ArenaZAlloc",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PORT_FreeArena(arena, PR_FALSE);
+ ret = -1;
+ goto done;
+ }
+ pubkey->arena = arena;
+ pubkey->keyType = rsaKey;
+
+ cur = xmlSecGetNextElementNode(node->children);
+
+ /* first is Modulus node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.rsa.modulus)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is Exponent node. It is REQUIRED because we do not support Seed and PgenCounter*/
+ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ ret = -1;
+ goto done;
+ }
+ if(xmlSecNssNodeGetBigNumValue(arena, cur, &(pubkey->u.rsa.publicExponent)) == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeGetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ ret = -1;
+ goto done;
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
+ /* next is X node. It is REQUIRED for private key but
+ * NSS does not support it. We just ignore it */
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE,
+ "no nodes expected");
+ ret = -1;
+ goto done;
+ }
+
+ data = xmlSecKeyDataCreate(id);
+ if(data == NULL ) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyDataCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ ret = -1;
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ goto done;
+ }
+ pubkey = NULL;
+
+ ret = xmlSecKeySetValue(key, data);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(data);
+ goto done;
+ }
+ data = NULL;
+
+ ret = 0;
+
+done:
+ if (slot != 0) {
+ PK11_FreeSlot(slot);
+ }
+ if (ret != 0) {
+ if (pubkey != 0) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (data != 0) {
+ xmlSecKeyDataDestroy(data);
+ }
+ }
+ return(ret);
+}
+
+static int
+xmlSecNssKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataRsaId), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(xmlSecKeyGetValue(key));
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -1);
+
+
+ if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
+ /* we can have only private key or public key */
+ return(0);
+ }
+
+ /* first is Modulus node */
+ cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ return(-1);
+ }
+ ret = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.rsa.modulus), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
+ return(-1);
+ }
+
+ /* next is Exponent node. */
+ cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ return(-1);
+ }
+ ret = xmlSecNssNodeSetBigNumValue(cur, &(ctx->pubkey->u.rsa.publicExponent), 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssNodeSetBigNumValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
+ return(-1);
+ }
+
+ /* next is PrivateExponent node: not supported in NSS */
+
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ PK11RSAGenParams params;
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ int ret = -1;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ params.keySizeInBits = sizeBits;
+ params.pe = 65537;
+
+ slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, NULL);
+ PK11_Authenticate(slot, PR_TRUE, NULL /* default pwd callback */);
+ privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &params,
+ &pubkey, PR_FALSE, PR_TRUE, NULL);
+
+ if(privkey == NULL || pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PK11_GenerateKeyPair",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+
+ goto done;
+ }
+
+ ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssPKIKeyDataAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (slot != NULL) {
+ PK11_FreeSlot(slot);
+ }
+ if (ret == 0) {
+ return (0);
+ }
+
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (privkey != NULL) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ return(-1);
+}
+
+static xmlSecKeyDataType
+xmlSecNssKeyDataRsaGetType(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), xmlSecKeyDataTypeUnknown);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->pubkey == NULL || SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -1);
+ if (ctx->privkey != NULL) {
+ return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
+ } else {
+ return(xmlSecKeyDataTypePublic);
+ }
+
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecNssKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
+ xmlSecNssPKIKeyDataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), 0);
+
+ ctx = xmlSecNssPKIKeyDataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -1);
+
+ return(8 * SECKEY_PublicKeyStrength(ctx->pubkey));
+}
+
+static void
+xmlSecNssKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== rsa key: size = %d\n",
+ xmlSecNssKeyDataRsaGetSize(data));
+}
+
+static void
+xmlSecNssKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
+ xmlSecNssKeyDataRsaGetSize(data));
+}
+
+#endif /* XMLSEC_NO_RSA */
+
+
+
diff --git a/src/nss/signatures.c b/src/nss/signatures.c
new file mode 100644
index 00000000..4f54170e
--- /dev/null
+++ b/src/nss/signatures.c
@@ -0,0 +1,841 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <secerr.h>
+#include <prmem.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/pkikeys.h>
+
+
+/**************************************************************************
+ *
+ * Internal NSS signatures ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecNssSignatureCtx xmlSecNssSignatureCtx,
+ *xmlSecNssSignatureCtxPtr;
+struct _xmlSecNssSignatureCtx {
+ xmlSecKeyDataId keyId;
+ SECOidTag alg;
+
+ union {
+ struct {
+ SGNContext *sigctx;
+ SECKEYPrivateKey *privkey;
+ } sig;
+
+ struct {
+ VFYContext *vfyctx;
+ SECKEYPublicKey *pubkey;
+ } vfy;
+ } u;
+};
+
+/******************************************************************************
+ *
+ * Signature transforms
+ *
+ * xmlSecNssSignatureCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecNssSignatureSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecNssSignatureCtx))
+#define xmlSecNssSignatureGetCtx(transform) \
+ ((xmlSecNssSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecNssSignatureCheckId (xmlSecTransformPtr transform);
+static int xmlSecNssSignatureInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssSignatureFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssSignatureSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssSignatureSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssSignatureVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecNssSignatureExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecNssSignatureCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformDsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaMd5Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha1Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha256Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha384Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha512Id)) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ return(0);
+}
+
+static int
+xmlSecNssSignatureInitialize(xmlSecTransformPtr transform) {
+ xmlSecNssSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssSignatureCtx));
+
+#ifndef XMLSEC_NO_DSA
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformDsaSha1Id)) {
+ ctx->keyId = xmlSecNssKeyDataDsaId;
+ /* This creates a signature which is ASN1 encoded */
+ ctx->alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+ } else
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaMd5Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha1Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha256Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha384Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformRsaSha512Id)) {
+ ctx->keyId = xmlSecNssKeyDataRsaId;
+ ctx->alg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static void
+xmlSecNssSignatureFinalize(xmlSecTransformPtr transform) {
+ xmlSecNssSignatureCtxPtr ctx;
+
+ xmlSecAssert(xmlSecNssSignatureCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize));
+ xmlSecAssert((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify));
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if (transform->operation == xmlSecTransformOperationSign) {
+ SGN_DestroyContext(ctx->u.sig.sigctx, PR_TRUE);
+ if (ctx->u.sig.privkey) {
+ SECKEY_DestroyPrivateKey(ctx->u.sig.privkey);
+ }
+ } else {
+ VFY_DestroyContext(ctx->u.vfy.vfyctx, PR_TRUE);
+ if (ctx->u.vfy.pubkey) {
+ SECKEY_DestroyPublicKey(ctx->u.vfy.pubkey);
+ }
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssSignatureCtx));
+}
+
+static int
+xmlSecNssSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecNssSignatureCtxPtr ctx;
+ xmlSecKeyDataPtr value;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ value = xmlSecKeyGetValue(key);
+ xmlSecAssert2(value != NULL, -1);
+
+ if (transform->operation == xmlSecTransformOperationSign) {
+ if (ctx->u.sig.privkey)
+ SECKEY_DestroyPrivateKey(ctx->u.sig.privkey);
+ ctx->u.sig.privkey = xmlSecNssPKIKeyDataGetPrivKey(value);
+ if(ctx->u.sig.privkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssPKIKeyDataGetPrivKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->u.sig.sigctx = SGN_NewContext(ctx->alg, ctx->u.sig.privkey);
+ if (ctx->u.sig.sigctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_NewContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ } else {
+ if (ctx->u.vfy.pubkey)
+ SECKEY_DestroyPublicKey(ctx->u.vfy.pubkey);
+ ctx->u.vfy.pubkey = xmlSecNssPKIKeyDataGetPubKey(value);
+ if(ctx->u.vfy.pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssPKIKeyDataGetPubKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ctx->u.vfy.vfyctx = VFY_CreateContext(ctx->u.vfy.pubkey, NULL,
+ ctx->alg, NULL);
+ if (ctx->u.vfy.vfyctx == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_CreateContext",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecNssSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+
+ keyReq->keyId = ctx->keyId;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+ return(0);
+}
+
+
+static int
+xmlSecNssSignatureVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssSignatureCtxPtr ctx;
+ SECStatus status;
+ SECItem signature;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ signature.data = (unsigned char *)data;
+ signature.len = dataSize;
+
+ if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
+ /* This creates a signature which is ASN1 encoded */
+ SECItem signatureDer;
+ SECStatus statusDer;
+
+ statusDer = DSAU_EncodeDerSig(&signatureDer, &signature);
+ if(statusDer != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "DSAU_EncodeDerSig",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d",
+ PORT_GetError());
+ return(-1);
+ }
+ status = VFY_EndWithSignature(ctx->u.vfy.vfyctx, &signatureDer);
+ SECITEM_FreeItem(&signatureDer, PR_FALSE);
+ } else {
+ status = VFY_EndWithSignature(ctx->u.vfy.vfyctx, &signature);
+ }
+
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_EndWithSignature",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d",
+ PORT_GetError());
+
+ if (PORT_GetError() == SEC_ERROR_PKCS7_BAD_SIGNATURE) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_EndWithSignature",
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "signature does not verify");
+ transform->status = xmlSecTransformStatusFail;
+ }
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusOk;
+ return(0);
+}
+
+static int
+xmlSecNssSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecNssSignatureCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize, outSize;
+ SECStatus status;
+ SECItem signature;
+ int ret;
+
+ xmlSecAssert2(xmlSecNssSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssSignatureSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ ctx = xmlSecNssSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ if(transform->operation == xmlSecTransformOperationSign) {
+ xmlSecAssert2(ctx->u.sig.sigctx != NULL, -1);
+ xmlSecAssert2(ctx->u.sig.privkey != NULL, -1);
+ } else {
+ xmlSecAssert2(ctx->u.vfy.vfyctx != NULL, -1);
+ xmlSecAssert2(ctx->u.vfy.pubkey != NULL, -1);
+ }
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ status = SGN_Begin(ctx->u.sig.sigctx);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_Begin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ } else {
+ status = VFY_Begin(ctx->u.vfy.vfyctx);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_Begin",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (inSize > 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ if(transform->operation == xmlSecTransformOperationSign) {
+ status = SGN_Update(ctx->u.sig.sigctx, xmlSecBufferGetData(in), inSize);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_Update",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ } else {
+ status = VFY_Update(ctx->u.vfy.vfyctx, xmlSecBufferGetData(in), inSize);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "VFY_Update",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+ xmlSecAssert2(outSize == 0, -1);
+ if(transform->operation == xmlSecTransformOperationSign) {
+ memset(&signature, 0, sizeof(signature));
+ status = SGN_End(ctx->u.sig.sigctx, &signature);
+ if(status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "SGN_End",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
+ /* This creates a signature which is ASN1 encoded */
+ SECItem * signatureClr;
+
+ signatureClr = DSAU_DecodeDerSig(&signature);
+ if(signatureClr == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "DSAU_EncodeDerSig",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d",
+ PORT_GetError());
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ return(-1);
+ }
+
+ ret = xmlSecBufferSetData(out, signatureClr->data, signatureClr->len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ signatureClr->len);
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ return(-1);
+ }
+
+ SECITEM_FreeItem(signatureClr, PR_TRUE);
+ } else {
+ /* This signature is used as-is */
+ ret = xmlSecBufferSetData(out, signature.data, signature.len);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ signature.len);
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ return(-1);
+ }
+ }
+
+ /* cleanup */
+ SECITEM_FreeItem(&signature, PR_FALSE);
+ }
+ transform->status = xmlSecTransformStatusFinished;
+ }
+
+
+ if((transform->status == xmlSecTransformStatusWorking) || (transform->status == xmlSecTransformStatusFinished)) {
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
+ }
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+/****************************************************************************
+ *
+ * DSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+
+static xmlSecTransformKlass xmlSecNssDsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameDsaSha1, /* const xmlChar* name; */
+ xmlSecHrefDsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformDsaSha1GetKlass(void) {
+ return(&xmlSecNssDsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+/****************************************************************************
+ *
+ * RSA-MD5 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaMd5, /* const xmlChar* name; */
+ xmlSecHrefRsaMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaMd5GetKlass(void) {
+ return(&xmlSecNssRsaMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha1, /* const xmlChar* name; */
+ xmlSecHrefRsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha1GetKlass(void) {
+ return(&xmlSecNssRsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha256, /* const xmlChar* name; */
+ xmlSecHrefRsaSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha256GetKlass(void) {
+ return(&xmlSecNssRsaSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha384, /* const xmlChar* name; */
+ xmlSecHrefRsaSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha384GetKlass(void) {
+ return(&xmlSecNssRsaSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecNssRsaSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha512, /* const xmlChar* name; */
+ xmlSecHrefRsaSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecNssTransformRsaSha512GetKlass(void) {
+ return(&xmlSecNssRsaSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+
diff --git a/src/nss/symkeys.c b/src/nss/symkeys.c
new file mode 100644
index 00000000..3da7a694
--- /dev/null
+++ b/src/nss/symkeys.c
@@ -0,0 +1,440 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+
+/*****************************************************************************
+ *
+ * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary
+ *
+ ****************************************************************************/
+static int xmlSecNssSymKeyDataInitialize (xmlSecKeyDataPtr data);
+static int xmlSecNssSymKeyDataDuplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssSymKeyDataFinalize (xmlSecKeyDataPtr data);
+static int xmlSecNssSymKeyDataXmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataXmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataBinWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlSecByte** buf,
+ xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssSymKeyDataGenerate (xmlSecKeyDataPtr data,
+ xmlSecSize sizeBits,
+ xmlSecKeyDataType type);
+
+static xmlSecKeyDataType xmlSecNssSymKeyDataGetType (xmlSecKeyDataPtr data);
+static xmlSecSize xmlSecNssSymKeyDataGetSize (xmlSecKeyDataPtr data);
+static void xmlSecNssSymKeyDataDebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static int xmlSecNssSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass);
+
+#define xmlSecNssSymKeyDataCheckId(data) \
+ (xmlSecKeyDataIsValid((data)) && \
+ xmlSecNssSymKeyDataKlassCheck((data)->id))
+
+static int
+xmlSecNssSymKeyDataInitialize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), -1);
+
+ return(xmlSecKeyDataBinaryValueInitialize(data));
+}
+
+static int
+xmlSecNssSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(dst), -1);
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ return(xmlSecKeyDataBinaryValueDuplicate(dst, src));
+}
+
+static void
+xmlSecNssSymKeyDataFinalize(xmlSecKeyDataPtr data) {
+ xmlSecAssert(xmlSecNssSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueFinalize(data);
+}
+
+static int
+xmlSecNssSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlSecByte** buf, xmlSecSize* bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecAssert2(xmlSecNssSymKeyDataKlassCheck(id), -1);
+
+ return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx));
+}
+
+static int
+xmlSecNssSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), -1);
+ xmlSecAssert2(sizeBits > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecNssGenerateRandom(buffer, (sizeBits + 7) / 8));
+}
+
+static xmlSecKeyDataType
+xmlSecNssSymKeyDataGetType(xmlSecKeyDataPtr data) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown);
+
+ return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown);
+}
+
+static xmlSecSize
+xmlSecNssSymKeyDataGetSize(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecNssSymKeyDataCheckId(data), 0);
+
+ return(xmlSecKeyDataBinaryValueGetSize(data));
+}
+
+static void
+xmlSecNssSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecNssSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugDump(data, output);
+}
+
+static void
+xmlSecNssSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ xmlSecAssert(xmlSecNssSymKeyDataCheckId(data));
+
+ xmlSecKeyDataBinaryValueDebugXmlDump(data, output);
+}
+
+static int
+xmlSecNssSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) {
+#ifndef XMLSEC_NO_DES
+ if(klass == xmlSecNssKeyDataDesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+ if(klass == xmlSecNssKeyDataAesId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_HMAC
+ if(klass == xmlSecNssKeyDataHmacId) {
+ return(1);
+ }
+#endif /* XMLSEC_NO_HMAC */
+
+ return(0);
+}
+
+#ifndef XMLSEC_NO_AES
+/**************************************************************************
+ *
+ * <xmlsec:AESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecNssKeyDataAesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameAESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefAESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecNssSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataAesGetKlass:
+ *
+ * The AES key data klass.
+ *
+ * Returns: AES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataAesGetKlass(void) {
+ return(&xmlSecNssKeyDataAesKlass);
+}
+
+/**
+ * xmlSecNssKeyDataAesSet:
+ * @data: the pointer to AES key data.
+ * @buf: the pointer to key value.
+ * @bufSize: the key value size (in bytes).
+ *
+ * Sets the value of AES key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataAesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+#endif /* XMLSEC_NO_AES */
+
+#ifndef XMLSEC_NO_DES
+/**************************************************************************
+ *
+ * <xmlsec:DESKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecNssKeyDataDesKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameDESKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefDESKeyValue, /* const xmlChar* href; */
+ xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecNssSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataDesGetKlass:
+ *
+ * The DES key data klass.
+ *
+ * Returns: DES key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataDesGetKlass(void) {
+ return(&xmlSecNssKeyDataDesKlass);
+}
+
+/**
+ * xmlSecNssKeyDataDesSet:
+ * @data: the pointer to DES key data.
+ * @buf: the pointer to key value.
+ * @bufSize: the key value size (in bytes).
+ *
+ * Sets the value of DES key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDesId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_HMAC
+/**************************************************************************
+ *
+ * <xmlsec:HMACKeyValue> processing
+ *
+ *************************************************************************/
+static xmlSecKeyDataKlass xmlSecNssKeyDataHmacKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecKeyDataBinarySize,
+
+ /* data */
+ xmlSecNameHMACKeyValue,
+ xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefHMACKeyValue, /* const xmlChar* href; */
+ xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */
+ xmlSecNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ xmlSecNssSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ xmlSecNssSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ xmlSecNssSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataHmacGetKlass:
+ *
+ * The HMAC key data klass.
+ *
+ * Returns: HMAC key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataHmacGetKlass(void) {
+ return(&xmlSecNssKeyDataHmacKlass);
+}
+
+/**
+ * xmlSecNssKeyDataHmacSet:
+ * @data: the pointer to HMAC key data.
+ * @buf: the pointer to key value.
+ * @bufSize: the key value size (in bytes).
+ *
+ * Sets the value of HMAC key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) {
+ xmlSecBufferPtr buffer;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataHmacId), -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+
+ buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+ xmlSecAssert2(buffer != NULL, -1);
+
+ return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+#endif /* XMLSEC_NO_HMAC */
+
diff --git a/src/nss/x509.c b/src/nss/x509.c
new file mode 100644
index 00000000..887c77cf
--- /dev/null
+++ b/src/nss/x509.c
@@ -0,0 +1,2223 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+#include <prmem.h>
+#include <pratom.h>
+#include <keyhi.h>
+#include <cert.h>
+#include <certdb.h>
+#include <pk11func.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/x509.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+#include <xmlsec/nss/pkikeys.h>
+
+
+/* workaround - NSS exports this but doesn't declare it */
+extern CERTCertificate * __CERT_NewTempCertificate(CERTCertDBHandle *handle,
+ SECItem *derCert,
+ char *nickname,
+ PRBool isperm,
+ PRBool copyDER);
+
+/*************************************************************************
+ *
+ * X509 utility functions
+ *
+ ************************************************************************/
+static int xmlSecNssX509DataNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CertificateNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CertificateNodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SubjectNameNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SubjectNameNodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509IssuerSerialNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509IssuerSerialNodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SKINodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509SKINodeWrite (CERTCertificate* cert,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CRLNodeRead (xmlSecKeyDataPtr data,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssX509CRLNodeWrite (CERTSignedCrl* crl,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data,
+ xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static CERTCertificate* xmlSecNssX509CertDerRead (const xmlSecByte* buf,
+ xmlSecSize size);
+static CERTCertificate* xmlSecNssX509CertBase64DerRead (xmlChar* buf);
+static xmlChar* xmlSecNssX509CertBase64DerWrite (CERTCertificate* cert,
+ int base64LineWrap);
+static CERTSignedCrl* xmlSecNssX509CrlDerRead (xmlSecByte* buf,
+ xmlSecSize size,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static CERTSignedCrl* xmlSecNssX509CrlBase64DerRead (xmlChar* buf,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlChar* xmlSecNssX509CrlBase64DerWrite (CERTSignedCrl* crl,
+ int base64LineWrap);
+static xmlChar* xmlSecNssX509NameWrite (CERTName* nm);
+static xmlChar* xmlSecNssASN1IntegerWrite (SECItem *num);
+static xmlChar* xmlSecNssX509SKIWrite (CERTCertificate* cert);
+static void xmlSecNssX509CertDebugDump (CERTCertificate* cert,
+ FILE* output);
+static void xmlSecNssX509CertDebugXmlDump (CERTCertificate* cert,
+ FILE* output);
+static int xmlSecNssX509CertGetTime (PRTime* t,
+ time_t* res);
+
+/*************************************************************************
+ *
+ * Internal NSS X509 data CTX
+ *
+ ************************************************************************/
+typedef struct _xmlSecNssX509DataCtx xmlSecNssX509DataCtx,
+ *xmlSecNssX509DataCtxPtr;
+typedef struct _xmlSecNssX509CrlNode xmlSecNssX509CrlNode,
+ *xmlSecNssX509CrlNodePtr;
+struct _xmlSecNssX509CrlNode {
+ xmlSecNssX509CrlNodePtr next;
+ CERTSignedCrl *crl;
+};
+
+struct _xmlSecNssX509DataCtx {
+ CERTCertificate* keyCert;
+
+ CERTCertList* certsList;
+ unsigned int numCerts;
+
+ xmlSecNssX509CrlNodePtr crlsList;
+ unsigned int numCrls;
+};
+
+/**************************************************************************
+ *
+ * <dsig:X509Data> processing
+ *
+ *
+ * The X509Data Element (http://www.w3.org/TR/xmldsig-core/#sec-X509Data)
+ *
+ * An X509Data element within KeyInfo contains one or more identifiers of keys
+ * or X509 certificates (or certificates' identifiers or a revocation list).
+ * The content of X509Data is:
+ *
+ * 1. At least one element, from the following set of element types; any of these may appear together or more than once iff (if and only if) each instance describes or is related to the same certificate:
+ * 2.
+ * * The X509IssuerSerial element, which contains an X.509 issuer
+ * distinguished name/serial number pair that SHOULD be compliant
+ * with RFC2253 [LDAP-DN],
+ * * The X509SubjectName element, which contains an X.509 subject
+ * distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN],
+ * * The X509SKI element, which contains the base64 encoded plain (i.e.
+ * non-DER-encoded) value of a X509 V.3 SubjectKeyIdentifier extension.
+ * * The X509Certificate element, which contains a base64-encoded [X509v3]
+ * certificate, and
+ * * Elements from an external namespace which accompanies/complements any
+ * of the elements above.
+ * * The X509CRL element, which contains a base64-encoded certificate
+ * revocation list (CRL) [X509v3].
+ *
+ * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear
+ * MUST refer to the certificate or certificates containing the validation key.
+ * All such elements that refer to a particular individual certificate MUST be
+ * grouped inside a single X509Data element and if the certificate to which
+ * they refer appears, it MUST also be in that X509Data element.
+ *
+ * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that relate to
+ * the same key but different certificates MUST be grouped within a single
+ * KeyInfo but MAY occur in multiple X509Data elements.
+ *
+ * All certificates appearing in an X509Data element MUST relate to the
+ * validation key by either containing it or being part of a certification
+ * chain that terminates in a certificate containing the validation key.
+ *
+ * No ordering is implied by the above constraints.
+ *
+ * Note, there is no direct provision for a PKCS#7 encoded "bag" of
+ * certificates or CRLs. However, a set of certificates and CRLs can occur
+ * within an X509Data element and multiple X509Data elements can occur in a
+ * KeyInfo. Whenever multiple certificates occur in an X509Data element, at
+ * least one such certificate must contain the public key which verifies the
+ * signature.
+ *
+ * Schema Definition
+ *
+ * <element name="X509Data" type="ds:X509DataType"/>
+ * <complexType name="X509DataType">
+ * <sequence maxOccurs="unbounded">
+ * <choice>
+ * <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+ * <element name="X509SKI" type="base64Binary"/>
+ * <element name="X509SubjectName" type="string"/>
+ * <element name="X509Certificate" type="base64Binary"/>
+ * <element name="X509CRL" type="base64Binary"/>
+ * <any namespace="##other" processContents="lax"/>
+ * </choice>
+ * </sequence>
+ * </complexType>
+ * <complexType name="X509IssuerSerialType">
+ * <sequence>
+ * <element name="X509IssuerName" type="string"/>
+ * <element name="X509SerialNumber" type="integer"/>
+ * </sequence>
+ * </complexType>
+ *
+ * DTD
+ *
+ * <!ELEMENT X509Data ((X509IssuerSerial | X509SKI | X509SubjectName |
+ * X509Certificate | X509CRL)+ %X509.ANY;)>
+ * <!ELEMENT X509IssuerSerial (X509IssuerName, X509SerialNumber) >
+ * <!ELEMENT X509IssuerName (#PCDATA) >
+ * <!ELEMENT X509SubjectName (#PCDATA) >
+ * <!ELEMENT X509SerialNumber (#PCDATA) >
+ * <!ELEMENT X509SKI (#PCDATA) >
+ * <!ELEMENT X509Certificate (#PCDATA) >
+ * <!ELEMENT X509CRL (#PCDATA) >
+ *
+ * -----------------------------------------------------------------------
+ *
+ * xmlSecNssX509DataCtx is located after xmlSecTransform
+ *
+ *************************************************************************/
+#define xmlSecNssX509DataSize \
+ (sizeof(xmlSecKeyData) + sizeof(xmlSecNssX509DataCtx))
+#define xmlSecNssX509DataGetCtx(data) \
+ ((xmlSecNssX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int xmlSecNssKeyDataX509Initialize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataX509Duplicate (xmlSecKeyDataPtr dst,
+ xmlSecKeyDataPtr src);
+static void xmlSecNssKeyDataX509Finalize (xmlSecKeyDataPtr data);
+static int xmlSecNssKeyDataX509XmlRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int xmlSecNssKeyDataX509XmlWrite (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ xmlNodePtr node,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyDataType xmlSecNssKeyDataX509GetType (xmlSecKeyDataPtr data);
+static const xmlChar* xmlSecNssKeyDataX509GetIdentifier (xmlSecKeyDataPtr data);
+
+static void xmlSecNssKeyDataX509DebugDump (xmlSecKeyDataPtr data,
+ FILE* output);
+static void xmlSecNssKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data,
+ FILE* output);
+
+
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataX509Klass = {
+ sizeof(xmlSecKeyDataKlass),
+ xmlSecNssX509DataSize,
+
+ /* data */
+ xmlSecNameX509Data,
+ xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefX509Data, /* const xmlChar* href; */
+ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ xmlSecNssKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
+ xmlSecNssKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ xmlSecNssKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ xmlSecNssKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ xmlSecNssKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ xmlSecNssKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ xmlSecNssKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ NULL, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ xmlSecNssKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ xmlSecNssKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataX509GetKlass:
+ *
+ * The NSS X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data).
+ *
+ * Returns: the X509 data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataX509GetKlass(void) {
+ return(&xmlSecNssKeyDataX509Klass);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetKeyCert:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the certificate from which the key was extracted.
+ *
+ * Returns: the key's certificate or NULL if key data was not used for key
+ * extraction or an error occurs.
+ */
+CERTCertificate*
+xmlSecNssKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return(ctx->keyCert);
+}
+
+/**
+ * xmlSecNssKeyDataX509AdoptKeyCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to NSS X509 certificate.
+ *
+ * Sets the key's certificate in @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, CERTCertificate* cert) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->keyCert != NULL) {
+ CERT_DestroyCertificate(ctx->keyCert);
+ }
+ ctx->keyCert = cert;
+ return(0);
+}
+
+/**
+ * xmlSecNssKeyDataX509AdoptCert:
+ * @data: the pointer to X509 key data.
+ * @cert: the pointer to NSS X509 certificate.
+ *
+ * Adds certificate to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataX509AdoptCert(xmlSecKeyDataPtr data, CERTCertificate* cert) {
+ xmlSecNssX509DataCtxPtr ctx;
+ SECStatus ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->certsList == NULL) {
+ ctx->certsList = CERT_NewCertList();
+ if(ctx->certsList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CERT_NewCertList",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ ret = CERT_AddCertToListTail(ctx->certsList, cert);
+ if(ret != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CERT_AddCertToListTail",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ ctx->numCerts++;
+
+ return(0);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCert:
+ * @data: the pointer to X509 key data.
+ * @pos: the desired certificate position.
+ *
+ * Gets a certificate from X509 key data.
+ *
+ * Returns: the pointer to certificate or NULL if @pos is larger than the
+ * number of certificates in @data or an error occurs.
+ */
+CERTCertificate*
+xmlSecNssKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecNssX509DataCtxPtr ctx;
+ CERTCertListNode* head;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+ xmlSecAssert2(ctx->certsList != NULL, NULL);
+ xmlSecAssert2(pos < ctx->numCerts, NULL);
+
+ head = CERT_LIST_HEAD(ctx->certsList);
+ while (pos > 0)
+ {
+ head = CERT_LIST_NEXT(head);
+ pos--;
+ }
+
+ return (head->cert);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCertsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of certificates in @data.
+ *
+ * Returns: te number of certificates in @data.
+ */
+xmlSecSize
+xmlSecNssKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), 0);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->numCerts);
+}
+
+/**
+ * xmlSecNssKeyDataX509AdoptCrl:
+ * @data: the pointer to X509 key data.
+ * @crl: the pointer to NSS X509 CRL.
+ *
+ * Adds CRL to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, CERTSignedCrl* crl) {
+ xmlSecNssX509DataCtxPtr ctx;
+ xmlSecNssX509CrlNodePtr crlnode;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(crl != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ crlnode = (xmlSecNssX509CrlNodePtr)PR_Malloc(sizeof(xmlSecNssX509CrlNode));
+
+ if(crlnode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "PR_Malloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ memset(crlnode, 0, sizeof(xmlSecNssX509CrlNode));
+ crlnode->next = ctx->crlsList;
+ crlnode->crl = crl;
+ ctx->crlsList = crlnode;
+ ctx->numCrls++;
+
+ return(0);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCrl:
+ * @data: the pointer to X509 key data.
+ * @pos: the desired CRL position.
+ *
+ * Gets a CRL from X509 key data.
+ *
+ * Returns: the pointer to CRL or NULL if @pos is larger than the
+ * number of CRLs in @data or an error occurs.
+ */
+CERTSignedCrl *
+xmlSecNssKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) {
+ xmlSecNssX509DataCtxPtr ctx;
+ xmlSecNssX509CrlNodePtr head;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ xmlSecAssert2(ctx->crlsList != NULL, NULL);
+ xmlSecAssert2(pos < ctx->numCrls, NULL);
+
+ head = ctx->crlsList;
+ while (pos > 0)
+ {
+ head = head->next;
+ pos--;
+ }
+
+ return (head->crl);
+}
+
+/**
+ * xmlSecNssKeyDataX509GetCrlsSize:
+ * @data: the pointer to X509 key data.
+ *
+ * Gets the number of CRLs in @data.
+ *
+ * Returns: te number of CRLs in @data.
+ */
+xmlSecSize
+xmlSecNssKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), 0);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, 0);
+
+ return(ctx->numCrls);
+}
+
+static int
+xmlSecNssKeyDataX509Initialize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssX509DataCtx));
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+ CERTCertificate* certSrc;
+ CERTCertificate* certDst;
+ CERTSignedCrl* crlSrc;
+ CERTSignedCrl* crlDst;
+ xmlSecSize size, pos;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataX509Id), -1);
+
+ /* copy certsList */
+ size = xmlSecNssKeyDataX509GetCertsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ /* TBD: function below does linear scan, eliminate loop within
+ * loop
+ */
+ certSrc = xmlSecNssKeyDataX509GetCert(src, pos);
+ if(certSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ certDst = CERT_DupCertificate(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(certDst);
+ return(-1);
+ }
+ }
+
+ /* copy crls */
+ size = xmlSecNssKeyDataX509GetCrlsSize(src);
+ for(pos = 0; pos < size; ++pos) {
+ crlSrc = xmlSecNssKeyDataX509GetCrl(src, pos);
+ if(crlSrc == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+ "xmlSecNssKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ crlDst = SEC_DupCrl(crlSrc);
+ if(crlDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "SEC_DupCrl",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCrl(dst, crlDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssKeyDataX509AdoptCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SEC_DestroyCrl(crlDst);
+ return(-1);
+ }
+ }
+
+ /* copy key cert if exist */
+ certSrc = xmlSecNssKeyDataX509GetKeyCert(src);
+ if(certSrc != NULL) {
+ certDst = CERT_DupCertificate(certSrc);
+ if(certDst == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ ret = xmlSecNssKeyDataX509AdoptKeyCert(dst, certDst);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+ "xmlSecNssKeyDataX509AdoptKeyCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(certDst);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static void
+xmlSecNssKeyDataX509Finalize(xmlSecKeyDataPtr data) {
+ xmlSecNssX509DataCtxPtr ctx;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id));
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->certsList != NULL) {
+ CERT_DestroyCertList(ctx->certsList);
+ }
+
+ if(ctx->crlsList != NULL) {
+ xmlSecNssX509CrlNodePtr head;
+ xmlSecNssX509CrlNodePtr tmp;
+
+ head = ctx->crlsList;
+ while (head)
+ {
+ tmp = head->next;
+ SEC_DestroyCrl(head->crl);
+ PR_Free(head);
+ head = tmp;
+ }
+ }
+
+ if(ctx->keyCert != NULL) {
+ CERT_DestroyCertificate(ctx->keyCert);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssX509DataCtx));
+}
+
+static int
+xmlSecNssKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataX509Id, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ data = xmlSecKeyEnsureData(key, id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ret = xmlSecNssX509DataNodeRead(data, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509DataNodeRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
+ ret = xmlSecNssKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecNssKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ CERTCertificate* cert;
+ CERTSignedCrl* crl;
+ xmlSecSize size, pos;
+ int content = 0;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataX509Id, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ content = xmlSecX509DataGetNodeContent (node, 1, keyInfoCtx);
+ if (content < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecX509DataGetNodeContent",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "content=%d", content);
+ return(-1);
+ } else if(content == 0) {
+ /* by default we are writing certificates and crls */
+ content = XMLSEC_X509DATA_DEFAULT;
+ }
+
+ /* get x509 data */
+ data = xmlSecKeyGetData(key, id);
+ if(data == NULL) {
+ /* no x509 data in the key */
+ return(0);
+ }
+
+ /* write certs */
+ size = xmlSecNssKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecNssKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) {
+ ret = xmlSecNssX509CertificateNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509CertificateNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) {
+ ret = xmlSecNssX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509SubjectNameNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) {
+ ret = xmlSecNssX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509IssuerSerialNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+
+ if((content & XMLSEC_X509DATA_SKI_NODE) != 0) {
+ ret = xmlSecNssX509SKINodeWrite(cert, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509SKINodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ /* write crls if needed */
+ if((content & XMLSEC_X509DATA_CRL_NODE) != 0) {
+ size = xmlSecNssKeyDataX509GetCrlsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ crl = xmlSecNssKeyDataX509GetCrl(data, pos);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509GetCrl",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+
+ ret = xmlSecNssX509CRLNodeWrite(crl, node, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssX509CRLNodeWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return(-1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+static xmlSecKeyDataType
+xmlSecNssKeyDataX509GetType(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), xmlSecKeyDataTypeUnknown);
+
+ /* TODO: return verified/not verified status */
+ return(xmlSecKeyDataTypeUnknown);
+}
+
+static const xmlChar*
+xmlSecNssKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) {
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL);
+
+ /* TODO */
+ return(NULL);
+}
+
+static void
+xmlSecNssKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+ CERTCertificate* cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== X509 Data:\n");
+ cert = xmlSecNssKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "==== Key Certificate:\n");
+ xmlSecNssX509CertDebugDump(cert, output);
+ }
+
+ size = xmlSecNssKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecNssKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "==== Certificate:\n");
+ xmlSecNssX509CertDebugDump(cert, output);
+ }
+
+ /* we don't print out crls */
+}
+
+static void
+xmlSecNssKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+ CERTCertificate* cert;
+ xmlSecSize size, pos;
+
+ xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<X509Data>\n");
+ cert = xmlSecNssKeyDataX509GetKeyCert(data);
+ if(cert != NULL) {
+ fprintf(output, "<KeyCertificate>\n");
+ xmlSecNssX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</KeyCertificate>\n");
+ }
+
+ size = xmlSecNssKeyDataX509GetCertsSize(data);
+ for(pos = 0; pos < size; ++pos) {
+ cert = xmlSecNssKeyDataX509GetCert(data, pos);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509GetCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "pos=%d", pos);
+ return;
+ }
+ fprintf(output, "<Certificate>\n");
+ xmlSecNssX509CertDebugXmlDump(cert, output);
+ fprintf(output, "</Certificate>\n");
+ }
+
+ /* we don't print out crls */
+ fprintf(output, "</X509Data>\n");
+}
+
+static int
+xmlSecNssX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlNodePtr cur;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ for(cur = xmlSecGetNextElementNode(node->children);
+ cur != NULL;
+ cur = xmlSecGetNextElementNode(cur->next)) {
+
+ ret = 0;
+ if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) {
+ ret = xmlSecNssX509CertificateNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+ ret = xmlSecNssX509SubjectNameNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+ ret = xmlSecNssX509IssuerSerialNodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+ ret = xmlSecNssX509SKINodeRead(data, cur, keyInfoCtx);
+ } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+ ret = xmlSecNssX509CRLNodeRead(data, cur, keyInfoCtx);
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CHILD) != 0) {
+ /* laxi schema validation: ignore unknown nodes */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "read node failed");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecNssX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ content = xmlNodeGetContent(node);
+ if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+ if(content != NULL) {
+ xmlFree(content);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert = xmlSecNssX509CertBase64DerRead(content);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(content);
+ return(-1);
+ }
+
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecNssX509CertificateNodeWrite(CERTCertificate* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar* buf;
+ xmlNodePtr cur;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ /* set base64 lines size from context */
+ buf = xmlSecNssX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CertBase64DerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509Certificate));
+ xmlFree(buf);
+ return(-1);
+ }
+
+ /* todo: add \n around base64 data - from context */
+ /* todo: add errors check */
+ xmlNodeSetContent(cur, xmlSecStringCR);
+ xmlNodeSetContent(cur, buf);
+ xmlFree(buf);
+ return(0);
+}
+
+static int
+xmlSecNssX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* subject;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ subject = xmlNodeGetContent(node);
+ if((subject == NULL) || (xmlSecIsEmptyString(subject) == 1)) {
+ if(subject != NULL) {
+ xmlFree(subject);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert = xmlSecNssX509StoreFindCert(x509Store, subject, NULL, NULL, NULL, keyInfoCtx);
+ if(cert == NULL){
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ "subject=%s",
+ xmlSecErrorsSafeString(subject));
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(subject);
+ return(-1);
+ }
+
+ xmlFree(subject);
+ return(0);
+}
+
+static int
+xmlSecNssX509SubjectNameNodeWrite(CERTCertificate* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecNssX509NameWrite(&(cert->subject));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameWrite(&(cert->subject))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SubjectName));
+ xmlFree(buf);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(cur, buf);
+ xmlFree(buf);
+ return(0);
+}
+
+static int
+xmlSecNssX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlNodePtr cur;
+ xmlChar *issuerName;
+ xmlChar *issuerSerial;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecGetNextElementNode(node->children);
+ if(cur == NULL) {
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ return(0);
+ }
+
+ /* the first is required node X509IssuerName */
+ if(!xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ return(-1);
+ }
+ issuerName = xmlNodeGetContent(cur);
+ if(issuerName == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ /* next is required node X509SerialNumber */
+ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+ xmlFree(issuerName);
+ return(-1);
+ }
+ issuerSerial = xmlNodeGetContent(cur);
+ if(issuerSerial == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+ xmlFree(issuerName);
+ return(-1);
+ }
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if(cur != NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+ XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ cert = xmlSecNssX509StoreFindCert(x509Store, NULL, issuerName, issuerSerial, NULL, keyInfoCtx);
+ if(cert == NULL){
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ "issuerName=%s;issuerSerial=%s",
+ xmlSecErrorsSafeString(issuerName),
+ xmlSecErrorsSafeString(issuerSerial));
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(-1);
+ }
+
+ xmlFree(issuerSerial);
+ xmlFree(issuerName);
+ return(0);
+}
+
+static int
+xmlSecNssX509IssuerSerialNodeWrite(CERTCertificate* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlNodePtr cur;
+ xmlNodePtr issuerNameNode;
+ xmlNodePtr issuerNumberNode;
+ xmlChar* buf;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ /* create xml nodes */
+ cur = xmlSecAddChild(node, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial));
+ return(-1);
+ }
+
+ issuerNameNode = xmlSecAddChild(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs);
+ if(issuerNameNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+ return(-1);
+ }
+
+ issuerNumberNode = xmlSecAddChild(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs);
+ if(issuerNumberNode == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+ return(-1);
+ }
+
+ /* write data */
+ buf = xmlSecNssX509NameWrite(&(cert->issuer));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameWrite(&(cert->issuer))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(issuerNameNode, buf);
+ xmlFree(buf);
+
+ buf = xmlSecNssASN1IntegerWrite(&(cert->serialNumber));
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssASN1IntegerWrite(&(cert->serialNumber))",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ xmlNodeSetContent(issuerNumberNode, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+static int
+xmlSecNssX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataStorePtr x509Store;
+ xmlChar* ski;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ ski = xmlNodeGetContent(node);
+ if((ski == NULL) || (xmlSecIsEmptyString(ski) == 1)) {
+ if(ski != NULL) {
+ xmlFree(ski);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ "node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+ return(-1);
+ }
+ return(0);
+ }
+
+ cert = xmlSecNssX509StoreFindCert(x509Store, NULL, NULL, NULL, ski, keyInfoCtx);
+ if(cert == NULL){
+ xmlFree(ski);
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ "ski=%s",
+ xmlSecErrorsSafeString(ski));
+ return(-1);
+ }
+ return(0);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ xmlFree(ski);
+ return(-1);
+ }
+
+ xmlFree(ski);
+ return(0);
+}
+
+static int
+xmlSecNssX509SKINodeWrite(CERTCertificate* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+ xmlChar *buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(cert != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+
+ buf = xmlSecNssX509SKIWrite(cert);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509SKIWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "new_node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+ xmlFree(buf);
+ return(-1);
+ }
+ xmlSecNodeEncodeAndSetContent(cur, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+static int
+xmlSecNssX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar *content;
+ CERTSignedCrl* crl;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ content = xmlNodeGetContent(node);
+ if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+ if(content != NULL) {
+ xmlFree(content);
+ }
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+ }
+
+ crl = xmlSecNssX509CrlBase64DerRead(content, keyInfoCtx);
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CrlBase64DerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(content);
+ return(-1);
+ }
+
+ SEC_DestroyCrl(crl);
+ xmlFree(content);
+ return(0);
+}
+
+static int
+xmlSecNssX509CRLNodeWrite(CERTSignedCrl* crl, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlChar* buf = NULL;
+ xmlNodePtr cur = NULL;
+
+ xmlSecAssert2(crl != NULL, -1);
+ xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ /* set base64 lines size from context */
+ buf = xmlSecNssX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CrlBase64DerWrite",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ cur = xmlSecAddChild(node, xmlSecNodeX509CRL, xmlSecDSigNs);
+ if(cur == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecAddChild",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "new_node=%s",
+ xmlSecErrorsSafeString(xmlSecNodeX509CRL));
+ xmlFree(buf);
+ return(-1);
+ }
+ /* todo: add \n around base64 data - from context */
+ /* todo: add errors check */
+ xmlNodeSetContent(cur, xmlSecStringCR);
+ xmlNodeSetContent(cur, buf);
+ xmlFree(buf);
+
+ return(0);
+}
+
+
+static int
+xmlSecNssKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecNssX509DataCtxPtr ctx;
+ xmlSecKeyDataStorePtr x509Store;
+ int ret;
+ SECStatus status;
+ PRTime notBefore, notAfter;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+ xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+ ctx = xmlSecNssX509DataGetCtx(data);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId);
+ if(x509Store == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ if((ctx->keyCert == NULL) && (ctx->certsList != NULL) && (xmlSecKeyGetValue(key) == NULL)) {
+ CERTCertificate* cert;
+
+ cert = xmlSecNssX509StoreVerify(x509Store, ctx->certsList, keyInfoCtx);
+ if(cert != NULL) {
+ xmlSecKeyDataPtr keyValue;
+
+ ctx->keyCert = CERT_DupCertificate(cert);
+ if(ctx->keyCert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ keyValue = xmlSecNssX509CertGetKey(ctx->keyCert);
+ if(keyValue == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertGetKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* verify that the key matches our expectations */
+ if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), keyValue) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeyReqMatchKeyValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(keyValue);
+ return(-1);
+ }
+
+ ret = xmlSecKeySetValue(key, keyValue);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecKeySetValue",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecKeyDataDestroy(keyValue);
+ return(-1);
+ }
+
+ status = CERT_GetCertTimes(ctx->keyCert, &notBefore, &notAfter);
+ if (status == SECSuccess) {
+ ret = xmlSecNssX509CertGetTime(&notBefore, &(key->notValidBefore));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidBefore");
+ return(-1);
+ }
+ ret = xmlSecNssX509CertGetTime(&notAfter, &(key->notValidAfter));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ "xmlSecNssX509CertGetTime",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "notValidAfter");
+ return(-1);
+ }
+ } else {
+ key->notValidBefore = key->notValidAfter = 0;
+ }
+ } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_INVALID_CERT) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+static int
+xmlSecNssX509CertGetTime(PRTime* t, time_t* res) {
+
+ PRTime tmp64_1, tmp64_2;
+ PRUint32 tmp32 = 1000000;
+
+ xmlSecAssert2(t != NULL, -1);
+ xmlSecAssert2(res != NULL, -1);
+
+ /* PRTime is time in microseconds since epoch. Divide by 1000000 to
+ * convert to seconds, then convert to an unsigned 32 bit number
+ */
+ (*res) = 0;
+ LL_UI2L(tmp64_1, tmp32);
+ LL_DIV(tmp64_2, *t, tmp64_1);
+ LL_L2UI(tmp32, tmp64_2);
+
+ (*res) = (time_t)(tmp32);
+
+ return(0);
+}
+
+/**
+ * xmlSecNssX509CertGetKey:
+ * @cert: the certificate.
+ *
+ * Extracts public key from the @cert.
+ *
+ * Returns: public key value or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecNssX509CertGetKey(CERTCertificate* cert) {
+ xmlSecKeyDataPtr data;
+ SECKEYPublicKey *pubkey = NULL;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ pubkey = CERT_ExtractPublicKey(cert);
+ if(pubkey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_ExtractPublicKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(NULL);
+ }
+
+ data = xmlSecNssPKIAdoptKey(NULL, pubkey);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssPKIAdoptKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECKEY_DestroyPublicKey(pubkey);
+ return(NULL);
+ }
+
+ return(data);
+}
+
+static CERTCertificate*
+xmlSecNssX509CertBase64DerRead(xmlChar* buf) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+
+ /* usual trick with base64 decoding "in-place" */
+ ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecNssX509CertDerRead((xmlSecByte*)buf, ret));
+}
+
+
+static CERTCertificate*
+xmlSecNssX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
+ CERTCertificate *cert;
+ SECItem derCert;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ derCert.data = (unsigned char *)buf;
+ derCert.len = size;
+
+ /* decode cert and import to temporary cert db */
+ cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
+ NULL, PR_FALSE, PR_TRUE);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "__CERT_NewTempCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(NULL);
+ }
+
+
+ return(cert);
+}
+
+static xmlChar*
+xmlSecNssX509CertBase64DerWrite(CERTCertificate* cert, int base64LineWrap) {
+ xmlChar *res = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ p = cert->derCert.data;
+ size = cert->derCert.len;
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "cert->derCert",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(p, size, base64LineWrap);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+static CERTSignedCrl*
+xmlSecNssX509CrlBase64DerRead(xmlChar* buf,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ int ret;
+
+ xmlSecAssert2(buf != NULL, NULL);
+
+ /* usual trick with base64 decoding "in-place" */
+ ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(xmlSecNssX509CrlDerRead((xmlSecByte*)buf, ret, keyInfoCtx));
+}
+
+
+static CERTSignedCrl*
+xmlSecNssX509CrlDerRead(xmlSecByte* buf, xmlSecSize size,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ CERTSignedCrl *crl = NULL;
+ SECItem derCrl;
+ PK11SlotInfo *slot = NULL;
+ PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
+
+ xmlSecAssert2(buf != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+ xmlSecAssert2(size > 0, NULL);
+
+ derCrl.data = buf;
+ derCrl.len = size;
+
+ /* we're importing a CRL, it is ok to use the internal slot.
+ * crlutil does it :)
+ */
+ slot = xmlSecNssGetInternalKeySlot();
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetInternalKeySlot",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return NULL;
+ }
+
+ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS) != 0)
+ importOptions |= CRL_IMPORT_BYPASS_CHECKS;
+
+ crl = PK11_ImportCRL(slot, &derCrl, NULL, SEC_CRL_TYPE, NULL,
+ importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
+
+ if(crl == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportCRL",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ PK11_FreeSlot(slot);
+ return(NULL);
+ }
+
+ PK11_FreeSlot(slot);
+ return(crl);
+}
+
+static xmlChar*
+xmlSecNssX509CrlBase64DerWrite(CERTSignedCrl* crl, int base64LineWrap) {
+ xmlChar *res = NULL;
+ xmlSecByte *p = NULL;
+ long size;
+
+ xmlSecAssert2(crl != NULL && crl->derCrl != NULL, NULL);
+
+ p = crl->derCrl->data;
+ size = crl->derCrl->len;
+ if((size <= 0) || (p == NULL)){
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "crl->derCrl",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(p, size, base64LineWrap);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ return(res);
+}
+
+static xmlChar*
+xmlSecNssX509NameWrite(CERTName* nm) {
+ xmlChar *res = NULL;
+ char *str;
+
+ xmlSecAssert2(nm != NULL, NULL);
+
+ str = CERT_NameToAscii(nm);
+ if (str == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_NameToAscii",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ res = xmlStrdup(BAD_CAST str);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ PORT_Free(str);
+ return(NULL);
+ }
+ PORT_Free(str);
+ return(res);
+}
+
+static xmlChar*
+xmlSecNssASN1IntegerWrite(SECItem *num) {
+ xmlChar *res = NULL;
+ int resLen = 64; /* not more than 64 chars */
+ PRUint64 val = 0;
+ unsigned int ii = 0;
+ int shift = 0;
+
+ xmlSecAssert2(num != NULL, NULL);
+ xmlSecAssert2(num->type == siBuffer, NULL);
+ xmlSecAssert2(num->len <= 9, NULL);
+ xmlSecAssert2(num->data != NULL, NULL);
+
+ /* HACK : to be fixed after
+ * NSS bug http://bugzilla.mozilla.org/show_bug.cgi?id=212864 is fixed
+ */
+ for(ii = num->len; ii > 0; --ii, shift += 8) {
+ val |= ((PRUint64)num->data[ii - 1]) << shift;
+ }
+
+ res = (xmlChar*)xmlMalloc(resLen + 1);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlStrdup",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return (NULL);
+ }
+
+ PR_snprintf((char*)res, resLen, "%llu", val);
+ return(res);
+}
+
+static xmlChar*
+xmlSecNssX509SKIWrite(CERTCertificate* cert) {
+ xmlChar *res = NULL;
+ SECItem ski;
+ SECStatus rv;
+
+ xmlSecAssert2(cert != NULL, NULL);
+
+ memset(&ski, 0, sizeof(ski));
+
+ rv = CERT_FindSubjectKeyIDExtension(cert, &ski);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_FindSubjectKeyIDExtension",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&ski, PR_FALSE);
+ return(NULL);
+ }
+
+ res = xmlSecBase64Encode(ski.data, ski.len, 0);
+ if(res == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Encode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ SECITEM_FreeItem(&ski, PR_FALSE);
+ return(NULL);
+ }
+ SECITEM_FreeItem(&ski, PR_FALSE);
+
+ return(res);
+}
+
+
+static void
+xmlSecNssX509CertDebugDump(CERTCertificate* cert, FILE* output) {
+ SECItem *sn;
+ unsigned int i;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "==== Subject Name: %s\n", cert->subjectName);
+ fprintf(output, "==== Issuer Name: %s\n", cert->issuerName);
+ sn = &cert->serialNumber;
+
+ for (i = 0; i < sn->len; i++) {
+ if (i != sn->len - 1) {
+ fprintf(output, "%02x:", sn->data[i]);
+ } else {
+ fprintf(output, "%02x", sn->data[i]);
+ }
+ }
+ fprintf(output, "\n");
+}
+
+
+static void
+xmlSecNssX509CertDebugXmlDump(CERTCertificate* cert, FILE* output) {
+ SECItem *sn;
+ unsigned int i;
+
+ xmlSecAssert(cert != NULL);
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<SubjectName>");
+ xmlSecPrintXmlString(output, BAD_CAST cert->subjectName);
+ fprintf(output, "</SubjectName>\n");
+
+ fprintf(output, "<IssuerName>");
+ xmlSecPrintXmlString(output, BAD_CAST cert->issuerName);
+ fprintf(output, "</IssuerName>\n");
+
+ fprintf(output, "<SerialNumber>");
+ sn = &cert->serialNumber;
+ for (i = 0; i < sn->len; i++) {
+ if (i != sn->len - 1) {
+ fprintf(output, "%02x:", sn->data[i]);
+ } else {
+ fprintf(output, "%02x", sn->data[i]);
+ }
+ }
+ fprintf(output, "</SerialNumber>\n");
+}
+
+
+/**************************************************************************
+ *
+ * Raw X509 Certificate processing
+ *
+ *
+ *************************************************************************/
+static int xmlSecNssKeyDataRawX509CertBinRead (xmlSecKeyDataId id,
+ xmlSecKeyPtr key,
+ const xmlSecByte* buf,
+ xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecNssKeyDataRawX509CertKlass = {
+ sizeof(xmlSecKeyDataKlass),
+ sizeof(xmlSecKeyData),
+
+ /* data */
+ xmlSecNameRawX509Cert,
+ xmlSecKeyDataUsageRetrievalMethodNodeBin,
+ /* xmlSecKeyDataUsage usage; */
+ xmlSecHrefRawX509Cert, /* const xmlChar* href; */
+ NULL, /* const xmlChar* dataNodeName; */
+ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
+
+ /* constructors/destructor */
+ NULL, /* xmlSecKeyDataInitializeMethod initialize; */
+ NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */
+ NULL, /* xmlSecKeyDataFinalizeMethod finalize; */
+ NULL, /* xmlSecKeyDataGenerateMethod generate; */
+
+ /* get info */
+ NULL, /* xmlSecKeyDataGetTypeMethod getType; */
+ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
+ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+ /* read/write */
+ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
+ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+ xmlSecNssKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */
+ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+ /* debug */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
+ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecNssKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 certificates key data klass.
+ *
+ * Returns: raw X509 certificates key data klass.
+ */
+xmlSecKeyDataId
+xmlSecNssKeyDataRawX509CertGetKlass(void) {
+ return(&xmlSecNssKeyDataRawX509CertKlass);
+}
+
+static int
+xmlSecNssKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+ const xmlSecByte* buf, xmlSecSize bufSize,
+ xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyDataPtr data;
+ CERTCertificate* cert;
+ int ret;
+
+ xmlSecAssert2(id == xmlSecNssKeyDataRawX509CertId, -1);
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(buf != NULL, -1);
+ xmlSecAssert2(bufSize > 0, -1);
+ xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+ cert = xmlSecNssX509CertDerRead(buf, bufSize);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509CertDerRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id);
+ if(data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecKeyEnsureData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509AdoptCert(data, cert);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509AdoptCert",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ CERT_DestroyCertificate(cert);
+ return(-1);
+ }
+
+ ret = xmlSecNssKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+ "xmlSecNssKeyDataX509VerifyAndExtractKey",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/nss/x509vfy.c b/src/nss/x509vfy.c
new file mode 100644
index 00000000..fdb866fe
--- /dev/null
+++ b/src/nss/x509vfy.c
@@ -0,0 +1,808 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (c) 2003 America Online, Inc. All rights reserved.
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <cert.h>
+#include <secerr.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/x509.h>
+
+/**************************************************************************
+ *
+ * Internal NSS X509 store CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecNssX509StoreCtx xmlSecNssX509StoreCtx,
+ *xmlSecNssX509StoreCtxPtr;
+struct _xmlSecNssX509StoreCtx {
+ /* Two uses:
+ *
+ * 1) Just keeping a reference to destroy later.
+ *
+ * 2) NSS doesn't update it's cache correctly when new certs are added
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=211051
+ * we use this list to perform search ourselves.
+ */
+
+ CERTCertList* certsList; /* just keeping a reference to destroy later */
+};
+
+/****************************************************************************
+ *
+ * xmlSecNssKeyDataStoreX509Id:
+ *
+ * xmlSecNssX509StoreCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecNssX509StoreGetCtx(store) \
+ ((xmlSecNssX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
+ sizeof(xmlSecKeyDataStoreKlass)))
+#define xmlSecNssX509StoreSize \
+ (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecNssX509StoreCtx))
+
+static int xmlSecNssX509StoreInitialize (xmlSecKeyDataStorePtr store);
+static void xmlSecNssX509StoreFinalize (xmlSecKeyDataStorePtr store);
+static int xmlSecNssX509NameStringRead (xmlSecByte **str,
+ int *strLen,
+ xmlSecByte *res,
+ int resLen,
+ xmlSecByte delim,
+ int ingoreTrailingSpaces);
+static xmlSecByte * xmlSecNssX509NameRead (xmlSecByte *str,
+ int len);
+
+static int xmlSecNssNumToItem (SECItem *it,
+ PRUint64 num);
+
+
+static xmlSecKeyDataStoreKlass xmlSecNssX509StoreKlass = {
+ sizeof(xmlSecKeyDataStoreKlass),
+ xmlSecNssX509StoreSize,
+
+ /* data */
+ xmlSecNameX509Store, /* const xmlChar* name; */
+
+ /* constructors/destructor */
+ xmlSecNssX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
+ xmlSecNssX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static CERTCertificate* xmlSecNssX509FindCert(CERTCertList* certsList,
+ const xmlChar *subjectName,
+ const xmlChar *issuerName,
+ const xmlChar *issuerSerial,
+ xmlChar *ski);
+
+
+/**
+ * xmlSecNssX509StoreGetKlass:
+ *
+ * The NSS X509 certificates key data store klass.
+ *
+ * Returns: pointer to NSS X509 certificates key data store klass.
+ */
+xmlSecKeyDataStoreId
+xmlSecNssX509StoreGetKlass(void) {
+ return(&xmlSecNssX509StoreKlass);
+}
+
+/**
+ * xmlSecNssX509StoreFindCert:
+ * @store: the pointer to X509 key data store klass.
+ * @subjectName: the desired certificate name.
+ * @issuerName: the desired certificate issuer name.
+ * @issuerSerial: the desired certificate issuer serial number.
+ * @ski: the desired certificate SKI.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Searches @store for a certificate that matches given criteria.
+ *
+ * Returns: pointer to found certificate or NULL if certificate is not found
+ * or an error occurs.
+ */
+CERTCertificate *
+xmlSecNssX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
+ xmlChar *issuerName, xmlChar *issuerSerial,
+ xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecNssX509StoreCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ return xmlSecNssX509FindCert(ctx->certsList, subjectName, issuerName, issuerSerial, ski);
+}
+
+/**
+ * xmlSecNssX509StoreVerify:
+ * @store: the pointer to X509 key data store klass.
+ * @certs: the untrusted certificates stack.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Verifies @certs list.
+ *
+ * Returns: pointer to the first verified certificate from @certs.
+ */
+CERTCertificate *
+xmlSecNssX509StoreVerify(xmlSecKeyDataStorePtr store, CERTCertList* certs,
+ xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ CERTCertListNode* head;
+ CERTCertificate* cert = NULL;
+ CERTCertListNode* head1;
+ CERTCertificate* cert1 = NULL;
+ SECStatus status = SECFailure;
+ int64 timeboundary;
+ int64 tmp1, tmp2;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), NULL);
+ xmlSecAssert2(certs != NULL, NULL);
+ xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, NULL);
+
+ for (head = CERT_LIST_HEAD(certs);
+ !CERT_LIST_END(head, certs);
+ head = CERT_LIST_NEXT(head)) {
+ cert = head->cert;
+ if(keyInfoCtx->certsVerificationTime > 0) {
+ /* convert the time since epoch in seconds to microseconds */
+ LL_UI2L(timeboundary, keyInfoCtx->certsVerificationTime);
+ tmp1 = (int64)PR_USEC_PER_SEC;
+ tmp2 = timeboundary;
+ LL_MUL(timeboundary, tmp1, tmp2);
+ } else {
+ timeboundary = PR_Now();
+ }
+
+ /* if cert is the issuer of any other cert in the list, then it is
+ * to be skipped */
+ for (head1 = CERT_LIST_HEAD(certs);
+ !CERT_LIST_END(head1, certs);
+ head1 = CERT_LIST_NEXT(head1)) {
+
+ cert1 = head1->cert;
+ if (cert1 == cert) {
+ continue;
+ }
+
+ if (SECITEM_CompareItem(&cert1->derIssuer, &cert->derSubject)
+ == SECEqual) {
+ break;
+ }
+ }
+
+ if (!CERT_LIST_END(head1, certs)) {
+ continue;
+ }
+
+ status = CERT_VerifyCertificate(CERT_GetDefaultCertDB(),
+ cert, PR_FALSE,
+ (SECCertificateUsage)0,
+ timeboundary , NULL, NULL, NULL);
+ if (status == SECSuccess) {
+ break;
+ }
+ }
+
+ if (status == SECSuccess) {
+ return (cert);
+ }
+
+ switch(PORT_GetError()) {
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ case SEC_ERROR_CA_CERT_INVALID:
+ case SEC_ERROR_UNKNOWN_SIGNER:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
+ "cert with subject name %s could not be verified because the issuer's cert is expired/invalid or not found",
+ cert->subjectName);
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
+ "cert with subject name %s has expired",
+ cert->subjectName);
+ break;
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_REVOKED,
+ "cert with subject name %s has been revoked",
+ cert->subjectName);
+ break;
+ default:
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ NULL,
+ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+ "cert with subject name %s could not be verified, errcode %d",
+ cert->subjectName,
+ PORT_GetError());
+ break;
+ }
+
+ return (NULL);
+}
+
+/**
+ * xmlSecNssX509StoreAdoptCert:
+ * @store: the pointer to X509 key data store klass.
+ * @cert: the pointer to NSS X509 certificate.
+ * @type: the certificate type (trusted/untrusted).
+ *
+ * Adds trusted (root) or untrusted certificate to the store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecNssX509StoreAdoptCert(xmlSecKeyDataStorePtr store, CERTCertificate* cert, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), -1);
+ xmlSecAssert2(cert != NULL, -1);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ if(ctx->certsList == NULL) {
+ ctx->certsList = CERT_NewCertList();
+ if(ctx->certsList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CERT_NewCertList",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+ }
+
+ ret = CERT_AddCertToListTail(ctx->certsList, cert);
+ if(ret != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+ "CERT_AddCertToListTail",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecNssX509StoreInitialize(xmlSecKeyDataStorePtr store) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId), -1);
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecNssX509StoreCtx));
+
+ return(0);
+}
+
+static void
+xmlSecNssX509StoreFinalize(xmlSecKeyDataStorePtr store) {
+ xmlSecNssX509StoreCtxPtr ctx;
+ xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecNssX509StoreId));
+
+ ctx = xmlSecNssX509StoreGetCtx(store);
+ xmlSecAssert(ctx != NULL);
+
+ if (ctx->certsList) {
+ CERT_DestroyCertList(ctx->certsList);
+ ctx->certsList = NULL;
+ }
+
+ memset(ctx, 0, sizeof(xmlSecNssX509StoreCtx));
+}
+
+
+/*****************************************************************************
+ *
+ * Low-level x509 functions
+ *
+ *****************************************************************************/
+static CERTName *
+xmlSecNssGetCertName(const xmlChar * name) {
+ xmlChar *tmp, *name2;
+ xmlChar *p;
+ CERTName *res;
+
+ xmlSecAssert2(name != NULL, NULL);
+
+ /* nss doesn't support emailAddress (see https://bugzilla.mozilla.org/show_bug.cgi?id=561689)
+ * This code is not bullet proof and may produce incorrect results if someone has
+ * "emailAddress=" string in one of the fields, but it is best I can suggest to fix
+ * this problem.
+ */
+ name2 = xmlStrdup(name);
+ if(name2 == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "xmlStrlen(name)=%d",
+ xmlStrlen(name));
+ return(NULL);
+ }
+ while( (p = (xmlChar*)xmlStrstr(name2, BAD_CAST "emailAddress=")) != NULL) {
+ memcpy(p, " E=", 13);
+ }
+
+ tmp = xmlSecNssX509NameRead(name2, xmlStrlen(name2));
+ if(tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "name2=\"%s\"",
+ xmlSecErrorsSafeString(name2));
+ xmlFree(name2);
+ return(NULL);
+ }
+
+ res = CERT_AsciiToName((char*)tmp);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_AsciiToName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ascii=\"%s\", error code=%d",
+ xmlSecErrorsSafeString((char*)tmp),
+ PORT_GetError());
+ PORT_Free(tmp);
+ xmlFree(name2);
+ return(NULL);
+ }
+
+ PORT_Free(tmp);
+ return(res);
+}
+
+static CERTCertificate*
+xmlSecNssX509FindCert(CERTCertList* certsList, const xmlChar *subjectName,
+ const xmlChar *issuerName, const xmlChar *issuerSerial,
+ xmlChar *ski) {
+ CERTCertificate *cert = NULL;
+ CERTName *name = NULL;
+ SECItem *nameitem = NULL;
+ CERTCertListNode* head;
+ SECItem tmpitem;
+ SECStatus status;
+ PRArenaPool *arena = NULL;
+ int rv;
+
+ if ((cert == NULL) && (subjectName != NULL)) {
+ name = xmlSecNssGetCertName(subjectName);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetCertName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "subject=%s",
+ xmlSecErrorsSafeString(subjectName));
+ goto done;
+ }
+
+ if(arena == NULL) {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
+ SEC_ASN1_GET(CERT_NameTemplate));
+ if (nameitem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_ASN1EncodeItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PORT_GetError());
+ goto done;
+ }
+
+ cert = CERT_FindCertByName(CERT_GetDefaultCertDB(), nameitem);
+ }
+
+ if((cert == NULL) && (issuerName != NULL) && (issuerSerial != NULL)) {
+ CERTIssuerAndSN issuerAndSN;
+ PRUint64 issuerSN = 0;
+
+ name = xmlSecNssGetCertName(issuerName);
+ if (name == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssGetCertName",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "issuer=%s",
+ xmlSecErrorsSafeString(issuerName));
+ goto done;
+ }
+
+ if(arena == NULL) {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_NewArena",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ }
+
+ nameitem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
+ SEC_ASN1_GET(CERT_NameTemplate));
+ if (nameitem == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "SEC_ASN1EncodeItem",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ goto done;
+ }
+
+ memset(&issuerAndSN, 0, sizeof(issuerAndSN));
+
+ issuerAndSN.derIssuer.data = nameitem->data;
+ issuerAndSN.derIssuer.len = nameitem->len;
+
+ /* TBD: serial num can be arbitrarily long */
+ if(PR_sscanf((char *)issuerSerial, "%llu", &issuerSN) != 1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PR_sscanf",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PR_GetError());
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ goto done;
+ }
+
+ rv = xmlSecNssNumToItem(&issuerAndSN.serialNumber, issuerSN);
+ if(rv <= 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssNumToItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "error code=%d", PR_GetError());
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ goto done;
+ }
+
+ cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerAndSN);
+ SECITEM_FreeItem(&issuerAndSN.serialNumber, PR_FALSE);
+ }
+
+ if((cert == NULL) && (ski != NULL)) {
+ SECItem subjKeyID;
+ int len;
+
+ len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski));
+ if(len < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBase64Decode",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "ski=%s",
+ xmlSecErrorsSafeString(ski));
+ goto done;
+ }
+
+ memset(&subjKeyID, 0, sizeof(subjKeyID));
+ subjKeyID.data = ski;
+ subjKeyID.len = len;
+ cert = CERT_FindCertBySubjectKeyID(CERT_GetDefaultCertDB(),
+ &subjKeyID);
+
+ /* try to search in our list - NSS doesn't update it's cache correctly
+ * when new certs are added https://bugzilla.mozilla.org/show_bug.cgi?id=211051
+ */
+ if((cert == NULL) && (certsList != NULL)) {
+
+ for(head = CERT_LIST_HEAD(certsList);
+ (cert == NULL) && !CERT_LIST_END(head, certsList) &&
+ (head != NULL) && (head->cert != NULL);
+ head = CERT_LIST_NEXT(head)
+ ) {
+
+ memset(&tmpitem, 0, sizeof(tmpitem));
+ status = CERT_FindSubjectKeyIDExtension(head->cert, &tmpitem);
+ if (status != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_FindSubjectKeyIDExtension",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "ski");
+ SECITEM_FreeItem(&tmpitem, PR_FALSE);
+ goto done;
+ }
+
+ if((tmpitem.len == subjKeyID.len) &&
+ (memcmp(tmpitem.data, subjKeyID.data, subjKeyID.len) == 0)
+ ) {
+ cert = CERT_DupCertificate(head->cert);
+ if(cert == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "CERT_DupCertificate",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ "error code=%d", PORT_GetError());
+ SECITEM_FreeItem(&tmpitem, PR_FALSE);
+ goto done;
+ }
+ }
+ SECITEM_FreeItem(&tmpitem, PR_FALSE);
+ }
+ }
+ }
+
+done:
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if (name != NULL) {
+ CERT_DestroyName(name);
+ }
+
+ return(cert);
+}
+
+static xmlSecByte *
+xmlSecNssX509NameRead(xmlSecByte *str, int len) {
+ xmlSecByte name[256];
+ xmlSecByte value[256];
+ xmlSecByte *retval = NULL;
+ xmlSecByte *p = NULL;
+ int nameLen, valueLen;
+
+ xmlSecAssert2(str != NULL, NULL);
+
+ /* return string should be no longer than input string */
+ retval = (xmlSecByte *)PORT_Alloc(len+1);
+ if(retval == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PORT_Alloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+ p = retval;
+
+ while(len > 0) {
+ /* skip spaces after comma or semicolon */
+ while((len > 0) && isspace(*str)) {
+ ++str; --len;
+ }
+
+ nameLen = xmlSecNssX509NameStringRead(&str, &len, name, sizeof(name), '=', 0);
+ if(nameLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ memcpy(p, name, nameLen);
+ p+=nameLen;
+ *p++='=';
+ if(len > 0) {
+ ++str; --len;
+ if((*str) == '\"') {
+ valueLen = xmlSecNssX509NameStringRead(&str, &len,
+ value, sizeof(value), '"', 1);
+ if(valueLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ /* skip spaces before comma or semicolon */
+ while((len > 0) && isspace(*str)) {
+ ++str; --len;
+ }
+ if((len > 0) && ((*str) != ',')) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "comma is expected");
+ goto done;
+ }
+ if(len > 0) {
+ ++str; --len;
+ }
+ *p++='\"';
+ memcpy(p, value, valueLen);
+ p+=valueLen;
+ *p++='\"';
+ } else if((*str) == '#') {
+ /* TODO: read octect values */
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "reading octect values is not implemented yet");
+ goto done;
+ } else {
+ valueLen = xmlSecNssX509NameStringRead(&str, &len,
+ value, sizeof(value), ',', 1);
+ if(valueLen < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssX509NameStringRead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ memcpy(p, value, valueLen);
+ p+=valueLen;
+ if (len > 0)
+ *p++=',';
+ }
+ } else {
+ valueLen = 0;
+ }
+ if(len > 0) {
+ ++str; --len;
+ }
+ }
+
+ *p = 0;
+ return(retval);
+
+done:
+ PORT_Free(retval);
+ return (NULL);
+}
+
+static int
+xmlSecNssX509NameStringRead(xmlSecByte **str, int *strLen,
+ xmlSecByte *res, int resLen,
+ xmlSecByte delim, int ingoreTrailingSpaces) {
+ xmlSecByte *p, *q, *nonSpace;
+
+ xmlSecAssert2(str != NULL, -1);
+ xmlSecAssert2(strLen != NULL, -1);
+ xmlSecAssert2(res != NULL, -1);
+
+ p = (*str);
+ nonSpace = q = res;
+ while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) {
+ if((*p) != '\\') {
+ if(ingoreTrailingSpaces && !isspace(*p)) {
+ nonSpace = q;
+ }
+ *(q++) = *(p++);
+ } else {
+ ++p;
+ nonSpace = q;
+ if(xmlSecIsHex((*p))) {
+ if((p - (*str) + 1) >= (*strLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "two hex digits expected");
+ return(-1);
+ }
+ *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]);
+ p += 2;
+ } else {
+ if(((++p) - (*str)) >= (*strLen)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "escaped symbol missed");
+ return(-1);
+ }
+ *(q++) = *(p++);
+ }
+ }
+ }
+ if(((p - (*str)) < (*strLen)) && ((*p) != delim)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "buffer is too small");
+ return(-1);
+ }
+ (*strLen) -= (p - (*str));
+ (*str) = p;
+ return((ingoreTrailingSpaces) ? nonSpace - res + 1 : q - res);
+}
+
+/* code lifted from NSS */
+static int
+xmlSecNssNumToItem(SECItem *it, PRUint64 ui)
+{
+ unsigned char bb[9];
+ unsigned int zeros_len;
+
+ xmlSecAssert2(it != NULL, -1);
+
+ bb[0] = 0; /* important: we should have 0 at the beginning! */
+ bb[1] = (unsigned char) (ui >> 56);
+ bb[2] = (unsigned char) (ui >> 48);
+ bb[3] = (unsigned char) (ui >> 40);
+ bb[4] = (unsigned char) (ui >> 32);
+ bb[5] = (unsigned char) (ui >> 24);
+ bb[6] = (unsigned char) (ui >> 16);
+ bb[7] = (unsigned char) (ui >> 8);
+ bb[8] = (unsigned char) (ui);
+
+ /*
+ ** Small integers are encoded in a single byte. Larger integers
+ ** require progressively more space. Start from 1 because byte at
+ ** position 0 is zero
+ */
+ for(zeros_len = 1; (zeros_len < sizeof(bb)) && (bb[zeros_len] == 0); ++zeros_len);
+
+ it->len = sizeof(bb) - (zeros_len - 1);
+ it->data = (unsigned char *)PORT_Alloc(it->len);
+ if (it->data == NULL) {
+ it->len = 0;
+ return (-1);
+ }
+
+ PORT_Memcpy(it->data, bb + (zeros_len - 1), it->len);
+ return(it->len);
+}
+#endif /* XMLSEC_NO_X509 */
+
+