diff options
Diffstat (limited to 'src/libstrongswan/plugins/pkcs11')
17 files changed, 5546 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.am b/src/libstrongswan/plugins/pkcs11/Makefile.am new file mode 100644 index 000000000..199039d95 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-pkcs11.la +else +plugin_LTLIBRARIES = libstrongswan-pkcs11.la +endif + +libstrongswan_pkcs11_la_SOURCES = \ + pkcs11_plugin.h pkcs11_plugin.c pkcs11.h \ + pkcs11_library.h pkcs11_library.c \ + pkcs11_creds.h pkcs11_creds.c \ + pkcs11_private_key.h pkcs11_private_key.c \ + pkcs11_public_key.h pkcs11_public_key.c \ + pkcs11_hasher.h pkcs11_hasher.c \ + pkcs11_manager.h pkcs11_manager.c + +libstrongswan_pkcs11_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.in b/src/libstrongswan/plugins/pkcs11/Makefile.in new file mode 100644 index 000000000..c27310910 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/Makefile.in @@ -0,0 +1,614 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libstrongswan/plugins/pkcs11 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_pkcs11_la_LIBADD = +am_libstrongswan_pkcs11_la_OBJECTS = pkcs11_plugin.lo \ + pkcs11_library.lo pkcs11_creds.lo pkcs11_private_key.lo \ + pkcs11_public_key.lo pkcs11_hasher.lo pkcs11_manager.lo +libstrongswan_pkcs11_la_OBJECTS = \ + $(am_libstrongswan_pkcs11_la_OBJECTS) +libstrongswan_pkcs11_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_pkcs11_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_pkcs11_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_pkcs11_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_pkcs11_la_SOURCES) +DIST_SOURCES = $(libstrongswan_pkcs11_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +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@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +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@ +ipsecdir = @ipsecdir@ +ipsecgid = @ipsecgid@ +ipsecgroup = @ipsecgroup@ +ipsecuid = @ipsecuid@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-pkcs11.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-pkcs11.la +libstrongswan_pkcs11_la_SOURCES = \ + pkcs11_plugin.h pkcs11_plugin.c pkcs11.h \ + pkcs11_library.h pkcs11_library.c \ + pkcs11_creds.h pkcs11_creds.c \ + pkcs11_private_key.h pkcs11_private_key.c \ + pkcs11_public_key.h pkcs11_public_key.c \ + pkcs11_hasher.h pkcs11_hasher.c \ + pkcs11_manager.h pkcs11_manager.c + +libstrongswan_pkcs11_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(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/libstrongswan/plugins/pkcs11/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libstrongswan/plugins/pkcs11/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: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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 +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || 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)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_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 +libstrongswan-pkcs11.la: $(libstrongswan_pkcs11_la_OBJECTS) $(libstrongswan_pkcs11_la_DEPENDENCIES) + $(libstrongswan_pkcs11_la_LINK) $(am_libstrongswan_pkcs11_la_rpath) $(libstrongswan_pkcs11_la_OBJECTS) $(libstrongswan_pkcs11_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_creds.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_hasher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_library.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_private_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11_public_key.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +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)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES 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-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +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-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + 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-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES 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-pluginLTLIBRARIES + + +# 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/libstrongswan/plugins/pkcs11/pkcs11.h b/src/libstrongswan/plugins/pkcs11/pkcs11.h new file mode 100644 index 000000000..2e6a1e3ed --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11.h @@ -0,0 +1,1357 @@ +/* pkcs11.h + Copyright 2006, 2007 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file 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. */ + +/* Please submit changes back to the Scute project at + http://www.scute.org/ (or send them to marcus@g10code.com), so that + they can be picked up by other projects from there as well. */ + +/* This file is a modified implementation of the PKCS #11 standard by + RSA Security Inc. It is mostly a drop-in replacement, with the + following change: + + This header file does not require any macro definitions by the user + (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros + for you (if useful, some are missing, let me know if you need + more). + + There is an additional API available that does comply better to the + GNU coding standard. It can be switched on by defining + CRYPTOKI_GNU before including this header file. For this, the + following changes are made to the specification: + + All structure types are changed to a "struct ck_foo" where CK_FOO + is the type name in PKCS #11. + + All non-structure types are changed to ck_foo_t where CK_FOO is the + lowercase version of the type name in PKCS #11. The basic types + (CK_ULONG et al.) are removed without substitute. + + All members of structures are modified in the following way: Type + indication prefixes are removed, and underscore characters are + inserted before words. Then the result is lowercased. + + Note that function names are still in the original case, as they + need for ABI compatibility. + + CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use + <stdbool.h>. + + If CRYPTOKI_COMPAT is defined before including this header file, + then none of the API changes above take place, and the API is the + one defined by the PKCS #11 standard. */ + +#ifndef PKCS11_H +#define PKCS11_H 1 + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The version of cryptoki we implement. The revision is changed with + each modification of this file. If you do not use the "official" + version of this file, please consider deleting the revision macro + (you may use a macro with a different name to keep track of your + versions). */ +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_REVISION 6 + + +/* Compatibility interface is default, unless CRYPTOKI_GNU is + given. */ +#ifndef CRYPTOKI_GNU +#ifndef CRYPTOKI_COMPAT +#define CRYPTOKI_COMPAT 1 +#endif +#endif + +/* System dependencies. */ + +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) + +/* There is a matching pop below. */ +#pragma pack(push, cryptoki, 1) + +#ifdef CRYPTOKI_EXPORTS +#define CK_SPEC __declspec(dllexport) +#else +#define CK_SPEC __declspec(dllimport) +#endif + +#else + +#define CK_SPEC + +#endif + + +#ifdef CRYPTOKI_COMPAT + /* If we are in compatibility mode, switch all exposed names to the + PKCS #11 variant. There are corresponding #undefs below. */ + +#define ck_flags_t CK_FLAGS +#define ck_version _CK_VERSION + +#define ck_info _CK_INFO +#define cryptoki_version cryptokiVersion +#define manufacturer_id manufacturerID +#define library_description libraryDescription +#define library_version libraryVersion + +#define ck_notification_t CK_NOTIFICATION +#define ck_slot_id_t CK_SLOT_ID + +#define ck_slot_info _CK_SLOT_INFO +#define slot_description slotDescription +#define hardware_version hardwareVersion +#define firmware_version firmwareVersion + +#define ck_token_info _CK_TOKEN_INFO +#define serial_number serialNumber +#define max_session_count ulMaxSessionCount +#define session_count ulSessionCount +#define max_rw_session_count ulMaxRwSessionCount +#define rw_session_count ulRwSessionCount +#define max_pin_len ulMaxPinLen +#define min_pin_len ulMinPinLen +#define total_public_memory ulTotalPublicMemory +#define free_public_memory ulFreePublicMemory +#define total_private_memory ulTotalPrivateMemory +#define free_private_memory ulFreePrivateMemory +#define utc_time utcTime + +#define ck_session_handle_t CK_SESSION_HANDLE +#define ck_user_type_t CK_USER_TYPE +#define ck_state_t CK_STATE + +#define ck_session_info _CK_SESSION_INFO +#define slot_id slotID +#define device_error ulDeviceError + +#define ck_object_handle_t CK_OBJECT_HANDLE +#define ck_object_class_t CK_OBJECT_CLASS +#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE +#define ck_key_type_t CK_KEY_TYPE +#define ck_certificate_type_t CK_CERTIFICATE_TYPE +#define ck_attribute_type_t CK_ATTRIBUTE_TYPE + +#define ck_attribute _CK_ATTRIBUTE +#define value pValue +#define value_len ulValueLen + +#define ck_date _CK_DATE + +#define ck_mechanism_type_t CK_MECHANISM_TYPE + +#define ck_mechanism _CK_MECHANISM +#define parameter pParameter +#define parameter_len ulParameterLen + +#define ck_mechanism_info _CK_MECHANISM_INFO +#define min_key_size ulMinKeySize +#define max_key_size ulMaxKeySize + +#define ck_rv_t CK_RV +#define ck_notify_t CK_NOTIFY + +#define ck_function_list _CK_FUNCTION_LIST + +#define ck_createmutex_t CK_CREATEMUTEX +#define ck_destroymutex_t CK_DESTROYMUTEX +#define ck_lockmutex_t CK_LOCKMUTEX +#define ck_unlockmutex_t CK_UNLOCKMUTEX + +#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS +#define create_mutex CreateMutex +#define destroy_mutex DestroyMutex +#define lock_mutex LockMutex +#define unlock_mutex UnlockMutex +#define reserved pReserved + +#endif /* CRYPTOKI_COMPAT */ + + + +typedef unsigned long ck_flags_t; + +struct ck_version +{ + unsigned char major; + unsigned char minor; +}; + + +struct ck_info +{ + struct ck_version cryptoki_version; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + unsigned char library_description[32]; + struct ck_version library_version; +}; + + +typedef unsigned long ck_notification_t; + +#define CKN_SURRENDER (0) + + +typedef unsigned long ck_slot_id_t; + + +struct ck_slot_info +{ + unsigned char slot_description[64]; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + struct ck_version hardware_version; + struct ck_version firmware_version; +}; + + +#define CKF_TOKEN_PRESENT (1 << 0) +#define CKF_REMOVABLE_DEVICE (1 << 1) +#define CKF_HW_SLOT (1 << 2) +#define CKF_ARRAY_ATTRIBUTE (1 << 30) + + +struct ck_token_info +{ + unsigned char label[32]; + unsigned char manufacturer_id[32]; + unsigned char model[16]; + unsigned char serial_number[16]; + ck_flags_t flags; + unsigned long max_session_count; + unsigned long session_count; + unsigned long max_rw_session_count; + unsigned long rw_session_count; + unsigned long max_pin_len; + unsigned long min_pin_len; + unsigned long total_public_memory; + unsigned long free_public_memory; + unsigned long total_private_memory; + unsigned long free_private_memory; + struct ck_version hardware_version; + struct ck_version firmware_version; + unsigned char utc_time[16]; +}; + + +#define CKF_RNG (1 << 0) +#define CKF_WRITE_PROTECTED (1 << 1) +#define CKF_LOGIN_REQUIRED (1 << 2) +#define CKF_USER_PIN_INITIALIZED (1 << 3) +#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) +#define CKF_CLOCK_ON_TOKEN (1 << 6) +#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) +#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) +#define CKF_TOKEN_INITIALIZED (1 << 10) +#define CKF_SECONDARY_AUTHENTICATION (1 << 11) +#define CKF_USER_PIN_COUNT_LOW (1 << 16) +#define CKF_USER_PIN_FINAL_TRY (1 << 17) +#define CKF_USER_PIN_LOCKED (1 << 18) +#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) +#define CKF_SO_PIN_COUNT_LOW (1 << 20) +#define CKF_SO_PIN_FINAL_TRY (1 << 21) +#define CKF_SO_PIN_LOCKED (1 << 22) +#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) + +#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) +#define CK_EFFECTIVELY_INFINITE (0) + + +typedef unsigned long ck_session_handle_t; + +#define CK_INVALID_HANDLE (0) + + +typedef unsigned long ck_user_type_t; + +#define CKU_SO (0) +#define CKU_USER (1) +#define CKU_CONTEXT_SPECIFIC (2) + + +typedef unsigned long ck_state_t; + +#define CKS_RO_PUBLIC_SESSION (0) +#define CKS_RO_USER_FUNCTIONS (1) +#define CKS_RW_PUBLIC_SESSION (2) +#define CKS_RW_USER_FUNCTIONS (3) +#define CKS_RW_SO_FUNCTIONS (4) + + +struct ck_session_info +{ + ck_slot_id_t slot_id; + ck_state_t state; + ck_flags_t flags; + unsigned long device_error; +}; + +#define CKF_RW_SESSION (1 << 1) +#define CKF_SERIAL_SESSION (1 << 2) + + +typedef unsigned long ck_object_handle_t; + + +typedef unsigned long ck_object_class_t; + +#define CKO_DATA (0) +#define CKO_CERTIFICATE (1) +#define CKO_PUBLIC_KEY (2) +#define CKO_PRIVATE_KEY (3) +#define CKO_SECRET_KEY (4) +#define CKO_HW_FEATURE (5) +#define CKO_DOMAIN_PARAMETERS (6) +#define CKO_MECHANISM (7) +#define CKO_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_hw_feature_type_t; + +#define CKH_MONOTONIC_COUNTER (1) +#define CKH_CLOCK (2) +#define CKH_USER_INTERFACE (3) +#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_key_type_t; + +#define CKK_RSA (0) +#define CKK_DSA (1) +#define CKK_DH (2) +#define CKK_ECDSA (3) +#define CKK_EC (3) +#define CKK_X9_42_DH (4) +#define CKK_KEA (5) +#define CKK_GENERIC_SECRET (0x10) +#define CKK_RC2 (0x11) +#define CKK_RC4 (0x12) +#define CKK_DES (0x13) +#define CKK_DES2 (0x14) +#define CKK_DES3 (0x15) +#define CKK_CAST (0x16) +#define CKK_CAST3 (0x17) +#define CKK_CAST128 (0x18) +#define CKK_RC5 (0x19) +#define CKK_IDEA (0x1a) +#define CKK_SKIPJACK (0x1b) +#define CKK_BATON (0x1c) +#define CKK_JUNIPER (0x1d) +#define CKK_CDMF (0x1e) +#define CKK_AES (0x1f) +#define CKK_BLOWFISH (0x20) +#define CKK_TWOFISH (0x21) +#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_certificate_type_t; + +#define CKC_X_509 (0) +#define CKC_X_509_ATTR_CERT (1) +#define CKC_WTLS (2) +#define CKC_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_attribute_type_t; + +#define CKA_CLASS (0) +#define CKA_TOKEN (1) +#define CKA_PRIVATE (2) +#define CKA_LABEL (3) +#define CKA_APPLICATION (0x10) +#define CKA_VALUE (0x11) +#define CKA_OBJECT_ID (0x12) +#define CKA_CERTIFICATE_TYPE (0x80) +#define CKA_ISSUER (0x81) +#define CKA_SERIAL_NUMBER (0x82) +#define CKA_AC_ISSUER (0x83) +#define CKA_OWNER (0x84) +#define CKA_ATTR_TYPES (0x85) +#define CKA_TRUSTED (0x86) +#define CKA_CERTIFICATE_CATEGORY (0x87) +#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) +#define CKA_URL (0x89) +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) +#define CKA_CHECK_VALUE (0x90) +#define CKA_KEY_TYPE (0x100) +#define CKA_SUBJECT (0x101) +#define CKA_ID (0x102) +#define CKA_SENSITIVE (0x103) +#define CKA_ENCRYPT (0x104) +#define CKA_DECRYPT (0x105) +#define CKA_WRAP (0x106) +#define CKA_UNWRAP (0x107) +#define CKA_SIGN (0x108) +#define CKA_SIGN_RECOVER (0x109) +#define CKA_VERIFY (0x10a) +#define CKA_VERIFY_RECOVER (0x10b) +#define CKA_DERIVE (0x10c) +#define CKA_START_DATE (0x110) +#define CKA_END_DATE (0x111) +#define CKA_MODULUS (0x120) +#define CKA_MODULUS_BITS (0x121) +#define CKA_PUBLIC_EXPONENT (0x122) +#define CKA_PRIVATE_EXPONENT (0x123) +#define CKA_PRIME_1 (0x124) +#define CKA_PRIME_2 (0x125) +#define CKA_EXPONENT_1 (0x126) +#define CKA_EXPONENT_2 (0x127) +#define CKA_COEFFICIENT (0x128) +#define CKA_PRIME (0x130) +#define CKA_SUBPRIME (0x131) +#define CKA_BASE (0x132) +#define CKA_PRIME_BITS (0x133) +#define CKA_SUB_PRIME_BITS (0x134) +#define CKA_VALUE_BITS (0x160) +#define CKA_VALUE_LEN (0x161) +#define CKA_EXTRACTABLE (0x162) +#define CKA_LOCAL (0x163) +#define CKA_NEVER_EXTRACTABLE (0x164) +#define CKA_ALWAYS_SENSITIVE (0x165) +#define CKA_KEY_GEN_MECHANISM (0x166) +#define CKA_MODIFIABLE (0x170) +#define CKA_ECDSA_PARAMS (0x180) +#define CKA_EC_PARAMS (0x180) +#define CKA_EC_POINT (0x181) +#define CKA_SECONDARY_AUTH (0x200) +#define CKA_AUTH_PIN_FLAGS (0x201) +#define CKA_ALWAYS_AUTHENTICATE (0x202) +#define CKA_WRAP_WITH_TRUSTED (0x210) +#define CKA_HW_FEATURE_TYPE (0x300) +#define CKA_RESET_ON_INIT (0x301) +#define CKA_HAS_RESET (0x302) +#define CKA_PIXEL_X (0x400) +#define CKA_PIXEL_Y (0x401) +#define CKA_RESOLUTION (0x402) +#define CKA_CHAR_ROWS (0x403) +#define CKA_CHAR_COLUMNS (0x404) +#define CKA_COLOR (0x405) +#define CKA_BITS_PER_PIXEL (0x406) +#define CKA_CHAR_SETS (0x480) +#define CKA_ENCODING_METHODS (0x481) +#define CKA_MIME_TYPES (0x482) +#define CKA_MECHANISM_TYPE (0x500) +#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) +#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) +#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) +#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +struct ck_attribute +{ + ck_attribute_type_t type; + void *value; + unsigned long value_len; +}; + + +struct ck_date +{ + unsigned char year[4]; + unsigned char month[2]; + unsigned char day[2]; +}; + + +typedef unsigned long ck_mechanism_type_t; + +#define CKM_RSA_PKCS_KEY_PAIR_GEN (0) +#define CKM_RSA_PKCS (1) +#define CKM_RSA_9796 (2) +#define CKM_RSA_X_509 (3) +#define CKM_MD2_RSA_PKCS (4) +#define CKM_MD5_RSA_PKCS (5) +#define CKM_SHA1_RSA_PKCS (6) +#define CKM_RIPEMD128_RSA_PKCS (7) +#define CKM_RIPEMD160_RSA_PKCS (8) +#define CKM_RSA_PKCS_OAEP (9) +#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) +#define CKM_RSA_X9_31 (0xb) +#define CKM_SHA1_RSA_X9_31 (0xc) +#define CKM_RSA_PKCS_PSS (0xd) +#define CKM_SHA1_RSA_PKCS_PSS (0xe) +#define CKM_DSA_KEY_PAIR_GEN (0x10) +#define CKM_DSA (0x11) +#define CKM_DSA_SHA1 (0x12) +#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) +#define CKM_DH_PKCS_DERIVE (0x21) +#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) +#define CKM_X9_42_DH_DERIVE (0x31) +#define CKM_X9_42_DH_HYBRID_DERIVE (0x32) +#define CKM_X9_42_MQV_DERIVE (0x33) +#define CKM_SHA256_RSA_PKCS (0x40) +#define CKM_SHA384_RSA_PKCS (0x41) +#define CKM_SHA512_RSA_PKCS (0x42) +#define CKM_SHA256_RSA_PKCS_PSS (0x43) +#define CKM_SHA384_RSA_PKCS_PSS (0x44) +#define CKM_SHA512_RSA_PKCS_PSS (0x45) +#define CKM_RC2_KEY_GEN (0x100) +#define CKM_RC2_ECB (0x101) +#define CKM_RC2_CBC (0x102) +#define CKM_RC2_MAC (0x103) +#define CKM_RC2_MAC_GENERAL (0x104) +#define CKM_RC2_CBC_PAD (0x105) +#define CKM_RC4_KEY_GEN (0x110) +#define CKM_RC4 (0x111) +#define CKM_DES_KEY_GEN (0x120) +#define CKM_DES_ECB (0x121) +#define CKM_DES_CBC (0x122) +#define CKM_DES_MAC (0x123) +#define CKM_DES_MAC_GENERAL (0x124) +#define CKM_DES_CBC_PAD (0x125) +#define CKM_DES2_KEY_GEN (0x130) +#define CKM_DES3_KEY_GEN (0x131) +#define CKM_DES3_ECB (0x132) +#define CKM_DES3_CBC (0x133) +#define CKM_DES3_MAC (0x134) +#define CKM_DES3_MAC_GENERAL (0x135) +#define CKM_DES3_CBC_PAD (0x136) +#define CKM_CDMF_KEY_GEN (0x140) +#define CKM_CDMF_ECB (0x141) +#define CKM_CDMF_CBC (0x142) +#define CKM_CDMF_MAC (0x143) +#define CKM_CDMF_MAC_GENERAL (0x144) +#define CKM_CDMF_CBC_PAD (0x145) +#define CKM_MD2 (0x200) +#define CKM_MD2_HMAC (0x201) +#define CKM_MD2_HMAC_GENERAL (0x202) +#define CKM_MD5 (0x210) +#define CKM_MD5_HMAC (0x211) +#define CKM_MD5_HMAC_GENERAL (0x212) +#define CKM_SHA_1 (0x220) +#define CKM_SHA_1_HMAC (0x221) +#define CKM_SHA_1_HMAC_GENERAL (0x222) +#define CKM_RIPEMD128 (0x230) +#define CKM_RIPEMD128_HMAC (0x231) +#define CKM_RIPEMD128_HMAC_GENERAL (0x232) +#define CKM_RIPEMD160 (0x240) +#define CKM_RIPEMD160_HMAC (0x241) +#define CKM_RIPEMD160_HMAC_GENERAL (0x242) +#define CKM_SHA256 (0x250) +#define CKM_SHA256_HMAC (0x251) +#define CKM_SHA256_HMAC_GENERAL (0x252) +#define CKM_SHA384 (0x260) +#define CKM_SHA384_HMAC (0x261) +#define CKM_SHA384_HMAC_GENERAL (0x262) +#define CKM_SHA512 (0x270) +#define CKM_SHA512_HMAC (0x271) +#define CKM_SHA512_HMAC_GENERAL (0x272) +#define CKM_CAST_KEY_GEN (0x300) +#define CKM_CAST_ECB (0x301) +#define CKM_CAST_CBC (0x302) +#define CKM_CAST_MAC (0x303) +#define CKM_CAST_MAC_GENERAL (0x304) +#define CKM_CAST_CBC_PAD (0x305) +#define CKM_CAST3_KEY_GEN (0x310) +#define CKM_CAST3_ECB (0x311) +#define CKM_CAST3_CBC (0x312) +#define CKM_CAST3_MAC (0x313) +#define CKM_CAST3_MAC_GENERAL (0x314) +#define CKM_CAST3_CBC_PAD (0x315) +#define CKM_CAST5_KEY_GEN (0x320) +#define CKM_CAST128_KEY_GEN (0x320) +#define CKM_CAST5_ECB (0x321) +#define CKM_CAST128_ECB (0x321) +#define CKM_CAST5_CBC (0x322) +#define CKM_CAST128_CBC (0x322) +#define CKM_CAST5_MAC (0x323) +#define CKM_CAST128_MAC (0x323) +#define CKM_CAST5_MAC_GENERAL (0x324) +#define CKM_CAST128_MAC_GENERAL (0x324) +#define CKM_CAST5_CBC_PAD (0x325) +#define CKM_CAST128_CBC_PAD (0x325) +#define CKM_RC5_KEY_GEN (0x330) +#define CKM_RC5_ECB (0x331) +#define CKM_RC5_CBC (0x332) +#define CKM_RC5_MAC (0x333) +#define CKM_RC5_MAC_GENERAL (0x334) +#define CKM_RC5_CBC_PAD (0x335) +#define CKM_IDEA_KEY_GEN (0x340) +#define CKM_IDEA_ECB (0x341) +#define CKM_IDEA_CBC (0x342) +#define CKM_IDEA_MAC (0x343) +#define CKM_IDEA_MAC_GENERAL (0x344) +#define CKM_IDEA_CBC_PAD (0x345) +#define CKM_GENERIC_SECRET_KEY_GEN (0x350) +#define CKM_CONCATENATE_BASE_AND_KEY (0x360) +#define CKM_CONCATENATE_BASE_AND_DATA (0x362) +#define CKM_CONCATENATE_DATA_AND_BASE (0x363) +#define CKM_XOR_BASE_AND_DATA (0x364) +#define CKM_EXTRACT_KEY_FROM_KEY (0x365) +#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) +#define CKM_SSL3_MASTER_KEY_DERIVE (0x371) +#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) +#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) +#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) +#define CKM_TLS_MASTER_KEY_DERIVE (0x375) +#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) +#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) +#define CKM_SSL3_MD5_MAC (0x380) +#define CKM_SSL3_SHA1_MAC (0x381) +#define CKM_MD5_KEY_DERIVATION (0x390) +#define CKM_MD2_KEY_DERIVATION (0x391) +#define CKM_SHA1_KEY_DERIVATION (0x392) +#define CKM_PBE_MD2_DES_CBC (0x3a0) +#define CKM_PBE_MD5_DES_CBC (0x3a1) +#define CKM_PBE_MD5_CAST_CBC (0x3a2) +#define CKM_PBE_MD5_CAST3_CBC (0x3a3) +#define CKM_PBE_MD5_CAST5_CBC (0x3a4) +#define CKM_PBE_MD5_CAST128_CBC (0x3a4) +#define CKM_PBE_SHA1_CAST5_CBC (0x3a5) +#define CKM_PBE_SHA1_CAST128_CBC (0x3a5) +#define CKM_PBE_SHA1_RC4_128 (0x3a6) +#define CKM_PBE_SHA1_RC4_40 (0x3a7) +#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) +#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) +#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) +#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) +#define CKM_PKCS5_PBKD2 (0x3b0) +#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) +#define CKM_KEY_WRAP_LYNKS (0x400) +#define CKM_KEY_WRAP_SET_OAEP (0x401) +#define CKM_SKIPJACK_KEY_GEN (0x1000) +#define CKM_SKIPJACK_ECB64 (0x1001) +#define CKM_SKIPJACK_CBC64 (0x1002) +#define CKM_SKIPJACK_OFB64 (0x1003) +#define CKM_SKIPJACK_CFB64 (0x1004) +#define CKM_SKIPJACK_CFB32 (0x1005) +#define CKM_SKIPJACK_CFB16 (0x1006) +#define CKM_SKIPJACK_CFB8 (0x1007) +#define CKM_SKIPJACK_WRAP (0x1008) +#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) +#define CKM_SKIPJACK_RELAYX (0x100a) +#define CKM_KEA_KEY_PAIR_GEN (0x1010) +#define CKM_KEA_KEY_DERIVE (0x1011) +#define CKM_FORTEZZA_TIMESTAMP (0x1020) +#define CKM_BATON_KEY_GEN (0x1030) +#define CKM_BATON_ECB128 (0x1031) +#define CKM_BATON_ECB96 (0x1032) +#define CKM_BATON_CBC128 (0x1033) +#define CKM_BATON_COUNTER (0x1034) +#define CKM_BATON_SHUFFLE (0x1035) +#define CKM_BATON_WRAP (0x1036) +#define CKM_ECDSA_KEY_PAIR_GEN (0x1040) +#define CKM_EC_KEY_PAIR_GEN (0x1040) +#define CKM_ECDSA (0x1041) +#define CKM_ECDSA_SHA1 (0x1042) +#define CKM_ECDH1_DERIVE (0x1050) +#define CKM_ECDH1_COFACTOR_DERIVE (0x1051) +#define CKM_ECMQV_DERIVE (0x1052) +#define CKM_JUNIPER_KEY_GEN (0x1060) +#define CKM_JUNIPER_ECB128 (0x1061) +#define CKM_JUNIPER_CBC128 (0x1062) +#define CKM_JUNIPER_COUNTER (0x1063) +#define CKM_JUNIPER_SHUFFLE (0x1064) +#define CKM_JUNIPER_WRAP (0x1065) +#define CKM_FASTHASH (0x1070) +#define CKM_AES_KEY_GEN (0x1080) +#define CKM_AES_ECB (0x1081) +#define CKM_AES_CBC (0x1082) +#define CKM_AES_MAC (0x1083) +#define CKM_AES_MAC_GENERAL (0x1084) +#define CKM_AES_CBC_PAD (0x1085) +#define CKM_DSA_PARAMETER_GEN (0x2000) +#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) +#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) +#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +struct ck_mechanism +{ + ck_mechanism_type_t mechanism; + void *parameter; + unsigned long parameter_len; +}; + + +struct ck_mechanism_info +{ + unsigned long min_key_size; + unsigned long max_key_size; + ck_flags_t flags; +}; + +#define CKF_HW (1 << 0) +#define CKF_ENCRYPT (1 << 8) +#define CKF_DECRYPT (1 << 9) +#define CKF_DIGEST (1 << 10) +#define CKF_SIGN (1 << 11) +#define CKF_SIGN_RECOVER (1 << 12) +#define CKF_VERIFY (1 << 13) +#define CKF_VERIFY_RECOVER (1 << 14) +#define CKF_GENERATE (1 << 15) +#define CKF_GENERATE_KEY_PAIR (1 << 16) +#define CKF_WRAP (1 << 17) +#define CKF_UNWRAP (1 << 18) +#define CKF_DERIVE (1 << 19) +#define CKF_EXTENSION ((unsigned long) (1 << 31)) + + +/* Flags for C_WaitForSlotEvent. */ +#define CKF_DONT_BLOCK (1) + + +typedef unsigned long ck_rv_t; + + +typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, + ck_notification_t event, void *application); + +/* Forward reference. */ +struct ck_function_list; + +#define _CK_DECLARE_FUNCTION(name, args) \ +typedef ck_rv_t (*CK_ ## name) args; \ +ck_rv_t CK_SPEC name args + +_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args)); +_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved)); +_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info)); +_CK_DECLARE_FUNCTION (C_GetFunctionList, + (struct ck_function_list **function_list)); + +_CK_DECLARE_FUNCTION (C_GetSlotList, + (unsigned char token_present, ck_slot_id_t *slot_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetSlotInfo, + (ck_slot_id_t slot_id, struct ck_slot_info *info)); +_CK_DECLARE_FUNCTION (C_GetTokenInfo, + (ck_slot_id_t slot_id, struct ck_token_info *info)); +_CK_DECLARE_FUNCTION (C_WaitForSlotEvent, + (ck_flags_t flags, ck_slot_id_t *slot, void *reserved)); +_CK_DECLARE_FUNCTION (C_GetMechanismList, + (ck_slot_id_t slot_id, + ck_mechanism_type_t *mechanism_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetMechanismInfo, + (ck_slot_id_t slot_id, ck_mechanism_type_t type, + struct ck_mechanism_info *info)); +_CK_DECLARE_FUNCTION (C_InitToken, + (ck_slot_id_t slot_id, unsigned char *pin, + unsigned long pin_len, unsigned char *label)); +_CK_DECLARE_FUNCTION (C_InitPIN, + (ck_session_handle_t session, unsigned char *pin, + unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_SetPIN, + (ck_session_handle_t session, unsigned char *old_pin, + unsigned long old_len, unsigned char *new_pin, + unsigned long new_len)); + +_CK_DECLARE_FUNCTION (C_OpenSession, + (ck_slot_id_t slot_id, ck_flags_t flags, + void *application, ck_notify_t notify, + ck_session_handle_t *session)); +_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id)); +_CK_DECLARE_FUNCTION (C_GetSessionInfo, + (ck_session_handle_t session, + struct ck_session_info *info)); +_CK_DECLARE_FUNCTION (C_GetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long *operation_state_len)); +_CK_DECLARE_FUNCTION (C_SetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long operation_state_len, + ck_object_handle_t encryption_key, + ck_object_handle_t authentiation_key)); +_CK_DECLARE_FUNCTION (C_Login, + (ck_session_handle_t session, ck_user_type_t user_type, + unsigned char *pin, unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_CreateObject, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count, ck_object_handle_t *object)); +_CK_DECLARE_FUNCTION (C_CopyObject, + (ck_session_handle_t session, ck_object_handle_t object, + struct ck_attribute *templ, unsigned long count, + ck_object_handle_t *new_object)); +_CK_DECLARE_FUNCTION (C_DestroyObject, + (ck_session_handle_t session, + ck_object_handle_t object)); +_CK_DECLARE_FUNCTION (C_GetObjectSize, + (ck_session_handle_t session, + ck_object_handle_t object, + unsigned long *size)); +_CK_DECLARE_FUNCTION (C_GetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_SetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjectsInit, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjects, + (ck_session_handle_t session, + ck_object_handle_t *object, + unsigned long max_object_count, + unsigned long *object_count)); +_CK_DECLARE_FUNCTION (C_FindObjectsFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_EncryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Encrypt, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *encrypted_data, + unsigned long *encrypted_data_len)); +_CK_DECLARE_FUNCTION (C_EncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_EncryptFinal, + (ck_session_handle_t session, + unsigned char *last_encrypted_part, + unsigned long *last_encrypted_part_len)); + +_CK_DECLARE_FUNCTION (C_DecryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Decrypt, + (ck_session_handle_t session, + unsigned char *encrypted_data, + unsigned long encrypted_data_len, + unsigned char *data, unsigned long *data_len)); +_CK_DECLARE_FUNCTION (C_DecryptUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_DecryptFinal, + (ck_session_handle_t session, + unsigned char *last_part, + unsigned long *last_part_len)); + +_CK_DECLARE_FUNCTION (C_DigestInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism)); +_CK_DECLARE_FUNCTION (C_Digest, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *digest, + unsigned long *digest_len)); +_CK_DECLARE_FUNCTION (C_DigestUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_DigestKey, + (ck_session_handle_t session, ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_DigestFinal, + (ck_session_handle_t session, + unsigned char *digest, + unsigned long *digest_len)); + +_CK_DECLARE_FUNCTION (C_SignInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Sign, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_SignFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_SignRecover, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); + +_CK_DECLARE_FUNCTION (C_VerifyInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Verify, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_VerifyFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_VerifyRecover, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len, + unsigned char *data, + unsigned long *data_len)); + +_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_SignEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); + +_CK_DECLARE_FUNCTION (C_GenerateKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *templ, + unsigned long count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_GenerateKeyPair, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *public_key_template, + unsigned long public_key_attribute_count, + struct ck_attribute *private_key_template, + unsigned long private_key_attribute_count, + ck_object_handle_t *public_key, + ck_object_handle_t *private_key)); +_CK_DECLARE_FUNCTION (C_WrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t wrapping_key, + ck_object_handle_t key, + unsigned char *wrapped_key, + unsigned long *wrapped_key_len)); +_CK_DECLARE_FUNCTION (C_UnwrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t unwrapping_key, + unsigned char *wrapped_key, + unsigned long wrapped_key_len, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_DeriveKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t base_key, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); + +_CK_DECLARE_FUNCTION (C_SeedRandom, + (ck_session_handle_t session, unsigned char *seed, + unsigned long seed_len)); +_CK_DECLARE_FUNCTION (C_GenerateRandom, + (ck_session_handle_t session, + unsigned char *random_data, + unsigned long random_len)); + +_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); + + +struct ck_function_list +{ + struct ck_version version; + CK_C_Initialize C_Initialize; + CK_C_Finalize C_Finalize; + CK_C_GetInfo C_GetInfo; + CK_C_GetFunctionList C_GetFunctionList; + CK_C_GetSlotList C_GetSlotList; + CK_C_GetSlotInfo C_GetSlotInfo; + CK_C_GetTokenInfo C_GetTokenInfo; + CK_C_GetMechanismList C_GetMechanismList; + CK_C_GetMechanismInfo C_GetMechanismInfo; + CK_C_InitToken C_InitToken; + CK_C_InitPIN C_InitPIN; + CK_C_SetPIN C_SetPIN; + CK_C_OpenSession C_OpenSession; + CK_C_CloseSession C_CloseSession; + CK_C_CloseAllSessions C_CloseAllSessions; + CK_C_GetSessionInfo C_GetSessionInfo; + CK_C_GetOperationState C_GetOperationState; + CK_C_SetOperationState C_SetOperationState; + CK_C_Login C_Login; + CK_C_Logout C_Logout; + CK_C_CreateObject C_CreateObject; + CK_C_CopyObject C_CopyObject; + CK_C_DestroyObject C_DestroyObject; + CK_C_GetObjectSize C_GetObjectSize; + CK_C_GetAttributeValue C_GetAttributeValue; + CK_C_SetAttributeValue C_SetAttributeValue; + CK_C_FindObjectsInit C_FindObjectsInit; + CK_C_FindObjects C_FindObjects; + CK_C_FindObjectsFinal C_FindObjectsFinal; + CK_C_EncryptInit C_EncryptInit; + CK_C_Encrypt C_Encrypt; + CK_C_EncryptUpdate C_EncryptUpdate; + CK_C_EncryptFinal C_EncryptFinal; + CK_C_DecryptInit C_DecryptInit; + CK_C_Decrypt C_Decrypt; + CK_C_DecryptUpdate C_DecryptUpdate; + CK_C_DecryptFinal C_DecryptFinal; + CK_C_DigestInit C_DigestInit; + CK_C_Digest C_Digest; + CK_C_DigestUpdate C_DigestUpdate; + CK_C_DigestKey C_DigestKey; + CK_C_DigestFinal C_DigestFinal; + CK_C_SignInit C_SignInit; + CK_C_Sign C_Sign; + CK_C_SignUpdate C_SignUpdate; + CK_C_SignFinal C_SignFinal; + CK_C_SignRecoverInit C_SignRecoverInit; + CK_C_SignRecover C_SignRecover; + CK_C_VerifyInit C_VerifyInit; + CK_C_Verify C_Verify; + CK_C_VerifyUpdate C_VerifyUpdate; + CK_C_VerifyFinal C_VerifyFinal; + CK_C_VerifyRecoverInit C_VerifyRecoverInit; + CK_C_VerifyRecover C_VerifyRecover; + CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; + CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; + CK_C_SignEncryptUpdate C_SignEncryptUpdate; + CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; + CK_C_GenerateKey C_GenerateKey; + CK_C_GenerateKeyPair C_GenerateKeyPair; + CK_C_WrapKey C_WrapKey; + CK_C_UnwrapKey C_UnwrapKey; + CK_C_DeriveKey C_DeriveKey; + CK_C_SeedRandom C_SeedRandom; + CK_C_GenerateRandom C_GenerateRandom; + CK_C_GetFunctionStatus C_GetFunctionStatus; + CK_C_CancelFunction C_CancelFunction; + CK_C_WaitForSlotEvent C_WaitForSlotEvent; +}; + + +typedef ck_rv_t (*ck_createmutex_t) (void **mutex); +typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); +typedef ck_rv_t (*ck_lockmutex_t) (void *mutex); +typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex); + + +struct ck_c_initialize_args +{ + ck_createmutex_t create_mutex; + ck_destroymutex_t destroy_mutex; + ck_lockmutex_t lock_mutex; + ck_unlockmutex_t unlock_mutex; + ck_flags_t flags; + void *reserved; +}; + + +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) +#define CKF_OS_LOCKING_OK (1 << 1) + +#define CKR_OK (0) +#define CKR_CANCEL (1) +#define CKR_HOST_MEMORY (2) +#define CKR_SLOT_ID_INVALID (3) +#define CKR_GENERAL_ERROR (5) +#define CKR_FUNCTION_FAILED (6) +#define CKR_ARGUMENTS_BAD (7) +#define CKR_NO_EVENT (8) +#define CKR_NEED_TO_CREATE_THREADS (9) +#define CKR_CANT_LOCK (0xa) +#define CKR_ATTRIBUTE_READ_ONLY (0x10) +#define CKR_ATTRIBUTE_SENSITIVE (0x11) +#define CKR_ATTRIBUTE_TYPE_INVALID (0x12) +#define CKR_ATTRIBUTE_VALUE_INVALID (0x13) +#define CKR_DATA_INVALID (0x20) +#define CKR_DATA_LEN_RANGE (0x21) +#define CKR_DEVICE_ERROR (0x30) +#define CKR_DEVICE_MEMORY (0x31) +#define CKR_DEVICE_REMOVED (0x32) +#define CKR_ENCRYPTED_DATA_INVALID (0x40) +#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) +#define CKR_FUNCTION_CANCELED (0x50) +#define CKR_FUNCTION_NOT_PARALLEL (0x51) +#define CKR_FUNCTION_NOT_SUPPORTED (0x54) +#define CKR_KEY_HANDLE_INVALID (0x60) +#define CKR_KEY_SIZE_RANGE (0x62) +#define CKR_KEY_TYPE_INCONSISTENT (0x63) +#define CKR_KEY_NOT_NEEDED (0x64) +#define CKR_KEY_CHANGED (0x65) +#define CKR_KEY_NEEDED (0x66) +#define CKR_KEY_INDIGESTIBLE (0x67) +#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) +#define CKR_KEY_NOT_WRAPPABLE (0x69) +#define CKR_KEY_UNEXTRACTABLE (0x6a) +#define CKR_MECHANISM_INVALID (0x70) +#define CKR_MECHANISM_PARAM_INVALID (0x71) +#define CKR_OBJECT_HANDLE_INVALID (0x82) +#define CKR_OPERATION_ACTIVE (0x90) +#define CKR_OPERATION_NOT_INITIALIZED (0x91) +#define CKR_PIN_INCORRECT (0xa0) +#define CKR_PIN_INVALID (0xa1) +#define CKR_PIN_LEN_RANGE (0xa2) +#define CKR_PIN_EXPIRED (0xa3) +#define CKR_PIN_LOCKED (0xa4) +#define CKR_SESSION_CLOSED (0xb0) +#define CKR_SESSION_COUNT (0xb1) +#define CKR_SESSION_HANDLE_INVALID (0xb3) +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) +#define CKR_SESSION_READ_ONLY (0xb5) +#define CKR_SESSION_EXISTS (0xb6) +#define CKR_SESSION_READ_ONLY_EXISTS (0xb7) +#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) +#define CKR_SIGNATURE_INVALID (0xc0) +#define CKR_SIGNATURE_LEN_RANGE (0xc1) +#define CKR_TEMPLATE_INCOMPLETE (0xd0) +#define CKR_TEMPLATE_INCONSISTENT (0xd1) +#define CKR_TOKEN_NOT_PRESENT (0xe0) +#define CKR_TOKEN_NOT_RECOGNIZED (0xe1) +#define CKR_TOKEN_WRITE_PROTECTED (0xe2) +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) +#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) +#define CKR_USER_ALREADY_LOGGED_IN (0x100) +#define CKR_USER_NOT_LOGGED_IN (0x101) +#define CKR_USER_PIN_NOT_INITIALIZED (0x102) +#define CKR_USER_TYPE_INVALID (0x103) +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) +#define CKR_USER_TOO_MANY_TYPES (0x105) +#define CKR_WRAPPED_KEY_INVALID (0x110) +#define CKR_WRAPPED_KEY_LEN_RANGE (0x112) +#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) +#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) +#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) +#define CKR_RANDOM_NO_RNG (0x121) +#define CKR_DOMAIN_PARAMS_INVALID (0x130) +#define CKR_BUFFER_TOO_SMALL (0x150) +#define CKR_SAVED_STATE_INVALID (0x160) +#define CKR_INFORMATION_SENSITIVE (0x170) +#define CKR_STATE_UNSAVEABLE (0x180) +#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) +#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) +#define CKR_MUTEX_BAD (0x1a0) +#define CKR_MUTEX_NOT_LOCKED (0x1a1) +#define CKR_FUNCTION_REJECTED (0x200) +#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + + +/* Compatibility layer. */ + +#ifdef CRYPTOKI_COMPAT + +#undef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name + +/* For NULL. */ +#include <stddef.h> + +typedef unsigned char CK_BYTE; +typedef unsigned char CK_CHAR; +typedef unsigned char CK_UTF8CHAR; +typedef unsigned char CK_BBOOL; +typedef unsigned long int CK_ULONG; +typedef long int CK_LONG; +typedef CK_BYTE *CK_BYTE_PTR; +typedef CK_CHAR *CK_CHAR_PTR; +typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; +typedef CK_ULONG *CK_ULONG_PTR; +typedef void *CK_VOID_PTR; +typedef void **CK_VOID_PTR_PTR; +#define CK_FALSE 0 +#define CK_TRUE 1 +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#endif + +typedef struct ck_version CK_VERSION; +typedef struct ck_version *CK_VERSION_PTR; + +typedef struct ck_info CK_INFO; +typedef struct ck_info *CK_INFO_PTR; + +typedef ck_slot_id_t *CK_SLOT_ID_PTR; + +typedef struct ck_slot_info CK_SLOT_INFO; +typedef struct ck_slot_info *CK_SLOT_INFO_PTR; + +typedef struct ck_token_info CK_TOKEN_INFO; +typedef struct ck_token_info *CK_TOKEN_INFO_PTR; + +typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; + +typedef struct ck_session_info CK_SESSION_INFO; +typedef struct ck_session_info *CK_SESSION_INFO_PTR; + +typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; + +typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; + +typedef struct ck_attribute CK_ATTRIBUTE; +typedef struct ck_attribute *CK_ATTRIBUTE_PTR; + +typedef struct ck_date CK_DATE; +typedef struct ck_date *CK_DATE_PTR; + +typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; + +typedef struct ck_mechanism CK_MECHANISM; +typedef struct ck_mechanism *CK_MECHANISM_PTR; + +typedef struct ck_mechanism_info CK_MECHANISM_INFO; +typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; + +typedef struct ck_function_list CK_FUNCTION_LIST; +typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; +typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; + +typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; +typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; + +#define NULL_PTR NULL + +/* Delete the helper macros defined at the top of the file. */ +#undef ck_flags_t +#undef ck_version + +#undef ck_info +#undef cryptoki_version +#undef manufacturer_id +#undef library_description +#undef library_version + +#undef ck_notification_t +#undef ck_slot_id_t + +#undef ck_slot_info +#undef slot_description +#undef hardware_version +#undef firmware_version + +#undef ck_token_info +#undef serial_number +#undef max_session_count +#undef session_count +#undef max_rw_session_count +#undef rw_session_count +#undef max_pin_len +#undef min_pin_len +#undef total_public_memory +#undef free_public_memory +#undef total_private_memory +#undef free_private_memory +#undef utc_time + +#undef ck_session_handle_t +#undef ck_user_type_t +#undef ck_state_t + +#undef ck_session_info +#undef slot_id +#undef device_error + +#undef ck_object_handle_t +#undef ck_object_class_t +#undef ck_hw_feature_type_t +#undef ck_key_type_t +#undef ck_certificate_type_t +#undef ck_attribute_type_t + +#undef ck_attribute +#undef value +#undef value_len + +#undef ck_date + +#undef ck_mechanism_type_t + +#undef ck_mechanism +#undef parameter +#undef parameter_len + +#undef ck_mechanism_info +#undef min_key_size +#undef max_key_size + +#undef ck_rv_t +#undef ck_notify_t + +#undef ck_function_list + +#undef ck_createmutex_t +#undef ck_destroymutex_t +#undef ck_lockmutex_t +#undef ck_unlockmutex_t + +#undef ck_c_initialize_args +#undef create_mutex +#undef destroy_mutex +#undef lock_mutex +#undef unlock_mutex +#undef reserved + +#endif /* CRYPTOKI_COMPAT */ + + +/* System dependencies. */ +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) +#pragma pack(pop, cryptoki) +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* PKCS11_H */ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c new file mode 100644 index 000000000..1b1448c6a --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_creds.h" + +#include <debug.h> +#include <utils/linked_list.h> + +typedef struct private_pkcs11_creds_t private_pkcs11_creds_t; + +/** + * Private data of an pkcs11_creds_t object. + */ +struct private_pkcs11_creds_t { + + /** + * Public pkcs11_creds_t interface. + */ + pkcs11_creds_t public; + + /** + * PKCS# library + */ + pkcs11_library_t *lib; + + /** + * Token slot + */ + CK_SLOT_ID slot; + + /** + * List of trusted certificates + */ + linked_list_t *trusted; + + /** + * List of untrusted certificates + */ + linked_list_t *untrusted; +}; + +/** + * Find certificates, optionally trusted + */ +static void find_certificates(private_pkcs11_creds_t *this, + CK_SESSION_HANDLE session, CK_BBOOL trusted) +{ + CK_OBJECT_CLASS class = CKO_CERTIFICATE; + CK_CERTIFICATE_TYPE type = CKC_X_509; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_CERTIFICATE_TYPE, &type, sizeof(type)}, + {CKA_TRUSTED, &trusted, sizeof(trusted)}, + }; + CK_OBJECT_HANDLE object; + CK_ATTRIBUTE attr[] = { + {CKA_VALUE, NULL, 0}, + {CKA_LABEL, NULL, 0}, + }; + enumerator_t *enumerator; + linked_list_t *raw; + certificate_t *cert; + struct { + chunk_t value; + chunk_t label; + } *entry; + + raw = linked_list_create(); + enumerator = this->lib->create_object_enumerator(this->lib, + session, tmpl, countof(tmpl), attr, countof(attr)); + while (enumerator->enumerate(enumerator, &object)) + { + entry = malloc(sizeof(*entry)); + entry->value = chunk_clone( + chunk_create(attr[0].pValue, attr[0].ulValueLen)); + entry->label = chunk_clone( + chunk_create(attr[1].pValue, attr[1].ulValueLen)); + raw->insert_last(raw, entry); + } + enumerator->destroy(enumerator); + + while (raw->remove_first(raw, (void**)&entry) == SUCCESS) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, entry->value, + BUILD_END); + if (cert) + { + DBG1(DBG_CFG, " loaded %strusted cert '%.*s'", + trusted ? "" : "un", entry->label.len, entry->label.ptr); + /* trusted certificates are also returned as untrusted */ + this->untrusted->insert_last(this->untrusted, cert); + if (trusted) + { + this->trusted->insert_last(this->trusted, cert->get_ref(cert)); + } + } + else + { + DBG1(DBG_CFG, " loading cert '%.*s' failed", + entry->label.len, entry->label.ptr); + } + free(entry->value.ptr); + free(entry->label.ptr); + free(entry); + } + raw->destroy(raw); +} + +/** + * Load in the certificates from the token + */ +static bool load_certificates(private_pkcs11_creds_t *this) +{ + CK_SESSION_HANDLE session; + CK_RV rv; + + rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, + NULL, NULL, &session); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "opening session failed: %N", ck_rv_names, rv); + return FALSE; + } + + find_certificates(this, session, CK_TRUE); + find_certificates(this, session, CK_FALSE); + + this->lib->f->C_CloseSession(session); + return TRUE; +} + +/** + * filter function for certs enumerator + */ +static bool certs_filter(identification_t *id, + certificate_t **in, certificate_t **out) +{ + public_key_t *public; + certificate_t *cert = *in; + + if (id == NULL || cert->has_subject(cert, id)) + { + *out = *in; + return TRUE; + } + public = cert->get_public_key(cert); + if (public) + { + if (public->has_fingerprint(public, id->get_encoding(id))) + { + public->destroy(public); + *out = *in; + return TRUE; + } + public->destroy(public); + } + return FALSE; +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_pkcs11_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + enumerator_t *inner; + + if (cert != CERT_X509 && cert != CERT_ANY) + { + return NULL; + } + if (trusted) + { + inner = this->trusted->create_enumerator(this->trusted); + } + else + { + inner = this->untrusted->create_enumerator(this->untrusted); + } + return enumerator_create_filter(inner, (void*)certs_filter, id, NULL); +} + +METHOD(pkcs11_creds_t, get_library, pkcs11_library_t*, + private_pkcs11_creds_t *this) +{ + return this->lib; +} + +METHOD(pkcs11_creds_t, get_slot, CK_SLOT_ID, + private_pkcs11_creds_t *this) +{ + return this->slot; +} + +METHOD(pkcs11_creds_t, destroy, void, + private_pkcs11_creds_t *this) +{ + this->trusted->destroy_offset(this->trusted, + offsetof(certificate_t, destroy)); + this->untrusted->destroy_offset(this->untrusted, + offsetof(certificate_t, destroy)); + free(this); +} + +/** + * See header + */ +pkcs11_creds_t *pkcs11_creds_create(pkcs11_library_t *p11, CK_SLOT_ID slot) +{ + private_pkcs11_creds_t *this; + + INIT(this, + .public = { + .set = { + .create_shared_enumerator = (void*)enumerator_create_empty, + .create_private_enumerator = (void*)enumerator_create_empty, + .create_cert_enumerator = _create_cert_enumerator, + .create_cdp_enumerator = (void*)enumerator_create_empty, + .cache_cert = (void*)nop, + }, + .get_library = _get_library, + .get_slot = _get_slot, + .destroy = _destroy, + }, + .lib = p11, + .slot = slot, + .trusted = linked_list_create(), + .untrusted = linked_list_create(), + ); + + if (!load_certificates(this)) + { + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h new file mode 100644 index 000000000..c40a8dea6 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11_creds pkcs11_creds + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_CREDS_H_ +#define PKCS11_CREDS_H_ + +typedef struct pkcs11_creds_t pkcs11_creds_t; + +#include "pkcs11_library.h" + +#include <credentials/credential_manager.h> + +/** + * Credential set on top on a PKCS#11 token. + */ +struct pkcs11_creds_t { + + /** + * Implements credential_set_t. + */ + credential_set_t set; + + /** + * Get the PKCS#11 library this set uses. + * + * @return library + */ + pkcs11_library_t* (*get_library)(pkcs11_creds_t *this); + + /** + * Get the slot of the token this set uses. + * + * @return slot + */ + CK_SLOT_ID (*get_slot)(pkcs11_creds_t *this); + + /** + * Destroy a pkcs11_creds_t. + */ + void (*destroy)(pkcs11_creds_t *this); +}; + +/** + * Create a pkcs11_creds instance. + * + * @param p11 loaded PKCS#11 library + * @param slot slot of the token we hand out credentials + */ +pkcs11_creds_t *pkcs11_creds_create(pkcs11_library_t *p11, CK_SLOT_ID slot); + +#endif /** PKCS11_CREDS_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c b/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c new file mode 100644 index 000000000..6d327be40 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_hasher.h" + +#include <unistd.h> + +#include <debug.h> +#include <threading/mutex.h> + +#include "pkcs11_manager.h" + +typedef struct private_pkcs11_hasher_t private_pkcs11_hasher_t; + +/** + * Private data of an pkcs11_hasher_t object. + */ +struct private_pkcs11_hasher_t { + + /** + * Public pkcs11_hasher_t interface. + */ + pkcs11_hasher_t public; + + /** + * PKCS#11 library + */ + pkcs11_library_t *lib; + + /** + * Mechanism for this hasher + */ + CK_MECHANISM_PTR mech; + + /** + * Token session + */ + CK_SESSION_HANDLE session; + + /** + * size of the hash + */ + size_t size; + + /** + * Mutex to lock the tokens hashing engine + */ + mutex_t *mutex; + + /** + * do we have an initialized state? + */ + bool have_state; + + /** + * state buffer + */ + CK_BYTE_PTR state; + + /** + * Length of the state buffer + */ + CK_ULONG state_len; +}; + +METHOD(hasher_t, get_hash_size, size_t, + private_pkcs11_hasher_t *this) +{ + return this->size; +} + +/** + * Save the Operation state to host memory + */ +static void save_state(private_pkcs11_hasher_t *this) +{ + CK_RV rv; + + while (TRUE) + { + if (!this->state) + { + rv = this->lib->f->C_GetOperationState(this->session, NULL, + &this->state_len); + if (rv != CKR_OK) + { + break; + } + this->state = malloc(this->state_len); + } + rv = this->lib->f->C_GetOperationState(this->session, this->state, + &this->state_len); + switch (rv) + { + case CKR_BUFFER_TOO_SMALL: + free(this->state); + this->state = NULL; + continue; + case CKR_OK: + this->have_state = TRUE; + return; + default: + break; + } + break; + } + DBG1(DBG_CFG, "C_GetOperationState() failed: %N", ck_rv_names, rv); + abort(); +} + +/** + * Load the Operation state from host memory + */ +static void load_state(private_pkcs11_hasher_t *this) +{ + CK_RV rv; + + rv = this->lib->f->C_SetOperationState(this->session, this->state, + this->state_len, CK_INVALID_HANDLE, CK_INVALID_HANDLE); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_SetOperationState() failed: %N", ck_rv_names, rv); + abort(); + } + this->have_state = FALSE; +} + +METHOD(hasher_t, reset, void, + private_pkcs11_hasher_t *this) +{ + this->have_state = FALSE; +} + +METHOD(hasher_t, get_hash, void, + private_pkcs11_hasher_t *this, chunk_t chunk, u_int8_t *hash) +{ + CK_RV rv; + CK_ULONG len; + + this->mutex->lock(this->mutex); + if (this->have_state) + { + load_state(this); + } + else + { + rv = this->lib->f->C_DigestInit(this->session, this->mech); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_DigestInit() failed: %N", ck_rv_names, rv); + abort(); + } + } + if (chunk.len) + { + rv = this->lib->f->C_DigestUpdate(this->session, chunk.ptr, chunk.len); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_DigestUpdate() failed: %N", ck_rv_names, rv); + abort(); + } + } + if (hash) + { + len = this->size; + rv = this->lib->f->C_DigestFinal(this->session, + hash, &len); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_DigestFinal() failed: %N", ck_rv_names, rv); + abort(); + } + } + else + { + save_state(this); + } + this->mutex->unlock(this->mutex); +} + +METHOD(hasher_t, allocate_hash, void, + private_pkcs11_hasher_t *this, chunk_t chunk, chunk_t *hash) +{ + if (hash) + { + *hash = chunk_alloc(this->size); + get_hash(this, chunk, hash->ptr); + } + else + { + get_hash(this, chunk, NULL); + } +} + +METHOD(hasher_t, destroy, void, + private_pkcs11_hasher_t *this) +{ + this->lib->f->C_CloseSession(this->session); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * Get the Cryptoki mechanism for a hash algorithm + */ +static CK_MECHANISM_PTR algo_to_mechanism(hash_algorithm_t algo, size_t *size) +{ + static struct { + hash_algorithm_t algo; + CK_MECHANISM mechanism; + size_t size; + } mappings[] = { + {HASH_MD2, {CKM_MD2, NULL, 0}, HASH_SIZE_MD2}, + {HASH_MD5, {CKM_MD5, NULL, 0}, HASH_SIZE_MD5}, + {HASH_SHA1, {CKM_SHA_1, NULL, 0}, HASH_SIZE_SHA1}, + {HASH_SHA256, {CKM_SHA256, NULL, 0}, HASH_SIZE_SHA256}, + {HASH_SHA384, {CKM_SHA384, NULL, 0}, HASH_SIZE_SHA384}, + {HASH_SHA512, {CKM_SHA512, NULL, 0}, HASH_SIZE_SHA512}, + }; + int i; + + for (i = 0; i < countof(mappings); i++) + { + if (mappings[i].algo == algo) + { + *size = mappings[i].size; + return &mappings[i].mechanism; + } + } + return NULL; +} + +/** + * Find a token we can use for a hash algorithm + */ +static pkcs11_library_t* find_token(hash_algorithm_t algo, + CK_SESSION_HANDLE *session, CK_MECHANISM_PTR *mout, size_t *size) +{ + enumerator_t *tokens, *mechs; + pkcs11_manager_t *manager; + pkcs11_library_t *current, *found = NULL; + CK_MECHANISM_TYPE type; + CK_MECHANISM_PTR mech; + CK_SLOT_ID slot; + + mech = algo_to_mechanism(algo, size); + if (!mech) + { + return NULL; + } + manager = pkcs11_manager_get(); + if (!manager) + { + return NULL; + } + tokens = manager->create_token_enumerator(manager); + while (tokens->enumerate(tokens, ¤t, &slot)) + { + mechs = current->create_mechanism_enumerator(current, slot); + while (mechs->enumerate(mechs, &type, NULL)) + { + if (type == mech->mechanism) + { + if (current->f->C_OpenSession(slot, CKF_SERIAL_SESSION, + NULL, NULL, session) == CKR_OK) + { + found = current; + *mout = mech; + break; + } + } + } + mechs->destroy(mechs); + if (found) + { + break; + } + } + tokens->destroy(tokens); + return found; +} + +/** + * See header + */ +pkcs11_hasher_t *pkcs11_hasher_create(hash_algorithm_t algo) +{ + private_pkcs11_hasher_t *this; + + INIT(this, + .public = { + .hasher = { + .get_hash_size = _get_hash_size, + .reset = _reset, + .get_hash = _get_hash, + .allocate_hash = _allocate_hash, + .destroy = _destroy, + }, + }, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + this->lib = find_token(algo, &this->session, &this->mech, &this->size); + if (!this->lib) + { + free(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.h b/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.h new file mode 100644 index 000000000..9c55d463e --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_hasher.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11_hasher pkcs11_hasher + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_HASHER_H_ +#define PKCS11_HASHER_H_ + +#include <crypto/hashers/hasher.h> + +typedef struct pkcs11_hasher_t pkcs11_hasher_t; + +/** + * Hash implementation using a PKCS#11 token. + */ +struct pkcs11_hasher_t { + + /** + * Implements hasher_t interface. + */ + hasher_t hasher; +}; + +/** + * Creates a PKCS#11 based hasher. + * + * @param algo hash algorithm + * @return hasher, NULL if not supported + */ +pkcs11_hasher_t *pkcs11_hasher_create(hash_algorithm_t algo); + +#endif /** PKCS11_HASHER_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.c b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c new file mode 100644 index 000000000..9fb1b7769 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_library.h" + +#include <dlfcn.h> + +#include <library.h> +#include <debug.h> +#include <threading/mutex.h> +#include <utils/linked_list.h> + +typedef struct private_pkcs11_library_t private_pkcs11_library_t; + + +ENUM_BEGIN(ck_rv_names, CKR_OK, CKR_CANT_LOCK, + "OK", + "CANCEL", + "HOST_MEMORY", + "SLOT_ID_INVALID", + "(0x04)", + "GENERAL_ERROR", + "FUNCTION_FAILED", + "ARGUMENTS_BAD", + "NO_EVENT", + "NEED_TO_CREATE_THREADS", + "CANT_LOCK"); +ENUM_NEXT(ck_rv_names, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_CANT_LOCK, + "ATTRIBUTE_READ_ONLY", + "ATTRIBUTE_SENSITIVE", + "ATTRIBUTE_TYPE_INVALID", + "ATTRIBUTE_VALUE_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE, + CKR_ATTRIBUTE_VALUE_INVALID, + "DATA_INVALID" + "DATA_LEN_RANGE"); +ENUM_NEXT(ck_rv_names, CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED, + CKR_DATA_LEN_RANGE, + "DEVICE_ERROR", + "DEVICE_MEMORY", + "DEVICE_REMOVED"); +ENUM_NEXT(ck_rv_names, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, + CKR_DEVICE_REMOVED, + "ENCRYPTED_DATA_INVALID", + "ENCRYPTED_DATA_LEN_RANGE"); +ENUM_NEXT(ck_rv_names, CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED, + CKR_ENCRYPTED_DATA_LEN_RANGE, + "FUNCTION_CANCELED", + "FUNCTION_NOT_PARALLEL", + "(0x52)", + "(0x53)", + "FUNCTION_NOT_SUPPORTED"); +ENUM_NEXT(ck_rv_names, CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE, + CKR_FUNCTION_NOT_SUPPORTED, + "KEY_HANDLE_INVALID", + "(0x61)", + "KEY_SIZE_RANGE", + "KEY_TYPE_INCONSISTENT", + "KEY_NOT_NEEDED", + "KEY_CHANGED", + "KEY_NEEDED", + "KEY_INDIGESTIBLE", + "KEY_FUNCTION_NOT_PERMITTED", + "KEY_NOT_WRAPPABLE", + "KEY_UNEXTRACTABLE"); +ENUM_NEXT(ck_rv_names, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_KEY_UNEXTRACTABLE, + "MECHANISM_INVALID", + "MECHANISM_PARAM_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID, + CKR_MECHANISM_PARAM_INVALID, + "OBJECT_HANDLE_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED, + CKR_OBJECT_HANDLE_INVALID, + "OPERATION_ACTIVE", + "OPERATION_NOT_INITIALIZED"); +ENUM_NEXT(ck_rv_names, CKR_PIN_INCORRECT, CKR_PIN_LOCKED, + CKR_OPERATION_NOT_INITIALIZED, + "PIN_INCORRECT", + "PIN_INVALID", + "PIN_LEN_RANGE", + "PIN_EXPIRED", + "PIN_LOCKED"); +ENUM_NEXT(ck_rv_names, CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS, + CKR_PIN_LOCKED, + "SESSION_CLOSED", + "SESSION_COUNT", + "(0xb2)", + "SESSION_HANDLE_INVALID", + "SESSION_PARALLEL_NOT_SUPPORTED", + "SESSION_READ_ONLY", + "SESSION_EXISTS", + "SESSION_READ_ONLY_EXISTS", + "SESSION_READ_WRITE_SO_EXISTS"); +ENUM_NEXT(ck_rv_names, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE, + CKR_SESSION_READ_WRITE_SO_EXISTS, + "SIGNATURE_INVALID", + "SIGNATURE_LEN_RANGE"); +ENUM_NEXT(ck_rv_names, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, + CKR_SIGNATURE_LEN_RANGE, + "TEMPLATE_INCOMPLETE", + "TEMPLATE_INCONSISTENT", +); +ENUM_NEXT(ck_rv_names, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED, + CKR_TEMPLATE_INCONSISTENT, + "TOKEN_NOT_PRESENT", + "TOKEN_NOT_RECOGNIZED", + "TOKEN_WRITE_PROTECTED"); +ENUM_NEXT(ck_rv_names, CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, + "UNWRAPPING_KEY_HANDLE_INVALID", + "UNWRAPPING_KEY_SIZE_RANGE", + "UNWRAPPING_KEY_TYPE_INCONSISTENT"); +ENUM_NEXT(ck_rv_names, CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES, + CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, + "USER_ALREADY_LOGGED_IN", + "USER_NOT_LOGGED_IN", + "USER_PIN_NOT_INITIALIZED", + "USER_TYPE_INVALID", + "USER_ANOTHER_ALREADY_LOGGED_IN", + "USER_TOO_MANY_TYPES"); +ENUM_NEXT(ck_rv_names, CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, + CKR_USER_TOO_MANY_TYPES, + "WRAPPED_KEY_INVALID", + "(0x111)", + "WRAPPED_KEY_LEN_RANGE", + "WRAPPING_KEY_HANDLE_INVALID", + "WRAPPING_KEY_SIZE_RANGE", + "WRAPPING_KEY_TYPE_INCONSISTENT"); +ENUM_NEXT(ck_rv_names, CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG, + CKR_WRAPPING_KEY_TYPE_INCONSISTENT, + "RANDOM_SEED_NOT_SUPPORTED", + "RANDOM_NO_RNG"); +ENUM_NEXT(ck_rv_names, CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID, + CKR_RANDOM_NO_RNG, + "DOMAIN_PARAMS_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL, + CKR_DOMAIN_PARAMS_INVALID, + "BUFFER_TOO_SMALL"); +ENUM_NEXT(ck_rv_names, CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID, + CKR_BUFFER_TOO_SMALL, + "SAVED_STATE_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE, + CKR_SAVED_STATE_INVALID, + "INFORMATION_SENSITIVE"); +ENUM_NEXT(ck_rv_names, CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE, + CKR_INFORMATION_SENSITIVE, + "STATE_UNSAVEABLE"); +ENUM_NEXT(ck_rv_names, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED, + CKR_STATE_UNSAVEABLE, + "CRYPTOKI_NOT_INITIALIZED", + "CRYPTOKI_ALREADY_INITIALIZED"); +ENUM_NEXT(ck_rv_names, CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED, + CKR_CRYPTOKI_ALREADY_INITIALIZED, + "MUTEX_BAD", + "MUTEX_NOT_LOCKED"); +ENUM_NEXT(ck_rv_names, CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED, + CKR_MUTEX_NOT_LOCKED, + "FUNCTION_REJECTED"); +ENUM_END(ck_rv_names, CKR_FUNCTION_REJECTED); + + +ENUM_BEGIN(ck_mech_names, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_DSA_SHA1, + "RSA_PKCS_KEY_PAIR_GEN", + "RSA_PKCS", + "RSA_9796", + "RSA_X_509", + "MD2_RSA_PKCS", + "MD5_RSA_PKCS", + "SHA1_RSA_PKCS", + "RIPEMD128_RSA_PKCS", + "RIPEMD160_RSA_PKCS", + "RSA_PKCS_OAEP", + "RSA_X9_31_KEY_PAIR_GEN", + "RSA_X9_31", + "SHA1_RSA_X9_31", + "RSA_PKCS_PSS", + "SHA1_RSA_PKCS_PSS", + "(0xf)", + "DSA_KEY_PAIR_GEN", + "DSA", + "DSA_SHA1"); +ENUM_NEXT(ck_mech_names, CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE, + CKM_DSA_SHA1, + "DH_PKCS_KEY_PAIR_GEN", + "DH_PKCS_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_MQV_DERIVE, + CKM_DH_PKCS_DERIVE, + "X9_42_DH_KEY_PAIR_GEN", + "X9_42_DH_DERIVE", + "X9_42_DH_HYBRID_DERIVE", + "X9_42_MQV_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_SHA256_RSA_PKCS, CKM_SHA512_RSA_PKCS_PSS, + CKM_X9_42_MQV_DERIVE, + "SHA256_RSA_PKCS", + "SHA384_RSA_PKCS", + "SHA512_RSA_PKCS", + "SHA256_RSA_PKCS_PSS", + "SHA384_RSA_PKCS_PSS", + "SHA512_RSA_PKCS_PSS"); +ENUM_NEXT(ck_mech_names, CKM_RC2_KEY_GEN, CKM_RC2_CBC_PAD, + CKM_SHA512_RSA_PKCS_PSS, + "RC2_KEY_GEN", + "RC2_ECB", + "RC2_CBC", + "RC2_MAC", + "RC2_MAC_GENERAL", + "RC2_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_RC4_KEY_GEN, CKM_RC4, + CKM_RC2_CBC_PAD, + "RC4_KEY_GEN", + "RC4"); +ENUM_NEXT(ck_mech_names, CKM_DES_KEY_GEN, CKM_DES_CBC_PAD, + CKM_RC4, + "DES_KEY_GEN", + "DES_ECB", + "DES_CBC", + "DES_MAC", + "DES_MAC_GENERAL", + "DES_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_DES2_KEY_GEN, CKM_DES3_CBC_PAD, + CKM_DES_CBC_PAD, + "DES2_KEY_GEN", + "DES3_KEY_GEN", + "DES3_ECB", + "DES3_CBC", + "DES3_MAC", + "DES3_MAC_GENERAL", + "DES3_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_CDMF_KEY_GEN, CKM_CDMF_CBC_PAD, + CKM_DES3_CBC_PAD, + "CDMF_KEY_GEN", + "CDMF_ECB", + "CDMF_CBC", + "CDMF_MAC", + "CDMF_MAC_GENERAL", + "CDMF_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_MD2, CKM_MD2_HMAC_GENERAL, + CKM_CDMF_CBC_PAD, + "MD2", + "MD2_HMAC", + "MD2_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_MD5, CKM_MD5_HMAC_GENERAL, + CKM_MD2_HMAC_GENERAL, + "MD5", + "MD5_HMAC", + "MD5_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA_1, CKM_SHA_1_HMAC_GENERAL, + CKM_MD5_HMAC_GENERAL, + "SHA_1", + "SHA_1_HMAC", + "SHA_1_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_RIPEMD128, CKM_RIPEMD128_HMAC_GENERAL, + CKM_SHA_1_HMAC_GENERAL, + "RIPEMD128", + "RIPEMD128_HMAC", + "RIPEMD128_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_RIPEMD160, CKM_RIPEMD160_HMAC_GENERAL, + CKM_RIPEMD128_HMAC_GENERAL, + "RIPEMD160", + "RIPEMD160_HMAC", + "RIPEMD160_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA256, CKM_SHA256_HMAC_GENERAL, + CKM_RIPEMD160_HMAC_GENERAL, + "SHA256", + "SHA256_HMAC", + "SHA256_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA384, CKM_SHA384_HMAC_GENERAL, + CKM_SHA256_HMAC_GENERAL, + "SHA384", + "SHA384_HMAC", + "SHA384_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA512, CKM_SHA512_HMAC_GENERAL, + CKM_SHA384_HMAC_GENERAL , + "SHA512", + "SHA512_HMAC", + "SHA512_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_CAST_KEY_GEN, CKM_CAST_CBC_PAD, + CKM_SHA512_HMAC_GENERAL, + "CAST_KEY_GEN", + "CAST_ECB", + "CAST_CBC", + "CAST_MAC", + "CAST_MAC_GENERAL", + "CAST_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_CAST3_KEY_GEN, CKM_CAST3_CBC_PAD, + CKM_CAST_CBC_PAD, + "CAST3_KEY_GEN", + "CAST3_ECB", + "CAST3_CBC", + "CAST3_MAC", + "CAST3_MAC_GENERAL", + "CAST3_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_CAST128_KEY_GEN, CKM_CAST128_CBC_PAD, + CKM_CAST3_CBC_PAD, + "CAST128_KEY_GEN", + "CAST128_ECB", + "CAST128_CBC", + "CAST128_MAC", + "CAST128_MAC_GENERAL", + "CAST128_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_RC5_KEY_GEN, CKM_RC5_CBC_PAD, + CKM_CAST128_CBC_PAD, + "RC5_KEY_GEN", + "RC5_ECB", + "RC5_CBC", + "RC5_MAC", + "RC5_MAC_GENERAL", + "RC5_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_IDEA_KEY_GEN, CKM_IDEA_CBC_PAD, + CKM_RC5_CBC_PAD, + "IDEA_KEY_GEN", + "IDEA_ECB", + "IDEA_CBC", + "IDEA_MAC", + "IDEA_MAC_GENERAL", + "IDEA_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_GENERIC_SECRET_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN, + CKM_IDEA_CBC_PAD, + "GENERIC_SECRET_KEY_GEN"); +ENUM_NEXT(ck_mech_names, CKM_CONCATENATE_BASE_AND_KEY, CKM_EXTRACT_KEY_FROM_KEY, + CKM_GENERIC_SECRET_KEY_GEN, + "CONCATENATE_BASE_AND_KEY", + "(0x361)", + "CONCATENATE_BASE_AND_DATA", + "CONCATENATE_DATA_AND_BASE", + "XOR_BASE_AND_DATA", + "EXTRACT_KEY_FROM_KEY"); +ENUM_NEXT(ck_mech_names, CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_MASTER_KEY_DERIVE_DH, + CKM_EXTRACT_KEY_FROM_KEY, + "SSL3_PRE_MASTER_KEY_GEN", + "SSL3_MASTER_KEY_DERIVE", + "SSL3_KEY_AND_MAC_DERIVE", + "SSL3_MASTER_KEY_DERIVE_DH", + "TLS_PRE_MASTER_KEY_GEN", + "TLS_MASTER_KEY_DERIVE", + "TLS_KEY_AND_MAC_DERIVE", + "TLS_MASTER_KEY_DERIVE_DH"); +ENUM_NEXT(ck_mech_names, CKM_SSL3_MD5_MAC, CKM_SSL3_SHA1_MAC, + CKM_TLS_MASTER_KEY_DERIVE_DH, + "SSL3_MD5_MAC", + "SSL3_SHA1_MAC"); +ENUM_NEXT(ck_mech_names, CKM_MD5_KEY_DERIVATION, CKM_SHA1_KEY_DERIVATION, + CKM_SSL3_SHA1_MAC, + "MD5_KEY_DERIVATION", + "MD2_KEY_DERIVATION", + "SHA1_KEY_DERIVATION"); +ENUM_NEXT(ck_mech_names, CKM_PBE_MD2_DES_CBC, CKM_PBE_SHA1_RC2_40_CBC, + CKM_SHA1_KEY_DERIVATION, + "PBE_MD2_DES_CBC", + "PBE_MD5_DES_CBC", + "PBE_MD5_CAST_CBC", + "PBE_MD5_CAST3_CBC", + "PBE_MD5_CAST128_CBC", + "PBE_SHA1_CAST128_CBC", + "PBE_SHA1_RC4_128", + "PBE_SHA1_RC4_40", + "PBE_SHA1_DES3_EDE_CBC", + "PBE_SHA1_DES2_EDE_CBC", + "PBE_SHA1_RC2_128_CBC", + "PBE_SHA1_RC2_40_CBC"); +ENUM_NEXT(ck_mech_names, CKM_PKCS5_PBKD2, CKM_PKCS5_PBKD2, + CKM_PBE_SHA1_RC2_40_CBC, + "PKCS5_PBKD2"); +ENUM_NEXT(ck_mech_names, CKM_PBA_SHA1_WITH_SHA1_HMAC, CKM_PBA_SHA1_WITH_SHA1_HMAC, + CKM_PKCS5_PBKD2, + "PBA_SHA1_WITH_SHA1_HMAC"); +ENUM_NEXT(ck_mech_names, CKM_KEY_WRAP_LYNKS, CKM_KEY_WRAP_SET_OAEP, + CKM_PBA_SHA1_WITH_SHA1_HMAC, + "KEY_WRAP_LYNKS", + "KEY_WRAP_SET_OAEP"); +ENUM_NEXT(ck_mech_names, CKM_SKIPJACK_KEY_GEN, CKM_SKIPJACK_RELAYX, + CKM_KEY_WRAP_SET_OAEP, + "SKIPJACK_KEY_GEN", + "SKIPJACK_ECB64", + "SKIPJACK_CBC64", + "SKIPJACK_OFB64", + "SKIPJACK_CFB64", + "SKIPJACK_CFB32", + "SKIPJACK_CFB16", + "SKIPJACK_CFB8", + "SKIPJACK_WRAP", + "SKIPJACK_PRIVATE_WRAP", + "SKIPJACK_RELAYX"); +ENUM_NEXT(ck_mech_names, CKM_KEA_KEY_PAIR_GEN, CKM_KEA_KEY_DERIVE, + CKM_SKIPJACK_RELAYX, + "KEA_KEY_PAIR_GEN", + "KEA_KEY_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_FORTEZZA_TIMESTAMP, CKM_FORTEZZA_TIMESTAMP, + CKM_KEA_KEY_DERIVE, + "FORTEZZA_TIMESTAMP"); +ENUM_NEXT(ck_mech_names, CKM_BATON_KEY_GEN, CKM_BATON_WRAP, + CKM_FORTEZZA_TIMESTAMP, + "BATON_KEY_GEN", + "BATON_ECB128", + "BATON_ECB96", + "BATON_CBC128", + "BATON_COUNTER", + "BATON_SHUFFLE", + "BATON_WRAP"); +ENUM_NEXT(ck_mech_names, CKM_ECDSA_KEY_PAIR_GEN, CKM_ECDSA_SHA1, + CKM_BATON_WRAP, + "ECDSA_KEY_PAIR_GEN", + "ECDSA", + "ECDSA_SHA1"); +ENUM_NEXT(ck_mech_names, CKM_ECDH1_DERIVE, CKM_ECMQV_DERIVE, + CKM_ECDSA_SHA1, + "ECDH1_DERIVE", + "ECDH1_COFACTOR_DERIVE", + "ECMQV_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_JUNIPER_KEY_GEN, CKM_JUNIPER_WRAP, + CKM_ECMQV_DERIVE, + "JUNIPER_KEY_GEN", + "JUNIPER_ECB128", + "JUNIPER_CBC128", + "JUNIPER_COUNTER", + "JUNIPER_SHUFFLE", + "JUNIPER_WRAP"); +ENUM_NEXT(ck_mech_names, CKM_FASTHASH, CKM_FASTHASH, + CKM_JUNIPER_WRAP, + "FASTHASH"); +ENUM_NEXT(ck_mech_names, CKM_AES_KEY_GEN, CKM_AES_CBC_PAD, + CKM_FASTHASH, + "AES_KEY_GEN", + "AES_ECB", + "AES_CBC", + "AES_MAC", + "AES_MAC_GENERAL", + "AES_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_DSA_PARAMETER_GEN, CKM_X9_42_DH_PARAMETER_GEN, + CKM_AES_CBC_PAD, + "DSA_PARAMETER_GEN", + "DH_PKCS_PARAMETER_GEN", + "X9_42_DH_PARAMETER_GEN"); +ENUM_END(ck_mech_names, CKM_X9_42_DH_PARAMETER_GEN); + +/** + * Private data of an pkcs11_library_t object. + */ +struct private_pkcs11_library_t { + + /** + * Public pkcs11_library_t interface. + */ + pkcs11_library_t public; + + /** + * dlopen() handle + */ + void *handle; + + /** + * Name as passed to the constructor + */ + char *name; +}; + +METHOD(pkcs11_library_t, get_name, char*, + private_pkcs11_library_t *this) +{ + return this->name; +} + +/** + * Object enumerator + */ +typedef struct { + /* implements enumerator_t */ + enumerator_t public; + /* session */ + CK_SESSION_HANDLE session; + /* pkcs11 library */ + pkcs11_library_t *lib; + /* attributes to retreive */ + CK_ATTRIBUTE_PTR attr; + /* number of attributes */ + CK_ULONG count; + /* currently allocated attributes, to free */ + linked_list_t *freelist; +} object_enumerator_t; + +/** + * Free contents of attributes in a list + */ +static void free_attrs(object_enumerator_t *this) +{ + CK_ATTRIBUTE_PTR attr; + + while (this->freelist->remove_last(this->freelist, (void**)&attr) == SUCCESS) + { + free(attr->pValue); + attr->pValue = NULL; + attr->ulValueLen = 0; + } +} + +/** + * Get attributes for a given object during enumeration + */ +static bool get_attributes(object_enumerator_t *this, CK_OBJECT_HANDLE object) +{ + CK_RV rv; + int i; + + free_attrs(this); + + /* get length of objects first */ + rv = this->lib->f->C_GetAttributeValue(this->session, object, + this->attr, this->count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv); + return FALSE; + } + /* allocate required chunks */ + for (i = 0; i < this->count; i++) + { + if (this->attr[i].pValue == NULL && + this->attr[i].ulValueLen != 0 && this->attr[i].ulValueLen != -1) + { + this->attr[i].pValue = malloc(this->attr[i].ulValueLen); + this->freelist->insert_last(this->freelist, &this->attr[i]); + } + } + /* get the data */ + rv = this->lib->f->C_GetAttributeValue(this->session, object, + this->attr, this->count); + if (rv != CKR_OK) + { + free_attrs(this); + DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv); + return FALSE; + } + return TRUE; +} + +METHOD(enumerator_t, object_enumerate, bool, + object_enumerator_t *this, CK_OBJECT_HANDLE *out) +{ + CK_OBJECT_HANDLE object; + CK_ULONG found; + CK_RV rv; + + rv = this->lib->f->C_FindObjects(this->session, &object, 1, &found); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_FindObjects() failed: %N", ck_rv_names, rv); + return FALSE; + } + if (found) + { + if (this->attr) + { + if (!get_attributes(this, object)) + { + return FALSE; + } + } + *out = object; + return TRUE; + } + return FALSE; +} + +METHOD(enumerator_t, object_destroy, void, + object_enumerator_t *this) +{ + this->lib->f->C_FindObjectsFinal(this->session); + free_attrs(this); + this->freelist->destroy(this->freelist); + free(this); +} + +METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*, + private_pkcs11_library_t *this, CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount, + CK_ATTRIBUTE_PTR attr, CK_ULONG acount) +{ + object_enumerator_t *enumerator; + CK_RV rv; + + rv = this->public.f->C_FindObjectsInit(session, tmpl, tcount); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_FindObjectsInit() failed: %N", ck_rv_names, rv); + return enumerator_create_empty(); + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_object_enumerate, + .destroy = _object_destroy, + }, + .session = session, + .lib = &this->public, + .attr = attr, + .count = acount, + .freelist = linked_list_create(), + ); + return &enumerator->public; +} + +/** + * Enumerator over mechanisms + */ +typedef struct { + /* implements enumerator_t */ + enumerator_t public; + /* PKCS#11 library */ + pkcs11_library_t *lib; + /* slot of token */ + CK_SLOT_ID slot; + /* mechanism type list */ + CK_MECHANISM_TYPE_PTR mechs; + /* number of mechanism types */ + CK_ULONG count; + /* current mechanism */ + CK_ULONG current; +} mechanism_enumerator_t; + +METHOD(enumerator_t, enumerate_mech, bool, + mechanism_enumerator_t *this, CK_MECHANISM_TYPE* type, + CK_MECHANISM_INFO *info) +{ + CK_RV rv; + + if (this->current >= this->count) + { + return FALSE; + } + if (info) + { + rv = this->lib->f->C_GetMechanismInfo(this->slot, + this->mechs[this->current], info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetMechanismInfo() failed: %N", ck_rv_names, rv); + return FALSE; + } + } + *type = this->mechs[this->current++]; + return TRUE; +} + +METHOD(enumerator_t, destroy_mech, void, + mechanism_enumerator_t *this) +{ + free(this->mechs); + free(this); +} + +METHOD(pkcs11_library_t, create_mechanism_enumerator, enumerator_t*, + private_pkcs11_library_t *this, CK_SLOT_ID slot) +{ + mechanism_enumerator_t *enumerator; + CK_RV rv; + + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_mech, + .destroy = _destroy_mech, + }, + .lib = &this->public, + .slot = slot, + ); + + rv = enumerator->lib->f->C_GetMechanismList(slot, NULL, &enumerator->count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv); + free(enumerator); + return enumerator_create_empty(); + } + enumerator->mechs = malloc(sizeof(CK_MECHANISM_TYPE) * enumerator->count); + enumerator->lib->f->C_GetMechanismList(slot, enumerator->mechs, + &enumerator->count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv); + destroy_mech(enumerator); + return enumerator_create_empty(); + } + return &enumerator->public; +} + +METHOD(pkcs11_library_t, destroy, void, + private_pkcs11_library_t *this) +{ + this->public.f->C_Finalize(NULL); + dlclose(this->handle); + free(this); +} + +/** + * See header + */ +void pkcs11_library_trim(char *str, int len) +{ + int i; + + str[len - 1] = '\0'; + for (i = len - 2; i > 0; i--) + { + if (str[i] == ' ') + { + str[i] = '\0'; + continue; + } + break; + } +} + +/** + * Mutex creation callback + */ +static CK_RV CreateMutex(CK_VOID_PTR_PTR data) +{ + *data = mutex_create(MUTEX_TYPE_DEFAULT); + return CKR_OK; +} + +/** + * Mutex destruction callback + */ +static CK_RV DestroyMutex(CK_VOID_PTR data) +{ + mutex_t *mutex = (mutex_t*)data; + + mutex->destroy(mutex); + return CKR_OK; +} + +/** + * Mutex lock callback + */ +static CK_RV LockMutex(CK_VOID_PTR data) +{ + mutex_t *mutex = (mutex_t*)data; + + mutex->lock(mutex); + return CKR_OK; +} + +/** + * Mutex unlock callback + */ +static CK_RV UnlockMutex(CK_VOID_PTR data) +{ + mutex_t *mutex = (mutex_t*)data; + + mutex->unlock(mutex); + return CKR_OK; +} + +/** + * Initialize a PKCS#11 library + */ +static bool initialize(private_pkcs11_library_t *this, char *name, char *file) +{ + CK_C_GetFunctionList pC_GetFunctionList; + CK_INFO info; + CK_RV rv; + CK_C_INITIALIZE_ARGS args = { + .CreateMutex = CreateMutex, + .DestroyMutex = DestroyMutex, + .LockMutex = LockMutex, + .UnlockMutex = UnlockMutex, + }; + + pC_GetFunctionList = dlsym(this->handle, "C_GetFunctionList"); + if (!pC_GetFunctionList) + { + DBG1(DBG_CFG, "C_GetFunctionList not found for '%s': %s", name, dlerror()); + return FALSE; + } + rv = pC_GetFunctionList(&this->public.f); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetFunctionList() error for '%s': %N", + name, ck_rv_names, rv); + return FALSE; + } + + rv = this->public.f->C_Initialize(&args); + if (rv == CKR_CANT_LOCK) + { /* try OS locking */ + memset(&args, 0, sizeof(args)); + args.flags = CKF_OS_LOCKING_OK; + rv = this->public.f->C_Initialize(&args); + } + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_Initialize() error for '%s': %N", + name, ck_rv_names, rv); + return FALSE; + } + rv = this->public.f->C_GetInfo(&info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetInfo() error for '%s': %N", + name, ck_rv_names, rv); + this->public.f->C_Finalize(NULL); + return FALSE; + } + + pkcs11_library_trim(info.manufacturerID, + strnlen(info.manufacturerID, sizeof(info.manufacturerID))); + pkcs11_library_trim(info.libraryDescription, + strnlen(info.libraryDescription, sizeof(info.libraryDescription))); + + DBG1(DBG_CFG, "loaded PKCS#11 v%d.%d library '%s' (%s)", + info.cryptokiVersion.major, info.cryptokiVersion.minor, name, file); + DBG1(DBG_CFG, " %s: %s v%d.%d", + info.manufacturerID, info.libraryDescription, + info.libraryVersion.major, info.libraryVersion.minor); + if (args.flags & CKF_OS_LOCKING_OK) + { + DBG1(DBG_CFG, " uses OS locking functions"); + } + return TRUE; +} + +/** + * See header + */ +pkcs11_library_t *pkcs11_library_create(char *name, char *file) +{ + private_pkcs11_library_t *this; + + INIT(this, + .public = { + .get_name = _get_name, + .create_object_enumerator = _create_object_enumerator, + .create_mechanism_enumerator = _create_mechanism_enumerator, + .destroy = _destroy, + }, + .name = name, + .handle = dlopen(file, RTLD_LAZY), + ); + + if (!this->handle) + { + DBG1(DBG_CFG, "opening PKCS#11 library failed: %s", dlerror()); + free(this); + return NULL; + } + + if (!initialize(this, name, file)) + { + dlclose(this->handle); + free(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h new file mode 100644 index 000000000..1457d24d4 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11_library pkcs11_library + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_LIBRARY_H_ +#define PKCS11_LIBRARY_H_ + +typedef struct pkcs11_library_t pkcs11_library_t; + +#include "pkcs11.h" + +#include <enum.h> +#include <utils/enumerator.h> + +/** + * A loaded and initialized PKCS#11 library. + */ +struct pkcs11_library_t { + + /** + * PKCS#11 function list, as returned by C_GetFunctionList + */ + CK_FUNCTION_LIST_PTR f; + + /** + * Get the name this instance was created with. + * + * @return name, as passed to constructor + */ + char* (*get_name)(pkcs11_library_t *this); + + /** + * Create an enumerator over CK_OBJECT_HANDLE using a search template. + * + * An optional attribute array is automatically filled in with the + * objects associated attributes. If the value of an output attribute + * is NULL, the value gets allocated/freed during enumeration. + * + * @param session session to use + * @param tmpl search template + * @param tcount number of attributes in the search template + * @param attr attributes to read from object + * @param acount number of attributes to read + */ + enumerator_t* (*create_object_enumerator)(pkcs11_library_t *this, + CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount, + CK_ATTRIBUTE_PTR attr, CK_ULONG acount); + + /** + * Create an enumerator over supported mechanisms of a token. + * + * The resulting enumerator enumerates over the mechanism type, and if + * a non-NULL pointer is given, over the mechanism info details. + * + * @param slot slot of the token + * @return enumerator over (CK_MECHANISM_TYPE, CK_MECHANISM_INFO) + */ + enumerator_t* (*create_mechanism_enumerator)(pkcs11_library_t *this, + CK_SLOT_ID slot); + + /** + * Destroy a pkcs11_library_t. + */ + void (*destroy)(pkcs11_library_t *this); +}; + +/** + * Enum names for CK_RV return values + */ +extern enum_name_t *ck_rv_names; + +/** + * Enum names for CK_MECHANISM_TYPE values + */ +extern enum_name_t *ck_mech_names; + +/** + * Trim/null terminate a string returned by the varius PKCS#11 functions. + * + * @param str string to trim + * @param len max length of the string + */ +void pkcs11_library_trim(char *str, int len); + +/** + * Create a pkcs11_library instance. + * + * @param name an arbitrary name, for debugging + * @param file pkcs11 library file to dlopen() + * @return library abstraction + */ +pkcs11_library_t *pkcs11_library_create(char *name, char *file); + +#endif /** PKCS11_LIBRARY_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c new file mode 100644 index 000000000..0c27600a6 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_manager.h" + +#include <debug.h> +#include <utils/linked_list.h> +#include <threading/thread.h> + +#include "pkcs11_library.h" + +#include <processing/jobs/callback_job.h> + +typedef struct private_pkcs11_manager_t private_pkcs11_manager_t; + +/** + * Private data of an pkcs11_manager_t object. + */ +struct private_pkcs11_manager_t { + + /** + * Public pkcs11_manager_t interface. + */ + pkcs11_manager_t public; + + /** + * List of loaded libraries, as lib_entry_t + */ + linked_list_t *libs; + + /** + * Slot event callback function + */ + pkcs11_manager_token_event_t cb; + + /** + * Slot event user data + */ + void *data; +}; + +/** + * Entry for a loaded library + */ +typedef struct { + /* back reference to this */ + private_pkcs11_manager_t *this; + /* associated library path */ + char *path; + /* loaded library */ + pkcs11_library_t *lib; + /* event dispatcher job */ + callback_job_t *job; +} lib_entry_t; + +/** + * Destroy a lib_entry_t + */ +static void lib_entry_destroy(lib_entry_t *entry) +{ + if (entry->job) + { + entry->job->cancel(entry->job); + } + entry->lib->destroy(entry->lib); + free(entry); +} + +/** + * Print supported mechanisms of a token in a slot + */ +static void print_mechs(lib_entry_t *entry, CK_SLOT_ID slot) +{ + enumerator_t *enumerator; + CK_MECHANISM_TYPE type; + CK_MECHANISM_INFO info; + + enumerator = entry->lib->create_mechanism_enumerator(entry->lib, slot); + while (enumerator->enumerate(enumerator, &type, &info)) + { + DBG2(DBG_CFG, " %N %lu-%lu [ %s%s%s%s%s%s%s%s%s%s%s%s%s]", + ck_mech_names, type, + info.ulMinKeySize, info.ulMaxKeySize, + info.flags & CKF_HW ? "HW " : "", + info.flags & CKF_ENCRYPT ? "ENCR " : "", + info.flags & CKF_DECRYPT ? "DECR " : "", + info.flags & CKF_DIGEST ? "DGST " : "", + info.flags & CKF_SIGN ? "SIGN " : "", + info.flags & CKF_SIGN_RECOVER ? "SIGN_RCVR " : "", + info.flags & CKF_VERIFY ? "VRFY " : "", + info.flags & CKF_VERIFY_RECOVER ? "VRFY_RCVR " : "", + info.flags & CKF_GENERATE ? "GEN " : "", + info.flags & CKF_GENERATE_KEY_PAIR ? "GEN_KEY_PAIR " : "", + info.flags & CKF_WRAP ? "WRAP " : "", + info.flags & CKF_UNWRAP ? "UNWRAP " : "", + info.flags & CKF_DERIVE ? "DERIVE " : ""); + } + enumerator->destroy(enumerator); +} + +/** + * Handle a token + */ +static void handle_token(lib_entry_t *entry, CK_SLOT_ID slot) +{ + CK_TOKEN_INFO info; + CK_RV rv; + + rv = entry->lib->f->C_GetTokenInfo(slot, &info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetTokenInfo failed: %N", ck_rv_names, rv); + return; + } + pkcs11_library_trim(info.label, sizeof(info.label)); + pkcs11_library_trim(info.manufacturerID, sizeof(info.manufacturerID)); + pkcs11_library_trim(info.model, sizeof(info.model)); + DBG1(DBG_CFG, " %s (%s: %s)", + info.label, info.manufacturerID, info.model); + + print_mechs(entry, slot); +} + +/** + * Handle slot changes + */ +static void handle_slot(lib_entry_t *entry, CK_SLOT_ID slot, bool hot) +{ + CK_SLOT_INFO info; + CK_RV rv; + + rv = entry->lib->f->C_GetSlotInfo(slot, &info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetSlotInfo failed: %N", ck_rv_names, rv); + return; + } + + pkcs11_library_trim(info.slotDescription, sizeof(info.slotDescription)); + if (info.flags & CKF_TOKEN_PRESENT) + { + DBG1(DBG_CFG, " found token in slot '%s':%lu (%s)", + entry->lib->get_name(entry->lib), slot, info.slotDescription); + handle_token(entry, slot); + if (hot) + { + entry->this->cb(entry->this->data, entry->lib, slot, TRUE); + } + } + else + { + DBG1(DBG_CFG, "token removed from slot '%s':%lu (%s)", + entry->lib->get_name(entry->lib), slot, info.slotDescription); + if (hot) + { + entry->this->cb(entry->this->data, entry->lib, slot, FALSE); + } + } +} + +/** + * Dispatch slot events + */ +static job_requeue_t dispatch_slot_events(lib_entry_t *entry) +{ + CK_SLOT_ID slot; + CK_RV rv; + bool old; + + old = thread_cancelability(TRUE); + rv = entry->lib->f->C_WaitForSlotEvent(0, &slot, NULL); + thread_cancelability(old); + if (rv == CKR_FUNCTION_NOT_SUPPORTED || rv == CKR_NO_EVENT) + { + DBG1(DBG_CFG, "module '%s' does not support hot-plugging, cancelled", + entry->lib->get_name(entry->lib)); + return JOB_REQUEUE_NONE; + } + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { /* C_Finalize called, abort */ + return JOB_REQUEUE_NONE; + } + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "error in C_WaitForSlotEvent: %N", ck_rv_names, rv); + } + handle_slot(entry, slot, TRUE); + + return JOB_REQUEUE_DIRECT; +} + +/** + * End dispatching, unset job + */ +static void end_dispatch(lib_entry_t *entry) +{ + entry->job = NULL; +} + +/** + * Get the slot list of a library + */ +static CK_SLOT_ID_PTR get_slot_list(pkcs11_library_t *p11, CK_ULONG *out) +{ + CK_SLOT_ID_PTR slots; + CK_ULONG count; + CK_RV rv; + + rv = p11->f->C_GetSlotList(TRUE, NULL, &count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetSlotList() failed: %N", ck_rv_names, rv); + return NULL; + } + if (count == 0) + { + return NULL; + } + slots = malloc(sizeof(CK_SLOT_ID) * count); + rv = p11->f->C_GetSlotList(TRUE, slots, &count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetSlotList() failed: %N", ck_rv_names, rv); + free(slots); + return NULL; + } + *out = count; + return slots; +} + +/** + * Query the slots for tokens + */ +static void query_slots(lib_entry_t *entry) +{ + CK_ULONG count; + CK_SLOT_ID_PTR slots; + int i; + + slots = get_slot_list(entry->lib, &count); + if (slots) + { + for (i = 0; i < count; i++) + { + handle_slot(entry, slots[i], FALSE); + } + free(slots); + } +} + +/** + * Token enumerator + */ +typedef struct { + /* implements enumerator */ + enumerator_t public; + /* inner enumerator over PKCS#11 libraries */ + enumerator_t *inner; + /* active library entry */ + lib_entry_t *entry; + /* slot list with tokens */ + CK_SLOT_ID_PTR slots; + /* number of slots */ + CK_ULONG count; + /* current slot */ + int current; +} token_enumerator_t; + +METHOD(enumerator_t, enumerate_token, bool, + token_enumerator_t *this, pkcs11_library_t **out, CK_SLOT_ID *slot) +{ + if (this->current >= this->count) + { + free(this->slots); + this->slots = NULL; + this->current = 0; + } + while (!this->slots) + { + if (!this->inner->enumerate(this->inner, &this->entry)) + { + return FALSE; + } + this->slots = get_slot_list(this->entry->lib, &this->count); + } + *out = this->entry->lib; + *slot = this->slots[this->current++]; + return TRUE; +} + +METHOD(enumerator_t, destroy_token, void, + token_enumerator_t *this) +{ + this->inner->destroy(this->inner); + free(this->slots); + free(this); +} + +METHOD(pkcs11_manager_t, create_token_enumerator, enumerator_t*, + private_pkcs11_manager_t *this) +{ + token_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_token, + .destroy = _destroy_token, + }, + .inner = this->libs->create_enumerator(this->libs), + ); + return &enumerator->public; +} + +/** + * Singleton instance + */ +static private_pkcs11_manager_t *singleton = NULL; + +METHOD(pkcs11_manager_t, destroy, void, + private_pkcs11_manager_t *this) +{ + this->libs->destroy_function(this->libs, (void*)lib_entry_destroy); + free(this); + singleton = NULL; +} + +/** + * See header + */ +pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb, + void *data) +{ + private_pkcs11_manager_t *this; + enumerator_t *enumerator; + lib_entry_t *entry; + char *module; + + INIT(this, + .public = { + .create_token_enumerator = _create_token_enumerator, + .destroy = _destroy, + }, + .libs = linked_list_create(), + .cb = cb, + .data = data, + ); + + enumerator = lib->settings->create_section_enumerator(lib->settings, + "libstrongswan.plugins.pkcs11.modules"); + while (enumerator->enumerate(enumerator, &module)) + { + INIT(entry, + .this = this, + ); + + entry->path = lib->settings->get_str(lib->settings, + "libstrongswan.plugins.pkcs11.modules.%s.path", NULL, module); + if (!entry->path) + { + DBG1(DBG_CFG, "PKCS11 module '%s' misses library path", module); + free(entry); + continue; + } + entry->lib = pkcs11_library_create(module, entry->path); + if (!entry->lib) + { + free(entry); + continue; + } + this->libs->insert_last(this->libs, entry); + } + enumerator->destroy(enumerator); + + singleton = this; + + enumerator = this->libs->create_enumerator(this->libs); + while (enumerator->enumerate(enumerator, &entry)) + { + query_slots(entry); + entry->job = callback_job_create((void*)dispatch_slot_events, + entry, (void*)end_dispatch, NULL); + lib->processor->queue_job(lib->processor, (job_t*)entry->job); + } + enumerator->destroy(enumerator); + + return &this->public; +} + +/** + * See header + */ +pkcs11_manager_t *pkcs11_manager_get() +{ + return (pkcs11_manager_t*)singleton; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.h b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.h new file mode 100644 index 000000000..b80d67324 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11_manager pkcs11_manager + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_MANAGER_H_ +#define PKCS11_MANAGER_H_ + +typedef struct pkcs11_manager_t pkcs11_manager_t; + +#include <library.h> + +#include "pkcs11_library.h" + +/** + * Token event callback function. + * + * @param data user supplied data, as passed to pkcs11_manager_create() + * @param p11 loaded PKCS#11 library token belongs to + * @param slot slot number the event occured in + * @param add TRUE if token was added to the slot, FALSE if removed + */ +typedef void (*pkcs11_manager_token_event_t)(void *data, pkcs11_library_t *p11, + CK_SLOT_ID slot, bool add); + + +/** + * Manages multiple PKCS#11 libraries with hot pluggable slots + */ +struct pkcs11_manager_t { + + /** + * Create an enumerator over all tokens. + * + * @return enumerator over (pkcs11_library_t*,CK_SLOT_ID) + */ + enumerator_t* (*create_token_enumerator)(pkcs11_manager_t *this); + + /** + * Destroy a pkcs11_manager_t. + */ + void (*destroy)(pkcs11_manager_t *this); +}; + +/** + * Create a pkcs11_manager instance. + * + * @param cb token event callback function + * @param data user data to pass to token event callback + * @return instance + */ +pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb, + void *data); + + +/** + * Get the singleton instance of the manager + * + * @return instance, NULL if none available + */ +pkcs11_manager_t *pkcs11_manager_get(); + +#endif /** PKCS11_MANAGER_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c new file mode 100644 index 000000000..ace405c23 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_plugin.h" + +#include <library.h> +#include <debug.h> +#include <utils/linked_list.h> +#include <threading/mutex.h> + +#include "pkcs11_manager.h" +#include "pkcs11_creds.h" +#include "pkcs11_private_key.h" +#include "pkcs11_public_key.h" +#include "pkcs11_hasher.h" + +typedef struct private_pkcs11_plugin_t private_pkcs11_plugin_t; + +/** + * private data of pkcs11_plugin + */ +struct private_pkcs11_plugin_t { + + /** + * public functions + */ + pkcs11_plugin_t public; + + /** + * PKCS#11 library/slot manager + */ + pkcs11_manager_t *manager; + + /** + * List of credential sets, pkcs11_creds_t + */ + linked_list_t *creds; + + /** + * mutex to lock list + */ + mutex_t *mutex; +}; + +/** + * Token event callback function + */ +static void token_event_cb(private_pkcs11_plugin_t *this, pkcs11_library_t *p11, + CK_SLOT_ID slot, bool add) +{ + enumerator_t *enumerator; + pkcs11_creds_t *creds, *found = NULL;; + + if (add) + { + creds = pkcs11_creds_create(p11, slot); + if (creds) + { + this->mutex->lock(this->mutex); + this->creds->insert_last(this->creds, creds); + this->mutex->unlock(this->mutex); + lib->credmgr->add_set(lib->credmgr, &creds->set); + } + } + else + { + this->mutex->lock(this->mutex); + enumerator = this->creds->create_enumerator(this->creds); + while (enumerator->enumerate(enumerator, &creds)) + { + if (creds->get_library(creds) == p11 && + creds->get_slot(creds) == slot) + { + found = creds; + this->creds->remove_at(this->creds, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + if (found) + { + lib->credmgr->remove_set(lib->credmgr, &found->set); + found->destroy(found); + /* flush the cache after a token is gone */ + lib->credmgr->flush_cache(lib->credmgr, CERT_X509); + } + } +} + +METHOD(plugin_t, destroy, void, + private_pkcs11_plugin_t *this) +{ + pkcs11_creds_t *creds; + + lib->creds->remove_builder(lib->creds, + (builder_function_t)pkcs11_private_key_connect); + while (this->creds->remove_last(this->creds, (void**)&creds) == SUCCESS) + { + lib->credmgr->remove_set(lib->credmgr, &creds->set); + creds->destroy(creds); + } + lib->crypto->remove_hasher(lib->crypto, + (hasher_constructor_t)pkcs11_hasher_create); + this->creds->destroy(this->creds); + this->manager->destroy(this->manager); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +plugin_t *pkcs11_plugin_create() +{ + private_pkcs11_plugin_t *this; + enumerator_t *enumerator; + pkcs11_library_t *p11; + CK_SLOT_ID slot; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .creds = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + this->manager = pkcs11_manager_create((void*)token_event_cb, this); + + if (lib->settings->get_bool(lib->settings, + "libstrongswan.plugins.pkcs11.use_hasher", FALSE)) + { + lib->crypto->add_hasher(lib->crypto, HASH_MD2, + (hasher_constructor_t)pkcs11_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_MD5, + (hasher_constructor_t)pkcs11_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + (hasher_constructor_t)pkcs11_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA256, + (hasher_constructor_t)pkcs11_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA384, + (hasher_constructor_t)pkcs11_hasher_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA512, + (hasher_constructor_t)pkcs11_hasher_create); + } + + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, FALSE, + (builder_function_t)pkcs11_private_key_connect); + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, TRUE, + (builder_function_t)pkcs11_public_key_load); + + enumerator = this->manager->create_token_enumerator(this->manager); + while (enumerator->enumerate(enumerator, &p11, &slot)) + { + token_event_cb(this, p11, slot, TRUE); + } + enumerator->destroy(enumerator); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.h b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.h new file mode 100644 index 000000000..432e2173a --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11 pkcs11 + * @ingroup plugins + * + * @defgroup pkcs11_plugin pkcs11_plugin + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_PLUGIN_H_ +#define PKCS11_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct pkcs11_plugin_t pkcs11_plugin_t; + +/** + * Plugin providing PKCS#11 token support. + */ +struct pkcs11_plugin_t { + + /** + * Implements plugin interface, + */ + plugin_t plugin; +}; + +#endif /** PKCS11_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c new file mode 100644 index 000000000..cabca3f54 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c @@ -0,0 +1,600 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_private_key.h" + +#include "pkcs11_library.h" +#include "pkcs11_manager.h" + +#include <debug.h> +#include <threading/mutex.h> + +typedef struct private_pkcs11_private_key_t private_pkcs11_private_key_t; + +/** + * Private data of an pkcs11_private_key_t object. + */ +struct private_pkcs11_private_key_t { + + /** + * Public pkcs11_private_key_t interface. + */ + pkcs11_private_key_t public; + + /** + * PKCS#11 module + */ + pkcs11_library_t *lib; + + /** + * Token session + */ + CK_SESSION_HANDLE session; + + /** + * Mutex to lock session + */ + mutex_t *mutex; + + /** + * Key object on the token + */ + CK_OBJECT_HANDLE object; + + /** + * Key requires reauthentication for each signature/decryption + */ + CK_BBOOL reauth; + + /** + * Keyid of the key we use + */ + identification_t *keyid; + + /** + * Associated public key + */ + public_key_t *pubkey; + + /** + * References to this key + */ + refcount_t ref; +}; + +METHOD(private_key_t, get_type, key_type_t, + private_pkcs11_private_key_t *this) +{ + return this->pubkey->get_type(this->pubkey); +} + +METHOD(private_key_t, get_keysize, int, + private_pkcs11_private_key_t *this) +{ + return this->pubkey->get_keysize(this->pubkey); +} + +/** + * See header. + */ +CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme) +{ + static struct { + signature_scheme_t scheme; + CK_MECHANISM mechanism; + } mappings[] = { + {SIGN_RSA_EMSA_PKCS1_NULL, {CKM_RSA_PKCS, NULL, 0}}, + {SIGN_RSA_EMSA_PKCS1_SHA1, {CKM_SHA1_RSA_PKCS, NULL, 0}}, + {SIGN_RSA_EMSA_PKCS1_SHA256, {CKM_SHA256_RSA_PKCS, NULL, 0}}, + {SIGN_RSA_EMSA_PKCS1_SHA384, {CKM_SHA384_RSA_PKCS, NULL, 0}}, + {SIGN_RSA_EMSA_PKCS1_SHA512, {CKM_SHA512_RSA_PKCS, NULL, 0}}, + {SIGN_RSA_EMSA_PKCS1_MD5, {CKM_MD5_RSA_PKCS, NULL, 0}}, + }; + int i; + + for (i = 0; i < countof(mappings); i++) + { + if (mappings[i].scheme == scheme) + { + return &mappings[i].mechanism; + } + } + return NULL; +} + +/** + * See header. + */ +CK_MECHANISM_PTR pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme) +{ + static struct { + encryption_scheme_t scheme; + CK_MECHANISM mechanism; + } mappings[] = { + {ENCRYPT_RSA_PKCS1, {CKM_RSA_PKCS, NULL, 0}}, + {ENCRYPT_RSA_OAEP_SHA1, {CKM_RSA_PKCS_OAEP, NULL, 0}}, + }; + int i; + + for (i = 0; i < countof(mappings); i++) + { + if (mappings[i].scheme == scheme) + { + return &mappings[i].mechanism; + } + } + return NULL; +} + +/** + * Reauthenticate to do a signature + */ +static bool reauth(private_pkcs11_private_key_t *this) +{ + enumerator_t *enumerator; + shared_key_t *shared; + chunk_t pin; + CK_RV rv; + bool found = FALSE, success = FALSE; + + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_PIN, this->keyid, NULL); + while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) + { + found = TRUE; + pin = shared->get_key(shared); + rv = this->lib->f->C_Login(this->session, CKU_CONTEXT_SPECIFIC, + pin.ptr, pin.len); + if (rv == CKR_OK) + { + success = TRUE; + break; + } + DBG1(DBG_CFG, "reauthentication login failed: %N", ck_rv_names, rv); + } + enumerator->destroy(enumerator); + + if (!found) + { + DBG1(DBG_CFG, "private key requires reauthentication, but no PIN found"); + return FALSE; + } + return success; +} + +METHOD(private_key_t, sign, bool, + private_pkcs11_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) +{ + CK_MECHANISM_PTR mechanism; + CK_BYTE_PTR buf; + CK_ULONG len; + CK_RV rv; + + mechanism = pkcs11_signature_scheme_to_mech(scheme); + if (!mechanism) + { + DBG1(DBG_LIB, "signature scheme %N not supported", + signature_scheme_names, scheme); + return FALSE; + } + this->mutex->lock(this->mutex); + rv = this->lib->f->C_SignInit(this->session, mechanism, this->object); + if (this->reauth && !reauth(this)) + { + return FALSE; + } + if (rv != CKR_OK) + { + this->mutex->unlock(this->mutex); + DBG1(DBG_LIB, "C_SignInit() failed: %N", ck_rv_names, rv); + return FALSE; + } + len = (get_keysize(this) + 7) / 8; + buf = malloc(len); + rv = this->lib->f->C_Sign(this->session, data.ptr, data.len, buf, &len); + this->mutex->unlock(this->mutex); + if (rv != CKR_OK) + { + DBG1(DBG_LIB, "C_Sign() failed: %N", ck_rv_names, rv); + free(buf); + return FALSE; + } + *signature = chunk_create(buf, len); + return TRUE; +} + +METHOD(private_key_t, decrypt, bool, + private_pkcs11_private_key_t *this, encryption_scheme_t scheme, + chunk_t crypt, chunk_t *plain) +{ + CK_MECHANISM_PTR mechanism; + CK_BYTE_PTR buf; + CK_ULONG len; + CK_RV rv; + + mechanism = pkcs11_encryption_scheme_to_mech(scheme); + if (!mechanism) + { + DBG1(DBG_LIB, "encryption scheme %N not supported", + encryption_scheme_names, scheme); + return FALSE; + } + this->mutex->lock(this->mutex); + rv = this->lib->f->C_DecryptInit(this->session, mechanism, this->object); + if (this->reauth && !reauth(this)) + { + return FALSE; + } + if (rv != CKR_OK) + { + this->mutex->unlock(this->mutex); + DBG1(DBG_LIB, "C_DecryptInit() failed: %N", ck_rv_names, rv); + return FALSE; + } + len = (get_keysize(this) + 7) / 8; + buf = malloc(len); + rv = this->lib->f->C_Decrypt(this->session, crypt.ptr, crypt.len, buf, &len); + this->mutex->unlock(this->mutex); + if (rv != CKR_OK) + { + DBG1(DBG_LIB, "C_Decrypt() failed: %N", ck_rv_names, rv); + free(buf); + return FALSE; + } + *plain = chunk_create(buf, len); + return TRUE; +} + +METHOD(private_key_t, get_public_key, public_key_t*, + private_pkcs11_private_key_t *this) +{ + return this->pubkey->get_ref(this->pubkey); +} + +METHOD(private_key_t, get_fingerprint, bool, + private_pkcs11_private_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) +{ + return this->pubkey->get_fingerprint(this->pubkey, type, fingerprint); +} + +METHOD(private_key_t, get_encoding, bool, + private_pkcs11_private_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + return FALSE; +} + +METHOD(private_key_t, get_ref, private_key_t*, + private_pkcs11_private_key_t *this) +{ + ref_get(&this->ref); + return &this->public.key; +} + +METHOD(private_key_t, destroy, void, + private_pkcs11_private_key_t *this) +{ + if (ref_put(&this->ref)) + { + if (this->pubkey) + { + this->pubkey->destroy(this->pubkey); + } + this->mutex->destroy(this->mutex); + this->keyid->destroy(this->keyid); + this->lib->f->C_CloseSession(this->session); + free(this); + } +} + +/** + * Find the PKCS#11 library by its friendly name + */ +static pkcs11_library_t* find_lib(char *module) +{ + pkcs11_manager_t *manager; + enumerator_t *enumerator; + pkcs11_library_t *p11, *found = NULL; + CK_SLOT_ID slot; + + manager = pkcs11_manager_get(); + if (!manager) + { + return NULL; + } + enumerator = manager->create_token_enumerator(manager); + while (enumerator->enumerate(enumerator, &p11, &slot)) + { + if (streq(module, p11->get_name(p11))) + { + found = p11; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * Find the PKCS#11 lib having a keyid, and optionally a slot + */ +static pkcs11_library_t* find_lib_by_keyid(chunk_t keyid, int *slot) +{ + pkcs11_manager_t *manager; + enumerator_t *enumerator; + pkcs11_library_t *p11, *found = NULL; + CK_SLOT_ID current; + + manager = pkcs11_manager_get(); + if (!manager) + { + return NULL; + } + enumerator = manager->create_token_enumerator(manager); + while (enumerator->enumerate(enumerator, &p11, ¤t)) + { + if (*slot == -1 || *slot == current) + { + /* we look for a public key, it is usually readable without login */ + CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_ID, keyid.ptr, keyid.len}, + }; + CK_OBJECT_HANDLE object; + CK_SESSION_HANDLE session; + CK_RV rv; + enumerator_t *keys; + + rv = p11->f->C_OpenSession(current, CKF_SERIAL_SESSION, NULL, NULL, + &session); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", + ck_rv_names, rv); + continue; + } + keys = p11->create_object_enumerator(p11, session, + tmpl, countof(tmpl), NULL, 0); + if (keys->enumerate(keys, &object)) + { + DBG1(DBG_CFG, "found key on PKCS#11 token '%s':%d", + p11->get_name(p11), current); + found = p11; + *slot = current; + } + keys->destroy(keys); + p11->f->C_CloseSession(session); + if (found) + { + break; + } + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * Find the key on the token + */ +static bool find_key(private_pkcs11_private_key_t *this, chunk_t keyid) +{ + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_ID, keyid.ptr, keyid.len}, + }; + CK_OBJECT_HANDLE object; + CK_KEY_TYPE type; + CK_BBOOL reauth; + CK_ATTRIBUTE attr[] = { + {CKA_KEY_TYPE, &type, sizeof(type)}, + {CKA_ALWAYS_AUTHENTICATE, &reauth, sizeof(reauth)}, + {CKA_MODULUS, NULL, 0}, + {CKA_PUBLIC_EXPONENT, NULL, 0}, + }; + enumerator_t *enumerator; + chunk_t modulus, pubexp; + + enumerator = this->lib->create_object_enumerator(this->lib, + this->session, tmpl, countof(tmpl), attr, countof(attr)); + if (enumerator->enumerate(enumerator, &object)) + { + switch (type) + { + case CKK_RSA: + if (attr[2].ulValueLen == -1 || attr[3].ulValueLen == -1) + { + DBG1(DBG_CFG, "reading modulus/exponent from PKCS#1 failed"); + break; + } + modulus = chunk_create(attr[2].pValue, attr[2].ulValueLen); + pubexp = chunk_create(attr[3].pValue, attr[3].ulValueLen); + this->pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, + KEY_RSA, BUILD_RSA_MODULUS, modulus, + BUILD_RSA_PUB_EXP, pubexp, BUILD_END); + if (!this->pubkey) + { + DBG1(DBG_CFG, "extracting public key from PKCS#11 RSA " + "private key failed"); + } + this->reauth = reauth; + this->object = object; + break; + default: + DBG1(DBG_CFG, "PKCS#11 key type %d not supported", type); + break; + } + } + enumerator->destroy(enumerator); + return this->pubkey != NULL; +} + +/** + * Find a PIN and try to log in + */ +static bool login(private_pkcs11_private_key_t *this, int slot) +{ + enumerator_t *enumerator; + shared_key_t *shared; + chunk_t pin; + CK_RV rv; + CK_SESSION_INFO info; + bool found = FALSE, success = FALSE; + + rv = this->lib->f->C_GetSessionInfo(this->session, &info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetSessionInfo failed: %N", ck_rv_names, rv); + return FALSE; + } + if (info.state != CKS_RO_PUBLIC_SESSION && + info.state != CKS_RW_PUBLIC_SESSION) + { /* already logged in with another session, skip */ + return TRUE; + } + + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_PIN, this->keyid, NULL); + while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) + { + found = TRUE; + pin = shared->get_key(shared); + rv = this->lib->f->C_Login(this->session, CKU_USER, pin.ptr, pin.len); + if (rv == CKR_OK) + { + success = TRUE; + break; + } + DBG1(DBG_CFG, "login to '%s':%d failed: %N", + this->lib->get_name(this->lib), slot, ck_rv_names, rv); + } + enumerator->destroy(enumerator); + + if (!found) + { + DBG1(DBG_CFG, "no PIN found for PKCS#11 key %Y", this->keyid); + return FALSE; + } + return success; +} + +/** + * See header. + */ +pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args) +{ + private_pkcs11_private_key_t *this; + char *module = NULL; + chunk_t keyid = chunk_empty; + int slot = -1; + CK_RV rv; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_PKCS11_KEYID: + keyid = va_arg(args, chunk_t); + continue; + case BUILD_PKCS11_SLOT: + slot = va_arg(args, int); + continue; + case BUILD_PKCS11_MODULE: + module = va_arg(args, char*); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (!keyid.len) + { + return NULL; + } + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .sign = _sign, + .decrypt = _decrypt, + .get_keysize = _get_keysize, + .get_public_key = _get_public_key, + .equals = private_key_equals, + .belongs_to = private_key_belongs_to, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = private_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .ref = 1, + ); + + if (module && slot != -1) + { + this->lib = find_lib(module); + if (!this->lib) + { + DBG1(DBG_CFG, "PKCS#11 module '%s' not found", module); + free(this); + return NULL; + } + } + else + { + this->lib = find_lib_by_keyid(keyid, &slot); + if (!this->lib) + { + DBG1(DBG_CFG, "no PKCS#11 module found having a keyid %#B", &keyid); + free(this); + return NULL; + } + } + + rv = this->lib->f->C_OpenSession(slot, CKF_SERIAL_SESSION, + NULL, NULL, &this->session); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "opening private key session on '%s':%d failed: %N", + module, slot, ck_rv_names, rv); + free(this); + return NULL; + } + + this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); + this->keyid = identification_create_from_encoding(ID_KEY_ID, keyid); + + if (!login(this, slot)) + { + destroy(this); + return NULL; + } + + if (!find_key(this, keyid)) + { + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h new file mode 100644 index 000000000..428913f0a --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11_private_key pkcs11_private_key + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_PRIVATE_KEY_H_ +#define PKCS11_PRIVATE_KEY_H_ + +typedef struct pkcs11_private_key_t pkcs11_private_key_t; + +#include <credentials/builder.h> +#include <credentials/keys/private_key.h> + +#include "pkcs11.h" + +/** + * Private Key implementation on top of PKCS#11. + */ +struct pkcs11_private_key_t { + + /** + * Implements private_key_t interface. + */ + private_key_t key; +}; + +/** + * Open a private key on a PKCS#11 device. + * + * Accepts the BUILD_SMARTCARD_KEYID and the BUILD_SMARTCARD_PIN arguments. + * + * @param type type of the key + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args); + +/** + * Get the Cryptoki mechanism for a signature scheme. + */ +CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme); + +/** + * Get the Cryptoki mechanism for a encryption scheme. + */ +CK_MECHANISM_PTR pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme); + +#endif /** PKCS11_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c new file mode 100644 index 000000000..8d32d9a3f --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c @@ -0,0 +1,473 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_public_key.h" + +#include "pkcs11.h" +#include "pkcs11_private_key.h" +#include "pkcs11_manager.h" + +#include <debug.h> +#include <threading/mutex.h> + +typedef struct private_pkcs11_public_key_t private_pkcs11_public_key_t; + +/** + * Private data of an pkcs11_public_key_t object. + */ +struct private_pkcs11_public_key_t { + + /** + * Public pkcs11_public_key_t interface. + */ + pkcs11_public_key_t public; + + /** + * Type of the key + */ + key_type_t type; + + /** + * Key size in bytes + */ + size_t k; + + /** + * PKCS#11 library this key uses + */ + pkcs11_library_t *lib; + + /** + * Slot the token is in + */ + CK_SLOT_ID slot; + + /** + * Session we use + */ + CK_SESSION_HANDLE session; + + /** + * Object handle to the key + */ + CK_OBJECT_HANDLE object; + + /** + * Mutex to lock session + */ + mutex_t *mutex; + + /** + * References to this key + */ + refcount_t ref; +}; + +METHOD(public_key_t, get_type, key_type_t, + private_pkcs11_public_key_t *this) +{ + return this->type; +} + +METHOD(public_key_t, get_keysize, int, + private_pkcs11_public_key_t *this) +{ + return this->k * 8; +} + +METHOD(public_key_t, verify, bool, + private_pkcs11_public_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t sig) +{ + CK_MECHANISM_PTR mechanism; + CK_RV rv; + + mechanism = pkcs11_signature_scheme_to_mech(scheme); + if (!mechanism) + { + DBG1(DBG_LIB, "signature scheme %N not supported", + signature_scheme_names, scheme); + return FALSE; + } + if (sig.len && sig.ptr[0] == 0) + { /* trim leading zero byte in sig */ + sig = chunk_skip(sig, 1); + } + this->mutex->lock(this->mutex); + rv = this->lib->f->C_VerifyInit(this->session, mechanism, this->object); + if (rv != CKR_OK) + { + this->mutex->unlock(this->mutex); + DBG1(DBG_LIB, "C_VerifyInit() failed: %N", ck_rv_names, rv); + return FALSE; + } + rv = this->lib->f->C_Verify(this->session, data.ptr, data.len, + sig.ptr, sig.len); + this->mutex->unlock(this->mutex); + if (rv != CKR_OK) + { + DBG1(DBG_LIB, "C_Verify() failed: %N", ck_rv_names, rv); + return FALSE; + } + return TRUE; +} + +METHOD(public_key_t, encrypt, bool, + private_pkcs11_public_key_t *this, encryption_scheme_t scheme, + chunk_t plain, chunk_t *crypt) +{ + CK_MECHANISM_PTR mechanism; + CK_BYTE_PTR buf; + CK_ULONG len; + CK_RV rv; + + mechanism = pkcs11_encryption_scheme_to_mech(scheme); + if (!mechanism) + { + DBG1(DBG_LIB, "encryption scheme %N not supported", + encryption_scheme_names, scheme); + return FALSE; + } + this->mutex->lock(this->mutex); + rv = this->lib->f->C_EncryptInit(this->session, mechanism, this->object); + if (rv != CKR_OK) + { + this->mutex->unlock(this->mutex); + DBG1(DBG_LIB, "C_EncryptInit() failed: %N", ck_rv_names, rv); + return FALSE; + } + len = (get_keysize(this) + 7) / 8; + buf = malloc(len); + rv = this->lib->f->C_Encrypt(this->session, plain.ptr, plain.len, buf, &len); + this->mutex->unlock(this->mutex); + if (rv != CKR_OK) + { + DBG1(DBG_LIB, "C_Encrypt() failed: %N", ck_rv_names, rv); + free(buf); + return FALSE; + } + *crypt = chunk_create(buf, len); + return TRUE; +} + +/** + * Encode RSA key using a given encoding type + */ +static bool encode_rsa(private_pkcs11_public_key_t *this, + cred_encoding_type_t type, void *cache, chunk_t *encoding) +{ + CK_RV rv; + bool success = FALSE; + chunk_t n, e; + CK_ATTRIBUTE attr[] = { + {CKA_MODULUS, NULL, 0}, + {CKA_PUBLIC_EXPONENT, NULL, 0}, + }; + + rv = this->lib->f->C_GetAttributeValue(this->session, this->object, + attr, countof(attr)); + if (rv != CKR_OK || + attr[0].ulValueLen == 0 || attr[0].ulValueLen == -1 || + attr[1].ulValueLen == 0 || attr[1].ulValueLen == -1) + { + return FALSE; + } + attr[0].pValue = malloc(attr[0].ulValueLen); + attr[1].pValue = malloc(attr[1].ulValueLen); + rv = this->lib->f->C_GetAttributeValue(this->session, this->object, + attr, countof(attr)); + if (rv == CKR_OK) + { + n = chunk_create(attr[0].pValue, attr[0].ulValueLen); + e = chunk_create(attr[1].pValue, attr[1].ulValueLen); + success = lib->encoding->encode(lib->encoding, type, cache, encoding, + CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); + } + free(attr[0].pValue); + free(attr[1].pValue); + return success; +} + +METHOD(public_key_t, get_encoding, bool, + private_pkcs11_public_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + switch (this->type) + { + case KEY_RSA: + return encode_rsa(this, type, NULL, encoding); + default: + return FALSE; + } +} + +METHOD(public_key_t, get_fingerprint, bool, + private_pkcs11_public_key_t *this, cred_encoding_type_t type, chunk_t *fp) +{ + if (lib->encoding->get_cache(lib->encoding, type, this, fp)) + { + return TRUE; + } + switch (this->type) + { + case KEY_RSA: + return encode_rsa(this, type, this, fp); + default: + return FALSE; + } +} + +METHOD(public_key_t, get_ref, public_key_t*, + private_pkcs11_public_key_t *this) +{ + ref_get(&this->ref); + return &this->public.key; +} + +METHOD(public_key_t, destroy, void, + private_pkcs11_public_key_t *this) +{ + if (ref_put(&this->ref)) + { + lib->encoding->clear_cache(lib->encoding, this); + this->lib->f->C_CloseSession(this->session); + this->mutex->destroy(this->mutex); + free(this); + } +} + +/** + * Create an empty PKCS#11 public key + */ +static private_pkcs11_public_key_t *create(key_type_t type, size_t k, + pkcs11_library_t *p11, CK_SLOT_ID slot, + CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) +{ + private_pkcs11_public_key_t *this; + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .verify = _verify, + .encrypt = _encrypt, + .equals = public_key_equals, + .get_keysize = _get_keysize, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = public_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .type = type, + .k = k, + .lib = p11, + .slot = slot, + .session = session, + .object = object, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .ref = 1, + ); + + return this; +} + +/** + * Find a key object, including PKCS11 library and slot + */ +static private_pkcs11_public_key_t* find_rsa_key(chunk_t n, chunk_t e) +{ + private_pkcs11_public_key_t *this = NULL; + pkcs11_manager_t *manager; + enumerator_t *enumerator, *keys; + pkcs11_library_t *p11; + CK_SLOT_ID slot; + + manager = pkcs11_manager_get(); + if (!manager) + { + return NULL; + } + + enumerator = manager->create_token_enumerator(manager); + while (enumerator->enumerate(enumerator, &p11, &slot)) + { + CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; + CK_KEY_TYPE type = CKK_RSA; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_KEY_TYPE, &type, sizeof(type)}, + {CKA_MODULUS, n.ptr, n.len}, + {CKA_PUBLIC_EXPONENT, e.ptr, e.len}, + }; + CK_OBJECT_HANDLE object; + CK_SESSION_HANDLE session; + CK_RV rv; + + rv = p11->f->C_OpenSession(slot, CKF_SERIAL_SESSION, NULL, NULL, + &session); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv); + continue; + } + keys = p11->create_object_enumerator(p11, session, + tmpl, countof(tmpl), NULL, 0); + if (keys->enumerate(keys, &object)) + { + this = create(KEY_RSA, n.len, p11, slot, session, object); + keys->destroy(keys); + break; + } + keys->destroy(keys); + p11->f->C_CloseSession(session); + } + enumerator->destroy(enumerator); + return this; +} + +/** + * Create a key object in a suitable token session + */ +static private_pkcs11_public_key_t* create_rsa_key(chunk_t n, chunk_t e) +{ + private_pkcs11_public_key_t *this = NULL; + pkcs11_manager_t *manager; + enumerator_t *enumerator, *mechs; + pkcs11_library_t *p11; + CK_SLOT_ID slot; + + manager = pkcs11_manager_get(); + if (!manager) + { + return NULL; + } + + enumerator = manager->create_token_enumerator(manager); + while (enumerator->enumerate(enumerator, &p11, &slot)) + { + CK_MECHANISM_TYPE mech; + CK_MECHANISM_INFO info; + CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; + CK_KEY_TYPE type = CKK_RSA; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_KEY_TYPE, &type, sizeof(type)}, + {CKA_MODULUS, n.ptr, n.len}, + {CKA_PUBLIC_EXPONENT, e.ptr, e.len} + }; + CK_OBJECT_HANDLE object; + CK_SESSION_HANDLE session; + CK_RV rv; + + mechs = p11->create_mechanism_enumerator(p11, slot); + while (mechs->enumerate(mechs, &mech, &info)) + { + if (!(info.flags & CKF_VERIFY)) + { + continue; + } + switch (mech) + { + case CKM_RSA_PKCS: + case CKM_SHA1_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + case CKM_MD5_RSA_PKCS: + break; + default: + continue; + } + rv = p11->f->C_OpenSession(slot, CKF_SERIAL_SESSION, NULL, NULL, + &session); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", + ck_rv_names, rv); + continue; + } + rv = p11->f->C_CreateObject(session, tmpl, countof(tmpl), &object); + if (rv == CKR_OK) + { + this = create(KEY_RSA, n.len, p11, slot, session, object); + DBG2(DBG_CFG, "created RSA public key on token '%s':%d ", + p11->get_name(p11), slot); + break; + } + else + { + DBG1(DBG_CFG, "creating RSA public key on token '%s':%d " + "failed: %N", p11->get_name(p11), slot, ck_rv_names, rv); + p11->f->C_CloseSession(session); + } + } + mechs->destroy(mechs); + if (this) + { + break; + } + } + enumerator->destroy(enumerator); + return this; +} + +/** + * See header + */ +pkcs11_public_key_t *pkcs11_public_key_load(key_type_t type, va_list args) +{ + private_pkcs11_public_key_t *this; + chunk_t n, e; + + n = e = chunk_empty; + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_RSA_MODULUS: + n = va_arg(args, chunk_t); + continue; + case BUILD_RSA_PUB_EXP: + e = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (type == KEY_RSA && e.ptr && n.ptr) + { + if (n.len && n.ptr[0] == 0) + { /* trim leading zero byte in modulus */ + n = chunk_skip(n, 1); + } + this = find_rsa_key(n, e); + if (this) + { + return &this->public; + } + this = create_rsa_key(n, e); + if (this) + { + return &this->public; + } + } + return NULL; +} + diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.h b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.h new file mode 100644 index 000000000..4fd94620e --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pkcs11_public_key pkcs11_public_key + * @{ @ingroup pkcs11 + */ + +#ifndef PKCS11_PUBLIC_KEY_H_ +#define PKCS11_PUBLIC_KEY_H_ + +typedef struct pkcs11_public_key_t pkcs11_public_key_t; + +#include <credentials/builder.h> +#include <credentials/keys/private_key.h> + +/** + * PKCS#11 based public key implementation. + */ +struct pkcs11_public_key_t { + + /** + * Implements public_key_t. + */ + public_key_t key; +}; + +/** + * Create a public key in a PKCS#11 session. + * + * @param type type of the key + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +pkcs11_public_key_t *pkcs11_public_key_load(key_type_t type, va_list args); + +#endif /** PKCS11_PUBLIC_KEY_H_ @}*/ |