summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/pkcs11
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/pkcs11')
-rw-r--r--src/libstrongswan/plugins/pkcs11/Makefile.am21
-rw-r--r--src/libstrongswan/plugins/pkcs11/Makefile.in614
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11.h1357
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_creds.c249
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_creds.h68
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_hasher.c323
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_hasher.h47
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_library.c869
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_library.h110
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_manager.c407
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_manager.h78
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c176
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_plugin.h42
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c600
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h63
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c473
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_public_key.h49
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, &current, &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, &current))
+ {
+ 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_ @}*/