diff options
Diffstat (limited to 'src/gcrypt')
-rw-r--r-- | src/gcrypt/Makefile.am | 55 | ||||
-rw-r--r-- | src/gcrypt/Makefile.in | 794 | ||||
-rw-r--r-- | src/gcrypt/README | 9 | ||||
-rw-r--r-- | src/gcrypt/app.c | 663 | ||||
-rw-r--r-- | src/gcrypt/asn1.c | 602 | ||||
-rw-r--r-- | src/gcrypt/asn1.h | 39 | ||||
-rw-r--r-- | src/gcrypt/asymkeys.c | 1920 | ||||
-rw-r--r-- | src/gcrypt/ciphers.c | 855 | ||||
-rw-r--r-- | src/gcrypt/crypto.c | 315 | ||||
-rw-r--r-- | src/gcrypt/digests.c | 614 | ||||
-rw-r--r-- | src/gcrypt/globals.h | 30 | ||||
-rw-r--r-- | src/gcrypt/hmac.c | 823 | ||||
-rw-r--r-- | src/gcrypt/kw_aes.c | 593 | ||||
-rw-r--r-- | src/gcrypt/kw_des.c | 607 | ||||
-rw-r--r-- | src/gcrypt/signatures.c | 1490 | ||||
-rw-r--r-- | src/gcrypt/symkeys.c | 441 |
16 files changed, 9850 insertions, 0 deletions
diff --git a/src/gcrypt/Makefile.am b/src/gcrypt/Makefile.am new file mode 100644 index 00000000..734c429f --- /dev/null +++ b/src/gcrypt/Makefile.am @@ -0,0 +1,55 @@ +NULL = + +EXTRA_DIST = \ + README \ + $(NULL) + +lib_LTLIBRARIES = \ + libxmlsec1-gcrypt.la \ + $(NULL) + +libxmlsec1_gcrypt_la_CPPFLAGS = \ + -DPACKAGE=\"@PACKAGE@\" \ + -DGCRYPT_MIN_VERSION=\"$(GCRYPT_MIN_VERSION)\" \ + -I../../include \ + -I$(top_srcdir)/include \ + $(XMLSEC_DEFINES) \ + $(GCRYPT_CFLAGS) \ + $(LIBXSLT_CFLAGS) \ + $(LIBXML_CFLAGS) \ + $(NULL) + +libxmlsec1_gcrypt_la_SOURCES =\ + app.c \ + asn1.h \ + asn1.c \ + ciphers.c \ + crypto.c \ + digests.c \ + hmac.c \ + kw_aes.c \ + kw_des.c \ + symkeys.c \ + asymkeys.c \ + signatures.c \ + globals.h \ + $(NULL) + +if SHAREDLIB_HACK +libxmlsec1_gcrypt_la_SOURCES += ../strings.c +endif + +libxmlsec1_gcrypt_la_LIBADD = \ + $(GCRYPT_LIBS) \ + $(LIBXSLT_LIBS) \ + $(LIBXML_LIBS) \ + ../libxmlsec1.la \ + $(NULL) + +libxmlsec1_gcrypt_la_DEPENDENCIES = \ + $(NULL) + +libxmlsec1_gcrypt_la_LDFLAGS = \ + @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \ + -version-info @XMLSEC_VERSION_INFO@ \ + $(NULL) diff --git a/src/gcrypt/Makefile.in b/src/gcrypt/Makefile.in new file mode 100644 index 00000000..325e5cf8 --- /dev/null +++ b/src/gcrypt/Makefile.in @@ -0,0 +1,794 @@ +# Makefile.in generated by automake 1.11.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@SHAREDLIB_HACK_TRUE@am__append_1 = ../strings.c +subdir = src/gcrypt +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +am__libxmlsec1_gcrypt_la_SOURCES_DIST = app.c asn1.h asn1.c ciphers.c \ + crypto.c digests.c hmac.c kw_aes.c kw_des.c symkeys.c \ + asymkeys.c signatures.c globals.h ../strings.c +am__objects_1 = +@SHAREDLIB_HACK_TRUE@am__objects_2 = libxmlsec1_gcrypt_la-strings.lo +am_libxmlsec1_gcrypt_la_OBJECTS = libxmlsec1_gcrypt_la-app.lo \ + libxmlsec1_gcrypt_la-asn1.lo libxmlsec1_gcrypt_la-ciphers.lo \ + libxmlsec1_gcrypt_la-crypto.lo libxmlsec1_gcrypt_la-digests.lo \ + libxmlsec1_gcrypt_la-hmac.lo libxmlsec1_gcrypt_la-kw_aes.lo \ + libxmlsec1_gcrypt_la-kw_des.lo libxmlsec1_gcrypt_la-symkeys.lo \ + libxmlsec1_gcrypt_la-asymkeys.lo \ + libxmlsec1_gcrypt_la-signatures.lo $(am__objects_1) \ + $(am__objects_2) +libxmlsec1_gcrypt_la_OBJECTS = $(am_libxmlsec1_gcrypt_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +libxmlsec1_gcrypt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libxmlsec1_gcrypt_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libxmlsec1_gcrypt_la_SOURCES) +DIST_SOURCES = $(am__libxmlsec1_gcrypt_la_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +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@ +DLLTOOL = @DLLTOOL@ +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@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +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@ +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_AR = @ac_ct_AR@ +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@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +EXTRA_DIST = \ + README \ + $(NULL) + +lib_LTLIBRARIES = \ + libxmlsec1-gcrypt.la \ + $(NULL) + +libxmlsec1_gcrypt_la_CPPFLAGS = \ + -DPACKAGE=\"@PACKAGE@\" \ + -DGCRYPT_MIN_VERSION=\"$(GCRYPT_MIN_VERSION)\" \ + -I../../include \ + -I$(top_srcdir)/include \ + $(XMLSEC_DEFINES) \ + $(GCRYPT_CFLAGS) \ + $(LIBXSLT_CFLAGS) \ + $(LIBXML_CFLAGS) \ + $(NULL) + +libxmlsec1_gcrypt_la_SOURCES = app.c asn1.h asn1.c ciphers.c crypto.c \ + digests.c hmac.c kw_aes.c kw_des.c symkeys.c asymkeys.c \ + signatures.c globals.h $(NULL) $(am__append_1) +libxmlsec1_gcrypt_la_LIBADD = \ + $(GCRYPT_LIBS) \ + $(LIBXSLT_LIBS) \ + $(LIBXML_LIBS) \ + ../libxmlsec1.la \ + $(NULL) + +libxmlsec1_gcrypt_la_DEPENDENCIES = \ + $(NULL) + +libxmlsec1_gcrypt_la_LDFLAGS = \ + @XMLSEC_CRYPTO_EXTRA_LDFLAGS@ \ + -version-info @XMLSEC_VERSION_INFO@ \ + $(NULL) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gcrypt/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/gcrypt/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libxmlsec1-gcrypt.la: $(libxmlsec1_gcrypt_la_OBJECTS) $(libxmlsec1_gcrypt_la_DEPENDENCIES) $(EXTRA_libxmlsec1_gcrypt_la_DEPENDENCIES) + $(AM_V_CCLD)$(libxmlsec1_gcrypt_la_LINK) -rpath $(libdir) $(libxmlsec1_gcrypt_la_OBJECTS) $(libxmlsec1_gcrypt_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-app.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-digests.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-strings.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libxmlsec1_gcrypt_la-app.lo: app.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-app.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-app.Tpo -c -o libxmlsec1_gcrypt_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-app.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-app.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='app.c' object='libxmlsec1_gcrypt_la-app.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-app.lo `test -f 'app.c' || echo '$(srcdir)/'`app.c + +libxmlsec1_gcrypt_la-asn1.lo: asn1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-asn1.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Tpo -c -o libxmlsec1_gcrypt_la-asn1.lo `test -f 'asn1.c' || echo '$(srcdir)/'`asn1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-asn1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asn1.c' object='libxmlsec1_gcrypt_la-asn1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-asn1.lo `test -f 'asn1.c' || echo '$(srcdir)/'`asn1.c + +libxmlsec1_gcrypt_la-ciphers.lo: ciphers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-ciphers.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Tpo -c -o libxmlsec1_gcrypt_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-ciphers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ciphers.c' object='libxmlsec1_gcrypt_la-ciphers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-ciphers.lo `test -f 'ciphers.c' || echo '$(srcdir)/'`ciphers.c + +libxmlsec1_gcrypt_la-crypto.lo: crypto.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-crypto.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Tpo -c -o libxmlsec1_gcrypt_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-crypto.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto.c' object='libxmlsec1_gcrypt_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c + +libxmlsec1_gcrypt_la-digests.lo: digests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-digests.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-digests.Tpo -c -o libxmlsec1_gcrypt_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-digests.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-digests.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='digests.c' object='libxmlsec1_gcrypt_la-digests.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-digests.lo `test -f 'digests.c' || echo '$(srcdir)/'`digests.c + +libxmlsec1_gcrypt_la-hmac.lo: hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-hmac.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Tpo -c -o libxmlsec1_gcrypt_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-hmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac.c' object='libxmlsec1_gcrypt_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c + +libxmlsec1_gcrypt_la-kw_aes.lo: kw_aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-kw_aes.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Tpo -c -o libxmlsec1_gcrypt_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-kw_aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kw_aes.c' object='libxmlsec1_gcrypt_la-kw_aes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-kw_aes.lo `test -f 'kw_aes.c' || echo '$(srcdir)/'`kw_aes.c + +libxmlsec1_gcrypt_la-kw_des.lo: kw_des.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-kw_des.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Tpo -c -o libxmlsec1_gcrypt_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-kw_des.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kw_des.c' object='libxmlsec1_gcrypt_la-kw_des.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-kw_des.lo `test -f 'kw_des.c' || echo '$(srcdir)/'`kw_des.c + +libxmlsec1_gcrypt_la-symkeys.lo: symkeys.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-symkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Tpo -c -o libxmlsec1_gcrypt_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-symkeys.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='symkeys.c' object='libxmlsec1_gcrypt_la-symkeys.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-symkeys.lo `test -f 'symkeys.c' || echo '$(srcdir)/'`symkeys.c + +libxmlsec1_gcrypt_la-asymkeys.lo: asymkeys.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-asymkeys.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Tpo -c -o libxmlsec1_gcrypt_la-asymkeys.lo `test -f 'asymkeys.c' || echo '$(srcdir)/'`asymkeys.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-asymkeys.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asymkeys.c' object='libxmlsec1_gcrypt_la-asymkeys.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-asymkeys.lo `test -f 'asymkeys.c' || echo '$(srcdir)/'`asymkeys.c + +libxmlsec1_gcrypt_la-signatures.lo: signatures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-signatures.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Tpo -c -o libxmlsec1_gcrypt_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-signatures.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='signatures.c' object='libxmlsec1_gcrypt_la-signatures.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-signatures.lo `test -f 'signatures.c' || echo '$(srcdir)/'`signatures.c + +libxmlsec1_gcrypt_la-strings.lo: ../strings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxmlsec1_gcrypt_la-strings.lo -MD -MP -MF $(DEPDIR)/libxmlsec1_gcrypt_la-strings.Tpo -c -o libxmlsec1_gcrypt_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxmlsec1_gcrypt_la-strings.Tpo $(DEPDIR)/libxmlsec1_gcrypt_la-strings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../strings.c' object='libxmlsec1_gcrypt_la-strings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxmlsec1_gcrypt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxmlsec1_gcrypt_la-strings.lo `test -f '../strings.c' || echo '$(srcdir)/'`../strings.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/gcrypt/README b/src/gcrypt/README new file mode 100644 index 00000000..dcaa5a0d --- /dev/null +++ b/src/gcrypt/README @@ -0,0 +1,9 @@ +The xmlsec-gcrypt implementation is really limited and is not ready +for production use. The only supported crypto transforms are: + + - HMAC + - Tripple DES + - AES [128|192|256] + - SHA1 + + diff --git a/src/gcrypt/app.c b/src/gcrypt/app.c new file mode 100644 index 00000000..ab95f6dd --- /dev/null +++ b/src/gcrypt/app.c @@ -0,0 +1,663 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/app.h> +#include <xmlsec/gcrypt/crypto.h> + +#include "asn1.h" + +/** + * xmlSecGCryptAppInit: + * @config: the path to GCrypt configuration (unused). + * + * General crypto engine initialization. This function is used + * by XMLSec command line utility and called before + * @xmlSecInit function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppInit(const char* config ATTRIBUTE_UNUSED) { + /* Secure memory initialisation based on documentation from: + http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html + NOTE sample code don't check gcry_control(...) return code + + All flags from: + http://www.gnupg.org/documentation/manuals/gcrypt/Controlling-the-library.html + + Also libgcrypt NEWS entries: ++++++ +..... +Noteworthy changes in version 1.4.3 (2008-09-18) +------------------------------------------------ + + * Try to auto-initialize Libgcrypt to minimize the effect of + applications not doing that correctly. This is not a perfect + solution but given that many applicationion would totally fail + without such a hack, we try to help at least with the most common + cases. Folks, please read the manual to learn how to properly + initialize Libgcrypt! + + * Auto-initialize the secure memory to 32k instead of aborting the + process. +..... ++++++ + */ + + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + + /* NOTE configure.in defines GCRYPT_MIN_VERSION */ + if (!gcry_check_version (GCRYPT_MIN_VERSION)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_check_version", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* We don't want to see any warnings, e.g. because we have not yet + parsed program options which might be used to suppress such + warnings. */ + gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN); + + /* ... If required, other initialization goes here. Note that the + process might still be running with increased privileges and that + the secure memory has not been intialized. */ + + /* Allocate a pool of 32k secure memory. This make the secure memory + available and also drops privileges where needed. */ + gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0); + + /* It is now okay to let Libgcrypt complain when there was/is + a problem with the secure memory. */ + gcry_control(GCRYCTL_RESUME_SECMEM_WARN); + + /* ... If required, other initialization goes here. */ + + /* Tell Libgcrypt that initialization has completed. */ + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + + return(0); +} + +/** + * xmlSecGCryptAppShutdown: + * + * General crypto engine shutdown. This function is used + * by XMLSec command line utility and called after + * @xmlSecShutdown function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppShutdown(void) { + gcry_error_t err; + + err = gcry_control(GCRYCTL_TERM_SECMEM); + if (gcry_err_code(err)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_control(GCRYCTL_TERM_SECMEM)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + +/** + * xmlSecGCryptAppKeyLoad: + * @filename: the key filename. + * @format: the key file format. + * @pwd: the key file password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from the a file. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecGCryptAppKeyLoad(const char *filename, xmlSecKeyDataFormat format, + const char *pwd, + void* pwdCallback, + void* pwdCallbackCtx) { + xmlSecKeyPtr key; + xmlSecBuffer buffer; + int ret; + + xmlSecAssert2(filename != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + ret = xmlSecBufferInitialize(&buffer, 4*1024); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + ret = xmlSecBufferReadFile(&buffer, filename); + if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferReadFile", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s", + xmlSecErrorsSafeString(filename)); + xmlSecBufferFinalize(&buffer); + return(NULL); + } + + key = xmlSecGCryptAppKeyLoadMemory(xmlSecBufferGetData(&buffer), + xmlSecBufferGetSize(&buffer), + format, pwd, pwdCallback, pwdCallbackCtx); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeyLoadMemory", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s", + xmlSecErrorsSafeString(filename)); + xmlSecBufferFinalize(&buffer); + return(NULL); + } + + /* cleanup */ + xmlSecBufferFinalize(&buffer); + return(key); +} + +/** + * xmlSecGCryptAppKeyLoadMemory: + * @data: the binary key data. + * @dataSize: the size of binary key. + * @format: the key file format. + * @pwd: the key file password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from the memory buffer. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecGCryptAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, + xmlSecKeyDataFormat format, + const char *pwd ATTRIBUTE_UNUSED, + void* pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) +{ + xmlSecKeyPtr key = NULL; + xmlSecKeyDataPtr key_data = NULL; + int ret; + + xmlSecAssert2(data != NULL, NULL); + xmlSecAssert2(dataSize > 0, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + switch(format) { + case xmlSecKeyDataFormatDer: + key_data = xmlSecGCryptParseDer(data, dataSize, xmlSecGCryptDerKeyTypeAuto); + if(key_data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptParseDer", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; + case xmlSecKeyDataFormatPem: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeyLoadMemory", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return (NULL); +#ifndef XMLSEC_NO_X509 + case xmlSecKeyDataFormatPkcs12: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeyLoadMemory", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return (NULL); +#endif /* XMLSEC_NO_X509 */ + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", format); + return(NULL); + } + + /* we should have key data by now */ + xmlSecAssert2(key_data != NULL, NULL); + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(key_data); + return(NULL); + } + + ret = xmlSecKeySetValue(key, key_data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(key_data))); + xmlSecKeyDestroy(key); + xmlSecKeyDataDestroy(key_data); + return(NULL); + } + key_data = NULL; /* key_data is owned by key */ + + /* done */ + return(key); +} + +#ifndef XMLSEC_NO_X509 +/** + * xmlSecGCryptAppKeyCertLoad: + * @key: the pointer to key. + * @filename: the certificate filename. + * @format: the certificate file format. + * + * Reads the certificate from $@filename and adds it to key + * (not implemented yet). + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, + xmlSecKeyDataFormat format) { + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(filename != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + /* TODO */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeyCertLoad", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); +} + +/** + * xmlSecGCryptAppKeyCertLoadMemory: + * @key: the pointer to key. + * @data: the certificate binary data. + * @dataSize: the certificate binary data size. + * @format: the certificate file format. + * + * Reads the certificate from memory buffer and adds it to key (not implemented yet). + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppKeyCertLoadMemory(xmlSecKeyPtr key, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecKeyDataFormat format) { + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(dataSize > 0, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + /* TODO */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeyCertLoadMemory", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); +} + +/** + * xmlSecGCryptAppPkcs12Load: + * @filename: the PKCS12 key filename. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 file + * (not implemented yet). + * For uniformity, call xmlSecGCryptAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecGCryptAppPkcs12Load(const char *filename, + const char *pwd ATTRIBUTE_UNUSED, + void* pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) { + xmlSecAssert2(filename != NULL, NULL); + + /* TODO */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppPkcs12Load", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); +} + +/** + * xmlSecGCryptAppPkcs12LoadMemory: + * @data: the PKCS12 binary data. + * @dataSize: the PKCS12 binary data size. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 data in memory buffer. + * For uniformity, call xmlSecGCryptAppKeyLoadMemory instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12 (not implemented yet). + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecGCryptAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, + const char *pwd ATTRIBUTE_UNUSED, + void* pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) { + xmlSecAssert2(data != NULL, NULL); + xmlSecAssert2(dataSize > 0, NULL); + + /* TODO */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppPkcs12LoadMemory", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); +} + +/** + * xmlSecGCryptAppKeysMngrCertLoad: + * @mngr: the keys manager. + * @filename: the certificate file. + * @format: the certificate file format. + * @type: the flag that indicates is the certificate in @filename + * trusted or not. + * + * Reads cert from @filename and adds to the list of trusted or known + * untrusted certs in @store (not implemented yet). + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, + const char *filename, + xmlSecKeyDataFormat format, + xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(filename != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + /* TODO */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeysMngrCertLoad", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); +} + +/** + * xmlSecGCryptAppKeysMngrCertLoadMemory: + * @mngr: the keys manager. + * @data: the certificate binary data. + * @dataSize: the certificate binary data size. + * @format: the certificate file format. + * @type: the flag that indicates is the certificate trusted or not. + * + * Reads cert from binary buffer @data and adds to the list of trusted or known + * untrusted certs in @store (not implemented yet). + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecKeyDataFormat format, + xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(dataSize > 0, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + /* TODO */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppKeysMngrCertLoadMemory", + XMLSEC_ERRORS_R_NOT_IMPLEMENTED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); +} + +#endif /* XMLSEC_NO_X509 */ + +/** + * xmlSecGCryptAppDefaultKeysMngrInit: + * @mngr: the pointer to keys manager. + * + * Initializes @mngr with simple keys store #xmlSecSimpleKeysStoreId + * and a default GCrypt crypto key data stores. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) { + int ret; + + xmlSecAssert2(mngr != NULL, -1); + + /* create simple keys store if needed */ + if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) { + xmlSecKeyStorePtr keysStore; + + keysStore = xmlSecKeyStoreCreate(xmlSecSimpleKeysStoreId); + if(keysStore == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyStoreCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecSimpleKeysStoreId"); + return(-1); + } + + ret = xmlSecKeysMngrAdoptKeysStore(mngr, keysStore); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrAdoptKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyStoreDestroy(keysStore); + return(-1); + } + } + + ret = xmlSecGCryptKeysMngrInit(mngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKeysMngrInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* TODO */ + mngr->getKey = xmlSecKeysMngrGetKey; + return(0); +} + +/** + * xmlSecGCryptAppDefaultKeysMngrAdoptKey: + * @mngr: the pointer to keys manager. + * @key: the pointer to key. + * + * Adds @key to the keys manager @mngr created with #xmlSecGCryptAppDefaultKeysMngrInit + * function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) { + xmlSecKeyStorePtr store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(key != NULL, -1); + + store = xmlSecKeysMngrGetKeysStore(mngr); + if(store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecSimpleKeysStoreAdoptKey(store, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSimpleKeysStoreAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecGCryptAppDefaultKeysMngrLoad: + * @mngr: the pointer to keys manager. + * @uri: the uri. + * + * Loads XML keys file from @uri to the keys manager @mngr created + * with #xmlSecGCryptAppDefaultKeysMngrInit function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) { + xmlSecKeyStorePtr store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(uri != NULL, -1); + + store = xmlSecKeysMngrGetKeysStore(mngr); + if(store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecSimpleKeysStoreLoad(store, uri, mngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSimpleKeysStoreLoad", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "uri=%s", xmlSecErrorsSafeString(uri)); + return(-1); + } + + return(0); +} + +/** + * xmlSecGCryptAppDefaultKeysMngrSave: + * @mngr: the pointer to keys manager. + * @filename: the destination filename. + * @type: the type of keys to save (public/private/symmetric). + * + * Saves keys from @mngr to XML keys file. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename, xmlSecKeyDataType type) { + xmlSecKeyStorePtr store; + int ret; + + xmlSecAssert2(mngr != NULL, -1); + xmlSecAssert2(filename != NULL, -1); + + store = xmlSecKeysMngrGetKeysStore(mngr); + if(store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecSimpleKeysStoreSave(store, filename, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecSimpleKeysStoreSave", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename=%s", + xmlSecErrorsSafeString(filename)); + return(-1); + } + + return(0); +} + +/** + * xmlSecGCryptAppGetDefaultPwdCallback: + * + * Gets default password callback. + * + * Returns: default password callback. + */ +void* +xmlSecGCryptAppGetDefaultPwdCallback(void) { + return(NULL); +} + diff --git a/src/gcrypt/asn1.c b/src/gcrypt/asn1.c new file mode 100644 index 00000000..b1388420 --- /dev/null +++ b/src/gcrypt/asn1.c @@ -0,0 +1,602 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + +#include "asn1.h" + +/************************************************************************** + * + * ASN.1 parser is taken from GCrypt tests + * + *************************************************************************/ + +/* ASN.1 classes. */ +enum +{ + UNIVERSAL = 0, + APPLICATION = 1, + ASNCONTEXT = 2, + PRIVATE = 3 +}; + + +/* ASN.1 tags. */ +enum +{ + TAG_NONE = 0, + TAG_BOOLEAN = 1, + TAG_INTEGER = 2, + TAG_BIT_STRING = 3, + TAG_OCTET_STRING = 4, + TAG_NULL = 5, + TAG_OBJECT_ID = 6, + TAG_OBJECT_DESCRIPTOR = 7, + TAG_EXTERNAL = 8, + TAG_REAL = 9, + TAG_ENUMERATED = 10, + TAG_EMBEDDED_PDV = 11, + TAG_UTF8_STRING = 12, + TAG_REALTIVE_OID = 13, + TAG_SEQUENCE = 16, + TAG_SET = 17, + TAG_NUMERIC_STRING = 18, + TAG_PRINTABLE_STRING = 19, + TAG_TELETEX_STRING = 20, + TAG_VIDEOTEX_STRING = 21, + TAG_IA5_STRING = 22, + TAG_UTC_TIME = 23, + TAG_GENERALIZED_TIME = 24, + TAG_GRAPHIC_STRING = 25, + TAG_VISIBLE_STRING = 26, + TAG_GENERAL_STRING = 27, + TAG_UNIVERSAL_STRING = 28, + TAG_CHARACTER_STRING = 29, + TAG_BMP_STRING = 30 +}; + +/* ASN.1 Parser object. */ +struct tag_info +{ + int class; /* Object class. */ + unsigned long tag; /* The tag of the object. */ + unsigned long length; /* Length of the values. */ + int nhdr; /* Length of the header (TL). */ + unsigned int ndef:1; /* The object has an indefinite length. */ + unsigned int cons:1; /* This is a constructed object. */ +}; + +/* Parse the buffer at the address BUFFER which consists of the number + of octets as stored at BUFLEN. Return the tag and the length part + from the TLV triplet. Update BUFFER and BUFLEN on success. Checks + that the encoded length does not exhaust the length of the provided + buffer. */ +static int +xmlSecGCryptAsn1ParseTag (xmlSecByte const **buffer, xmlSecSize *buflen, struct tag_info *ti) +{ + int c; + unsigned long tag; + const xmlSecByte *buf; + xmlSecSize length; + + xmlSecAssert2(buffer != NULL, -1); + xmlSecAssert2((*buffer) != NULL, -1); + xmlSecAssert2(buflen != NULL, -1); + xmlSecAssert2(ti != NULL, -1); + + /* initialize */ + buf = *buffer; + length = *buflen; + + ti->length = 0; + ti->ndef = 0; + ti->nhdr = 0; + + /* Get the tag */ + if (length <= 0) { + return(-1); /* Premature EOF. */ + } + c = *buf++; + length--; + ti->nhdr++; + + ti->class = (c & 0xc0) >> 6; + ti->cons = !!(c & 0x20); + tag = (c & 0x1f); + + if (tag == 0x1f) { + tag = 0; + do { + tag <<= 7; + if (length <= 0) { + return(-1); /* Premature EOF. */ + } + c = *buf++; + length--; + ti->nhdr++; + tag |= (c & 0x7f); + } while ( (c & 0x80) ); + } + ti->tag = tag; + + /* Get the length */ + if(length <= 0) { + return -1; /* Premature EOF. */ + } + c = *buf++; + length--; + ti->nhdr++; + + if ( !(c & 0x80) ) { + ti->length = c; + } else if (c == 0x80) { + ti->ndef = 1; + } else if (c == 0xff) { + return -1; /* Forbidden length value. */ + } else { + xmlSecSize len = 0; + int count = c & 0x7f; + + for (; count; count--) { + len <<= 8; + if (length <= 0) { + return -1; /* Premature EOF. */ + } + c = *buf++; length--; + ti->nhdr++; + len |= (c & 0xff); + } + ti->length = len; + } + + if (ti->class == UNIVERSAL && !ti->tag) { + ti->length = 0; + } + + if (ti->length > length) { + return(-1); /* Data larger than buffer. */ + } + + /* done */ + *buffer = buf; + *buflen = length; + return(0); +} + +static int +xmlSecGCryptAsn1ParseIntegerSequence(xmlSecByte const **buffer, xmlSecSize *buflen, + gcry_mpi_t * params, int params_size) { + const xmlSecByte *buf; + xmlSecSize length; + struct tag_info ti; + gcry_error_t err; + int idx = 0; + int ret; + + xmlSecAssert2(buffer != NULL, -1); + xmlSecAssert2((*buffer) != NULL, -1); + xmlSecAssert2(buflen != NULL, -1); + xmlSecAssert2(params != NULL, -1); + xmlSecAssert2(params_size > 0, -1); + + /* initialize */ + buf = *buffer; + length = *buflen; + + /* read SEQUENCE */ + memset(&ti, 0, sizeof(ti)); + ret = xmlSecGCryptAsn1ParseTag (&buf, &length, &ti); + if((ret != 0) || (ti.tag != TAG_SEQUENCE) || ti.class || !ti.cons || ti.ndef) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsn1ParseTag", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "TAG_SEQUENCE is expected: tag=%d", + (int)ti.tag); + return(-1); + } + + /* read INTEGERs */ + for (idx = 0; ((idx < params_size) && (length > 0)); idx++) { + memset(&ti, 0, sizeof(ti)); + ret = xmlSecGCryptAsn1ParseTag (&buf, &length, &ti); + if((ret != 0) || (ti.tag != TAG_INTEGER) || ti.class || ti.cons || ti.ndef) + { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsn1ParseTag", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "TAG_INTEGER is expected - index=%d, tag=%d", + (int)idx, (int)ti.tag); + return(-1); + } + + err = gcry_mpi_scan(&(params[idx]), GCRYMPI_FMT_USG, buf, ti.length, NULL); + if((err != GPG_ERR_NO_ERROR) || (params[idx] == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + buf += ti.length; + length -= ti.length; + } + + /* did we parse everything? */ + if(length > 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsn1ParseTag", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "too many params - cur=%d, expected=%d", + (int)(idx - 1), (int)params_size); + return(-1); + } + + /* done */ + *buffer = buf; + *buflen = length; + return(idx); +} + +xmlSecKeyDataPtr +xmlSecGCryptParseDer(const xmlSecByte * der, xmlSecSize derlen, + enum xmlSecGCryptDerKeyType type) { + xmlSecKeyDataPtr key_data = NULL; + gcry_sexp_t s_pub_key = NULL; + gcry_sexp_t s_priv_key = NULL; + gcry_error_t err; + gcry_mpi_t keyparms[20]; + int keyparms_num; + unsigned int idx; + int ret; + + xmlSecAssert2(der != NULL, NULL); + xmlSecAssert2(derlen > 0, NULL); + + /* Parse the ASN.1 structure. */ + memset(&keyparms, 0, sizeof(keyparms)); + ret = xmlSecGCryptAsn1ParseIntegerSequence( + &der, &derlen, + keyparms, sizeof(keyparms) / sizeof(keyparms[0]) + ); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsn1ParseIntegerSequence", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + keyparms_num = ret; + + /* The value of the first integer should be 0. */ + if ((keyparms_num < 1) || (gcry_mpi_cmp_ui(keyparms[0], 0) != 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsn1ParseTag", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "num=%d", + (int)keyparms_num); + goto done; + } + + /* do we need to guess the key type? not robust but the best we can do */ + if(type == xmlSecGCryptDerKeyTypeAuto) { + switch(keyparms_num) { + case 3: + /* Public RSA */ + type = xmlSecGCryptDerKeyTypePublicRsa; + case 5: + /* Public DSA */ + type = xmlSecGCryptDerKeyTypePublicDsa; + case 6: + /* Private DSA */ + type = xmlSecGCryptDerKeyTypePrivateDsa; + break; + case 9: + /* Private RSA */ + type = xmlSecGCryptDerKeyTypePrivateRsa; + break; + default: + /* unknown */ + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Unexpected number of parameters, unknown key type", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "keyparms_num=%d", (int)keyparms_num); + goto done; + } + } + + + switch(type) { +#ifndef XMLSEC_NO_DSA + case xmlSecGCryptDerKeyTypePrivateDsa: + /* check we have enough params */ + if(keyparms_num != 6) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Private DSA key: 6 parameters exepcted", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "parms_num=%d", (int)keyparms_num); + goto done; + } + + /* Convert from OpenSSL parameter ordering to the OpenPGP order. */ + /* First check that x < y; if not swap x and y */ + if (gcry_mpi_cmp (keyparms[4], keyparms[5]) > 0) { + gcry_mpi_swap (keyparms[4], keyparms[5]); + } + + /* Build the S-expressions */ + err = gcry_sexp_build (&s_priv_key, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(x%m)(y%m)))", + keyparms[1], keyparms[2], keyparms[3], keyparms[4], keyparms[5] + ); + if((err != GPG_ERR_NO_ERROR) || (s_priv_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(private-key/dsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_sexp_build (&s_pub_key, NULL, + "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", + keyparms[1], keyparms[2], keyparms[3], keyparms[5] + ); + if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(public-key/dsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* construct key and key data */ + key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataDsaId); + if(key_data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataDsaId"); + goto done; + } + + ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(key_data, s_pub_key, s_priv_key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKeyDataDsaAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataDsaId"); + xmlSecKeyDataDestroy(key_data); + key_data = NULL; + goto done; + } + s_pub_key = NULL; /* owned by key_data now */ + s_priv_key = NULL; /* owned by key_data now */ + break; + + case xmlSecGCryptDerKeyTypePublicDsa: + /* check we have enough params */ + if(keyparms_num != 5) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Public DSA key: 5 parameters exepcted", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "parms_num=%d", (int)keyparms_num); + goto done; + } + + /* Build the S-expression. */ + err = gcry_sexp_build (&s_pub_key, NULL, + "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", + keyparms[2], keyparms[3], keyparms[4], keyparms[1] + ); + if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(public-key/dsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* construct key and key data */ + key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataDsaId); + if(key_data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataDsaId"); + goto done; + } + + ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(key_data, s_pub_key, NULL); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKeyDataDsaAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataDsaId"); + xmlSecKeyDataDestroy(key_data); + key_data = NULL; + goto done; + } + s_pub_key = NULL; /* owned by key_data now */ + break; +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + case xmlSecGCryptDerKeyTypePrivateRsa: + /* check we have enough params */ + if(keyparms_num != 9) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Private RSA key: 9 parameters exepcted", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "parms_num=%d", (int)keyparms_num); + goto done; + } + + /* Convert from OpenSSL parameter ordering to the OpenPGP order. */ + /* First check that p < q; if not swap p and q and recompute u. */ + if (gcry_mpi_cmp (keyparms[4], keyparms[5]) > 0) { + gcry_mpi_swap (keyparms[4], keyparms[5]); + gcry_mpi_invm (keyparms[8], keyparms[4], keyparms[5]); + } + + /* Build the S-expression. */ + err = gcry_sexp_build (&s_priv_key, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + keyparms[1], keyparms[2], + keyparms[3], keyparms[4], + keyparms[5], keyparms[8] + ); + if((err != GPG_ERR_NO_ERROR) || (s_priv_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(private-key/rsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_sexp_build (&s_pub_key, NULL, + "(public-key(rsa(n%m)(e%m)))", + keyparms[1], keyparms[2] + ); + if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(public-key/rsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* construct key and key data */ + key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataRsaId); + if(key_data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataRsaId"); + goto done; + } + + ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(key_data, s_pub_key, s_priv_key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKeyDataRsaAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataRsaId"); + xmlSecKeyDataDestroy(key_data); + key_data = NULL; + goto done; + } + s_pub_key = NULL; /* owned by key_data now */ + s_priv_key = NULL; /* owned by key_data now */ + break; + + case xmlSecGCryptDerKeyTypePublicRsa: + /* check we have enough params */ + if(keyparms_num != 3) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Public RSA key: 3 parameters exepcted", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "parms_num=%d", (int)keyparms_num); + goto done; + } + + /* Build the S-expression. */ + err = gcry_sexp_build (&s_pub_key, NULL, + "(public-key(rsa(n%m)(e%m)))", + keyparms[1], keyparms[2] + ); + if((err != GPG_ERR_NO_ERROR) || (s_pub_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(public-key/rsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* construct key and key data */ + key_data = xmlSecKeyDataCreate(xmlSecGCryptKeyDataRsaId); + if(key_data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataRsaId"); + goto done; + } + + ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(key_data, s_pub_key, NULL); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKeyDataRsaAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecGCryptKeyDataRsaId"); + xmlSecKeyDataDestroy(key_data); + key_data = NULL; + goto done; + } + s_pub_key = NULL; /* owned by key_data now */ + break; +#endif /* XMLSEC_NO_RSA */ + + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "Unsupported key type", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "type=%d", (int)type); + goto done; + break; + } + +done: + if(s_priv_key != NULL) { + gcry_sexp_release(s_priv_key); + } + if(s_pub_key != NULL) { + gcry_sexp_release(s_pub_key); + } + for (idx = 0; idx < sizeof(keyparms) / sizeof(keyparms[0]); idx++) { + if(keyparms[idx] != NULL) { + gcry_mpi_release (keyparms[idx]); + } + } + + return(key_data); +} diff --git a/src/gcrypt/asn1.h b/src/gcrypt/asn1.h new file mode 100644 index 00000000..d05b5305 --- /dev/null +++ b/src/gcrypt/asn1.h @@ -0,0 +1,39 @@ +/* + * XML Security Library + * + * gcrypt/asn1.h: internal header only used during the compilation + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef __XMLSEC_GCRYPT_ASN1_H__ +#define __XMLSEC_GCRYPT_ASN1_H__ + +#ifndef XMLSEC_PRIVATE +#error "gcrypt/asn1.h file contains private xmlsec-gcrypt definitions and should not be used outside xmlsec or xmlsec-<crypto> libraries" +#endif /* XMLSEC_PRIVATE */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum xmlSecGCryptDerKeyType { + xmlSecGCryptDerKeyTypeAuto = 0, + xmlSecGCryptDerKeyTypePublicDsa, + xmlSecGCryptDerKeyTypePublicRsa, + xmlSecGCryptDerKeyTypePrivateDsa, + xmlSecGCryptDerKeyTypePrivateRsa +}; + +xmlSecKeyDataPtr xmlSecGCryptParseDer (const xmlSecByte * der, + xmlSecSize derlen, + enum xmlSecGCryptDerKeyType type); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /*__XMLSEC_GCRYPT_ASN1_H__ */ diff --git a/src/gcrypt/asymkeys.c b/src/gcrypt/asymkeys.c new file mode 100644 index 00000000..8f0cec88 --- /dev/null +++ b/src/gcrypt/asymkeys.c @@ -0,0 +1,1920 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/base64.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + +/************************************************************************** + * + * Helpers + * + *************************************************************************/ +static gcry_sexp_t xmlSecGCryptAsymSExpDup (gcry_sexp_t sexp); + + +/************************************************************************** + * + * Internal GCrypt asym key CTX + * + *************************************************************************/ +typedef struct _xmlSecGCryptAsymKeyDataCtx xmlSecGCryptAsymKeyDataCtx, + *xmlSecGCryptAsymKeyDataCtxPtr; +struct _xmlSecGCryptAsymKeyDataCtx { + gcry_sexp_t pub_key; + gcry_sexp_t priv_key; +}; + +/****************************************************************************** + * + * Asym key (dsa/rsa) + * + * xmlSecGCryptAsymKeyDataCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecGCryptAsymKeyDataSize \ + (sizeof(xmlSecKeyData) + sizeof(xmlSecGCryptAsymKeyDataCtx)) +#define xmlSecGCryptAsymKeyDataGetCtx(data) \ + ((xmlSecGCryptAsymKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData))) + +static int xmlSecGCryptAsymKeyDataInitialize (xmlSecKeyDataPtr data); +static int xmlSecGCryptAsymKeyDataDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecGCryptAsymKeyDataFinalize (xmlSecKeyDataPtr data); + +static int xmlSecGCryptAsymKeyDataAdoptKey (xmlSecKeyDataPtr data, + gcry_sexp_t key_pair); +static int xmlSecGCryptAsymKeyDataAdoptKeyPair (xmlSecKeyDataPtr data, + gcry_sexp_t pub_key, + gcry_sexp_t priv_key); +static gcry_sexp_t xmlSecGCryptAsymKeyDataGetPublicKey (xmlSecKeyDataPtr data); +static gcry_sexp_t xmlSecGCryptAsymKeyDataGetPrivateKey (xmlSecKeyDataPtr data); +static int xmlSecGCryptAsymKeyDataGenerate (xmlSecKeyDataPtr data, + const char * alg, + xmlSecSize key_size); +static xmlSecKeyDataType xmlSecGCryptAsymKeyDataGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecGCryptAsymKeyDataGetSize (xmlSecKeyDataPtr data); + + +static int +xmlSecGCryptAsymKeyDataInitialize(xmlSecKeyDataPtr data) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecGCryptAsymKeyDataCtx)); + + return(0); +} + +static int +xmlSecGCryptAsymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecGCryptAsymKeyDataCtxPtr ctxDst; + xmlSecGCryptAsymKeyDataCtxPtr ctxSrc; + + xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecGCryptAsymKeyDataSize), -1); + xmlSecAssert2(xmlSecKeyDataIsValid(src), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecGCryptAsymKeyDataSize), -1); + + ctxDst = xmlSecGCryptAsymKeyDataGetCtx(dst); + xmlSecAssert2(ctxDst != NULL, -1); + xmlSecAssert2(ctxDst->pub_key == NULL, -1); + xmlSecAssert2(ctxDst->priv_key == NULL, -1); + + ctxSrc = xmlSecGCryptAsymKeyDataGetCtx(src); + xmlSecAssert2(ctxSrc != NULL, -1); + + if(ctxSrc->pub_key != NULL) { + ctxDst->pub_key = xmlSecGCryptAsymSExpDup(ctxSrc->pub_key); + if(ctxDst->pub_key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "xmlSecGCryptAsymSExpDup(pub_key)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + if(ctxSrc->priv_key != NULL) { + ctxDst->priv_key = xmlSecGCryptAsymSExpDup(ctxSrc->priv_key); + if(ctxDst->priv_key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), + "xmlSecGCryptAsymSExpDup(priv_key)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + return(0); +} + +static void +xmlSecGCryptAsymKeyDataFinalize(xmlSecKeyDataPtr data) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert(xmlSecKeyDataIsValid(data)); + xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize)); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert(ctx != NULL); + + if(ctx->pub_key != NULL) { + gcry_sexp_release(ctx->pub_key); + } + if(ctx->priv_key != NULL) { + gcry_sexp_release(ctx->priv_key); + } + memset(ctx, 0, sizeof(xmlSecGCryptAsymKeyDataCtx)); +} + +static int +xmlSecGCryptAsymKeyDataAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t key_pair) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + gcry_sexp_t pub_key = NULL; + gcry_sexp_t priv_key = NULL; + int res = -1; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1); + xmlSecAssert2(key_pair != NULL, -1); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + /* split the key pair, public part should be always present, private might + not be present */ + pub_key = gcry_sexp_find_token(key_pair, "public-key", 0); + if(pub_key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(public-key)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + priv_key = gcry_sexp_find_token(key_pair, "private-key", 0); + + /* assign */ + if(xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsymKeyDataAdoptKeyPair", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + pub_key = NULL; /* data owns it now */ + priv_key = NULL; /* data owns it now */ + + /* success */ + res = 0; + +done: + if(pub_key != NULL) { + gcry_sexp_release(pub_key); + } + + if(priv_key != NULL) { + gcry_sexp_release(priv_key); + } + + /* done */ + return(res); +} + +static int +xmlSecGCryptAsymKeyDataAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1); + xmlSecAssert2(pub_key != NULL, -1); /* public key should present always */ +/* + aleksey - we don't set optional parameters for RSA keys (p, k, u) and + because of that we can't actually test the key + + xmlSecAssert2(((priv_key == NULL) || (gcry_pk_testkey(priv_key) == GPG_ERR_NO_ERROR)), -1); +*/ + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + /* release prev values and assign new ones */ + if(ctx->pub_key != NULL) { + gcry_sexp_release(ctx->pub_key); + } + if(ctx->priv_key != NULL) { + gcry_sexp_release(ctx->priv_key); + } + + ctx->pub_key = pub_key; + ctx->priv_key = priv_key; + + /* done */ + return(0); +} + +static gcry_sexp_t +xmlSecGCryptAsymKeyDataGetPublicKey(xmlSecKeyDataPtr data) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), NULL); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, NULL); + + return(ctx->pub_key); +} + +static gcry_sexp_t +xmlSecGCryptAsymKeyDataGetPrivateKey(xmlSecKeyDataPtr data) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), NULL); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, NULL); + + return(ctx->priv_key); +} + +static int +xmlSecGCryptAsymKeyDataGenerate(xmlSecKeyDataPtr data, const char * alg, xmlSecSize key_size) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + gcry_sexp_t key_spec = NULL; + gcry_sexp_t key_pair = NULL; + gcry_error_t err; + int ret; + int res = -1; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1); + xmlSecAssert2(alg != NULL, -1); + xmlSecAssert2(key_size > 0, -1); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, -1); + + err = gcry_sexp_build(&key_spec, NULL, + "(genkey (%s (nbits %d)(transient-key)))", + alg, (int)key_size); + if((err != GPG_ERR_NO_ERROR) || (key_spec == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(genkey)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_pk_genkey(&key_pair, key_spec); + if((err != GPG_ERR_NO_ERROR) || (key_pair == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_pk_genkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + ret = xmlSecGCryptAsymKeyDataAdoptKey(data, key_pair); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAsymKeyDataAdopt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "ret=%d", (int)ret); + goto done; + } + key_pair = NULL; /* now owned by data */ + + /* success */ + res = 0; + +done: + if(key_spec != NULL) { + gcry_sexp_release(key_spec); + } + if(key_pair != NULL) { + gcry_sexp_release(key_pair); + } + + return(res); +} + +static xmlSecKeyDataType +xmlSecGCryptAsymKeyDataGetType(xmlSecKeyDataPtr data) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), xmlSecKeyDataTypeUnknown); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown); + + if((ctx->priv_key != NULL) && (ctx->pub_key != NULL)) { + return (xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic); + } else if(ctx->pub_key != NULL) { + return (xmlSecKeyDataTypePublic); + } + + return (xmlSecKeyDataTypeUnknown); +} + +static xmlSecSize +xmlSecGCryptAsymKeyDataGetSize(xmlSecKeyDataPtr data) { + xmlSecGCryptAsymKeyDataCtxPtr ctx; + + xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown); + xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), xmlSecKeyDataTypeUnknown); + + ctx = xmlSecGCryptAsymKeyDataGetCtx(data); + xmlSecAssert2(ctx != NULL, 0); + + /* use pub key since it is more often you have it than not */ + return (ctx->pub_key != NULL) ? gcry_pk_get_nbits(ctx->pub_key) : 0; +} + +/****************************************************************************** + * + * helper functions + * + *****************************************************************************/ +static gcry_sexp_t +xmlSecGCryptAsymSExpDup(gcry_sexp_t pKey) { + gcry_sexp_t res = NULL; + xmlSecByte *buf = NULL; + gcry_error_t err; + size_t size; + + xmlSecAssert2(pKey != NULL, NULL); + + size = gcry_sexp_sprint(pKey, GCRYSEXP_FMT_ADVANCED, NULL, 0); + if(size == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_sprint", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + buf = (xmlSecByte *)xmlMalloc(size); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlMalloc", + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", (int)size); + goto done; + } + + size = gcry_sexp_sprint(pKey, GCRYSEXP_FMT_ADVANCED, buf, size); + if(size == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_sprint", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "size=%d", (int)size); + goto done; + } + + err = gcry_sexp_new(&res, buf, size, 1); + if((err != GPG_ERR_NO_ERROR) || (res == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_new", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + +done: + if(buf != NULL) { + xmlFree(buf); + } + return (res); +} + +/** + * xmlSecGCryptNodeGetMpiValue: + * @cur: the poitner to an XML node. + * + * Converts the node content from CryptoBinary format + * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary) + * to a BIGNUM. If no BIGNUM buffer provided then a new + * BIGNUM is created (caller is responsible for freeing it). + * + * Returns: a pointer to MPI produced from CryptoBinary string + * or NULL if an error occurs. + */ +static gcry_mpi_t +xmlSecGCryptNodeGetMpiValue(const xmlNodePtr cur) { + xmlSecBuffer buf; + gcry_mpi_t res = NULL; + gcry_error_t err; + int ret; + + xmlSecAssert2(cur != NULL, NULL); + + ret = xmlSecBufferInitialize(&buf, 128); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + ret = xmlSecBufferBase64NodeContentRead(&buf, cur); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferBase64NodeContentRead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&buf); + return(NULL); + } + + err = gcry_mpi_scan(&res, GCRYMPI_FMT_USG, + xmlSecBufferGetData(&buf), + xmlSecBufferGetSize(&buf), + NULL); + if((err != GPG_ERR_NO_ERROR) || (res == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + xmlSecBufferFinalize(&buf); + return(NULL); + } + + /* done */ + xmlSecBufferFinalize(&buf); + return(res); +} + +/** + * xmlSecGCryptNodeSetMpiValue: + * @cur: the pointer to an XML node. + * @a: the mpi value + * @addLineBreaks: if the flag is equal to 1 then + * linebreaks will be added before and after + * new buffer content. + * + * Converts MPI to CryptoBinary string + * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary) + * and sets it as the content of the given node. If the + * addLineBreaks is set then line breaks are added + * before and after the CryptoBinary string. + * + * Returns: 0 on success or -1 otherwise. + */ +static int +xmlSecGCryptNodeSetMpiValue(xmlNodePtr cur, const gcry_mpi_t a, int addLineBreaks) { + xmlSecBuffer buf; + gcry_error_t err; + size_t written = 0; + int ret; + + xmlSecAssert2(a != NULL, -1); + xmlSecAssert2(cur != NULL, -1); + + written = 0; + err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &written, a); + if((err != GPG_ERR_NO_ERROR) || (written == 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_print", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + ret = xmlSecBufferInitialize(&buf, written + 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", (int)written + 1); + return(-1); + } + + written = 0; + err = gcry_mpi_print(GCRYMPI_FMT_USG, + xmlSecBufferGetData(&buf), + xmlSecBufferGetMaxSize(&buf), + &written, a); + if((err != GPG_ERR_NO_ERROR) || (written == 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_print", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + xmlSecBufferFinalize(&buf); + return(-1); + } + + ret = xmlSecBufferSetSize(&buf, written); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "written=%d", (int)written); + xmlSecBufferFinalize(&buf); + return(-1); + } + + if(addLineBreaks) { + xmlNodeSetContent(cur, xmlSecStringCR); + } else { + xmlNodeSetContent(cur, xmlSecStringEmpty); + } + + ret = xmlSecBufferBase64NodeContentWrite(&buf, cur, xmlSecBase64GetDefaultLineSize()); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferBase64NodeContentWrite", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&buf); + return(-1); + } + + if(addLineBreaks) { + xmlNodeAddContent(cur, xmlSecStringCR); + } + + xmlSecBufferFinalize(&buf); + return(0); +} + +/** + * xmlSecGCryptNodeSetSExpTokValue: + * @cur: the pointer to an XML node. + * @sexp: the sexp + * @tok: the token + * @addLineBreaks: if the flag is equal to 1 then + * linebreaks will be added before and after + * new buffer content. + * + * Converts MPI to CryptoBinary string + * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary) + * and sets it as the content of the given node. If the + * addLineBreaks is set then line breaks are added + * before and after the CryptoBinary string. + * + * Returns: 0 on success or -1 otherwise. + */ +static int +xmlSecGCryptNodeSetSExpTokValue(xmlNodePtr cur, const gcry_sexp_t sexp, + const char * tok, int addLineBreaks) +{ + gcry_sexp_t val = NULL; + gcry_mpi_t mpi = NULL; + int res = -1; + + xmlSecAssert2(cur != NULL, -1); + xmlSecAssert2(sexp != NULL, -1); + xmlSecAssert2(tok != NULL, -1); + + val = gcry_sexp_find_token(sexp, tok, 0); + if(val == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "tok=%s", + xmlSecErrorsSafeString(tok)); + goto done; + } + + mpi = gcry_sexp_nth_mpi(val, 1, GCRYMPI_FMT_USG); + if(mpi == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_nth_mpi", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "tok=%s", + xmlSecErrorsSafeString(tok)); + goto done; + } + + /* almost done */ + res = xmlSecGCryptNodeSetMpiValue(cur, mpi, addLineBreaks); + +done: + if(mpi != NULL) { + gcry_mpi_release(mpi); + } + if(val != NULL) { + gcry_sexp_release(val); + } + + return(res); +} + +#ifndef XMLSEC_NO_DSA +/************************************************************************** + * + * <dsig:DSAKeyValue> processing + * + * + * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue) + * + * DSA keys and the DSA signature algorithm are specified in [DSS]. + * DSA public key values can have the following fields: + * + * * P - a prime modulus meeting the [DSS] requirements + * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime + * divisor of P-1 + * * G - an integer with certain properties with respect to P and Q + * * Y - G**X mod P (where X is part of the private key and not made + * public) + * * J - (P - 1) / Q + * * seed - a DSA prime generation seed + * * pgenCounter - a DSA prime generation counter + * + * Parameter J is available for inclusion solely for efficiency as it is + * calculatable from P and Q. Parameters seed and pgenCounter are used in the + * DSA prime number generation algorithm specified in [DSS]. As such, they are + * optional but must either both be present or both be absent. This prime + * generation algorithm is designed to provide assurance that a weak prime is + * not being used and it yields a P and Q value. Parameters P, Q, and G can be + * public and common to a group of users. They might be known from application + * context. As such, they are optional but P and Q must either both appear or + * both be absent. If all of P, Q, seed, and pgenCounter are present, + * implementations are not required to check if they are consistent and are + * free to use either P and Q or seed and pgenCounter. All parameters are + * encoded as base64 [MIME] values. + * + * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are + * represented in XML as octet strings as defined by the ds:CryptoBinary type. + * + * Schema Definition: + * + * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/> + * <complexType name="DSAKeyValueType"> + * <sequence> + * <sequence minOccurs="0"> + * <element name="P" type="ds:CryptoBinary"/> + * <element name="Q" type="ds:CryptoBinary"/> + * </sequence> + * <element name="G" type="ds:CryptoBinary" minOccurs="0"/> + * <element name="Y" type="ds:CryptoBinary"/> + * <element name="J" type="ds:CryptoBinary" minOccurs="0"/> + * <sequence minOccurs="0"> + * <element name="Seed" type="ds:CryptoBinary"/> + * <element name="PgenCounter" type="ds:CryptoBinary"/> + * </sequence> + * </sequence> + * </complexType> + * + * DTD Definition: + * + * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) > + * <!ELEMENT P (#PCDATA) > + * <!ELEMENT Q (#PCDATA) > + * <!ELEMENT G (#PCDATA) > + * <!ELEMENT Y (#PCDATA) > + * <!ELEMENT J (#PCDATA) > + * <!ELEMENT Seed (#PCDATA) > + * <!ELEMENT PgenCounter (#PCDATA) > + * + * ============================================================================ + * + * To support reading/writing private keys an X element added (before Y). + * todo: The current implementation does not support Seed and PgenCounter! + * by this the P, Q and G are *required*! + * + *************************************************************************/ +static int xmlSecGCryptKeyDataDsaInitialize (xmlSecKeyDataPtr data); +static int xmlSecGCryptKeyDataDsaDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecGCryptKeyDataDsaFinalize (xmlSecKeyDataPtr data); +static int xmlSecGCryptKeyDataDsaXmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptKeyDataDsaXmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptKeyDataDsaGenerate (xmlSecKeyDataPtr data, + xmlSecSize sizeBits, + xmlSecKeyDataType type); + +static xmlSecKeyDataType xmlSecGCryptKeyDataDsaGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecGCryptKeyDataDsaGetSize (xmlSecKeyDataPtr data); +static void xmlSecGCryptKeyDataDsaDebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecGCryptKeyDataDsaDebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); + +static xmlSecKeyDataKlass xmlSecGCryptKeyDataDsaKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecGCryptAsymKeyDataSize, + + /* data */ + xmlSecNameDSAKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefDSAKeyValue, /* const xmlChar* href; */ + xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecGCryptKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecGCryptKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecGCryptKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecGCryptKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecGCryptKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecGCryptKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecGCryptKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecGCryptKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + NULL, /* xmlSecKeyDataBinReadMethod binRead; */ + NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecGCryptKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecGCryptKeyDataDsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptKeyDataDsaGetKlass: + * + * The DSA key data klass. + * + * Returns: pointer to DSA key data klass. + */ +xmlSecKeyDataId +xmlSecGCryptKeyDataDsaGetKlass(void) { + return(&xmlSecGCryptKeyDataDsaKlass); +} + +/** + * xmlSecGCryptKeyDataDsaAdoptKey: + * @data: the pointer to DSA key data. + * @dsa_key: the pointer to GCrypt DSA key. + * + * Sets the value of DSA key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptKeyDataDsaAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t dsa_key) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1); + xmlSecAssert2(dsa_key != NULL, -1); + + return xmlSecGCryptAsymKeyDataAdoptKey(data, dsa_key); +} + + +/** + * xmlSecGCryptKeyDataDsaAdoptKeyPair: + * @data: the pointer to DSA key data. + * @pub_key: the pointer to GCrypt DSA pub key. + * @priv_key: the pointer to GCrypt DSA priv key. + * + * Sets the value of DSA key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptKeyDataDsaAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1); + xmlSecAssert2(pub_key != NULL, -1); + + return xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key); +} + +/** + * xmlSecGCryptKeyDataDsaGetPublicKey: + * @data: the pointer to DSA key data. + * + * Gets the GCrypt DSA public key from DSA key data. + * + * Returns: pointer to GCrypt public DSA key or NULL if an error occurs. + */ +gcry_sexp_t +xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), NULL); + return xmlSecGCryptAsymKeyDataGetPublicKey(data); +} + +/** + * xmlSecGCryptKeyDataDsaGetPrivateKey: + * @data: the pointer to DSA key data. + * + * Gets the GCrypt DSA private key from DSA key data. + * + * Returns: pointer to GCrypt private DSA key or NULL if an error occurs. + */ +gcry_sexp_t +xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), NULL); + return xmlSecGCryptAsymKeyDataGetPrivateKey(data); +} + +static int +xmlSecGCryptKeyDataDsaInitialize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1); + + return(xmlSecGCryptAsymKeyDataInitialize(data)); +} + +static int +xmlSecGCryptKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGCryptKeyDataDsaId), -1); + xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGCryptKeyDataDsaId), -1); + + return(xmlSecGCryptAsymKeyDataDuplicate(dst, src)); +} + +static void +xmlSecGCryptKeyDataDsaFinalize(xmlSecKeyDataPtr data) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId)); + + xmlSecGCryptAsymKeyDataFinalize(data); +} + +static int +xmlSecGCryptKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1); + xmlSecAssert2(sizeBits > 0, -1); + + return xmlSecGCryptAsymKeyDataGenerate(data, "dsa", sizeBits); +} + +static xmlSecKeyDataType +xmlSecGCryptKeyDataDsaGetType(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), xmlSecKeyDataTypeUnknown); + + return xmlSecGCryptAsymKeyDataGetType(data); +} + +static xmlSecSize +xmlSecGCryptKeyDataDsaGetSize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), 0); + + return xmlSecGCryptAsymKeyDataGetSize(data); +} + +static void +xmlSecGCryptKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "=== dsa key: size = %d\n", + xmlSecGCryptKeyDataDsaGetSize(data)); +} + +static void +xmlSecGCryptKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "<DSAKeyValue size=\"%d\" />\n", + xmlSecGCryptKeyDataDsaGetSize(data)); +} + +static int +xmlSecGCryptKeyDataDsaXmlRead(xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx) +{ + xmlNodePtr cur; + xmlSecKeyDataPtr data = NULL; + gcry_mpi_t p = NULL; + gcry_mpi_t q = NULL; + gcry_mpi_t g = NULL; + gcry_mpi_t x = NULL; + gcry_mpi_t y = NULL; + gcry_sexp_t pub_key = NULL; + gcry_sexp_t priv_key = NULL; + gcry_error_t err; + int res = -1; + int ret; + + xmlSecAssert2(id == xmlSecGCryptKeyDataDsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + if(xmlSecKeyGetValue(key) != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + cur = xmlSecGetNextElementNode(node->children); + + /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + goto done; + } + p = xmlSecGCryptNodeGetMpiValue(cur); + if(p == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + goto done; + } + q = xmlSecGCryptNodeGetMpiValue(cur); + if(q == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + goto done; + } + g = xmlSecGCryptNodeGetMpiValue(cur); + if(g == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) { + /* next is X node. It is REQUIRED for private key but + * we are not sure exactly what do we read */ + x = xmlSecGCryptNodeGetMpiValue(cur); + if(x == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAX)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + } + + /* next is Y node. */ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAY)); + goto done; + } + y = xmlSecGCryptNodeGetMpiValue(cur); + if(y == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + + /* todo: add support for J */ + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) { + cur = xmlSecGetNextElementNode(cur->next); + } + + /* todo: add support for seed */ + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) { + cur = xmlSecGetNextElementNode(cur->next); + } + + /* todo: add support for pgencounter */ + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) { + cur = xmlSecGetNextElementNode(cur->next); + } + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_UNEXPECTED_NODE, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + + /* construct pub/priv key pairs */ + err = gcry_sexp_build(&pub_key, NULL, + "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", + p, q, g, y); + if((err != GPG_ERR_NO_ERROR) || (pub_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "gcry_sexp_build(public)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + if(x != NULL) { + err = gcry_sexp_build(&priv_key, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(x%m)(y%m)))", + p, q, g, x, y); + if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "gcry_sexp_build(private)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + } + + /* create key data */ + data = xmlSecKeyDataCreate(id); + if(data == NULL ) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, priv_key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecGCryptKeyDataDsaAdoptKeyPair", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + pub_key = NULL; /* pub_key is owned by data now */ + priv_key = NULL; /* priv_key is owned by data now */ + + /* set key */ + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + data = NULL; /* data is owned by key now */ + + /* success */ + res = 0; + +done: + /* cleanup */ + if(p != NULL) { + gcry_mpi_release(p); + } + + if(q != NULL) { + gcry_mpi_release(q); + } + + if(g != NULL) { + gcry_mpi_release(g); + } + + if(x != NULL) { + gcry_mpi_release(x); + } + + if(y != NULL) { + gcry_mpi_release(y); + } + + if(pub_key != NULL) { + gcry_sexp_release(pub_key); + } + + if(priv_key != NULL) { + gcry_sexp_release(priv_key); + } + + if(data != NULL) { + xmlSecKeyDataDestroy(data); + } + return(res); +} + +static int +xmlSecGCryptKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlNodePtr cur; + gcry_sexp_t pub_priv_key; + gcry_sexp_t dsa = NULL; + int private = 0; + int res = -1; + int ret; + + xmlSecAssert2(id == xmlSecGCryptKeyDataDsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataDsaId), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) { + /* we can have only private key or public key */ + return(0); + } + + /* find the private or public key */ + pub_priv_key = xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyGetValue(key)); + if(pub_priv_key == NULL) { + pub_priv_key = xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyGetValue(key)); + if(pub_priv_key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptKeyDataDsaGetPublicKey()", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } else { + private = 1; + } + + dsa = gcry_sexp_find_token(pub_priv_key, "dsa", 0); + if(dsa == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "gcry_sexp_find_token(dsa)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* first is P node */ + cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "p", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAP)); + goto done; + } + + /* next is Q node. */ + cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "q", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAQ)); + goto done; + } + + /* next is G node. */ + cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "g", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAG)); + goto done; + } + + /* next is X node: write it ONLY for private keys and ONLY if it is requested */ + if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (private != 0)) { + cur = xmlSecAddChild(node, xmlSecNodeDSAX, xmlSecNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAX)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "x", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAX)); + goto done; + } + } + + /* next is Y node. */ + cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAY)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "y", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeDSAY)); + goto done; + } + + /* success */ + res = 0; + +done: + if(dsa != NULL) { + gcry_sexp_release(dsa); + } + + return(res); +} + +#endif /* XMLSEC_NO_DSA */ + + +#ifndef XMLSEC_NO_RSA +/************************************************************************** + * + * <dsig:RSAKeyValue> processing + * + * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue + * The RSAKeyValue Element + * + * RSA key values have two fields: Modulus and Exponent. + * + * <RSAKeyValue> + * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W + * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV + * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= + * </Modulus> + * <Exponent>AQAB</Exponent> + * </RSAKeyValue> + * + * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are + * represented in XML as octet strings as defined by the ds:CryptoBinary type. + * + * Schema Definition: + * + * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/> + * <complexType name="RSAKeyValueType"> + * <sequence> + * <element name="Modulus" type="ds:CryptoBinary"/> + * <element name="Exponent" type="ds:CryptoBinary"/> + * </sequence> + * </complexType> + * + * DTD Definition: + * + * <!ELEMENT RSAKeyValue (Modulus, Exponent) > + * <!ELEMENT Modulus (#PCDATA) > + * <!ELEMENT Exponent (#PCDATA) > + * + * ============================================================================ + * + * To support reading/writing private keys an PrivateExponent element is added + * to the end + * + *************************************************************************/ + +static int xmlSecGCryptKeyDataRsaInitialize (xmlSecKeyDataPtr data); +static int xmlSecGCryptKeyDataRsaDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecGCryptKeyDataRsaFinalize (xmlSecKeyDataPtr data); +static int xmlSecGCryptKeyDataRsaXmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptKeyDataRsaXmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptKeyDataRsaGenerate (xmlSecKeyDataPtr data, + xmlSecSize sizeBits, + xmlSecKeyDataType type); + +static xmlSecKeyDataType xmlSecGCryptKeyDataRsaGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecGCryptKeyDataRsaGetSize (xmlSecKeyDataPtr data); +static void xmlSecGCryptKeyDataRsaDebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecGCryptKeyDataRsaDebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); +static xmlSecKeyDataKlass xmlSecGCryptKeyDataRsaKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecGCryptAsymKeyDataSize, + + /* data */ + xmlSecNameRSAKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefRSAKeyValue, /* const xmlChar* href; */ + xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecGCryptKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecGCryptKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecGCryptKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecGCryptKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecGCryptKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecGCryptKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecGCryptKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecGCryptKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + NULL, /* xmlSecKeyDataBinReadMethod binRead; */ + NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecGCryptKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecGCryptKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptKeyDataRsaGetKlass: + * + * The GCrypt RSA key data klass. + * + * Returns: pointer to GCrypt RSA key data klass. + */ +xmlSecKeyDataId +xmlSecGCryptKeyDataRsaGetKlass(void) { + return(&xmlSecGCryptKeyDataRsaKlass); +} + +/** + * xmlSecGCryptKeyDataRsaAdoptKey: + * @data: the pointer to RSA key data. + * @rsa_key: the pointer to GCrypt RSA key. + * + * Sets the value of RSA key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptKeyDataRsaAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t rsa_key) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1); + xmlSecAssert2(rsa_key != NULL, -1); + + return xmlSecGCryptAsymKeyDataAdoptKey(data, rsa_key); +} + + +/** + * xmlSecGCryptKeyDataRsaAdoptKeyPair: + * @data: the pointer to RSA key data. + * @pub_key: the pointer to GCrypt RSA pub key. + * @priv_key: the pointer to GCrypt RSA priv key. + * + * Sets the value of RSA key data. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptKeyDataRsaAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1); + xmlSecAssert2(pub_key != NULL, -1); + + return xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key); +} + +/** + * xmlSecGCryptKeyDataRsaGetPublicKey: + * @data: the pointer to RSA key data. + * + * Gets the GCrypt RSA public key from RSA key data. + * + * Returns: pointer to GCrypt public RSA key or NULL if an error occurs. + */ +gcry_sexp_t +xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), NULL); + return xmlSecGCryptAsymKeyDataGetPublicKey(data); +} + +/** + * xmlSecGCryptKeyDataRsaGetPrivateKey: + * @data: the pointer to RSA key data. + * + * Gets the GCrypt RSA private key from RSA key data. + * + * Returns: pointer to GCrypt private RSA key or NULL if an error occurs. + */ +gcry_sexp_t +xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), NULL); + return xmlSecGCryptAsymKeyDataGetPrivateKey(data); +} + +static int +xmlSecGCryptKeyDataRsaInitialize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1); + + return(xmlSecGCryptAsymKeyDataInitialize(data)); +} + +static int +xmlSecGCryptKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGCryptKeyDataRsaId), -1); + xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGCryptKeyDataRsaId), -1); + + return(xmlSecGCryptAsymKeyDataDuplicate(dst, src)); +} + +static void +xmlSecGCryptKeyDataRsaFinalize(xmlSecKeyDataPtr data) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId)); + + xmlSecGCryptAsymKeyDataFinalize(data); +} + +static int +xmlSecGCryptKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1); + xmlSecAssert2(sizeBits > 0, -1); + + return xmlSecGCryptAsymKeyDataGenerate(data, "rsa", sizeBits); +} + +static xmlSecKeyDataType +xmlSecGCryptKeyDataRsaGetType(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), xmlSecKeyDataTypeUnknown); + + return xmlSecGCryptAsymKeyDataGetType(data); +} + +static xmlSecSize +xmlSecGCryptKeyDataRsaGetSize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), 0); + + return xmlSecGCryptAsymKeyDataGetSize(data); +} + +static void +xmlSecGCryptKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "=== rsa key: size = %d\n", + xmlSecGCryptKeyDataRsaGetSize(data)); +} + +static void +xmlSecGCryptKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId)); + xmlSecAssert(output != NULL); + + fprintf(output, "<RSAKeyValue size=\"%d\" />\n", + xmlSecGCryptKeyDataRsaGetSize(data)); +} + +static int +xmlSecGCryptKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlNodePtr cur; + xmlSecKeyDataPtr data = NULL; + gcry_mpi_t n = NULL; + gcry_mpi_t e = NULL; + gcry_mpi_t d = NULL; + gcry_sexp_t pub_key = NULL; + gcry_sexp_t priv_key = NULL; + gcry_error_t err; + int res = -1; + int ret; + + xmlSecAssert2(id == xmlSecGCryptKeyDataRsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + if(xmlSecKeyGetValue(key) != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA, + "key already has a value"); + goto done; + } + + cur = xmlSecGetNextElementNode(node->children); + + /* first is Modulus node. It is REQUIRED */ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + goto done; + } + n = xmlSecGCryptNodeGetMpiValue(cur); + if(n == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + + /* next is Exponent node. It is REQUIRED */ + if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + goto done; + } + e = xmlSecGCryptNodeGetMpiValue(cur); + if(e == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + + if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) { + /* next is PrivateExponent node. It is REQUIRED for private key */ + d = xmlSecGCryptNodeGetMpiValue(cur); + if(d == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeGetMpiValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent)); + goto done; + } + cur = xmlSecGetNextElementNode(cur->next); + } + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "no nodes expected"); + goto done; + } + + /* construct pub/priv key pairs */ + err = gcry_sexp_build(&pub_key, NULL, + "(public-key(rsa(n%m)(e%m)))", + n, e); + if((err != GPG_ERR_NO_ERROR) || (pub_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "gcry_sexp_build(public)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + if(d != NULL) { + err = gcry_sexp_build(&priv_key, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)))", + n, e, d); + if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "gcry_sexp_build(private)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + } + + + /* create key data */ + data = xmlSecKeyDataCreate(id); + if(data == NULL ) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, priv_key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecGCryptKeyDataRsaAdoptKeyPair", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + pub_key = NULL; /* pub_key is owned by data now */ + priv_key = NULL; /* priv_key is owned by data now */ + + /* set key */ + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + data = NULL; /* data is owned by key now */ + + + /* success */ + res = 0; + +done: + /* cleanup */ + if(n != NULL) { + gcry_mpi_release(n); + } + + if(e != NULL) { + gcry_mpi_release(e); + } + + if(d != NULL) { + gcry_mpi_release(d); + } + + if(pub_key != NULL) { + gcry_sexp_release(pub_key); + } + + if(priv_key != NULL) { + gcry_sexp_release(priv_key); + } + + if(data != NULL) { + xmlSecKeyDataDestroy(data); + } + return(res); + +} + +static int +xmlSecGCryptKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlNodePtr cur; + gcry_sexp_t pub_priv_key; + gcry_sexp_t rsa = NULL; + int private = 0; + int res = -1; + int ret; + + xmlSecAssert2(id == xmlSecGCryptKeyDataRsaId, -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataRsaId), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(keyInfoCtx != NULL, -1); + + if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) { + /* we can have only private key or public key */ + return(0); + } + + /* find the private or public key */ + pub_priv_key = xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyGetValue(key)); + if(pub_priv_key == NULL) { + pub_priv_key = xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyGetValue(key)); + if(pub_priv_key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptKeyDataRsaGetPublicKey()", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } else { + private = 1; + } + + rsa = gcry_sexp_find_token(pub_priv_key, "rsa", 0); + if(rsa == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "gcry_sexp_find_token(rsa)", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* first is Modulus node */ + cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "n", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); + goto done; + } + + /* next is Exponent node. */ + cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "e", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); + goto done; + } + + /* next is PrivateExponent node: write it ONLY for private keys and ONLY if it is requested */ + if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (private != 0)) { + cur = xmlSecAddChild(node, xmlSecNodeRSAPrivateExponent, xmlSecNs); + if(cur == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecAddChild", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent)); + goto done; + } + ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "d", 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), + "xmlSecGCryptNodeSetSExpTokValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "node=%s", + xmlSecErrorsSafeString(xmlSecNodeRSAPrivateExponent)); + goto done; + } + } + + /* success */ + res = 0; + +done: + if(rsa != NULL) { + gcry_sexp_release(rsa); + } + + return(res); +} + +#endif /* XMLSEC_NO_RSA */ diff --git a/src/gcrypt/ciphers.c b/src/gcrypt/ciphers.c new file mode 100644 index 00000000..6192b8b2 --- /dev/null +++ b/src/gcrypt/ciphers.c @@ -0,0 +1,855 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + +/************************************************************************** + * + * Internal GCrypt Block cipher CTX + * + *****************************************************************************/ +typedef struct _xmlSecGCryptBlockCipherCtx xmlSecGCryptBlockCipherCtx, + *xmlSecGCryptBlockCipherCtxPtr; +struct _xmlSecGCryptBlockCipherCtx { + int cipher; + int mode; + gcry_cipher_hd_t cipherCtx; + xmlSecKeyDataId keyId; + int keyInitialized; + int ctxInitialized; +}; + +static int xmlSecGCryptBlockCipherCtxInit (xmlSecGCryptBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptBlockCipherCtxUpdate (xmlSecGCryptBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptBlockCipherCtxFinal (xmlSecGCryptBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int +xmlSecGCryptBlockCipherCtxInit(xmlSecGCryptBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + gcry_err_code_t err; + int blockLen; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->cipherCtx != NULL, -1); + xmlSecAssert2(ctx->keyInitialized != 0, -1); + xmlSecAssert2(ctx->ctxInitialized == 0, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + /* iv len == block len */ + blockLen = gcry_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + if(encrypt) { + xmlSecByte* iv; + xmlSecSize outSize; + + /* allocate space for IV */ + outSize = xmlSecBufferGetSize(out); + ret = xmlSecBufferSetSize(out, outSize + blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + blockLen); + return(-1); + } + iv = xmlSecBufferGetData(out) + outSize; + + /* generate and use random iv */ + gcry_randomize(iv, blockLen, GCRY_STRONG_RANDOM); + err = gcry_cipher_setiv(ctx->cipherCtx, iv, blockLen); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "gcry_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + } else { + /* if we don't have enough data, exit and hope that + * we'll have iv next time */ + if(xmlSecBufferGetSize(in) < (xmlSecSize)blockLen) { + return(0); + } + xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1); + + /* set iv */ + err = gcry_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "gcry_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + /* and remove from input */ + ret = xmlSecBufferRemoveHead(in, blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", blockLen); + return(-1); + } + } + + ctx->ctxInitialized = 1; + return(0); +} + +static int +xmlSecGCryptBlockCipherCtxUpdate(xmlSecGCryptBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSize inSize, inBlocks, outSize; + int blockLen; + xmlSecByte* outBuf; + gcry_err_code_t err; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->cipherCtx != NULL, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + blockLen = gcry_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + if(inSize < (xmlSecSize)blockLen) { + return(0); + } + + if(encrypt) { + inBlocks = inSize / ((xmlSecSize)blockLen); + } else { + /* we want to have the last block in the input buffer + * for padding check */ + inBlocks = (inSize - 1) / ((xmlSecSize)blockLen); + } + inSize = inBlocks * ((xmlSecSize)blockLen); + + /* we write out the input size plus may be one block */ + ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + inSize + blockLen); + return(-1); + } + outBuf = xmlSecBufferGetData(out) + outSize; + + if(encrypt) { + err = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "gcry_cipher_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + } else { + err = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "gcry_cipher_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + } + + /* set correct output buffer size */ + ret = xmlSecBufferSetSize(out, outSize + inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + inSize); + return(-1); + } + + /* remove the processed block from input */ + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + return(0); +} + +static int +xmlSecGCryptBlockCipherCtxFinal(xmlSecGCryptBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSize inSize, outSize; + int blockLen, outLen = 0; + xmlSecByte* inBuf; + xmlSecByte* outBuf; + gcry_err_code_t err; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->cipherCtx != NULL, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + blockLen = gcry_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + if(encrypt != 0) { + xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1); + + /* create padding */ + ret = xmlSecBufferSetMaxSize(in, blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", blockLen); + return(-1); + } + inBuf = xmlSecBufferGetData(in); + + /* create random padding */ + if((xmlSecSize)blockLen > (inSize + 1)) { + gcry_randomize(inBuf + inSize, blockLen - inSize - 1, + GCRY_STRONG_RANDOM); /* as usual, we are paranoid */ + } + inBuf[blockLen - 1] = blockLen - inSize; + inSize = blockLen; + } else { + if(inSize != (xmlSecSize)blockLen) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data=%d;block=%d", inSize, blockLen); + return(-1); + } + } + + /* process last block */ + ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + 2 * blockLen); + return(-1); + } + outBuf = xmlSecBufferGetData(out) + outSize; + + if(encrypt) { + err = gcry_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "gcry_cipher_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + } else { + err = gcry_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "gcry_cipher_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + } + + if(encrypt == 0) { + /* check padding */ + if(inSize < outBuf[blockLen - 1]) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "padding=%d;buffer=%d", + outBuf[blockLen - 1], inSize); + return(-1); + } + outLen = inSize - outBuf[blockLen - 1]; + } else { + outLen = inSize; + } + + /* set correct output buffer size */ + ret = xmlSecBufferSetSize(out, outSize + outLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + outLen); + return(-1); + } + + /* remove the processed block from input */ + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + + /* set correct output buffer size */ + ret = xmlSecBufferSetSize(out, outSize + outLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + outLen); + return(-1); + } + + /* remove the processed block from input */ + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + return(0); +} + + +/****************************************************************************** + * + * Block Cipher transforms + * + * xmlSecGCryptBlockCipherCtx block is located after xmlSecTransform structure + * + *****************************************************************************/ +#define xmlSecGCryptBlockCipherSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptBlockCipherCtx)) +#define xmlSecGCryptBlockCipherGetCtx(transform) \ + ((xmlSecGCryptBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecGCryptBlockCipherInitialize (xmlSecTransformPtr transform); +static void xmlSecGCryptBlockCipherFinalize (xmlSecTransformPtr transform); +static int xmlSecGCryptBlockCipherSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecGCryptBlockCipherSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecGCryptBlockCipherExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptBlockCipherCheckId (xmlSecTransformPtr transform); + + + +static int +xmlSecGCryptBlockCipherCheckId(xmlSecTransformPtr transform) { +#ifndef XMLSEC_NO_DES + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDes3CbcId)) { + return(1); + } +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes128CbcId) || + xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes192CbcId) || + xmlSecTransformCheckId(transform, xmlSecGCryptTransformAes256CbcId)) { + + return(1); + } +#endif /* XMLSEC_NO_AES */ + + return(0); +} + +static int +xmlSecGCryptBlockCipherInitialize(xmlSecTransformPtr transform) { + xmlSecGCryptBlockCipherCtxPtr ctx; + gcry_error_t err; + + xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1); + + ctx = xmlSecGCryptBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecGCryptBlockCipherCtx)); + +#ifndef XMLSEC_NO_DES + if(transform->id == xmlSecGCryptTransformDes3CbcId) { + ctx->cipher = GCRY_CIPHER_3DES; + ctx->mode = GCRY_CIPHER_MODE_CBC; + ctx->keyId = xmlSecGCryptKeyDataDesId; + } else +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(transform->id == xmlSecGCryptTransformAes128CbcId) { + ctx->cipher = GCRY_CIPHER_AES128; + ctx->mode = GCRY_CIPHER_MODE_CBC; + ctx->keyId = xmlSecGCryptKeyDataAesId; + } else if(transform->id == xmlSecGCryptTransformAes192CbcId) { + ctx->cipher = GCRY_CIPHER_AES192; + ctx->mode = GCRY_CIPHER_MODE_CBC; + ctx->keyId = xmlSecGCryptKeyDataAesId; + } else if(transform->id == xmlSecGCryptTransformAes256CbcId) { + ctx->cipher = GCRY_CIPHER_AES256; + ctx->mode = GCRY_CIPHER_MODE_CBC; + ctx->keyId = xmlSecGCryptKeyDataAesId; + } else +#endif /* XMLSEC_NO_AES */ + + if(1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + err = gcry_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, GCRY_CIPHER_SECURE); /* we are paranoid */ + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_cipher_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + return(0); +} + +static void +xmlSecGCryptBlockCipherFinalize(xmlSecTransformPtr transform) { + xmlSecGCryptBlockCipherCtxPtr ctx; + + xmlSecAssert(xmlSecGCryptBlockCipherCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize)); + + ctx = xmlSecGCryptBlockCipherGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->cipherCtx != NULL) { + gcry_cipher_close(ctx->cipherCtx); + } + + memset(ctx, 0, sizeof(xmlSecGCryptBlockCipherCtx)); +} + +static int +xmlSecGCryptBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecGCryptBlockCipherCtxPtr ctx; + + xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecGCryptBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + + keyReq->keyId = ctx->keyId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + + keyReq->keyBitsSize = 8 * gcry_cipher_get_algo_keylen(ctx->cipher); + return(0); +} + +static int +xmlSecGCryptBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecGCryptBlockCipherCtxPtr ctx; + xmlSecBufferPtr buffer; + xmlSecSize keySize; + gcry_err_code_t err; + + xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1); + xmlSecAssert2(key != NULL, -1); + + ctx = xmlSecGCryptBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->cipherCtx != NULL, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->keyInitialized == 0, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); + + keySize = gcry_cipher_get_algo_keylen(ctx->cipher); + xmlSecAssert2(keySize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer != NULL, -1); + + if(xmlSecBufferGetSize(buffer) < keySize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "keySize=%d;expected=%d", + xmlSecBufferGetSize(buffer), keySize); + return(-1); + } + + xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1); + err = gcry_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_cipher_setkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + ctx->keyInitialized = 1; + return(0); +} + +static int +xmlSecGCryptBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptBlockCipherCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecGCryptBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptBlockCipherSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + ctx = xmlSecGCryptBlockCipherGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + if(ctx->ctxInitialized == 0) { + ret = xmlSecGCryptBlockCipherCtxInit(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecGCryptBlockCipherCtxInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + if((ctx->ctxInitialized == 0) && (last != 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "not enough data to initialize transform"); + return(-1); + } + if(ctx->ctxInitialized != 0) { + ret = xmlSecGCryptBlockCipherCtxUpdate(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecGCryptBlockCipherCtxUpdate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + if(last) { + ret = xmlSecGCryptBlockCipherCtxFinal(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecGCryptBlockCipherCtxFinal", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + transform->status = xmlSecTransformStatusFinished; + } + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); + } else if(transform->status == xmlSecTransformStatusNone) { + /* the only way we can get here is if there is no enough data in the input */ + xmlSecAssert2(last == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + + +#ifndef XMLSEC_NO_AES +/********************************************************************* + * + * AES CBC cipher transforms + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecGCryptAes128CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes128Cbc, /* const xmlChar* name; */ + xmlSecHrefAes128Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformAes128CbcGetKlass: + * + * AES 128 CBC encryption transform klass. + * + * Returns: pointer to AES 128 CBC encryption transform. + */ +xmlSecTransformId +xmlSecGCryptTransformAes128CbcGetKlass(void) { + return(&xmlSecGCryptAes128CbcKlass); +} + +static xmlSecTransformKlass xmlSecGCryptAes192CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes192Cbc, /* const xmlChar* name; */ + xmlSecHrefAes192Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformAes192CbcGetKlass: + * + * AES 192 CBC encryption transform klass. + * + * Returns: pointer to AES 192 CBC encryption transform. + */ +xmlSecTransformId +xmlSecGCryptTransformAes192CbcGetKlass(void) { + return(&xmlSecGCryptAes192CbcKlass); +} + +static xmlSecTransformKlass xmlSecGCryptAes256CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes256Cbc, /* const xmlChar* name; */ + xmlSecHrefAes256Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformAes256CbcGetKlass: + * + * AES 256 CBC encryption transform klass. + * + * Returns: pointer to AES 256 CBC encryption transform. + */ +xmlSecTransformId +xmlSecGCryptTransformAes256CbcGetKlass(void) { + return(&xmlSecGCryptAes256CbcKlass); +} + +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES +static xmlSecTransformKlass xmlSecGCryptDes3CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameDes3Cbc, /* const xmlChar* name; */ + xmlSecHrefDes3Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformDes3CbcGetKlass: + * + * Triple DES CBC encryption transform klass. + * + * Returns: pointer to Triple DES encryption transform. + */ +xmlSecTransformId +xmlSecGCryptTransformDes3CbcGetKlass(void) { + return(&xmlSecGCryptDes3CbcKlass); +} +#endif /* XMLSEC_NO_DES */ + diff --git a/src/gcrypt/crypto.c b/src/gcrypt/crypto.c new file mode 100644 index 00000000..11def388 --- /dev/null +++ b/src/gcrypt/crypto.c @@ -0,0 +1,315 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> +#include <xmlsec/dl.h> +#include <xmlsec/private.h> + +#include <xmlsec/gcrypt/app.h> +#include <xmlsec/gcrypt/crypto.h> + +static xmlSecCryptoDLFunctionsPtr gXmlSecGCryptFunctions = NULL; + +/** + * xmlSecCryptoGetFunctions_gcrypt: + * + * Gets the pointer to xmlsec-gcrypt functions table. + * + * Returns: the xmlsec-gcrypt functions table or NULL if an error occurs. + */ +xmlSecCryptoDLFunctionsPtr +xmlSecCryptoGetFunctions_gcrypt(void) { + static xmlSecCryptoDLFunctions functions; + + if(gXmlSecGCryptFunctions != NULL) { + return(gXmlSecGCryptFunctions); + } + + memset(&functions, 0, sizeof(functions)); + gXmlSecGCryptFunctions = &functions; + + /******************************************************************** + * + * Crypto Init/shutdown + * + ********************************************************************/ + gXmlSecGCryptFunctions->cryptoInit = xmlSecGCryptInit; + gXmlSecGCryptFunctions->cryptoShutdown = xmlSecGCryptShutdown; + gXmlSecGCryptFunctions->cryptoKeysMngrInit = xmlSecGCryptKeysMngrInit; + + /******************************************************************** + * + * Key data ids + * + ********************************************************************/ +#ifndef XMLSEC_NO_AES + gXmlSecGCryptFunctions->keyDataAesGetKlass = xmlSecGCryptKeyDataAesGetKlass; +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES + gXmlSecGCryptFunctions->keyDataDesGetKlass = xmlSecGCryptKeyDataDesGetKlass; +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_DSA + gXmlSecGCryptFunctions->keyDataDsaGetKlass = xmlSecGCryptKeyDataDsaGetKlass; +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_HMAC + gXmlSecGCryptFunctions->keyDataHmacGetKlass = xmlSecGCryptKeyDataHmacGetKlass; +#endif /* XMLSEC_NO_HMAC */ + +#ifndef XMLSEC_NO_RSA + gXmlSecGCryptFunctions->keyDataRsaGetKlass = xmlSecGCryptKeyDataRsaGetKlass; +#endif /* XMLSEC_NO_RSA */ + + + /******************************************************************** + * + * Key data store ids + * + ********************************************************************/ + + /******************************************************************** + * + * Crypto transforms ids + * + ********************************************************************/ + + /******************************* AES ********************************/ +#ifndef XMLSEC_NO_AES + gXmlSecGCryptFunctions->transformAes128CbcGetKlass = xmlSecGCryptTransformAes128CbcGetKlass; + gXmlSecGCryptFunctions->transformAes192CbcGetKlass = xmlSecGCryptTransformAes192CbcGetKlass; + gXmlSecGCryptFunctions->transformAes256CbcGetKlass = xmlSecGCryptTransformAes256CbcGetKlass; + gXmlSecGCryptFunctions->transformKWAes128GetKlass = xmlSecGCryptTransformKWAes128GetKlass; + gXmlSecGCryptFunctions->transformKWAes192GetKlass = xmlSecGCryptTransformKWAes192GetKlass; + gXmlSecGCryptFunctions->transformKWAes256GetKlass = xmlSecGCryptTransformKWAes256GetKlass; +#endif /* XMLSEC_NO_AES */ + + /******************************* DES ********************************/ +#ifndef XMLSEC_NO_DES + gXmlSecGCryptFunctions->transformDes3CbcGetKlass = xmlSecGCryptTransformDes3CbcGetKlass; + gXmlSecGCryptFunctions->transformKWDes3GetKlass = xmlSecGCryptTransformKWDes3GetKlass; +#endif /* XMLSEC_NO_DES */ + + /******************************* DSA ********************************/ +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 + gXmlSecGCryptFunctions->transformDsaSha1GetKlass = xmlSecGCryptTransformDsaSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + + /******************************* HMAC ********************************/ +#ifndef XMLSEC_NO_HMAC + +#ifndef XMLSEC_NO_MD5 + gXmlSecGCryptFunctions->transformHmacMd5GetKlass = xmlSecGCryptTransformHmacMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + gXmlSecGCryptFunctions->transformHmacRipemd160GetKlass = xmlSecGCryptTransformHmacRipemd160GetKlass; +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + gXmlSecGCryptFunctions->transformHmacSha1GetKlass = xmlSecGCryptTransformHmacSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecGCryptFunctions->transformHmacSha256GetKlass = xmlSecGCryptTransformHmacSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecGCryptFunctions->transformHmacSha384GetKlass = xmlSecGCryptTransformHmacSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecGCryptFunctions->transformHmacSha512GetKlass = xmlSecGCryptTransformHmacSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_HMAC */ + + /******************************* MD5 ********************************/ +#ifndef XMLSEC_NO_MD5 + gXmlSecGCryptFunctions->transformMd5GetKlass = xmlSecGCryptTransformMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + + /******************************* RIPEMD160 ********************************/ +#ifndef XMLSEC_NO_RIPEMD160 + gXmlSecGCryptFunctions->transformRipemd160GetKlass = xmlSecGCryptTransformRipemd160GetKlass; +#endif /* XMLSEC_NO_RIPEMD160 */ + + /******************************* RSA ********************************/ +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + gXmlSecGCryptFunctions->transformRsaMd5GetKlass = xmlSecGCryptTransformRsaMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + gXmlSecGCryptFunctions->transformRsaRipemd160GetKlass = xmlSecGCryptTransformRsaRipemd160GetKlass; +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + gXmlSecGCryptFunctions->transformRsaSha1GetKlass = xmlSecGCryptTransformRsaSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecGCryptFunctions->transformRsaSha256GetKlass = xmlSecGCryptTransformRsaSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecGCryptFunctions->transformRsaSha384GetKlass = xmlSecGCryptTransformRsaSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecGCryptFunctions->transformRsaSha512GetKlass = xmlSecGCryptTransformRsaSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + /******************************* SHA ********************************/ +#ifndef XMLSEC_NO_SHA1 + gXmlSecGCryptFunctions->transformSha1GetKlass = xmlSecGCryptTransformSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecGCryptFunctions->transformSha256GetKlass = xmlSecGCryptTransformSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecGCryptFunctions->transformSha384GetKlass = xmlSecGCryptTransformSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecGCryptFunctions->transformSha512GetKlass = xmlSecGCryptTransformSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + + + /******************************************************************** + * + * High level routines form xmlsec command line utility + * + ********************************************************************/ + gXmlSecGCryptFunctions->cryptoAppInit = xmlSecGCryptAppInit; + gXmlSecGCryptFunctions->cryptoAppShutdown = xmlSecGCryptAppShutdown; + gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrInit = xmlSecGCryptAppDefaultKeysMngrInit; + gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecGCryptAppDefaultKeysMngrAdoptKey; + gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecGCryptAppDefaultKeysMngrLoad; + gXmlSecGCryptFunctions->cryptoAppDefaultKeysMngrSave = xmlSecGCryptAppDefaultKeysMngrSave; +#ifndef XMLSEC_NO_X509 + gXmlSecGCryptFunctions->cryptoAppKeysMngrCertLoad = xmlSecGCryptAppKeysMngrCertLoad; + gXmlSecGCryptFunctions->cryptoAppPkcs12Load = xmlSecGCryptAppPkcs12Load; + gXmlSecGCryptFunctions->cryptoAppKeyCertLoad = xmlSecGCryptAppKeyCertLoad; +#endif /* XMLSEC_NO_X509 */ + gXmlSecGCryptFunctions->cryptoAppKeyLoad = xmlSecGCryptAppKeyLoad; + gXmlSecGCryptFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecGCryptAppGetDefaultPwdCallback(); + + return(gXmlSecGCryptFunctions); +} + + +/** + * xmlSecGCryptInit: + * + * XMLSec library specific crypto engine initialization. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptInit (void) { + /* Check loaded xmlsec library version */ + if(xmlSecCheckVersionExact() != 1) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCheckVersionExact", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* register our klasses */ + if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_gcrypt()) < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecGCryptShutdown: + * + * XMLSec library specific crypto engine shutdown. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptShutdown(void) { + return(0); +} + +/** + * xmlSecGCryptKeysMngrInit: + * @mngr: the pointer to keys manager. + * + * Adds GCrypt specific key data stores in keys manager. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptKeysMngrInit(xmlSecKeysMngrPtr mngr) { + xmlSecAssert2(mngr != NULL, -1); + + /* TODO: add key data stores */ + return(0); +} + +/** + * xmlSecGCryptGenerateRandom: + * @buffer: the destination buffer. + * @size: the numer of bytes to generate. + * + * Generates @size random bytes and puts result in @buffer. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecGCryptGenerateRandom(xmlSecBufferPtr buffer, xmlSecSize size) { + int ret; + + xmlSecAssert2(buffer != NULL, -1); + xmlSecAssert2(size > 0, -1); + + ret = xmlSecBufferSetSize(buffer, size); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", size); + return(-1); + } + + /* get random data */ + gcry_randomize(xmlSecBufferGetData(buffer), size, GCRY_STRONG_RANDOM); + return(0); +} diff --git a/src/gcrypt/digests.c b/src/gcrypt/digests.c new file mode 100644 index 00000000..dcbe4c7f --- /dev/null +++ b/src/gcrypt/digests.c @@ -0,0 +1,614 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/app.h> +#include <xmlsec/gcrypt/crypto.h> + +/************************************************************************** + * + * Internal GCRYPT Digest CTX + * + *****************************************************************************/ +typedef struct _xmlSecGCryptDigestCtx xmlSecGCryptDigestCtx, *xmlSecGCryptDigestCtxPtr; +struct _xmlSecGCryptDigestCtx { + int digest; + gcry_md_hd_t digestCtx; + xmlSecByte dgst[XMLSEC_GCRYPT_MAX_DIGEST_SIZE]; + xmlSecSize dgstSize; /* dgst size in bytes */ +}; + +/****************************************************************************** + * + * Digest transforms + * + * xmlSecGCryptDigestCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecGCryptDigestSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptDigestCtx)) +#define xmlSecGCryptDigestGetCtx(transform) \ + ((xmlSecGCryptDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecGCryptDigestInitialize (xmlSecTransformPtr transform); +static void xmlSecGCryptDigestFinalize (xmlSecTransformPtr transform); +static int xmlSecGCryptDigestVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptDigestExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptDigestCheckId (xmlSecTransformPtr transform); + +static int +xmlSecGCryptDigestCheckId(xmlSecTransformPtr transform) { + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha256Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha384Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformMd5Id)) { + return(1); + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRipemd160Id)) { + return(1); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + + /* not found */ + { + return(0); + } + + /* just in case */ + return(0); +} + +static int +xmlSecGCryptDigestInitialize(xmlSecTransformPtr transform) { + xmlSecGCryptDigestCtxPtr ctx; + gcry_error_t err; + + xmlSecAssert2(xmlSecGCryptDigestCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize), -1); + + ctx = xmlSecGCryptDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + /* initialize context */ + memset(ctx, 0, sizeof(xmlSecGCryptDigestCtx)); + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha1Id)) { + ctx->digest = GCRY_MD_SHA1; + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha256Id)) { + ctx->digest = GCRY_MD_SHA256; + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha384Id)) { + ctx->digest = GCRY_MD_SHA384; + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformSha512Id)) { + ctx->digest = GCRY_MD_SHA512; + } else +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformMd5Id)) { + ctx->digest = GCRY_MD_MD5; + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRipemd160Id)) { + ctx->digest = GCRY_MD_RMD160; + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + + if(1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* create digest ctx */ + err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */ + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + return(0); +} + +static void +xmlSecGCryptDigestFinalize(xmlSecTransformPtr transform) { + xmlSecGCryptDigestCtxPtr ctx; + + xmlSecAssert(xmlSecGCryptDigestCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize)); + + ctx = xmlSecGCryptDigestGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->digestCtx != NULL) { + gcry_md_close(ctx->digestCtx); + } + memset(ctx, 0, sizeof(xmlSecGCryptDigestCtx)); +} + +static int +xmlSecGCryptDigestVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptDigestCtxPtr ctx; + + xmlSecAssert2(xmlSecGCryptDigestCheckId(transform), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize), -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->dgstSize > 0, -1); + + if(dataSize != ctx->dgstSize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data and digest sizes are different (data=%d, dgst=%d)", + dataSize, ctx->dgstSize); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + if(memcmp(ctx->dgst, data, dataSize) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data and digest do not match"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + transform->status = xmlSecTransformStatusOk; + return(0); +} + +static int +xmlSecGCryptDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptDigestCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecGCryptDigestCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(transformCtx != NULL, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptDigestSize), -1); + + ctx = xmlSecGCryptDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digest != GCRY_MD_NONE, -1); + xmlSecAssert2(ctx->digestCtx != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + xmlSecSize inSize; + + inSize = xmlSecBufferGetSize(in); + if(inSize > 0) { + gcry_md_write(ctx->digestCtx, xmlSecBufferGetData(in), inSize); + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + } + if(last != 0) { + xmlSecByte* buf; + + /* get the final digest */ + gcry_md_final(ctx->digestCtx); + buf = gcry_md_read(ctx->digestCtx, ctx->digest); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_read", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* copy it to our internal buffer */ + ctx->dgstSize = gcry_md_get_algo_dlen(ctx->digest); + xmlSecAssert2(ctx->dgstSize > 0, -1); + xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1); + memcpy(ctx->dgst, buf, ctx->dgstSize); + + /* and to the output if needed */ + if(transform->operation == xmlSecTransformOperationSign) { + ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferAppend", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", ctx->dgstSize); + return(-1); + } + } + transform->status = xmlSecTransformStatusFinished; + } + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + +#ifndef XMLSEC_NO_SHA1 +/****************************************************************************** + * + * SHA1 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameSha1, /* const xmlChar* name; */ + xmlSecHrefSha1, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformSha1GetKlass: + * + * SHA-1 digest transform klass. + * + * Returns: pointer to SHA-1 digest transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformSha1GetKlass(void) { + return(&xmlSecGCryptSha1Klass); +} +#endif /* XMLSEC_NO_SHA1 */ + + +#ifndef XMLSEC_NO_SHA256 +/****************************************************************************** + * + * SHA256 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameSha256, /* const xmlChar* name; */ + xmlSecHrefSha256, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformSha256GetKlass: + * + * SHA256 digest transform klass. + * + * Returns: pointer to SHA256 digest transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformSha256GetKlass(void) { + return(&xmlSecGCryptSha256Klass); +} +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 +/****************************************************************************** + * + * SHA384 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptSha384Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameSha384, /* const xmlChar* name; */ + xmlSecHrefSha384, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformSha384GetKlass: + * + * SHA384 digest transform klass. + * + * Returns: pointer to SHA384 digest transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformSha384GetKlass(void) { + return(&xmlSecGCryptSha384Klass); +} +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 +/****************************************************************************** + * + * SHA512 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptSha512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameSha512, /* const xmlChar* name; */ + xmlSecHrefSha512, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformSha512GetKlass: + * + * SHA512 digest transform klass. + * + * Returns: pointer to SHA512 digest transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformSha512GetKlass(void) { + return(&xmlSecGCryptSha512Klass); +} +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_MD5 +/****************************************************************************** + * + * MD5 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptMd5Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameMd5, /* const xmlChar* name; */ + xmlSecHrefMd5, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformMd5GetKlass: + * + * MD5 digest transform klass. + * + * Returns: pointer to MD5 digest transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformMd5GetKlass(void) { + return(&xmlSecGCryptMd5Klass); +} +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 +/****************************************************************************** + * + * RIPEMD160 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRipemd160Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameRipemd160, /* const xmlChar* name; */ + xmlSecHrefRipemd160, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGCryptDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRipemd160GetKlass: + * + * RIPEMD160 digest transform klass. + * + * Returns: pointer to RIPEMD160 digest transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRipemd160GetKlass(void) { + return(&xmlSecGCryptRipemd160Klass); +} +#endif /* XMLSEC_NO_RIPEMD160 */ diff --git a/src/gcrypt/globals.h b/src/gcrypt/globals.h new file mode 100644 index 00000000..7bc03c1c --- /dev/null +++ b/src/gcrypt/globals.h @@ -0,0 +1,30 @@ +/* + * XML Security Library + * + * globals.h: internal header only used during the compilation + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef __XMLSEC_GLOBALS_H__ +#define __XMLSEC_GLOBALS_H__ + +/** + * Use autoconf defines if present. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#define IN_XMLSEC_CRYPTO +#define XMLSEC_PRIVATE + + +#define XMLSEC_GCRYPT_MAX_DIGEST_SIZE 256 +#define XMLSEC_GCRYPT_REPORT_ERROR(err) \ + "error code=%d; error message='%s'", \ + (int)err, xmlSecErrorsSafeString(gcry_strerror((err))) + +#endif /* ! __XMLSEC_GLOBALS_H__ */ diff --git a/src/gcrypt/hmac.c b/src/gcrypt/hmac.c new file mode 100644 index 00000000..192cb17b --- /dev/null +++ b/src/gcrypt/hmac.c @@ -0,0 +1,823 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef XMLSEC_NO_HMAC +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/app.h> +#include <xmlsec/gcrypt/crypto.h> + +/* sizes in bits */ +#define XMLSEC_GCRYPT_MIN_HMAC_SIZE 80 +#define XMLSEC_GCRYPT_MAX_HMAC_SIZE (128 * 8) + +/************************************************************************** + * + * Configuration + * + *****************************************************************************/ +static int g_xmlsec_gcrypt_hmac_min_length = XMLSEC_GCRYPT_MIN_HMAC_SIZE; + +/** + * xmlSecGCryptHmacGetMinOutputLength: + * + * Gets the value of min HMAC length. + * + * Returns: the min HMAC output length + */ +int xmlSecGCryptHmacGetMinOutputLength(void) +{ + return g_xmlsec_gcrypt_hmac_min_length; +} + +/** + * xmlSecGCryptHmacSetMinOutputLength: + * @min_length: the new min length + * + * Sets the min HMAC output length + */ +void xmlSecGCryptHmacSetMinOutputLength(int min_length) +{ + g_xmlsec_gcrypt_hmac_min_length = min_length; +} + +/************************************************************************** + * + * Internal GCRYPT HMAC CTX + * + *****************************************************************************/ +typedef struct _xmlSecGCryptHmacCtx xmlSecGCryptHmacCtx, *xmlSecGCryptHmacCtxPtr; +struct _xmlSecGCryptHmacCtx { + int digest; + gcry_md_hd_t digestCtx; + xmlSecByte dgst[XMLSEC_GCRYPT_MAX_HMAC_SIZE / 8]; + xmlSecSize dgstSize; /* dgst size in bits */ +}; + +/****************************************************************************** + * + * HMAC transforms + * + * xmlSecGCryptHmacCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecGCryptHmacGetCtx(transform) \ + ((xmlSecGCryptHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) +#define xmlSecGCryptHmacSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptHmacCtx)) + +static int xmlSecGCryptHmacCheckId (xmlSecTransformPtr transform); +static int xmlSecGCryptHmacInitialize (xmlSecTransformPtr transform); +static void xmlSecGCryptHmacFinalize (xmlSecTransformPtr transform); +static int xmlSecGCryptHmacNodeRead (xmlSecTransformPtr transform, + xmlNodePtr node, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptHmacSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecGCryptHmacSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecGCryptHmacVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptHmacExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); + +static int +xmlSecGCryptHmacCheckId(xmlSecTransformPtr transform) { + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha256Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha384Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacRipemd160Id)) { + return(1); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacMd5Id)) { + return(1); + } else +#endif /* XMLSEC_NO_MD5 */ + + /* not found */ + { + return(0); + } + + /* just in case */ + return(0); +} + + +static int +xmlSecGCryptHmacInitialize(xmlSecTransformPtr transform) { + xmlSecGCryptHmacCtxPtr ctx; + gcry_error_t err; + + xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecGCryptHmacCtx)); + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha1Id)) { + ctx->digest = GCRY_MD_SHA1; + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha256Id)) { + ctx->digest = GCRY_MD_SHA256; + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha384Id)) { + ctx->digest = GCRY_MD_SHA384; + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacSha512Id)) { + ctx->digest = GCRY_MD_SHA512; + } else +#endif /* XMLSEC_NO_SHA512 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacRipemd160Id)) { + ctx->digest = GCRY_MD_RMD160; + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformHmacMd5Id)) { + ctx->digest = GCRY_MD_MD5; + } else +#endif /* XMLSEC_NO_MD5 */ + + /* not found */ + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* open context */ + err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); /* we are paranoid */ + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + return(0); +} + +static void +xmlSecGCryptHmacFinalize(xmlSecTransformPtr transform) { + xmlSecGCryptHmacCtxPtr ctx; + + xmlSecAssert(xmlSecGCryptHmacCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize)); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->digestCtx != NULL) { + gcry_md_close(ctx->digestCtx); + } + memset(ctx, 0, sizeof(xmlSecGCryptHmacCtx)); +} + +/** + * xmlSecGCryptHmacNodeRead: + * + * HMAC (http://www.w3.org/TR/xmldsig-core/#sec-HMAC): + * + * The HMAC algorithm (RFC2104 [HMAC]) takes the truncation length in bits + * as a parameter; if the parameter is not specified then all the bits of the + * hash are output. An example of an HMAC SignatureMethod element: + * <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"> + * <HMACOutputLength>128</HMACOutputLength> + * </SignatureMethod> + * + * Schema Definition: + * + * <simpleType name="HMACOutputLengthType"> + * <restriction base="integer"/> + * </simpleType> + * + * DTD: + * + * <!ELEMENT HMACOutputLength (#PCDATA)> + */ +static int +xmlSecGCryptHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptHmacCtxPtr ctx; + xmlNodePtr cur; + + xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1); + xmlSecAssert2(node != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + cur = xmlSecGetNextElementNode(node->children); + if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) { + xmlChar *content; + + content = xmlNodeGetContent(cur); + if(content != NULL) { + ctx->dgstSize = atoi((char*)content); + xmlFree(content); + } + + /* Ensure that HMAC length is greater than min specified. + Otherwise, an attacker can set this length to 0 or very + small value + */ + if((int)ctx->dgstSize < xmlSecGCryptHmacGetMinOutputLength()) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, + "HMAC output length is too small"); + return(-1); + } + + cur = xmlSecGetNextElementNode(cur->next); + } + + if(cur != NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), + XMLSEC_ERRORS_R_INVALID_NODE, + "no nodes expected"); + return(-1); + } + return(0); +} + + +static int +xmlSecGCryptHmacSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecGCryptHmacCtxPtr ctx; + + xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(keyReq != NULL, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecGCryptKeyDataHmacId; + keyReq->keyType= xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationSign) { + keyReq->keyUsage = xmlSecKeyUsageSign; + } else { + keyReq->keyUsage = xmlSecKeyUsageVerify; + } + + return(0); +} + +static int +xmlSecGCryptHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecGCryptHmacCtxPtr ctx; + xmlSecKeyDataPtr value; + xmlSecBufferPtr buffer; + gcry_error_t err; + + xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1); + xmlSecAssert2(key != NULL, -1); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digestCtx != NULL, -1); + + value = xmlSecKeyGetValue(key); + xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecGCryptKeyDataHmacId), -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(value); + xmlSecAssert2(buffer != NULL, -1); + + if(xmlSecBufferGetSize(buffer) == 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "key is empty"); + return(-1); + } + + err = gcry_md_setkey(ctx->digestCtx, xmlSecBufferGetData(buffer), + xmlSecBufferGetSize(buffer)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_setkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + return(0); +} + +static int +xmlSecGCryptHmacVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + static xmlSecByte last_byte_masks[] = + { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE }; + + xmlSecGCryptHmacCtxPtr ctx; + xmlSecByte mask; + + xmlSecAssert2(xmlSecTransformIsValid(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digestCtx != NULL, -1); + xmlSecAssert2(ctx->dgstSize > 0, -1); + + /* compare the digest size in bytes */ + if(dataSize != ((ctx->dgstSize + 7) / 8)){ + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "data=%d;dgst=%d", + dataSize, ((ctx->dgstSize + 7) / 8)); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + /* we check the last byte separatelly */ + xmlSecAssert2(dataSize > 0, -1); + mask = last_byte_masks[ctx->dgstSize % 8]; + if((ctx->dgst[dataSize - 1] & mask) != (data[dataSize - 1] & mask)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_DATA_NOT_MATCH, + "data and digest do not match (last byte)"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + /* now check the rest of the digest */ + if((dataSize > 1) && (memcmp(ctx->dgst, data, dataSize - 1) != 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_DATA_NOT_MATCH, + "data and digest do not match"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + transform->status = xmlSecTransformStatusOk; + return(0); +} + +static int +xmlSecGCryptHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptHmacCtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecByte* dgst; + xmlSecSize dgstSize; + int ret; + + xmlSecAssert2(xmlSecGCryptHmacCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptHmacSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptHmacGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digestCtx != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + xmlSecSize inSize; + + inSize = xmlSecBufferGetSize(in); + if(inSize > 0) { + gcry_md_write(ctx->digestCtx, xmlSecBufferGetData(in), inSize); + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + } + if(last) { + /* get the final digest */ + gcry_md_final(ctx->digestCtx); + dgst = gcry_md_read(ctx->digestCtx, ctx->digest); + if(dgst == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_read", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* copy it to our internal buffer */ + dgstSize = gcry_md_get_algo_dlen(ctx->digest); + xmlSecAssert2(dgstSize > 0, -1); + xmlSecAssert2(dgstSize <= sizeof(ctx->dgst), -1); + memcpy(ctx->dgst, dgst, dgstSize); + + /* check/set the result digest size */ + if(ctx->dgstSize == 0) { + ctx->dgstSize = dgstSize * 8; /* no dgst size specified, use all we have */ + } else if(ctx->dgstSize <= 8 * dgstSize) { + dgstSize = ((ctx->dgstSize + 7) / 8); /* we need to truncate result digest */ + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "result-bits=%d;required-bits=%d", + 8 * dgstSize, ctx->dgstSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationSign) { + ret = xmlSecBufferAppend(out, ctx->dgst, dgstSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferAppend", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", dgstSize); + return(-1); + } + } + transform->status = xmlSecTransformStatusFinished; + } + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "size=%d", transform->status); + return(-1); + } + + return(0); +} + +#ifndef XMLSEC_NO_SHA1 +/****************************************************************************** + * + * HMAC SHA1 + * + ******************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptHmacSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha1, /* const xmlChar* name; */ + xmlSecHrefHmacSha1, /* const xmlChar *href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformHmacSha1GetKlass: + * + * The HMAC-SHA1 transform klass. + * + * Returns: the HMAC-SHA1 transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformHmacSha1GetKlass(void) { + return(&xmlSecGCryptHmacSha1Klass); +} +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 +/****************************************************************************** + * + * HMAC SHA256 + * + ******************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptHmacSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha256, /* const xmlChar* name; */ + xmlSecHrefHmacSha256, /* const xmlChar *href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformHmacSha256GetKlass: + * + * The HMAC-SHA256 transform klass. + * + * Returns: the HMAC-SHA256 transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformHmacSha256GetKlass(void) { + return(&xmlSecGCryptHmacSha256Klass); +} +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 +/****************************************************************************** + * + * HMAC SHA384 + * + ******************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptHmacSha384Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha384, /* const xmlChar* name; */ + xmlSecHrefHmacSha384, /* const xmlChar *href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformHmacSha384GetKlass: + * + * The HMAC-SHA384 transform klass. + * + * Returns: the HMAC-SHA384 transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformHmacSha384GetKlass(void) { + return(&xmlSecGCryptHmacSha384Klass); +} +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 +/****************************************************************************** + * + * HMAC SHA512 + * + ******************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptHmacSha512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacSha512, /* const xmlChar* name; */ + xmlSecHrefHmacSha512, /* const xmlChar *href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformHmacSha512GetKlass: + * + * The HMAC-SHA512 transform klass. + * + * Returns: the HMAC-SHA512 transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformHmacSha512GetKlass(void) { + return(&xmlSecGCryptHmacSha512Klass); +} +#endif /* XMLSEC_NO_SHA512 */ + + +#ifndef XMLSEC_NO_RIPEMD160 +/****************************************************************************** + * + * HMAC Ripemd160 + * + ******************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptHmacRipemd160Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacRipemd160, /* const xmlChar* name; */ + xmlSecHrefHmacRipemd160, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformHmacRipemd160GetKlass: + * + * The HMAC-RIPEMD160 transform klass. + * + * Returns: the HMAC-RIPEMD160 transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformHmacRipemd160GetKlass(void) { + return(&xmlSecGCryptHmacRipemd160Klass); +} +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_MD5 +/****************************************************************************** + * + * HMAC MD5 + * + ******************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptHmacMd5Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptHmacSize, /* xmlSecSize objSize */ + + xmlSecNameHmacMd5, /* const xmlChar* name; */ + xmlSecHrefHmacMd5, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptHmacInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptHmacFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + xmlSecGCryptHmacNodeRead, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptHmacSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptHmacSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptHmacVerify, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptHmacExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformHmacMd5GetKlass: + * + * The HMAC-MD5 transform klass. + * + * Returns: the HMAC-MD5 transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformHmacMd5GetKlass(void) { + return(&xmlSecGCryptHmacMd5Klass); +} +#endif /* XMLSEC_NO_MD5 */ + + +#endif /* XMLSEC_NO_HMAC */ diff --git a/src/gcrypt/kw_aes.c b/src/gcrypt/kw_aes.c new file mode 100644 index 00000000..38ac8956 --- /dev/null +++ b/src/gcrypt/kw_aes.c @@ -0,0 +1,593 @@ +/** + * + * XMLSec library + * + * AES Algorithm support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef XMLSEC_NO_AES +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + +#include "../kw_aes_des.h" + + +/********************************************************************* + * + * AES KW implementation + * + *********************************************************************/ +static int xmlSecGCryptKWAesBlockEncrypt (const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize, + void * context); +static int xmlSecGCryptKWAesBlockDecrypt (const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize, + void * context); +static xmlSecKWAesKlass xmlSecGCryptKWAesKlass = { + /* callbacks */ + xmlSecGCryptKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */ + xmlSecGCryptKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */ + + /* for the future */ + NULL, /* void* reserved0; */ + NULL /* void* reserved1; */ +}; + + +/********************************************************************* + * + * AES KW transforms + * + ********************************************************************/ +typedef struct _xmlSecGCryptKWAesCtx xmlSecGCryptKWAesCtx, + *xmlSecGCryptKWAesCtxPtr; +struct _xmlSecGCryptKWAesCtx { + int cipher; + int mode; + int flags; + xmlSecSize blockSize; + xmlSecSize keyExpectedSize; + + xmlSecBuffer keyBuffer; +}; +#define xmlSecGCryptKWAesSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptKWAesCtx)) +#define xmlSecGCryptKWAesGetCtx(transform) \ + ((xmlSecGCryptKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) +#define xmlSecGCryptKWAesCheckId(transform) \ + (xmlSecTransformCheckId((transform), xmlSecGCryptTransformKWAes128Id) || \ + xmlSecTransformCheckId((transform), xmlSecGCryptTransformKWAes192Id) || \ + xmlSecTransformCheckId((transform), xmlSecGCryptTransformKWAes256Id)) + +static int xmlSecGCryptKWAesInitialize (xmlSecTransformPtr transform); +static void xmlSecGCryptKWAesFinalize (xmlSecTransformPtr transform); +static int xmlSecGCryptKWAesSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecGCryptKWAesSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecGCryptKWAesExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); + +static int +xmlSecGCryptKWAesInitialize(xmlSecTransformPtr transform) { + xmlSecGCryptKWAesCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1); + + ctx = xmlSecGCryptKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWAes128Id)) { + ctx->cipher = GCRY_CIPHER_AES128; + ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE; + } else if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWAes192Id)) { + ctx->cipher = GCRY_CIPHER_AES192; + ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE; + } else if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWAes256Id)) { + ctx->cipher = GCRY_CIPHER_AES256; + ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE; + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + ctx->mode = GCRY_CIPHER_MODE_CBC; + ctx->flags = GCRY_CIPHER_SECURE; /* we are paranoid */ + ctx->blockSize = gcry_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(ctx->blockSize > 0, -1); + + ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecGCryptKWAesGetKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static void +xmlSecGCryptKWAesFinalize(xmlSecTransformPtr transform) { + xmlSecGCryptKWAesCtxPtr ctx; + + xmlSecAssert(xmlSecGCryptKWAesCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize)); + + ctx = xmlSecGCryptKWAesGetCtx(transform); + xmlSecAssert(ctx != NULL); + + xmlSecBufferFinalize(&(ctx->keyBuffer)); +} + +static int +xmlSecGCryptKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecGCryptKWAesCtxPtr ctx; + + xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecGCryptKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecGCryptKeyDataAesId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + keyReq->keyBitsSize = 8 * ctx->keyExpectedSize; + + return(0); +} + +static int +xmlSecGCryptKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecGCryptKWAesCtxPtr ctx; + xmlSecBufferPtr buffer; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataAesId), -1); + + ctx = xmlSecGCryptKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer != NULL, -1); + + keySize = xmlSecBufferGetSize(buffer); + if(keySize < ctx->keyExpectedSize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "key=%d;expected=%d", + keySize, ctx->keyExpectedSize); + return(-1); + } + + ret = xmlSecBufferSetData(&(ctx->keyBuffer), + xmlSecBufferGetData(buffer), + ctx->keyExpectedSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "expected-size=%d", + ctx->keyExpectedSize); + return(-1); + } + + return(0); +} + +static int +xmlSecGCryptKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptKWAesCtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize, outSize, keySize; + int ret; + + xmlSecAssert2(xmlSecGCryptKWAesCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWAesSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptKWAesGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keySize = xmlSecBufferGetSize(&(ctx->keyBuffer)); + xmlSecAssert2(keySize == ctx->keyExpectedSize, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + xmlSecAssert2(outSize == 0, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) { + /* just do nothing */ + } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + if((inSize % 8) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "size=%d(not 8 bytes aligned)", inSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + /* the encoded key might be 8 bytes longer plus 8 bytes just in case */ + outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE + + XMLSEC_KW_AES_BLOCK_SIZE; + } else { + outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE; + } + + ret = xmlSecBufferSetMaxSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "outSize=%d", outSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + ret = xmlSecKWAesEncode(&xmlSecGCryptKWAesKlass, ctx, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWAesEncode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } else { + ret = xmlSecKWAesDecode(&xmlSecGCryptKWAesKlass, ctx, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWAesEncode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + outSize = ret; + } + + ret = xmlSecBufferSetSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "outSize=%d", outSize); + return(-1); + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "inSize%d", inSize); + return(-1); + } + + transform->status = xmlSecTransformStatusFinished; + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + return(0); +} + + +static xmlSecTransformKlass xmlSecGCryptKWAes128Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptKWAesSize, /* xmlSecSize objSize */ + + xmlSecNameKWAes128, /* const xmlChar* name; */ + xmlSecHrefKWAes128, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptKWAesExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformKWAes128GetKlass: + * + * The AES-128 kew wrapper transform klass. + * + * Returns: AES-128 kew wrapper transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformKWAes128GetKlass(void) { + return(&xmlSecGCryptKWAes128Klass); +} + +static xmlSecTransformKlass xmlSecGCryptKWAes192Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptKWAesSize, /* xmlSecSize objSize */ + + xmlSecNameKWAes192, /* const xmlChar* name; */ + xmlSecHrefKWAes192, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptKWAesExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + + +/** + * xmlSecGCryptTransformKWAes192GetKlass: + * + * The AES-192 kew wrapper transform klass. + * + * Returns: AES-192 kew wrapper transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformKWAes192GetKlass(void) { + return(&xmlSecGCryptKWAes192Klass); +} + +static xmlSecTransformKlass xmlSecGCryptKWAes256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptKWAesSize, /* xmlSecSize objSize */ + + xmlSecNameKWAes256, /* const xmlChar* name; */ + xmlSecHrefKWAes256, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptKWAesExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformKWAes256GetKlass: + * + * The AES-256 kew wrapper transform klass. + * + * Returns: AES-256 kew wrapper transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformKWAes256GetKlass(void) { + return(&xmlSecGCryptKWAes256Klass); +} + +/********************************************************************* + * + * AES KW implementation + * + *********************************************************************/ +static unsigned char g_zero_iv[XMLSEC_KW_AES_BLOCK_SIZE] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static int +xmlSecGCryptKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize, + void * context) { + xmlSecGCryptKWAesCtxPtr ctx = (xmlSecGCryptKWAesCtxPtr)context; + gcry_cipher_hd_t cipherCtx; + gcry_error_t err; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize >= ctx->blockSize, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= ctx->blockSize, -1); + + err = gcry_cipher_open(&cipherCtx, ctx->cipher, ctx->mode, ctx->flags); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + err = gcry_cipher_setkey(cipherCtx, + xmlSecBufferGetData(&ctx->keyBuffer), + xmlSecBufferGetSize(&ctx->keyBuffer)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_setkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + /* use zero IV and CBC mode to ensure we get result as-is */ + err = gcry_cipher_setiv(cipherCtx, g_zero_iv, sizeof(g_zero_iv)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + err = gcry_cipher_encrypt(cipherCtx, out, outSize, in, inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + gcry_cipher_close(cipherCtx); + return(-1); + } + gcry_cipher_close(cipherCtx); + + return(ctx->blockSize); +} + +static int +xmlSecGCryptKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize, + void * context) { + xmlSecGCryptKWAesCtxPtr ctx = (xmlSecGCryptKWAesCtxPtr)context; + gcry_cipher_hd_t cipherCtx; + gcry_error_t err; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize >= ctx->blockSize, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= ctx->blockSize, -1); + + err = gcry_cipher_open(&cipherCtx, ctx->cipher, ctx->mode, ctx->flags); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + err = gcry_cipher_setkey(cipherCtx, + xmlSecBufferGetData(&ctx->keyBuffer), + xmlSecBufferGetSize(&ctx->keyBuffer)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_setkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + /* use zero IV and CBC mode to ensure we get result as-is */ + err = gcry_cipher_setiv(cipherCtx, g_zero_iv, sizeof(g_zero_iv)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + err = gcry_cipher_decrypt(cipherCtx, out, outSize, in, inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + gcry_cipher_close(cipherCtx); + return(-1); + } + gcry_cipher_close(cipherCtx); + + return(ctx->blockSize); +} + +#endif /* XMLSEC_NO_AES */ diff --git a/src/gcrypt/kw_des.c b/src/gcrypt/kw_des.c new file mode 100644 index 00000000..b93eb9f5 --- /dev/null +++ b/src/gcrypt/kw_des.c @@ -0,0 +1,607 @@ +/** + * + * XMLSec library + * + * DES Algorithm support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#ifndef XMLSEC_NO_DES +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <gcrypt.h> + + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + +#include "../kw_aes_des.h" + +/********************************************************************* + * + * DES KW implementation + * + *********************************************************************/ +static int xmlSecGCryptKWDes3GenerateRandom (void * context, + xmlSecByte * out, + xmlSecSize outSize); +static int xmlSecGCryptKWDes3Sha1 (void * context, + const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize); +static int xmlSecGCryptKWDes3BlockEncrypt (void * context, + const xmlSecByte * iv, + xmlSecSize ivSize, + const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize); +static int xmlSecGCryptKWDes3BlockDecrypt (void * context, + const xmlSecByte * iv, + xmlSecSize ivSize, + const xmlSecByte * in, + xmlSecSize inSize, + xmlSecByte * out, + xmlSecSize outSize); + +static xmlSecKWDes3Klass xmlSecGCryptKWDes3ImplKlass = { + /* callbacks */ + xmlSecGCryptKWDes3GenerateRandom, /* xmlSecKWDes3GenerateRandomMethod generateRandom; */ + xmlSecGCryptKWDes3Sha1, /* xmlSecKWDes3Sha1Method sha1; */ + xmlSecGCryptKWDes3BlockEncrypt, /* xmlSecKWDes3BlockEncryptMethod encrypt; */ + xmlSecGCryptKWDes3BlockDecrypt, /* xmlSecKWDes3BlockDecryptMethod decrypt; */ + + /* for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +static int xmlSecGCryptKWDes3Encrypt (const xmlSecByte *key, + xmlSecSize keySize, + const xmlSecByte *iv, + xmlSecSize ivSize, + const xmlSecByte *in, + xmlSecSize inSize, + xmlSecByte *out, + xmlSecSize outSize, + int enc); + + +/********************************************************************* + * + * Triple DES Key Wrap transform + * + * key (xmlSecBuffer) is located after xmlSecTransform structure + * + ********************************************************************/ +typedef struct _xmlSecGCryptKWDes3Ctx xmlSecGCryptKWDes3Ctx, + *xmlSecGCryptKWDes3CtxPtr; +struct _xmlSecGCryptKWDes3Ctx { + xmlSecBuffer keyBuffer; +}; +#define xmlSecGCryptKWDes3Size \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptKWDes3Ctx)) +#define xmlSecGCryptKWDes3GetCtx(transform) \ + ((xmlSecGCryptKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecGCryptKWDes3Initialize (xmlSecTransformPtr transform); +static void xmlSecGCryptKWDes3Finalize (xmlSecTransformPtr transform); +static int xmlSecGCryptKWDes3SetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecGCryptKWDes3SetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecGCryptKWDes3Execute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static xmlSecTransformKlass xmlSecGCryptKWDes3Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptKWDes3Size, /* xmlSecSize objSize */ + + xmlSecNameKWDes3, /* const xmlChar* name; */ + xmlSecHrefKWDes3, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecGCryptKWDes3Initialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptKWDes3Finalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptKWDes3SetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecGCryptKWDes3SetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptKWDes3Execute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformKWDes3GetKlass: + * + * The Triple DES key wrapper transform klass. + * + * Returns: Triple DES key wrapper transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformKWDes3GetKlass(void) { + return(&xmlSecGCryptKWDes3Klass); +} + +static int +xmlSecGCryptKWDes3Initialize(xmlSecTransformPtr transform) { + xmlSecGCryptKWDes3CtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1); + + ctx = xmlSecGCryptKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static void +xmlSecGCryptKWDes3Finalize(xmlSecTransformPtr transform) { + xmlSecGCryptKWDes3CtxPtr ctx; + + xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size)); + + ctx = xmlSecGCryptKWDes3GetCtx(transform); + xmlSecAssert(ctx != NULL); + + xmlSecBufferFinalize(&(ctx->keyBuffer)); +} + +static int +xmlSecGCryptKWDes3SetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecGCryptKWDes3CtxPtr ctx; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecGCryptKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keyReq->keyId = xmlSecGCryptKeyDataDesId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage= xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage= xmlSecKeyUsageDecrypt; + } + keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH; + return(0); +} + +static int +xmlSecGCryptKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecGCryptKWDes3CtxPtr ctx; + xmlSecBufferPtr buffer; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1); + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataDesId), -1); + + ctx = xmlSecGCryptKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer != NULL, -1); + + keySize = xmlSecBufferGetSize(buffer); + if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "key length %d is not enough (%d expected)", + keySize, XMLSEC_KW_DES3_KEY_LENGTH); + return(-1); + } + + ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", XMLSEC_KW_DES3_KEY_LENGTH); + return(-1); + } + + return(0); +} + +static int +xmlSecGCryptKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptKWDes3CtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize, outSize, keySize; + int ret; + + xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGCryptTransformKWDes3Id), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptKWDes3Size), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptKWDes3GetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + keySize = xmlSecBufferGetSize(&(ctx->keyBuffer)); + xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + xmlSecAssert2(outSize == 0, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) { + /* just do nothing */ + } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { + if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_SIZE, + "%d bytes - not %d bytes aligned", + inSize, XMLSEC_KW_DES3_BLOCK_LENGTH); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + /* the encoded key might be 16 bytes longer plus one block just in case */ + outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH + + XMLSEC_KW_DES3_BLOCK_LENGTH + + XMLSEC_KW_DES3_BLOCK_LENGTH; + } else { + /* just in case, add a block */ + outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH; + } + + ret = xmlSecBufferSetMaxSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + if(transform->operation == xmlSecTransformOperationEncrypt) { + ret = xmlSecKWDes3Encode(&xmlSecGCryptKWDes3ImplKlass, ctx, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWDes3Encode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "key=%d,in=%d,out=%d", + keySize, inSize, outSize); + return(-1); + } + outSize = ret; + } else { + ret = xmlSecKWDes3Decode(&xmlSecGCryptKWDes3ImplKlass, ctx, + xmlSecBufferGetData(in), inSize, + xmlSecBufferGetData(out), outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKWDes3Decode", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "key=%d,in=%d,out=%d", + keySize, inSize, outSize); + return(-1); + } + outSize = ret; + } + + ret = xmlSecBufferSetSize(out, outSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize); + return(-1); + } + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + transform->status = xmlSecTransformStatusFinished; + } else if(transform->status == xmlSecTransformStatusFinished) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + return(0); +} + +/********************************************************************* + * + * DES KW implementation + * + *********************************************************************/ +static int +xmlSecGCryptKWDes3Sha1(void * context, + const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context; + gcry_md_hd_t digestCtx; + unsigned char * res; + unsigned int len; + gcry_error_t err; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize > 0, -1); + + len = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + xmlSecAssert2(outSize >= len, -1); + + err = gcry_md_open(&digestCtx, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); /* we are paranoid */ + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_md_open(GCRY_MD_SHA1)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + gcry_md_write(digestCtx, in, inSize); + + err = gcry_md_final(digestCtx); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_md_final", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + gcry_md_close(digestCtx); + return(-1); + } + + res = gcry_md_read(digestCtx, GCRY_MD_SHA1); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_md_read(GCRY_MD_SHA1)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + gcry_md_close(digestCtx); + return(-1); + } + + /* done */ + xmlSecAssert2(outSize >= len, -1); + memcpy(out, res, len); + gcry_md_close(digestCtx); + return(len); +} + +static int +xmlSecGCryptKWDes3GenerateRandom(void * context, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize > 0, -1); + + gcry_randomize(out, outSize, GCRY_STRONG_RANDOM); + return((int)outSize); +} + +static int +xmlSecGCryptKWDes3BlockEncrypt(void * context, + const xmlSecByte * iv, xmlSecSize ivSize, + const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1); + xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1); + xmlSecAssert2(iv != NULL, -1); + xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= inSize, -1); + + ret = xmlSecGCryptKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), + XMLSEC_KW_DES3_KEY_LENGTH, + iv, XMLSEC_KW_DES3_IV_LENGTH, + in, inSize, + out, outSize, + 1); /* encrypt */ + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKWDes3Encrypt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(ret); +} + +static int +xmlSecGCryptKWDes3BlockDecrypt(void * context, + const xmlSecByte * iv, xmlSecSize ivSize, + const xmlSecByte * in, xmlSecSize inSize, + xmlSecByte * out, xmlSecSize outSize) { + xmlSecGCryptKWDes3CtxPtr ctx = (xmlSecGCryptKWDes3CtxPtr)context; + int ret; + + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1); + xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1); + xmlSecAssert2(iv != NULL, -1); + xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= inSize, -1); + + ret = xmlSecGCryptKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)), + XMLSEC_KW_DES3_KEY_LENGTH, + iv, XMLSEC_KW_DES3_IV_LENGTH, + in, inSize, + out, outSize, + 0); /* decrypt */ + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptKWDes3Encrypt", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(ret); +} + +static int +xmlSecGCryptKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize, + const xmlSecByte *iv, xmlSecSize ivSize, + const xmlSecByte *in, xmlSecSize inSize, + xmlSecByte *out, xmlSecSize outSize, + int enc) { + size_t key_len = gcry_cipher_get_algo_keylen(GCRY_CIPHER_3DES); + size_t block_len = gcry_cipher_get_algo_blklen(GCRY_CIPHER_3DES); + gcry_cipher_hd_t cipherCtx; + gcry_error_t err; + + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(keySize >= key_len, -1); + xmlSecAssert2(iv != NULL, -1); + xmlSecAssert2(ivSize >= block_len, -1); + xmlSecAssert2(in != NULL, -1); + xmlSecAssert2(inSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + xmlSecAssert2(outSize >= inSize, -1); + + err = gcry_cipher_open(&cipherCtx, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE); /* we are paranoid */ + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_open(GCRY_CIPHER_3DES)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + err = gcry_cipher_setkey(cipherCtx, key, keySize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_setkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + err = gcry_cipher_setiv(cipherCtx, iv, ivSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + if(enc) { + err = gcry_cipher_encrypt(cipherCtx, out, outSize, in, inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + gcry_cipher_close(cipherCtx); + return(-1); + } + } else { + err = gcry_cipher_decrypt(cipherCtx, out, outSize, in, inSize); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_cipher_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + gcry_cipher_close(cipherCtx); + return(-1); + } + } + + /* done */ + gcry_cipher_close(cipherCtx); + return((int)inSize); /* out size == in size */ +} + + +#endif /* XMLSEC_NO_DES */ + diff --git a/src/gcrypt/signatures.c b/src/gcrypt/signatures.c new file mode 100644 index 00000000..c49638e4 --- /dev/null +++ b/src/gcrypt/signatures.c @@ -0,0 +1,1490 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <string.h> + +#include <gcrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + + +/************************************************************************** + * + * Forward declarations for actual sign/verify implementations + * + *****************************************************************************/ +typedef int (*xmlSecGCryptPkSignMethod) (int digest, + xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, + xmlSecSize dgstSize, + xmlSecBufferPtr out); +typedef int (*xmlSecGCryptPkVerifyMethod) (int digest, + xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, + xmlSecSize dgstSize, + const xmlSecByte* data, + xmlSecSize dataSize); + +#ifndef XMLSEC_NO_DSA +static int xmlSecGCryptDsaPkSign (int digest, + xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, + xmlSecSize dgstSize, + xmlSecBufferPtr out); +static int xmlSecGCryptDsaPkVerify (int digest, + xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, + xmlSecSize dgstSize, + const xmlSecByte* data, + xmlSecSize dataSize); +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA +static int xmlSecGCryptRsaPkcs1PkSign (int digest, + xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, + xmlSecSize dgstSize, + xmlSecBufferPtr out); +static int xmlSecGCryptRsaPkcs1PkVerify (int digest, + xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, + xmlSecSize dgstSize, + const xmlSecByte* data, + xmlSecSize dataSize); +#endif /* XMLSEC_NO_RSA */ + + +/************************************************************************** + * + * Internal GCrypt signatures ctx + * + *****************************************************************************/ +typedef struct _xmlSecGCryptPkSignatureCtx xmlSecGCryptPkSignatureCtx, + *xmlSecGCryptPkSignatureCtxPtr; + + +struct _xmlSecGCryptPkSignatureCtx { + int digest; + xmlSecKeyDataId keyId; + xmlSecGCryptPkSignMethod sign; + xmlSecGCryptPkVerifyMethod verify; + + gcry_md_hd_t digestCtx; + xmlSecKeyDataPtr key_data; + + xmlSecByte dgst[XMLSEC_GCRYPT_MAX_DIGEST_SIZE]; + xmlSecSize dgstSize; /* dgst size in bytes */ +}; + + +/****************************************************************************** + * + * Pk Signature transforms + * + * xmlSecGCryptPkSignatureCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecGCryptPkSignatureSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptPkSignatureCtx)) +#define xmlSecGCryptPkSignatureGetCtx(transform) \ + ((xmlSecGCryptPkSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecGCryptPkSignatureCheckId (xmlSecTransformPtr transform); +static int xmlSecGCryptPkSignatureInitialize (xmlSecTransformPtr transform); +static void xmlSecGCryptPkSignatureFinalize (xmlSecTransformPtr transform); +static int xmlSecGCryptPkSignatureSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecGCryptPkSignatureSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecGCryptPkSignatureVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGCryptPkSignatureExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); + +static int +xmlSecGCryptPkSignatureCheckId(xmlSecTransformPtr transform) { +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDsaSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaMd5Id)) { + return(1); + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaRipemd160Id)) { + return(1); + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha1Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha256Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha384Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + { + return(0); + } + + return(0); +} + +static int +xmlSecGCryptPkSignatureInitialize(xmlSecTransformPtr transform) { + xmlSecGCryptPkSignatureCtxPtr ctx; + gcry_error_t err; + + xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + memset(ctx, 0, sizeof(xmlSecGCryptPkSignatureCtx)); + +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDsaSha1Id)) { + ctx->digest = GCRY_MD_SHA1; + ctx->keyId = xmlSecGCryptKeyDataDsaId; + ctx->sign = xmlSecGCryptDsaPkSign; + ctx->verify = xmlSecGCryptDsaPkVerify; + } else +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaMd5Id)) { + ctx->digest = GCRY_MD_MD5; + ctx->keyId = xmlSecGCryptKeyDataRsaId; + ctx->sign = xmlSecGCryptRsaPkcs1PkSign; + ctx->verify = xmlSecGCryptRsaPkcs1PkVerify; + } else +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaRipemd160Id)) { + ctx->digest = GCRY_MD_RMD160; + ctx->keyId = xmlSecGCryptKeyDataRsaId; + ctx->sign = xmlSecGCryptRsaPkcs1PkSign; + ctx->verify = xmlSecGCryptRsaPkcs1PkVerify; + } else +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha1Id)) { + ctx->digest = GCRY_MD_SHA1; + ctx->keyId = xmlSecGCryptKeyDataRsaId; + ctx->sign = xmlSecGCryptRsaPkcs1PkSign; + ctx->verify = xmlSecGCryptRsaPkcs1PkVerify; + } else +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha256Id)) { + ctx->digest = GCRY_MD_SHA256; + ctx->keyId = xmlSecGCryptKeyDataRsaId; + ctx->sign = xmlSecGCryptRsaPkcs1PkSign; + ctx->verify = xmlSecGCryptRsaPkcs1PkVerify; + } else +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha384Id)) { + ctx->digest = GCRY_MD_SHA384; + ctx->keyId = xmlSecGCryptKeyDataRsaId; + ctx->sign = xmlSecGCryptRsaPkcs1PkSign; + ctx->verify = xmlSecGCryptRsaPkcs1PkVerify; + } else +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha512Id)) { + ctx->digest = GCRY_MD_SHA512; + ctx->keyId = xmlSecGCryptKeyDataRsaId; + ctx->sign = xmlSecGCryptRsaPkcs1PkSign; + ctx->verify = xmlSecGCryptRsaPkcs1PkVerify; + } else +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + if(1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* create digest ctx */ + err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */ + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + /* done */ + return(0); +} + +static void +xmlSecGCryptPkSignatureFinalize(xmlSecTransformPtr transform) { + xmlSecGCryptPkSignatureCtxPtr ctx; + + xmlSecAssert(xmlSecGCryptPkSignatureCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize)); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->key_data != NULL) { + xmlSecKeyDataDestroy(ctx->key_data); + } + if(ctx->digestCtx != NULL) { + gcry_md_close(ctx->digestCtx); + } + + memset(ctx, 0, sizeof(xmlSecGCryptPkSignatureCtx)); +} + +static int +xmlSecGCryptPkSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecGCryptPkSignatureCtxPtr ctx; + xmlSecKeyDataPtr key_data; + + xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1); + xmlSecAssert2(key != NULL, -1); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); + + key_data = xmlSecKeyGetValue(key); + xmlSecAssert2(key_data != NULL, -1); + + if(ctx->key_data != NULL) { + xmlSecKeyDataDestroy(ctx->key_data); + } + + ctx->key_data = xmlSecKeyDataDuplicate(key_data); + if(ctx->key_data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecKeyDataDuplicate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +static int +xmlSecGCryptPkSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecGCryptPkSignatureCtxPtr ctx; + + xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1); + xmlSecAssert2(keyReq != NULL, -1); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->keyId != NULL, -1); + + keyReq->keyId = ctx->keyId; + if(transform->operation == xmlSecTransformOperationSign) { + keyReq->keyType = xmlSecKeyDataTypePrivate; + keyReq->keyUsage = xmlSecKeyUsageSign; + } else { + keyReq->keyType = xmlSecKeyDataTypePublic; + keyReq->keyUsage = xmlSecKeyUsageVerify; + } + return(0); +} + + +static int +xmlSecGCryptPkSignatureVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptPkSignatureCtxPtr ctx; + int ret; + + xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->sign != NULL, -1); + xmlSecAssert2(ctx->verify != NULL, -1); + xmlSecAssert2(ctx->dgstSize > 0, -1); + xmlSecAssert2(ctx->key_data != NULL, -1); + + ret = ctx->verify(ctx->digest, ctx->key_data, ctx->dgst, ctx->dgstSize, data, dataSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "ctx->verify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* check result */ + if(ret == 1) { + transform->status = xmlSecTransformStatusOk; + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "ctx->verify", + XMLSEC_ERRORS_R_DATA_NOT_MATCH, + "signature do not match"); + transform->status = xmlSecTransformStatusFail; + } + + /* done */ + return(0); +} + +static int +xmlSecGCryptPkSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGCryptPkSignatureCtxPtr ctx; + xmlSecBufferPtr in, out; + xmlSecSize inSize; + xmlSecSize outSize; + int ret; + + xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->sign != NULL, -1); + xmlSecAssert2(ctx->verify != NULL, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + ctx = xmlSecGCryptPkSignatureGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->key_data != NULL, -1); + + if(transform->status == xmlSecTransformStatusNone) { + /* do nothing, already initialized */ + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + xmlSecAssert2(outSize == 0, -1); + + /* update the digest */ + if(inSize > 0) { + gcry_md_write(ctx->digestCtx, xmlSecBufferGetData(in), inSize); + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + } + + /* generate digest and signature */ + if(last != 0) { + xmlSecByte* buf; + + /* get the final digest */ + gcry_md_final(ctx->digestCtx); + buf = gcry_md_read(ctx->digestCtx, ctx->digest); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_read", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* copy it to our internal buffer */ + ctx->dgstSize = gcry_md_get_algo_dlen(ctx->digest); + xmlSecAssert2(ctx->dgstSize > 0, -1); + xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1); + memcpy(ctx->dgst, buf, ctx->dgstSize); + + xmlSecAssert2(outSize == 0, -1); + if(transform->operation == xmlSecTransformOperationSign) { + ret = ctx->sign(ctx->digest, ctx->key_data, ctx->dgst, ctx->dgstSize, out); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "ctx->sign", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + /* done */ + transform->status = xmlSecTransformStatusFinished; + } + } + + if((transform->status == xmlSecTransformStatusWorking) || (transform->status == xmlSecTransformStatusFinished)) { + /* the only way we can get here is if there is no input */ + xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + +/***************************************************************************** + * + * Helper + * + ****************************************************************************/ +static int +xmlSecGCryptAppendMpi(gcry_mpi_t a, xmlSecBufferPtr out, xmlSecSize min_size) { + xmlSecSize outSize; + size_t written; + gpg_error_t err; + int ret; + + xmlSecAssert2(a != NULL, -1); + xmlSecAssert2(out != NULL, -1); + + /* current size */ + outSize = xmlSecBufferGetSize(out); + + /* figure out how much space we need */ + written = 0; + err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &written, a); + if((err != GPG_ERR_NO_ERROR) || (written == 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_print", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + /* add zeros at the beggining (if needed) */ + if((min_size > 0) && (written < min_size)) { + outSize += (min_size - written); + } + + /* allocate space */ + ret = xmlSecBufferSetMaxSize(out, outSize + written + 1); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", (int)(outSize + written + 1)); + return(-1); + } + xmlSecAssert2(xmlSecBufferGetMaxSize(out) > outSize, -1); + + /* add zeros at the beggining (if needed) */ + if((min_size > 0) && (written < min_size)) { + xmlSecSize ii; + xmlSecByte * p = xmlSecBufferGetData(out); + + for(ii = 0; ii < (min_size - written); ++ii) { + p[outSize - ii - 1] = 0; + } + } + + /* write out */ + written = 0; + err = gcry_mpi_print(GCRYMPI_FMT_USG, + xmlSecBufferGetData(out) + outSize, + xmlSecBufferGetMaxSize(out) - outSize, + &written, a); + if((err != GPG_ERR_NO_ERROR) || (written == 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_print", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + return(-1); + } + + /* reset size */ + ret = xmlSecBufferSetSize(out, outSize + written); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", + (int)(outSize + written)); + return(-1); + } + + /* done */ + return(0); +} + +#ifndef XMLSEC_NO_DSA + +#ifndef XMLSEC_NO_SHA1 +/**************************************************************************** + * + * DSA-SHA1 signature transform + * + * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg: + * + * The output of the DSA algorithm consists of a pair of integers + * usually referred by the pair (r, s). The signature value consists of + * the base64 encoding of the concatenation of two octet-streams that + * respectively result from the octet-encoding of the values r and s in + * that order. Integer to octet-stream conversion must be done according + * to the I2OSP operation defined in the RFC 2437 [PKCS1] specification + * with a l parameter equal to 20. For example, the SignatureValue element + * for a DSA signature (r, s) with values specified in hexadecimal: + * + * r = 8BAC1AB6 6410435C B7181F95 B16AB97C 92B341C0 + * s = 41E2345F 1F56DF24 58F426D1 55B4BA2D B6DCD8C8 + * + * from the example in Appendix 5 of the DSS standard would be + * + * <SignatureValue>i6watmQQQ1y3GB+VsWq5fJKzQcBB4jRfH1bfJFj0JtFVtLotttzYyA==</SignatureValue> + * + ***************************************************************************/ +static int +xmlSecGCryptDsaPkSign(int digest ATTRIBUTE_UNUSED, xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, xmlSecSize dgstSize, + xmlSecBufferPtr out) { + gcry_mpi_t m_hash = NULL; + gcry_sexp_t s_data = NULL; + gcry_sexp_t s_sig = NULL; + gcry_sexp_t s_r = NULL; + gcry_sexp_t s_s = NULL; + gcry_mpi_t m_r = NULL; + gcry_mpi_t m_s = NULL; + gcry_sexp_t s_tmp; + gpg_error_t err; + int ret; + int res = -1; + + xmlSecAssert2(key_data != NULL, -1); + xmlSecAssert2(xmlSecGCryptKeyDataDsaGetPrivateKey(key_data) != NULL, -1); + xmlSecAssert2(dgst != NULL, -1); + xmlSecAssert2(dgstSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + + /* get the current digest, can't use "hash" :( */ + err = gcry_mpi_scan(&m_hash, GCRYMPI_FMT_USG, dgst, dgstSize, NULL); + if((err != GPG_ERR_NO_ERROR) || (m_hash == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan(hash)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(value %m))", + m_hash); + if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(data)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* create signature */ + err = gcry_pk_sign(&s_sig, s_data, xmlSecGCryptKeyDataDsaGetPrivateKey(key_data)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_pk_sign", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* find signature value */ + s_tmp = gcry_sexp_find_token(s_sig, "sig-val", 0); + if(s_tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(sig-val)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + gcry_sexp_release(s_sig); + s_sig = s_tmp; + + s_tmp = gcry_sexp_find_token(s_sig, "dsa", 0); + if(s_tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(rsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + gcry_sexp_release(s_sig); + s_sig = s_tmp; + + /* r */ + s_r = gcry_sexp_find_token(s_sig, "r", 0); + if(s_r == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(r)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + m_r = gcry_sexp_nth_mpi(s_r, 1, GCRYMPI_FMT_USG); + if(m_r == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_nth_mpi(r)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* s */ + s_s = gcry_sexp_find_token(s_sig, "s", 0); + if(s_s == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(s)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + m_s = gcry_sexp_nth_mpi(s_s, 1, GCRYMPI_FMT_USG); + if(m_s == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_nth_mpi(s)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* write out: r + s */ + ret = xmlSecGCryptAppendMpi(m_r, out, 20); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppendMpi", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + xmlSecAssert2(xmlSecBufferGetSize(out) == 20, -1); + ret = xmlSecGCryptAppendMpi(m_s, out, 20); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppendMpi", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + xmlSecAssert2(xmlSecBufferGetSize(out) == (20 + 20), -1); + + /* done */ + res = 0; + +done: + if(m_hash != NULL) { + gcry_mpi_release(m_hash); + } + if(m_r != NULL) { + gcry_mpi_release(m_r); + } + if(m_s != NULL) { + gcry_mpi_release(m_s); + } + + if(s_data != NULL) { + gcry_sexp_release(s_data); + } + if(s_sig != NULL) { + gcry_sexp_release(s_sig); + } + if(s_r != NULL) { + gcry_sexp_release(s_r); + } + if(s_s != NULL) { + gcry_sexp_release(s_s); + } + + return(res); +} + +static int +xmlSecGCryptDsaPkVerify(int digest ATTRIBUTE_UNUSED, xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, xmlSecSize dgstSize, + const xmlSecByte* data, xmlSecSize dataSize) { + gcry_mpi_t m_hash = NULL; + gcry_sexp_t s_data = NULL; + gcry_mpi_t m_sig_r = NULL; + gcry_mpi_t m_sig_s = NULL; + gcry_sexp_t s_sig = NULL; + gpg_error_t err; + int res = -1; + + xmlSecAssert2(key_data != NULL, -1); + xmlSecAssert2(xmlSecGCryptKeyDataDsaGetPublicKey(key_data) != NULL, -1); + xmlSecAssert2(dgst != NULL, -1); + xmlSecAssert2(dgstSize > 0, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(dataSize == (20 + 20), -1); + + /* get the current digest, can't use "hash" :( */ + err = gcry_mpi_scan(&m_hash, GCRYMPI_FMT_USG, dgst, dgstSize, NULL); + if((err != GPG_ERR_NO_ERROR) || (m_hash == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan(hash)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(value %m))", + m_hash); + if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(data)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* get the existing signature */ + err = gcry_mpi_scan(&m_sig_r, GCRYMPI_FMT_USG, data, 20, NULL); + if((err != GPG_ERR_NO_ERROR) || (m_sig_r == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan(r)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + err = gcry_mpi_scan(&m_sig_s, GCRYMPI_FMT_USG, data + 20, 20, NULL); + if((err != GPG_ERR_NO_ERROR) || (m_sig_s == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan(s)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_sexp_build (&s_sig, NULL, + "(sig-val(dsa(r %m)(s %m)))", + m_sig_r, m_sig_s); + if((err != GPG_ERR_NO_ERROR) || (s_sig == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(sig-val)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* verify signature */ + err = gcry_pk_verify(s_sig, s_data, xmlSecGCryptKeyDataDsaGetPublicKey(key_data)); + if(err == GPG_ERR_NO_ERROR) { + res = 1; /* good signature */ + } else if(err == GPG_ERR_BAD_SIGNATURE) { + res = 0; /* bad signature */ + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_pk_verify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* done */ +done: + if(m_hash != NULL) { + gcry_mpi_release(m_hash); + } + if(m_sig_r != NULL) { + gcry_mpi_release(m_sig_r); + } + if(m_sig_s != NULL) { + gcry_mpi_release(m_sig_s); + } + + if(s_data != NULL) { + gcry_sexp_release(s_data); + } + if(s_sig != NULL) { + gcry_sexp_release(s_sig); + } + + return(res); +} + + +static xmlSecTransformKlass xmlSecGCryptDsaSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameDsaSha1, /* const xmlChar* name; */ + xmlSecHrefDsaSha1, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformDsaSha1GetKlass: + * + * The DSA-SHA1 signature transform klass. + * + * Returns: DSA-SHA1 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformDsaSha1GetKlass(void) { + return(&xmlSecGCryptDsaSha1Klass); +} + +#endif /* XMLSEC_NO_SHA1 */ + +#endif /* XMLSEC_NO_DSA */ + +#ifndef XMLSEC_NO_RSA + +/**************************************************************************** + * + * RSA-SHA1 signature transform + * + * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg: + * + * The SignatureValue content for an RSA signature is the base64 [MIME] + * encoding of the octet string computed as per RFC 2437 [PKCS1, + * section 8.1.1: Signature generation for the RSASSA-PKCS1-v1_5 signature + * scheme]. As specified in the EMSA-PKCS1-V1_5-ENCODE function RFC 2437 + * [PKCS1, section 9.2.1], the value input to the signature function MUST + * contain a pre-pended algorithm object identifier for the hash function, + * but the availability of an ASN.1 parser and recognition of OIDs is not + * required of a signature verifier. The PKCS#1 v1.5 representation appears + * as: + * + * CRYPT (PAD (ASN.1 (OID, DIGEST (data)))) + * + * Note that the padded ASN.1 will be of the following form: + * + * 01 | FF* | 00 | prefix | hash + * + * where "|" is concatenation, "01", "FF", and "00" are fixed octets of + * the corresponding hexadecimal value, "hash" is the SHA1 digest of the + * data, and "prefix" is the ASN.1 BER SHA1 algorithm designator prefix + * required in PKCS1 [RFC 2437], that is, + * + * hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 + * + * This prefix is included to make it easier to use standard cryptographic + * libraries. The FF octet MUST be repeated the maximum number of times such + * that the value of the quantity being CRYPTed is one octet shorter than + * the RSA modulus. + * + ***************************************************************************/ +static int +xmlSecGCryptRsaPkcs1PkSign(int digest, xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, xmlSecSize dgstSize, + xmlSecBufferPtr out) { + gcry_sexp_t s_data = NULL; + gcry_mpi_t m_sig = NULL; + gcry_sexp_t s_sig = NULL; + gcry_sexp_t s_tmp; + gpg_error_t err; + int ret; + int res = -1; + + xmlSecAssert2(key_data != NULL, -1); + xmlSecAssert2(xmlSecGCryptKeyDataRsaGetPrivateKey(key_data) != NULL, -1); + xmlSecAssert2(dgst != NULL, -1); + xmlSecAssert2(dgstSize > 0, -1); + xmlSecAssert2(out != NULL, -1); + + /* get the current digest */ + err = gcry_sexp_build (&s_data, NULL, + "(data (flags pkcs1)(hash %s %b))", + gcry_md_algo_name(digest), + (int)dgstSize, dgst); + if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(data)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* create signature */ + err = gcry_pk_sign(&s_sig, s_data, xmlSecGCryptKeyDataRsaGetPrivateKey(key_data)); + if(err != GPG_ERR_NO_ERROR) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_pk_sign", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* find signature value */ + s_tmp = gcry_sexp_find_token(s_sig, "sig-val", 0); + if(s_tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(sig-val)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + gcry_sexp_release(s_sig); + s_sig = s_tmp; + + s_tmp = gcry_sexp_find_token(s_sig, "rsa", 0); + if(s_tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(rsa)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + gcry_sexp_release(s_sig); + s_sig = s_tmp; + + s_tmp = gcry_sexp_find_token(s_sig, "s", 0); + if(s_tmp == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_find_token(s)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + gcry_sexp_release(s_sig); + s_sig = s_tmp; + + m_sig = gcry_sexp_nth_mpi(s_sig, 1, GCRYMPI_FMT_USG); + if(m_sig == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_nth_mpi(1)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* write out */ + ret = xmlSecGCryptAppendMpi(m_sig, out, 0); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecGCryptAppendMpi", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + /* done */ + res = 0; + +done: + if(m_sig != NULL) { + gcry_mpi_release(m_sig); + } + + if(s_data != NULL) { + gcry_sexp_release(s_data); + } + if(s_sig != NULL) { + gcry_sexp_release(s_sig); + } + + return(res); +} + +static int +xmlSecGCryptRsaPkcs1PkVerify(int digest, xmlSecKeyDataPtr key_data, + const xmlSecByte* dgst, xmlSecSize dgstSize, + const xmlSecByte* data, xmlSecSize dataSize) { + gcry_sexp_t s_data = NULL; + gcry_mpi_t m_sig = NULL; + gcry_sexp_t s_sig = NULL; + gpg_error_t err; + int res = -1; + + xmlSecAssert2(key_data != NULL, -1); + xmlSecAssert2(xmlSecGCryptKeyDataRsaGetPublicKey(key_data) != NULL, -1); + xmlSecAssert2(dgst != NULL, -1); + xmlSecAssert2(dgstSize > 0, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(dataSize > 0, -1); + + /* get the current digest */ + err = gcry_sexp_build (&s_data, NULL, + "(data (flags pkcs1)(hash %s %b))", + gcry_md_algo_name(digest), + (int)dgstSize, dgst); + if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(data)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* get the existing signature */ + err = gcry_mpi_scan(&m_sig, GCRYMPI_FMT_USG, data, dataSize, NULL); + if((err != GPG_ERR_NO_ERROR) || (m_sig == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_mpi_scan", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + err = gcry_sexp_build (&s_sig, NULL, + "(sig-val(rsa(s %m)))", + m_sig); + if((err != GPG_ERR_NO_ERROR) || (s_sig == NULL)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_sexp_build(sig-val)", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* verify signature */ + err = gcry_pk_verify(s_sig, s_data, xmlSecGCryptKeyDataRsaGetPublicKey(key_data)); + if(err == GPG_ERR_NO_ERROR) { + res = 1; /* good signature */ + } else if(err == GPG_ERR_BAD_SIGNATURE) { + res = 0; /* bad signature */ + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "gcry_pk_verify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_GCRYPT_REPORT_ERROR(err)); + goto done; + } + + /* done */ +done: + if(m_sig != NULL) { + gcry_mpi_release(m_sig); + } + + if(s_data != NULL) { + gcry_sexp_release(s_data); + } + if(s_sig != NULL) { + gcry_sexp_release(s_sig); + } + + return(res); +} + + +#ifndef XMLSEC_NO_MD5 +/**************************************************************************** + * + * RSA-MD5 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRsaMd5Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaMd5, /* const xmlChar* name; */ + xmlSecHrefRsaMd5, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRsaMd5GetKlass: + * + * The RSA-MD5 signature transform klass. + * + * Returns: RSA-MD5 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRsaMd5GetKlass(void) { + return(&xmlSecGCryptRsaMd5Klass); +} + +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_RIPEMD160 +/**************************************************************************** + * + * RSA-RIPEMD160 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRsaRipemd160Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaRipemd160, /* const xmlChar* name; */ + xmlSecHrefRsaRipemd160, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRsaRipemd160GetKlass: + * + * The RSA-RIPEMD160 signature transform klass. + * + * Returns: RSA-RIPEMD160 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRsaRipemd160GetKlass(void) { + return(&xmlSecGCryptRsaRipemd160Klass); +} + +#endif /* XMLSEC_NO_RIPEMD160 */ + +#ifndef XMLSEC_NO_SHA1 +/**************************************************************************** + * + * RSA-SHA1 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRsaSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha1, /* const xmlChar* name; */ + xmlSecHrefRsaSha1, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRsaSha1GetKlass: + * + * The RSA-SHA1 signature transform klass. + * + * Returns: RSA-SHA1 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRsaSha1GetKlass(void) { + return(&xmlSecGCryptRsaSha1Klass); +} + +#endif /* XMLSEC_NO_SHA1 */ + + +#ifndef XMLSEC_NO_SHA256 +/**************************************************************************** + * + * RSA-SHA256 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRsaSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha256, /* const xmlChar* name; */ + xmlSecHrefRsaSha256, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRsaSha256GetKlass: + * + * The RSA-SHA256 signature transform klass. + * + * Returns: RSA-SHA256 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRsaSha256GetKlass(void) { + return(&xmlSecGCryptRsaSha256Klass); +} + +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 +/**************************************************************************** + * + * RSA-SHA384 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRsaSha384Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha384, /* const xmlChar* name; */ + xmlSecHrefRsaSha384, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRsaSha384GetKlass: + * + * The RSA-SHA384 signature transform klass. + * + * Returns: RSA-SHA384 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRsaSha384GetKlass(void) { + return(&xmlSecGCryptRsaSha384Klass); +} + +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 +/**************************************************************************** + * + * RSA-SHA512 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecGCryptRsaSha512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha512, /* const xmlChar* name; */ + xmlSecHrefRsaSha512, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptTransformRsaSha512GetKlass: + * + * The RSA-SHA512 signature transform klass. + * + * Returns: RSA-SHA512 signature transform klass. + */ +xmlSecTransformId +xmlSecGCryptTransformRsaSha512GetKlass(void) { + return(&xmlSecGCryptRsaSha512Klass); +} + +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_RSA */ + + + diff --git a/src/gcrypt/symkeys.c b/src/gcrypt/symkeys.c new file mode 100644 index 00000000..88272fe3 --- /dev/null +++ b/src/gcrypt/symkeys.c @@ -0,0 +1,441 @@ +/** + * + * XMLSec library + * + * DES Algorithm support + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + */ +#include "globals.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#include <xmlsec/keys.h> +#include <xmlsec/keyinfo.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/gcrypt/crypto.h> + + +/***************************************************************************** + * + * Symmetic (binary) keys - just a wrapper for xmlSecKeyDataBinary + * + ****************************************************************************/ +static int xmlSecGCryptSymKeyDataInitialize (xmlSecKeyDataPtr data); +static int xmlSecGCryptSymKeyDataDuplicate (xmlSecKeyDataPtr dst, + xmlSecKeyDataPtr src); +static void xmlSecGCryptSymKeyDataFinalize (xmlSecKeyDataPtr data); +static int xmlSecGCryptSymKeyDataXmlRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptSymKeyDataXmlWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlNodePtr node, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptSymKeyDataBinRead (xmlSecKeyDataId id, + xmlSecKeyPtr key, + const xmlSecByte* buf, + xmlSecSize bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptSymKeyDataBinWrite (xmlSecKeyDataId id, + xmlSecKeyPtr key, + xmlSecByte** buf, + xmlSecSize* bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx); +static int xmlSecGCryptSymKeyDataGenerate (xmlSecKeyDataPtr data, + xmlSecSize sizeBits, + xmlSecKeyDataType type); + +static xmlSecKeyDataType xmlSecGCryptSymKeyDataGetType (xmlSecKeyDataPtr data); +static xmlSecSize xmlSecGCryptSymKeyDataGetSize (xmlSecKeyDataPtr data); +static void xmlSecGCryptSymKeyDataDebugDump (xmlSecKeyDataPtr data, + FILE* output); +static void xmlSecGCryptSymKeyDataDebugXmlDump (xmlSecKeyDataPtr data, + FILE* output); +static int xmlSecGCryptSymKeyDataKlassCheck (xmlSecKeyDataKlass* klass); + +#define xmlSecGCryptSymKeyDataCheckId(data) \ + (xmlSecKeyDataIsValid((data)) && \ + xmlSecGCryptSymKeyDataKlassCheck((data)->id)) + +static int +xmlSecGCryptSymKeyDataInitialize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), -1); + + return(xmlSecKeyDataBinaryValueInitialize(data)); +} + +static int +xmlSecGCryptSymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { + xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(dst), -1); + xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(src), -1); + xmlSecAssert2(dst->id == src->id, -1); + + return(xmlSecKeyDataBinaryValueDuplicate(dst, src)); +} + +static void +xmlSecGCryptSymKeyDataFinalize(xmlSecKeyDataPtr data) { + xmlSecAssert(xmlSecGCryptSymKeyDataCheckId(data)); + + xmlSecKeyDataBinaryValueFinalize(data); +} + +static int +xmlSecGCryptSymKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueXmlRead(id, key, node, keyInfoCtx)); +} + +static int +xmlSecGCryptSymKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueXmlWrite(id, key, node, keyInfoCtx)); +} + +static int +xmlSecGCryptSymKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, + const xmlSecByte* buf, xmlSecSize bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueBinRead(id, key, buf, bufSize, keyInfoCtx)); +} + +static int +xmlSecGCryptSymKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, + xmlSecByte** buf, xmlSecSize* bufSize, + xmlSecKeyInfoCtxPtr keyInfoCtx) { + xmlSecAssert2(xmlSecGCryptSymKeyDataKlassCheck(id), -1); + + return(xmlSecKeyDataBinaryValueBinWrite(id, key, buf, bufSize, keyInfoCtx)); +} + +static int +xmlSecGCryptSymKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), -1); + xmlSecAssert2(sizeBits > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecGCryptGenerateRandom(buffer, (sizeBits + 7) / 8)); +} + +static xmlSecKeyDataType +xmlSecGCryptSymKeyDataGetType(xmlSecKeyDataPtr data) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), xmlSecKeyDataTypeUnknown); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, xmlSecKeyDataTypeUnknown); + + return((xmlSecBufferGetSize(buffer) > 0) ? xmlSecKeyDataTypeSymmetric : xmlSecKeyDataTypeUnknown); +} + +static xmlSecSize +xmlSecGCryptSymKeyDataGetSize(xmlSecKeyDataPtr data) { + xmlSecAssert2(xmlSecGCryptSymKeyDataCheckId(data), 0); + + return(xmlSecKeyDataBinaryValueGetSize(data)); +} + +static void +xmlSecGCryptSymKeyDataDebugDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecGCryptSymKeyDataCheckId(data)); + + xmlSecKeyDataBinaryValueDebugDump(data, output); +} + +static void +xmlSecGCryptSymKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { + xmlSecAssert(xmlSecGCryptSymKeyDataCheckId(data)); + + xmlSecKeyDataBinaryValueDebugXmlDump(data, output); +} + +static int +xmlSecGCryptSymKeyDataKlassCheck(xmlSecKeyDataKlass* klass) { +#ifndef XMLSEC_NO_DES + if(klass == xmlSecGCryptKeyDataDesId) { + return(1); + } +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(klass == xmlSecGCryptKeyDataAesId) { + return(1); + } +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_HMAC + if(klass == xmlSecGCryptKeyDataHmacId) { + return(1); + } +#endif /* XMLSEC_NO_HMAC */ + + return(0); +} + +#ifndef XMLSEC_NO_AES +/************************************************************************** + * + * <xmlsec:AESKeyValue> processing + * + *************************************************************************/ +static xmlSecKeyDataKlass xmlSecGCryptKeyDataAesKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecKeyDataBinarySize, + + /* data */ + xmlSecNameAESKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefAESKeyValue, /* const xmlChar* href; */ + xmlSecNodeAESKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecGCryptSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecGCryptSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecGCryptSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecGCryptSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecGCryptSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecGCryptSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecGCryptSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecGCryptSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecGCryptSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + xmlSecGCryptSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecGCryptSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecGCryptSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptKeyDataAesGetKlass: + * + * The AES key data klass. + * + * Returns: AES key data klass. + */ +xmlSecKeyDataId +xmlSecGCryptKeyDataAesGetKlass(void) { + return(&xmlSecGCryptKeyDataAesKlass); +} + +/** + * xmlSecGCryptKeyDataAesSet: + * @data: the pointer to AES key data. + * @buf: the pointer to key value. + * @bufSize: the key value size (in bytes). + * + * Sets the value of AES key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecGCryptKeyDataAesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataAesId), -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecBufferSetData(buffer, buf, bufSize)); +} +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES +/************************************************************************** + * + * <xmlsec:DESKeyValue> processing + * + *************************************************************************/ +static xmlSecKeyDataKlass xmlSecGCryptKeyDataDesKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecKeyDataBinarySize, + + /* data */ + xmlSecNameDESKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefDESKeyValue, /* const xmlChar* href; */ + xmlSecNodeDESKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecGCryptSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecGCryptSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecGCryptSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecGCryptSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecGCryptSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecGCryptSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecGCryptSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecGCryptSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecGCryptSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + xmlSecGCryptSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecGCryptSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecGCryptSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptKeyDataDesGetKlass: + * + * The DES key data klass. + * + * Returns: DES key data klass. + */ +xmlSecKeyDataId +xmlSecGCryptKeyDataDesGetKlass(void) { + return(&xmlSecGCryptKeyDataDesKlass); +} + +/** + * xmlSecGCryptKeyDataDesSet: + * @data: the pointer to DES key data. + * @buf: the pointer to key value. + * @bufSize: the key value size (in bytes). + * + * Sets the value of DES key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecGCryptKeyDataDesSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDesId), -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecBufferSetData(buffer, buf, bufSize)); +} + +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_HMAC +/************************************************************************** + * + * <xmlsec:HMACKeyValue> processing + * + *************************************************************************/ +static xmlSecKeyDataKlass xmlSecGCryptKeyDataHmacKlass = { + sizeof(xmlSecKeyDataKlass), + xmlSecKeyDataBinarySize, + + /* data */ + xmlSecNameHMACKeyValue, + xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, + /* xmlSecKeyDataUsage usage; */ + xmlSecHrefHMACKeyValue, /* const xmlChar* href; */ + xmlSecNodeHMACKeyValue, /* const xmlChar* dataNodeName; */ + xmlSecNs, /* const xmlChar* dataNodeNs; */ + + /* constructors/destructor */ + xmlSecGCryptSymKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ + xmlSecGCryptSymKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ + xmlSecGCryptSymKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ + xmlSecGCryptSymKeyDataGenerate, /* xmlSecKeyDataGenerateMethod generate; */ + + /* get info */ + xmlSecGCryptSymKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ + xmlSecGCryptSymKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ + NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ + + /* read/write */ + xmlSecGCryptSymKeyDataXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ + xmlSecGCryptSymKeyDataXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ + xmlSecGCryptSymKeyDataBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ + xmlSecGCryptSymKeyDataBinWrite, /* xmlSecKeyDataBinWriteMethod binWrite; */ + + /* debug */ + xmlSecGCryptSymKeyDataDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ + xmlSecGCryptSymKeyDataDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ + + /* reserved for the future */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecGCryptKeyDataHmacGetKlass: + * + * The HMAC key data klass. + * + * Returns: HMAC key data klass. + */ +xmlSecKeyDataId +xmlSecGCryptKeyDataHmacGetKlass(void) { + return(&xmlSecGCryptKeyDataHmacKlass); +} + +/** + * xmlSecGCryptKeyDataHmacSet: + * @data: the pointer to HMAC key data. + * @buf: the pointer to key value. + * @bufSize: the key value size (in bytes). + * + * Sets the value of HMAC key data. + * + * Returns: 0 on success or a negative value if an error occurs. + */ +int +xmlSecGCryptKeyDataHmacSet(xmlSecKeyDataPtr data, const xmlSecByte* buf, xmlSecSize bufSize) { + xmlSecBufferPtr buffer; + + xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataHmacId), -1); + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(bufSize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(data); + xmlSecAssert2(buffer != NULL, -1); + + return(xmlSecBufferSetData(buffer, buf, bufSize)); +} + +#endif /* XMLSEC_NO_HMAC */ + |