summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0>2006-06-09 18:39:11 +0000
committerrrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0>2006-06-09 18:39:11 +0000
commitd9119ff1fc1e32cdd060f33855c9bb0f1d12edf4 (patch)
tree4f7f4db50ea1a426fc134ae00c4706b92d807019
parentb974b595c8d60105667fce51b3e192c08f44a7bd (diff)
coolkey was check in with the wrong name initially
git-svn-id: http://svn.fedorahosted.org/svn/coolkey/trunk@6 fba4d07e-fe0f-4d7f-8147-e0026e666dc0
-rw-r--r--src/coolkey/Makefile.am84
-rw-r--r--src/coolkey/Makefile.in726
-rw-r--r--src/coolkey/PKCS11Exception.cpp54
-rw-r--r--src/coolkey/PKCS11Exception.h64
-rw-r--r--src/coolkey/config.mk81
-rw-r--r--src/coolkey/coolkey.cpp641
-rw-r--r--src/coolkey/coolkeypk11.def103
-rw-r--r--src/coolkey/coolkeypk11.rc89
-rw-r--r--src/coolkey/dllmain.cpp43
-rw-r--r--src/coolkey/locking.cpp133
-rw-r--r--src/coolkey/locking.h94
-rw-r--r--src/coolkey/log.cpp83
-rw-r--r--src/coolkey/log.h56
-rw-r--r--src/coolkey/machdep.cpp424
-rw-r--r--src/coolkey/machdep.h57
-rw-r--r--src/coolkey/manifest.mn46
-rw-r--r--src/coolkey/mypkcs11.h52
-rw-r--r--src/coolkey/object.cpp1065
-rw-r--r--src/coolkey/object.h205
-rw-r--r--src/coolkey/params.h49
-rw-r--r--src/coolkey/pkcs11.h302
-rw-r--r--src/coolkey/pkcs11f.h917
-rw-r--r--src/coolkey/pkcs11n.h76
-rw-r--r--src/coolkey/pkcs11t.h1354
-rw-r--r--src/coolkey/slot.cpp3192
-rw-r--r--src/coolkey/slot.h597
-rw-r--r--src/coolkey/test.cpp118
27 files changed, 10705 insertions, 0 deletions
diff --git a/src/coolkey/Makefile.am b/src/coolkey/Makefile.am
new file mode 100644
index 0000000..32531e8
--- /dev/null
+++ b/src/coolkey/Makefile.am
@@ -0,0 +1,84 @@
+# ***** BEGIN COPYRIGHT BLOCK *****
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation version
+# 2.1 of the License.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ***** END COPYRIGHT BLOCK *****
+
+# Process this file with automake to create Makefile.in
+
+SUBDIRS =
+AM_CPP_FLAGS =
+pkcs11dir = $(libdir)/pkcs11
+pkcs11_LTLIBRARIES = libcoolkeypk11.la
+
+libcoolkeypk11_la_SOURCES = \
+ coolkey.cpp \
+ dllmain.cpp \
+ locking.cpp \
+ log.cpp \
+ machdep.cpp \
+ object.cpp \
+ PKCS11Exception.cpp \
+ slot.cpp \
+ config.h \
+ locking.h \
+ log.h \
+ machdep.h \
+ mypkcs11.h \
+ object.h \
+ params.h \
+ PKCS11Exception.h \
+ pkcs11f.h \
+ pkcs11.h \
+ pkcs11n.h \
+ pkcs11t.h \
+ slot.h \
+ $(NULL)
+
+libcoolkeypk11_la_LDFLAGS = -module -avoid-version -export-symbols coolkeypk11.sym
+libcoolkeypk11_la_CPPFLAGS = $(CPPFLAGS) -DNSS_HIDE_NONSTANDARD_OBJECTS=1 -I$(top_srcdir)/clib $(PCSC_CFLAGS)
+libcoolkeypk11_la_DEPENDENCIES = coolkeypk11.sym
+libcoolkeypk11_la_LIBADD = @LIBCKYAPPLET@
+
+
+#
+# sigh, libtool doesn't maintain Linux and Solaris versioning info in
+# their .def file. So convert a very general, easy to work an any platform
+# coreconf .def file to a simplistic but acceptable libtool .sym file
+#
+coolkeypk11.sym: coolkeypk11.def
+ grep -v ';+' $< | grep -v ';-' | sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' > $@
+
+clean-generic:
+ rm -f coolkeypk11.sym
+
+
+
+#MODULE = coolkeypk11
+#REQUIRES = ckyapplet zlib
+#USE_STATIC_RTL=1
+
+#BASE_LIBRARY_NAME = coolkeypk11
+#LIBRARY_NAME = $(BASE_LIBRARY_NAME)
+#MAPFILE = $(OBJDIR)/coolkeypk11.def
+
+#DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \
+# -DPKCS11_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
+
+#DEFINES += -DNSS_HIDE_NONSTANDARD_OBJECTS=1
+
+#pcdir = $(libdir)/pkgconfig
+#pc_DATA = libcoolkey.pc
diff --git a/src/coolkey/Makefile.in b/src/coolkey/Makefile.in
new file mode 100644
index 0000000..3c7a680
--- /dev/null
+++ b/src/coolkey/Makefile.in
@@ -0,0 +1,726 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+
+# ***** BEGIN COPYRIGHT BLOCK *****
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation version
+# 2.1 of the License.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ***** END COPYRIGHT BLOCK *****
+
+# Process this file with automake to create Makefile.in
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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@
+target_triplet = @target@
+subdir = pkcs11/smartcard
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+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 = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(pkcs11dir)"
+pkcs11LTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(pkcs11_LTLIBRARIES)
+am_libcoolkeypk11_la_OBJECTS = libcoolkeypk11_la-coolkey.lo \
+ libcoolkeypk11_la-dllmain.lo libcoolkeypk11_la-locking.lo \
+ libcoolkeypk11_la-log.lo libcoolkeypk11_la-machdep.lo \
+ libcoolkeypk11_la-object.lo \
+ libcoolkeypk11_la-PKCS11Exception.lo libcoolkeypk11_la-slot.lo
+libcoolkeypk11_la_OBJECTS = $(am_libcoolkeypk11_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcoolkeypk11_la_SOURCES)
+DIST_SOURCES = $(libcoolkeypk11_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-exec-recursive install-info-recursive \
+ install-recursive installcheck-recursive installdirs-recursive \
+ pdf-recursive ps-recursive uninstall-info-recursive \
+ uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+HAVE_PCSC_FALSE = @HAVE_PCSC_FALSE@
+HAVE_PCSC_TRUE = @HAVE_PCSC_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBCKYAPPLET = @LIBCKYAPPLET@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCSC_CFLAGS = @PCSC_CFLAGS@
+PCSC_LIBS = @PCSC_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SCARD_LIB_NAME = @SCARD_LIB_NAME@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+SUBDIRS =
+AM_CPP_FLAGS =
+pkcs11dir = $(libdir)/pkcs11
+pkcs11_LTLIBRARIES = libcoolkeypk11.la
+libcoolkeypk11_la_SOURCES = \
+ coolkey.cpp \
+ dllmain.cpp \
+ locking.cpp \
+ log.cpp \
+ machdep.cpp \
+ object.cpp \
+ PKCS11Exception.cpp \
+ slot.cpp \
+ config.h \
+ locking.h \
+ log.h \
+ machdep.h \
+ mypkcs11.h \
+ object.h \
+ params.h \
+ PKCS11Exception.h \
+ pkcs11f.h \
+ pkcs11.h \
+ pkcs11n.h \
+ pkcs11t.h \
+ slot.h \
+ $(NULL)
+
+libcoolkeypk11_la_LDFLAGS = -module -avoid-version -export-symbols coolkeypk11.sym
+libcoolkeypk11_la_CPPFLAGS = $(CPPFLAGS) -DNSS_HIDE_NONSTANDARD_OBJECTS=1 -I$(top_srcdir)/clib $(PCSC_CFLAGS)
+libcoolkeypk11_la_DEPENDENCIES = coolkeypk11.sym
+libcoolkeypk11_la_LIBADD = @LIBCKYAPPLET@
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pkcs11/smartcard/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu pkcs11/smartcard/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pkcs11LTLIBRARIES: $(pkcs11_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkcs11dir)" || $(mkdir_p) "$(DESTDIR)$(pkcs11dir)"
+ @list='$(pkcs11_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(pkcs11LTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkcs11dir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(pkcs11LTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkcs11dir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pkcs11LTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(pkcs11_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(pkcs11dir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(pkcs11dir)/$$p"; \
+ done
+
+clean-pkcs11LTLIBRARIES:
+ -test -z "$(pkcs11_LTLIBRARIES)" || rm -f $(pkcs11_LTLIBRARIES)
+ @list='$(pkcs11_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
+libcoolkeypk11.la: $(libcoolkeypk11_la_OBJECTS) $(libcoolkeypk11_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(pkcs11dir) $(libcoolkeypk11_la_LDFLAGS) $(libcoolkeypk11_la_OBJECTS) $(libcoolkeypk11_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-PKCS11Exception.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-coolkey.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-dllmain.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-locking.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-log.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-machdep.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-object.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolkeypk11_la-slot.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+libcoolkeypk11_la-coolkey.lo: coolkey.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-coolkey.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-coolkey.Tpo" -c -o libcoolkeypk11_la-coolkey.lo `test -f 'coolkey.cpp' || echo '$(srcdir)/'`coolkey.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-coolkey.Tpo" "$(DEPDIR)/libcoolkeypk11_la-coolkey.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-coolkey.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='coolkey.cpp' object='libcoolkeypk11_la-coolkey.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-coolkey.lo `test -f 'coolkey.cpp' || echo '$(srcdir)/'`coolkey.cpp
+
+libcoolkeypk11_la-dllmain.lo: dllmain.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-dllmain.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-dllmain.Tpo" -c -o libcoolkeypk11_la-dllmain.lo `test -f 'dllmain.cpp' || echo '$(srcdir)/'`dllmain.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-dllmain.Tpo" "$(DEPDIR)/libcoolkeypk11_la-dllmain.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-dllmain.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dllmain.cpp' object='libcoolkeypk11_la-dllmain.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-dllmain.lo `test -f 'dllmain.cpp' || echo '$(srcdir)/'`dllmain.cpp
+
+libcoolkeypk11_la-locking.lo: locking.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-locking.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-locking.Tpo" -c -o libcoolkeypk11_la-locking.lo `test -f 'locking.cpp' || echo '$(srcdir)/'`locking.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-locking.Tpo" "$(DEPDIR)/libcoolkeypk11_la-locking.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-locking.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='locking.cpp' object='libcoolkeypk11_la-locking.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-locking.lo `test -f 'locking.cpp' || echo '$(srcdir)/'`locking.cpp
+
+libcoolkeypk11_la-log.lo: log.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-log.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-log.Tpo" -c -o libcoolkeypk11_la-log.lo `test -f 'log.cpp' || echo '$(srcdir)/'`log.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-log.Tpo" "$(DEPDIR)/libcoolkeypk11_la-log.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-log.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='log.cpp' object='libcoolkeypk11_la-log.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-log.lo `test -f 'log.cpp' || echo '$(srcdir)/'`log.cpp
+
+libcoolkeypk11_la-machdep.lo: machdep.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-machdep.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-machdep.Tpo" -c -o libcoolkeypk11_la-machdep.lo `test -f 'machdep.cpp' || echo '$(srcdir)/'`machdep.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-machdep.Tpo" "$(DEPDIR)/libcoolkeypk11_la-machdep.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-machdep.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='machdep.cpp' object='libcoolkeypk11_la-machdep.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-machdep.lo `test -f 'machdep.cpp' || echo '$(srcdir)/'`machdep.cpp
+
+libcoolkeypk11_la-object.lo: object.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-object.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-object.Tpo" -c -o libcoolkeypk11_la-object.lo `test -f 'object.cpp' || echo '$(srcdir)/'`object.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-object.Tpo" "$(DEPDIR)/libcoolkeypk11_la-object.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-object.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='object.cpp' object='libcoolkeypk11_la-object.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-object.lo `test -f 'object.cpp' || echo '$(srcdir)/'`object.cpp
+
+libcoolkeypk11_la-PKCS11Exception.lo: PKCS11Exception.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-PKCS11Exception.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-PKCS11Exception.Tpo" -c -o libcoolkeypk11_la-PKCS11Exception.lo `test -f 'PKCS11Exception.cpp' || echo '$(srcdir)/'`PKCS11Exception.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-PKCS11Exception.Tpo" "$(DEPDIR)/libcoolkeypk11_la-PKCS11Exception.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-PKCS11Exception.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PKCS11Exception.cpp' object='libcoolkeypk11_la-PKCS11Exception.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-PKCS11Exception.lo `test -f 'PKCS11Exception.cpp' || echo '$(srcdir)/'`PKCS11Exception.cpp
+
+libcoolkeypk11_la-slot.lo: slot.cpp
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libcoolkeypk11_la-slot.lo -MD -MP -MF "$(DEPDIR)/libcoolkeypk11_la-slot.Tpo" -c -o libcoolkeypk11_la-slot.lo `test -f 'slot.cpp' || echo '$(srcdir)/'`slot.cpp; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libcoolkeypk11_la-slot.Tpo" "$(DEPDIR)/libcoolkeypk11_la-slot.Plo"; else rm -f "$(DEPDIR)/libcoolkeypk11_la-slot.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='slot.cpp' object='libcoolkeypk11_la-slot.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolkeypk11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libcoolkeypk11_la-slot.lo `test -f 'slot.cpp' || echo '$(srcdir)/'`slot.cpp
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+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; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && 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)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(mkdir_p) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(pkcs11dir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+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:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-recursive
+
+clean-am: clean-generic clean-libtool clean-pkcs11LTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-pkcs11LTLIBRARIES
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-pkcs11LTLIBRARIES
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+ clean clean-generic clean-libtool clean-pkcs11LTLIBRARIES \
+ clean-recursive ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-recursive distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-pkcs11LTLIBRARIES \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-info-am uninstall-pkcs11LTLIBRARIES
+
+
+#
+# sigh, libtool doesn't maintain Linux and Solaris versioning info in
+# their .def file. So convert a very general, easy to work an any platform
+# coreconf .def file to a simplistic but acceptable libtool .sym file
+#
+coolkeypk11.sym: coolkeypk11.def
+ grep -v ';+' $< | grep -v ';-' | sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' > $@
+
+clean-generic:
+ rm -f coolkeypk11.sym
+
+#MODULE = coolkeypk11
+#REQUIRES = ckyapplet zlib
+#USE_STATIC_RTL=1
+
+#BASE_LIBRARY_NAME = coolkeypk11
+#LIBRARY_NAME = $(BASE_LIBRARY_NAME)
+#MAPFILE = $(OBJDIR)/coolkeypk11.def
+
+#DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \
+# -DPKCS11_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
+
+#DEFINES += -DNSS_HIDE_NONSTANDARD_OBJECTS=1
+
+#pcdir = $(libdir)/pkgconfig
+#pc_DATA = libcoolkey.pc
+# 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/coolkey/PKCS11Exception.cpp b/src/coolkey/PKCS11Exception.cpp
new file mode 100644
index 0000000..843c437
--- /dev/null
+++ b/src/coolkey/PKCS11Exception.cpp
@@ -0,0 +1,54 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include "mypkcs11.h"
+#include <string>
+#include <cstdarg>
+#include <assert.h>
+#include "log.h"
+#include "PKCS11Exception.h"
+
+#ifdef WIN32
+#define vsnprintf _vsnprintf
+#endif
+
+PKCS11Exception::PKCS11Exception(CK_RV crv_, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ makeMessage(format, args);
+
+ va_end(args);
+
+ crv = crv_;
+}
+void
+PKCS11Exception::log(Log *log) const
+{
+ log->log("Error 0x%08x: %s\n", crv, getMessageStr());
+}
+
+void
+PKCS11Exception::makeMessage(const char *format, va_list args)
+{
+ char buf[BUFSIZE];
+ vsnprintf(buf, BUFSIZE, format, args);
+ message = string(buf);
+}
diff --git a/src/coolkey/PKCS11Exception.h b/src/coolkey/PKCS11Exception.h
new file mode 100644
index 0000000..4e2a94f
--- /dev/null
+++ b/src/coolkey/PKCS11Exception.h
@@ -0,0 +1,64 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_PKCS11EXCEPTION_H
+#define COOLKEY_PKCS11EXCEPTION_H
+
+#include "mypkcs11.h"
+#include <string>
+#include <cstdarg>
+#include "log.h"
+
+using std::string;
+
+class PKCS11Exception {
+
+ private:
+ enum { BUFSIZE = 1024 };
+
+ CK_RV crv;
+ string message;
+
+ void makeMessage(const char *format, va_list args);
+
+ public:
+ PKCS11Exception(CK_RV crv_) : crv(crv_) { }
+ PKCS11Exception(CK_RV crv_, string message_)
+ : crv(crv_), message(message_) { }
+ PKCS11Exception(CK_RV crv_, const char *format, ...);
+
+ CK_RV getReturnValue() const {
+ return crv;
+ }
+
+ CK_RV getCRV() const {
+ return crv;
+ }
+
+ string getMessage() const {
+ return message;
+ }
+
+ const char *getMessageStr() const { return message.c_str(); }
+
+ void log(Log *l) const;
+
+};
+
+#endif
diff --git a/src/coolkey/config.mk b/src/coolkey/config.mk
new file mode 100644
index 0000000..11338f7
--- /dev/null
+++ b/src/coolkey/config.mk
@@ -0,0 +1,81 @@
+# ***** BEGIN COPYRIGHT BLOCK *****
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation version
+# 2.1 of the License.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ***** END COPYRIGHT BLOCK *****
+
+LIB_RTL_SUFFIX=
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+ifdef USE_STATIC_RTL
+LIB_RTL_SUFFIX=_srtl
+endif
+endif
+
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)ckyapplet$(LIB_RTL_SUFFIX).$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)zlib$(LIB_RTL_SUFFIX).$(LIB_SUFFIX) \
+ $(NULL)
+
+# can't do this in manifest.mn because OS_TARGET isn't defined there.
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+# don't want the 32 in the shared library name
+SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
+
+RES = $(OBJDIR)/$(LIBRARY_NAME).res
+RESNAME = $(LIBRARY_NAME).rc
+
+ifdef NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ $(NULL)
+else # ! NS_USE_GCC
+
+EXTRA_SHARED_LIBS += \
+ $(NULL)
+endif # NS_USE_GCC
+
+else
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib/ \
+ $(NULL)
+endif
+
+ifeq ($(OS_TARGET),SunOS)
+ifndef USE_64
+ifeq ($(CPU_ARCH),sparc)
+# The -R '$ORIGIN' linker option instructs libsoftokn3.so to search for its
+# dependencies (libfreebl_*.so) in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+endif
+endif
+
+ifeq ($(OS_TARGET),WINCE)
+DEFINES += -DDBM_USING_NSPR
+endif
+
+ifeq ($(OS_TARGET),Linux)
+CC=g++
+EXTRA_SHARED_LIBS += -ldl -lpthread
+#ifdef USE_STATIC_RTL
+#MKSHLIB += -static-libgcc
+#endif
+endif
diff --git a/src/coolkey/coolkey.cpp b/src/coolkey/coolkey.cpp
new file mode 100644
index 0000000..e129169
--- /dev/null
+++ b/src/coolkey/coolkey.cpp
@@ -0,0 +1,641 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include "mypkcs11.h"
+
+#include <assert.h>
+#include <string>
+#include <map>
+#include <set>
+#include <memory>
+#include "log.h"
+#include "PKCS11Exception.h"
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <winscard.h>
+#include "slot.h"
+#include "cky_base.h"
+#include "params.h"
+
+#define NULL 0
+
+/* static module data -------------------------------- */
+
+static Log *log = NULL;
+
+static SlotList *slotList = NULL;
+
+static OSLock finalizeLock(false);
+
+static CK_BBOOL initialized = FALSE;
+static CK_BBOOL finalizing = FALSE;
+static CK_BBOOL waitEvent = FALSE;
+
+char *Params::params = NULL;
+
+// manufacturerID and libraryDescription should not be NULL-terminated,
+// so the last character is overwritten with a blank in C_GetInfo().
+static CK_INFO ckInfo = {
+ {2, 11},
+ "Mozilla Foundation ",
+ 0,
+ "CoolKey PKCS #11 Module ",
+ {1, 0}
+};
+
+typedef struct {
+ CK_MECHANISM_TYPE mech;
+ CK_MECHANISM_INFO info;
+} MechInfo;
+
+/**********************************************************************
+ ************************** MECHANISM TABLE ***************************
+ **********************************************************************/
+static MechInfo
+mechanismList[] = {
+ {CKM_RSA_PKCS, { 1024, 4096, CKF_HW | CKF_SIGN | CKF_DECRYPT } }
+};
+static unsigned int numMechanisms = sizeof(mechanismList)/sizeof(MechInfo);
+
+/* ------------------------------------------------------------ */
+
+void
+dumpTemplates(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ // no try here, let caller catch it. try {
+ unsigned long i;
+ if (!pTemplate)
+ return;
+ for (i = 0; i < ulCount; ++i) {
+ CK_ATTRIBUTE_PTR pT = pTemplate + i;
+ if (pT->pValue && pT->ulValueLen == 4) {
+ log->log(
+ "template [%02lu] type: %04lx, pValue: %08lx, ulValueLen: %08lx, value: %lu\n",
+ i, pT->type, pT->pValue, pT->ulValueLen, *(CK_ULONG_PTR)pT->pValue);
+ } else
+ log->log("template [%02lu] type: %04lx, pValue: %08lx, ulValueLen: %08lx\n",
+ i, pT->type, pT->pValue, pT->ulValueLen);
+ }
+}
+
+/* PKCS11 defined functions ----------------------------------- */
+
+
+#define NOTSUPPORTED(name, args) \
+CK_RV name args \
+{ \
+ log->log(#name " called (notSupported)\n"); \
+ return CKR_FUNCTION_NOT_SUPPORTED; \
+}
+
+#define SUPPORTED(name, name2, dec_args, use_args) \
+CK_RV name dec_args \
+{ \
+ if( ! initialized ) { \
+ return CKR_CRYPTOKI_NOT_INITIALIZED; \
+ } \
+ try { \
+ log->log(#name " called\n"); \
+ slotList->name2 use_args ; \
+ return CKR_OK; \
+ } catch(PKCS11Exception& e) { \
+ e.log(log); \
+ return e.getCRV(); \
+ } \
+}
+
+
+
+extern "C" {
+
+NOTSUPPORTED(C_InitToken,(CK_SLOT_ID, CK_CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR))
+NOTSUPPORTED(C_InitPIN, (CK_SESSION_HANDLE, CK_CHAR_PTR, CK_ULONG))
+NOTSUPPORTED(C_SetPIN, (CK_SESSION_HANDLE, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG))
+NOTSUPPORTED(C_GetOperationState, (CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR))
+NOTSUPPORTED(C_SetOperationState, (CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_CreateObject, (CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR))
+NOTSUPPORTED(C_CopyObject, (CK_SESSION_HANDLE,CK_OBJECT_HANDLE,CK_ATTRIBUTE_PTR,CK_ULONG,CK_OBJECT_HANDLE_PTR))
+NOTSUPPORTED(C_DestroyObject, (CK_SESSION_HANDLE, CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_GetObjectSize, (CK_SESSION_HANDLE,CK_OBJECT_HANDLE,CK_ULONG_PTR))
+NOTSUPPORTED(C_SetAttributeValue, (CK_SESSION_HANDLE,CK_OBJECT_HANDLE,CK_ATTRIBUTE_PTR,CK_ULONG))
+NOTSUPPORTED(C_EncryptInit, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_Encrypt, (CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR))
+NOTSUPPORTED(C_EncryptUpdate, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_EncryptFinal, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DecryptUpdate,(CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DecryptFinal, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DigestInit, (CK_SESSION_HANDLE,CK_MECHANISM_PTR))
+NOTSUPPORTED(C_Digest, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DigestUpdate, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG))
+NOTSUPPORTED(C_DigestKey, (CK_SESSION_HANDLE,CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_DigestFinal, (CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR))
+NOTSUPPORTED(C_SignUpdate, (CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG))
+NOTSUPPORTED(C_SignFinal, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_SignRecoverInit, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_SignRecover, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_VerifyInit, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_Verify, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG))
+NOTSUPPORTED(C_VerifyUpdate, (CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG))
+NOTSUPPORTED(C_VerifyFinal, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG))
+NOTSUPPORTED(C_VerifyRecoverInit, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE))
+NOTSUPPORTED(C_VerifyRecover, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DigestEncryptUpdate, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DecryptDigestUpdate, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_SignEncryptUpdate, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_DecryptVerifyUpdate, (CK_SESSION_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_GenerateKey, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_ATTRIBUTE_PTR,CK_ULONG,CK_OBJECT_HANDLE_PTR))
+NOTSUPPORTED(C_GenerateKeyPair, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_ATTRIBUTE_PTR,CK_ULONG,CK_ATTRIBUTE_PTR,CK_ULONG,CK_OBJECT_HANDLE_PTR,CK_OBJECT_HANDLE_PTR))
+NOTSUPPORTED(C_WrapKey, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE,CK_OBJECT_HANDLE,CK_BYTE_PTR,CK_ULONG_PTR))
+NOTSUPPORTED(C_UnwrapKey, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE,CK_BYTE_PTR,CK_ULONG,CK_ATTRIBUTE_PTR,CK_ULONG,CK_OBJECT_HANDLE_PTR))
+NOTSUPPORTED(C_DeriveKey, (CK_SESSION_HANDLE,CK_MECHANISM_PTR,CK_OBJECT_HANDLE,CK_ATTRIBUTE_PTR,CK_ULONG,CK_OBJECT_HANDLE_PTR))
+NOTSUPPORTED(C_GetFunctionStatus, (CK_SESSION_HANDLE))
+NOTSUPPORTED(C_CancelFunction, (CK_SESSION_HANDLE))
+
+/* non-specialized functions supported with the slotList object */
+
+SUPPORTED(C_GetSlotList, getSlotList,
+ (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount),
+ (tokenPresent, pSlotList, pulCount))
+SUPPORTED(C_GetSessionInfo, getSessionInfo,
+ (CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo),
+ (hSession, pInfo) )
+SUPPORTED(C_Logout, logout, (CK_SESSION_HANDLE hSession), (hSession))
+SUPPORTED(C_Decrypt, decrypt,
+ (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pDecryptedData, CK_ULONG_PTR pulDecryptedDataLen),
+ (hSession, pData, ulDataLen, pDecryptedData, pulDecryptedDataLen))
+SUPPORTED(C_DecryptInit, decryptInit,
+ (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey), (hSession, pMechanism, hKey))
+SUPPORTED(C_SignInit, signInit,
+ (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey),
+ (hSession, pMechanism, hKey))
+SUPPORTED(C_Sign, sign,
+ (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen),
+ (hSession, pData, ulDataLen, pSignature, pulSignatureLen))
+SUPPORTED(C_SeedRandom, seedRandom,
+ (CK_SESSION_HANDLE hSession ,CK_BYTE_PTR data,CK_ULONG dataLen),
+ (hSession, data, dataLen))
+SUPPORTED(C_GenerateRandom, generateRandom,
+ (CK_SESSION_HANDLE hSession ,CK_BYTE_PTR data,CK_ULONG dataLen),
+ (hSession, data, dataLen))
+
+/* non-specialized functions supported with the slot directly */
+
+CK_RV
+C_Initialize(CK_VOID_PTR pInitArgs)
+{
+ try {
+ if( initialized ) {
+ return CKR_CRYPTOKI_ALREADY_INITIALIZED;
+ }
+ if (!finalizeLock.isValid()) {
+ return CKR_CANT_LOCK;
+ }
+ CK_C_INITIALIZE_ARGS* initArgs = (CK_C_INITIALIZE_ARGS*) pInitArgs;
+ if( initArgs != NULL ) {
+ /* work around a bug in NSS where the library parameters are only
+ * send if locking is requested */
+ if (initArgs->LibraryParameters) {
+ Params::SetParams(strdup((char *)initArgs->LibraryParameters));
+ } else {
+ Params::ClearParams();
+ }
+ if( (initArgs->flags & CKF_OS_LOCKING_OK) || initArgs->LockMutex ){
+ throw PKCS11Exception(CKR_CANT_LOCK);
+ }
+ }
+ char * logFileName = getenv("COOL_KEY_LOG_FILE");
+ if (logFileName)
+ log = new FileLog(logFileName);
+ else
+ log = new DummyLog();
+ log->log("Initialize called, hello %d\n", 5);
+ CKY_SetName("coolkey");
+ slotList = new SlotList(log);
+ initialized = TRUE;
+ return CKR_OK;
+ } catch(PKCS11Exception &e) {
+ if( log )
+ e.log(log);
+ return e.getReturnValue();
+ }
+}
+
+CK_RV
+C_Finalize(CK_VOID_PTR pReserved)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ // XXX cleanup all data structures !!!
+ //delete sessionManager;
+ log->log("Finalizing...\n");
+ // don't race the setting of finalizing. If C_WaitEvent gets passed
+ // the finalizing call first, we know it will set waitEvent before
+ // we can get the lock, so we only need to protect setting finalizing
+ // to true.
+ finalizeLock.getLock();
+ finalizing = TRUE;
+ finalizeLock.releaseLock();
+ if (waitEvent) {
+ /* we're waiting on a slot event, shutdown first to allow
+ * the wait function to complete before we pull the rug out.
+ */
+ slotList->shutdown();
+ while (waitEvent) {
+ OSSleep(500);
+ }
+ }
+ delete slotList;
+ delete log;
+ finalizeLock.getLock();
+ finalizing = FALSE;
+ initialized = FALSE;
+ finalizeLock.releaseLock();
+ return CKR_OK;
+}
+
+
+CK_RV
+C_GetInfo(CK_INFO_PTR p)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ log->log("C_GetInfo called\n");
+ ckInfo.manufacturerID[31] = ' ';
+ ckInfo.libraryDescription[31] = ' ';
+ *p = ckInfo;
+ return CKR_OK;
+}
+
+
+CK_RV
+C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pSlotInfo)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("Called C_GetSlotInfo\n");
+ slotList->validateSlotID(slotID);
+ return slotList->getSlot(
+ slotIDToIndex(slotID))->getSlotInfo(pSlotInfo);
+ } catch( PKCS11Exception &excep ) {
+ excep.log(log);
+ return excep.getCRV();
+ }
+}
+
+CK_RV
+C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pTokenInfo)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_GetTokenInfo called\n");
+ slotList->validateSlotID(slotID);
+ return slotList->getSlot(
+ slotIDToIndex(slotID))->getTokenInfo(pTokenInfo);
+ } catch( PKCS11Exception &excep ) {
+ excep.log(log);
+ return excep.getCRV();
+ }
+}
+
+CK_RV
+C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
+ CK_ULONG_PTR pulCount)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ CK_RV rv = CKR_OK;
+
+ log->log("C_GetMechanismList called\n");
+ if( pulCount == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+
+ slotList->validateSlotID(slotID);
+ if( ! slotList->getSlot(
+ slotIDToIndex(slotID))->isTokenPresent() ) {
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+
+ if( pMechanismList != NULL ) {
+ if( *pulCount < numMechanisms ) {
+ rv = CKR_BUFFER_TOO_SMALL;
+ } else {
+ for(unsigned int i=0; i < numMechanisms; ++i ) {
+ pMechanismList[i] = mechanismList[i].mech;
+ }
+ }
+ }
+
+ *pulCount = numMechanisms;
+
+ log->log("C_GetMechanismList returning %d\n", rv);
+ return rv;
+
+ } catch(PKCS11Exception &excep ) {
+ excep.log(log);
+ return excep.getCRV();
+ }
+
+}
+
+CK_RV
+C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_GetMechanismInfo called\n");
+ if( pInfo == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ slotList->validateSlotID(slotID);
+ if( ! slotList->getSlot(slotIDToIndex(slotID))->isTokenPresent() ) {
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+
+ for(unsigned int i=0; i < numMechanisms; ++i ) {
+ if( mechanismList[i].mech == type ) {
+ *pInfo = mechanismList[i].info;
+ log->log("C_GetMechanismInfo got info about %d\n", type);
+ return CKR_OK;
+ }
+ }
+ log->log("C_GetMechanismInfo failed to find info about %d\n", type);
+ return CKR_MECHANISM_INVALID; // mechanism not in the list
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+CK_RV
+C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
+ CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_OpenSession called\n");
+ slotList->validateSlotID(slotID);
+#ifdef LATER // the CSP isn't setting this bit right now.
+ if( ! (flags & CKF_SERIAL_SESSION) ) {
+ throw PKCS11Exception(CKR_SESSION_PARALLEL_NOT_SUPPORTED);
+ }
+#endif
+ if( phSession == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ Session::Type sessionType =
+ (flags & CKF_RW_SESSION) ? Session::RW : Session::RO;
+
+ slotList->openSession(sessionType, slotID, phSession);
+
+ return CKR_OK;
+
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+CK_RV
+C_CloseSession(CK_SESSION_HANDLE hSession)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_CloseSession(0x%x) called\n", hSession);
+ // !!!XXX Hack
+ // If nothing else, we need to logout the token when all
+ // its sessions are closed.
+ return CKR_OK;
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+CK_RV
+C_CloseAllSessions(CK_SLOT_ID slotID)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_CloseAllSessions(0x%x) called\n", slotID);
+ slotList->validateSlotID(slotID);
+ // !!!XXX Hack
+ // If nothing else, we need to logout the token when all
+ // its sessions are closed.
+ return CKR_OK;
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+
+CK_RV
+C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_FindObjectsInit called, %lu templates\n", ulCount);
+ dumpTemplates(pTemplate, ulCount);
+
+ if( pTemplate == NULL && ulCount != 0 ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ slotList->findObjectsInit(hSession, pTemplate, ulCount);
+ return CKR_OK;
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+CK_RV
+C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ CK_ULONG count = 0;
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_FindObjects called, max objects = %lu\n", ulMaxObjectCount );
+ if( phObject == NULL && ulMaxObjectCount != 0 ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ slotList->findObjects(hSession, phObject, ulMaxObjectCount,
+ pulObjectCount);
+ count = *pulObjectCount;
+ log->log("returned %lu objects:", count );
+ CK_ULONG i;
+ for (i = 0; i < count; ++i) {
+ log->log(" 0x%08lx", phObject[i]);
+ }
+ log->log("\n" );
+ return CKR_OK;
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+CK_RV
+C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ // we don't need to do any cleaup. We could check the session handle.
+ return CKR_OK;
+}
+
+CK_RV
+C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_Login called\n");
+ if( userType != CKU_USER ) {
+ throw PKCS11Exception(CKR_USER_TYPE_INVALID);
+ }
+ if( pPin == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ slotList->login(hSession, pPin, ulPinLen);
+ return CKR_OK;
+ } catch(PKCS11Exception &e) {
+ e.log(log);
+ return e.getCRV();
+ }
+}
+
+
+CK_RV
+C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if( ! initialized ) {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ try {
+ log->log("C_GetAttributeValue called, %lu templates for object 0x%08lx\n", ulCount, hObject);
+ dumpTemplates(pTemplate, ulCount);
+ if( pTemplate == NULL && ulCount != 0 ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ slotList->getAttributeValue(hSession, hObject, pTemplate, ulCount);
+ dumpTemplates(pTemplate, ulCount);
+ return CKR_OK;
+ } catch(PKCS11Exception& e) {
+ CK_RV rv = e.getCRV();
+ e.log(log);
+ if (rv == CKR_ATTRIBUTE_TYPE_INVALID ||
+ rv == CKR_BUFFER_TOO_SMALL) {
+ dumpTemplates(pTemplate, ulCount);
+ }
+ return rv;
+ }
+}
+
+
+/*
+ * While the rest of the C_ calls are protected by the callers lock,
+ * C_WaitForSlotEvent is guaranteed to be on a separate thread.
+ * Make sure we are locking with C_Finalize, which is likely to be racing
+ * with this function
+ */
+CK_RV
+C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ finalizeLock.getLock();
+ if( ! initialized ) {
+ finalizeLock.releaseLock();
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ if (finalizing) {
+ finalizeLock.releaseLock();
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ waitEvent = TRUE;
+ finalizeLock.releaseLock();
+ try {
+ log->log("C_WaitForSlotEvent called\n");
+ slotList->waitForSlotEvent(flags, pSlot, pReserved);
+ waitEvent = FALSE;
+ return CKR_OK;
+ } catch(PKCS11Exception& e) {
+ e.log(log);
+ waitEvent = FALSE;
+ return e.getCRV();
+ }
+}
+
+CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR pPtr);
+
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+#define CK_PKCS11_FUNCTION_INFO(func) (CK_##func) func,
+
+static CK_FUNCTION_LIST
+functionList = {
+ {2, 20}, // PKCS #11 spec version we support
+#include "pkcs11f.h"
+};
+
+CK_RV
+C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR pPtr)
+{
+ if( pPtr == NULL ) {
+ return CKR_ARGUMENTS_BAD;
+ }
+ *pPtr = &functionList;
+ return CKR_OK;
+}
+
+
+} // end extern C
+
diff --git a/src/coolkey/coolkeypk11.def b/src/coolkey/coolkeypk11.def
new file mode 100644
index 0000000..50420ca
--- /dev/null
+++ b/src/coolkey/coolkeypk11.def
@@ -0,0 +1,103 @@
+;+# ***** BEGIN COPYRIGHT BLOCK *****
+;+# Copyright (C) 2005 Red Hat, Inc.
+;+# All rights reserved.
+;+#
+;+# This library is free software; you can redistribute it and/or
+;+# modify it under the terms of the GNU Lesser General Public
+;+# License as published by the Free Software Foundation version
+;+# 2.1 of the License.
+;+#
+;+# This library 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
+;+# Lesser General Public License for more details.
+;+#
+;+# You should have received a copy of the GNU Lesser General Public
+;+# License along with this library; if not, write to the Free Software
+;+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+;+# ***** END COPYRIGHT BLOCK *****
+
+;+#
+;+# Coreconf smart .def file.
+;+# This .def file has encoded in it enough information so it can easily be
+;+# converted to an appropriate export symbol file an just about any platform.
+;+#
+;+# To add new symbols to this file, be sure to enclose those symbols in the
+;+# appropriate shared library version number. These version numbers are parsed
+;+# by Linux and Solaris. These commands should be prefixed with the
+;+# appropriate ';+'
+;+#
+;+# general comments are prefixed by ';+#'
+;+#
+;+# Windows & OS/2 key words should not be prefixed. The would contain the
+;+# the line ';-' somewhere in the line. This file will be fed 'AS IS' to
+;+# Windows and OS/2 with no processing. Anything following a ';' on these
+;+# platforms are already treated as a comment.
+;+#
+;+# As meantioned above, Linux and Solaris commands should be prefixed with ';+'
+;+# The ;+ will be removed, as well as any line that has ";-". The " DATA "
+;+# keyword will also be removed. The '#' is a comment on these platforms.
+;+#
+;+# A simple list of export symbols (needed for some platforms like AIX or
+;+# libtool can be generated by running the following command:
+;+# grep -v ';+' $(DEF_FILE) | grep -v ';-' | \
+;+# sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' > $(SYM_LIST)
+;+#
+;+# Some platforms take symbols in the form of a sym list with some prefix,
+;+# for instance the MAC symbol table can be processed with the above command
+;+# plus an extra -e 's,^,_,' to the sed command above. HP symbols can be
+;+# processed by adding an extra -e 's,^,-e ,'.
+;+#
+;+COOLKEY_2.10 { # Cool Key 2.10 is the PKCS #11 spec version
+;+ global:
+LIBRARY coolkey ;-
+EXPORTS ;-
+C_GetFunctionList
+;+# Make this function like a real PKCS #11 module as well
+C_CancelFunction;
+C_CloseAllSessions;
+C_CloseSession;
+C_CopyObject;
+C_CreateObject;
+C_Decrypt;
+C_DecryptDigestUpdate;
+C_DecryptFinal;
+C_DecryptInit;
+C_DecryptUpdate;
+C_DecryptVerifyUpdate;
+C_DeriveKey;
+C_DestroyObject;
+C_Digest;
+C_DigestEncryptUpdate;
+C_DigestFinal;
+C_DigestInit;
+C_DigestKey;
+C_DigestUpdate;
+C_Encrypt;
+C_EncryptFinal;
+C_EncryptInit;
+C_EncryptUpdate;
+C_Finalize;
+C_FindObjects;
+C_FindObjectsFinal;
+C_FindObjectsInit;
+C_GenerateKey;
+C_GenerateKeyPair;
+C_GenerateRandom;
+C_GetAttributeValue;
+C_GetFunctionStatus;
+C_GetInfo;
+C_GetMechanismInfo;
+C_GetMechanismList;
+C_GetObjectSize;
+C_GetOperationState;
+C_GetSessionInfo;
+C_GetSlotInfo;
+C_GetSlotList;
+C_GetTokenInfo;
+C_Initialize;
+C_InitPIN;
+C_InitToken;
+;+ local:
+;+ *;
+;+};
diff --git a/src/coolkey/coolkeypk11.rc b/src/coolkey/coolkeypk11.rc
new file mode 100644
index 0000000..1514109
--- /dev/null
+++ b/src/coolkey/coolkeypk11.rc
@@ -0,0 +1,89 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#define COOLKEY_VERSION "beta"
+#define COOLKEY_VMAJOR 0
+#define COOLKEY_VMINOR 9
+#define COOLKEY_VPATCH 0
+#define COOLKEY_BETA PR_TRUE
+
+#include <winver.h>
+
+#define MY_LIBNAME "coolkeypk11"
+#define MY_FILEDESCRIPTION "CoolKey PKCS #11 Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define COOLKEY_VMAJOR_STR STRINGIZE2(COOLKEY_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if COOLKEY_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#endif
+
+#define MY_INTERNAL_NAME MY_LIBNAME COOLKEY_VMAJOR_STR
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION COOLKEY_VMAJOR,COOLKEY_VMINOR,COOLKEY_VPATCH,0
+ PRODUCTVERSION COOLKEY_VMAJOR,COOLKEY_VMINOR,COOLKEY_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Mozilla Foundation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", COOLKEY_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 2005 Red Hat, Inc.\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "CoolKey\0"
+ VALUE "ProductVersion", COOLKEY_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/coolkey/dllmain.cpp b/src/coolkey/dllmain.cpp
new file mode 100644
index 0000000..dfef929
--- /dev/null
+++ b/src/coolkey/dllmain.cpp
@@ -0,0 +1,43 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifdef WIN32
+
+#include <windows.h>
+
+BOOL APIENTRY DllMain( HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+#endif
diff --git a/src/coolkey/locking.cpp b/src/coolkey/locking.cpp
new file mode 100644
index 0000000..a13e9e8
--- /dev/null
+++ b/src/coolkey/locking.cpp
@@ -0,0 +1,133 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include <assert.h>
+#include "mypkcs11.h"
+#include <string>
+#include "locking.h"
+#include "log.h"
+#include "PKCS11Exception.h"
+
+class BasicMutex : public Mutex {
+ public:
+ BasicMutex(CK_C_INITIALIZE_ARGS *initArgs);
+ virtual ~BasicMutex();
+
+ virtual void lock();
+ virtual void unlock();
+
+ private:
+ void *mutex;
+ CK_C_INITIALIZE_ARGS *initArgs;
+};
+
+class DummyMutex : public Mutex {
+ public:
+ virtual ~DummyMutex() { }
+ virtual void lock() { }
+ virtual void unlock() { }
+};
+
+BasicMutex::BasicMutex(CK_C_INITIALIZE_ARGS *initArgs_)
+ : initArgs(initArgs_)
+{
+ assert( initArgs->CreateMutex != NULL );
+ assert( initArgs->DestroyMutex != NULL );
+ assert( initArgs->LockMutex != NULL );
+ assert( initArgs->UnlockMutex != NULL );
+
+ CK_RV crv = initArgs->CreateMutex(&mutex);
+
+ if( crv != CKR_OK ) {
+ throw PKCS11Exception(crv, "CreateMutex");
+ }
+}
+
+BasicMutex::~BasicMutex()
+{
+ CK_RV crv = initArgs->DestroyMutex(mutex);
+
+ if( crv != CKR_OK ) {
+ throw PKCS11Exception(crv, "DestroyMutex");
+ }
+}
+
+void
+BasicMutex::lock()
+{
+ CK_RV crv = initArgs->LockMutex(mutex);
+
+ assert(crv != CKR_MUTEX_BAD);
+ if( crv != CKR_OK ) {
+ throw PKCS11Exception(crv, "LockMutex");
+ }
+}
+
+void
+BasicMutex::unlock()
+{
+ CK_RV crv = initArgs->UnlockMutex(mutex);
+
+ assert(crv != CKR_MUTEX_BAD);
+ assert(crv != CKR_MUTEX_NOT_LOCKED);
+ if( crv != CKR_OK ) {
+ throw PKCS11Exception(crv, "UnlockMutex");
+ }
+}
+
+MutexFactory::MutexFactory(const CK_C_INITIALIZE_ARGS* initArgs_)
+ : initArgs(NULL)
+{
+ if( initArgs_ != NULL ) {
+ if( initArgs_->CreateMutex == NULL || initArgs_->DestroyMutex == NULL
+ || initArgs_->LockMutex == NULL || initArgs_->UnlockMutex == NULL )
+ {
+ if( initArgs_->flags & CKF_OS_LOCKING_OK ) {
+ // application wants us to lock with OS primitives, which
+ // we can't do
+ throw PKCS11Exception(CKR_CANT_LOCK,
+ "Library cannot use OS locking primitives");
+ } else {
+ // Application is single threaded, so we won't do any
+ // locking. Leave initArgs == NULL.
+ }
+ } else {
+ // use the provided primitives for locking
+ initArgs = new CK_C_INITIALIZE_ARGS(*initArgs_);
+ }
+ }
+}
+
+MutexFactory::~MutexFactory()
+{
+ if( initArgs != NULL ) {
+ delete initArgs;
+ }
+}
+
+Mutex*
+MutexFactory::createMutex() const
+{
+ if( initArgs == NULL ) {
+ return new DummyMutex();
+ } else {
+ return new BasicMutex(initArgs);
+ }
+}
+
diff --git a/src/coolkey/locking.h b/src/coolkey/locking.h
new file mode 100644
index 0000000..d7f99cb
--- /dev/null
+++ b/src/coolkey/locking.h
@@ -0,0 +1,94 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_LOCKING_H
+#define COOLKEY_LOCKING_H
+
+#include "mypkcs11.h"
+#include <assert.h>
+
+class Mutex {
+ public:
+ virtual ~Mutex() { }
+ virtual void lock()=0;
+ virtual void unlock()=0;
+};
+
+class MutexFactory {
+
+ public:
+ MutexFactory(const CK_C_INITIALIZE_ARGS* initArgs);
+ ~MutexFactory();
+ Mutex* createMutex() const;
+
+ private:
+ CK_C_INITIALIZE_ARGS *initArgs;
+};
+
+class Guardable;
+
+class Guard {
+ public:
+ Guard(Mutex& mutex_) : mutex(&mutex_) { mutex->lock(); }
+ Guard(Mutex* mutex_) : mutex(mutex_) { mutex->lock(); }
+ Guard(Guardable& g);
+ Guard(Guardable* g);
+ ~Guard() { if( mutex ) mutex->unlock(); }
+
+ Guard(Guard& g) {
+ mutex = g.mutex;
+ g.mutex = 0;
+ }
+ Guard& operator=(Guard&g) {
+ mutex = g.mutex;
+ g.mutex = 0;
+ return *this;
+ }
+
+ void unlock() { if( mutex ) mutex->unlock(); mutex = 0; }
+ private:
+ Mutex* mutex;
+};
+
+class Guardable {
+ private:
+ friend class Guard;
+ Mutex *mutex;
+ public:
+ Guardable(const MutexFactory* mutexFactory) {
+ mutex = mutexFactory->createMutex();
+ }
+ ~Guardable() {
+ delete mutex;
+ }
+};
+
+inline
+Guard::Guard(Guardable& g) {
+ mutex = g.mutex;
+ mutex->lock();
+}
+
+inline
+Guard::Guard(Guardable* g) {
+ mutex = g->mutex;
+ mutex->lock();
+}
+
+#endif
diff --git a/src/coolkey/log.cpp b/src/coolkey/log.cpp
new file mode 100644
index 0000000..bfe312e
--- /dev/null
+++ b/src/coolkey/log.cpp
@@ -0,0 +1,83 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include <string>
+#include "mypkcs11.h"
+#include <assert.h>
+#include <stdio.h>
+#include "log.h"
+#include <cstdarg>
+#include "PKCS11Exception.h"
+
+
+FileLog::FileLog(const char *filename )
+{
+ file = fopen(filename, "at");
+ if( file == NULL ) {
+ throw PKCS11Exception(CKR_GENERAL_ERROR, "Failed to open logfile");
+ }
+}
+
+void
+FileLog::log(const char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+
+ vfprintf(file, msg, ap);
+ fflush(file);
+
+ va_end(ap);
+}
+
+#define ROW_LENGTH 16
+// dump the contents of an CKYBuffer, both in hex and 'ascii'.
+// change ROW_LENGTH above to change how many bytes are printed on a single
+// line
+void
+Log::dump(CKYBuffer *buf)
+{
+ CKYSize i;
+ CKYSize size = CKYBuffer_Size(buf);
+ char string[ROW_LENGTH+1];
+ char *bp = &string[0];
+ CKYByte c;
+
+ for (i=0; i < size; i++) {
+ if (i && ((i % (ROW_LENGTH-1)) == 0) ) {
+ *bp = 0;
+ log(" %s\n",string);
+ bp = &string[0];
+ }
+ c = CKYBuffer_GetChar(buf, i);
+ log("%02x ",c);
+ *bp++ = (c < ' ') ? '.' : ((c & 0x80) ? '*' : c);
+ }
+ *bp = 0;
+ for (i= (i % (ROW_LENGTH-1)); i && (i < ROW_LENGTH); i++) {
+ log(" ");
+ }
+ log(" %s\n",string);
+}
+
+FileLog::~FileLog()
+{
+ fclose(file);
+}
diff --git a/src/coolkey/log.h b/src/coolkey/log.h
new file mode 100644
index 0000000..8b24e5b
--- /dev/null
+++ b/src/coolkey/log.h
@@ -0,0 +1,56 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_LOG_H
+#define COOLKEY_LOG_H
+
+#include <string>
+#include <stdio.h>
+#include <cky_base.h>
+
+class Log {
+ public:
+ virtual void log(const char *msg, ...) = 0;
+ virtual void dump(CKYBuffer *buf);
+ virtual ~Log() { }
+};
+
+class DummyLog : public Log {
+ public:
+ DummyLog() { }
+ void log(const char *msg, ...) { }
+ void dump(CKYBuffer *buf) {}
+ ~DummyLog() { }
+};
+
+class FileLog : public Log {
+ private:
+ FILE *file;
+
+ // not allowed
+ FileLog(FileLog &) { }
+ FileLog& operator=(FileLog&) { return *this; }
+
+ public:
+ FileLog(const char *filename);
+ void log(const char *msg, ...);
+ virtual ~FileLog();
+};
+
+#endif
diff --git a/src/coolkey/machdep.cpp b/src/coolkey/machdep.cpp
new file mode 100644
index 0000000..8dfadc6
--- /dev/null
+++ b/src/coolkey/machdep.cpp
@@ -0,0 +1,424 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include "machdep.h"
+#include "mypkcs11.h"
+#include "PKCS11Exception.h"
+#ifdef _WIN32
+#include <windows.h>
+#include <memory.h>
+#else
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#endif
+
+#ifdef _WIN32
+//
+// Windows functions to grab a named shared memory segment of a specific size,
+// return whether or not it has been initialized, return it's size and address,
+// release it when done.
+//
+struct SHMemData {
+ char *addr;
+ HANDLE map;
+ int size;
+ SHMemData() : addr(0), map(0), size(0) {}
+};
+
+SHMem::SHMem(): shmemData(0) {}
+
+SHMem *
+SHMem::initSegment(const char *name, int size, bool &init)
+{
+ bool needInit;
+
+ init = 0;
+ SHMemData *shmemData = new SHMemData;
+ if (!shmemData ) {
+ // applications know we failed because they will get a NULL address
+ // from getSHMemAddr.
+ return NULL;
+ }
+
+ shmemData->map = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
+ PAGE_READWRITE, 0, size, name);
+ if (!shmemData->map) {
+ delete shmemData;
+ return NULL;
+ }
+ needInit = (GetLastError() != ERROR_ALREADY_EXISTS);
+
+ shmemData->addr =
+ (char *)MapViewOfFile(shmemData->map, FILE_MAP_WRITE, 0, 0, 0 );
+ if (!shmemData->addr) {
+ CloseHandle(shmemData->map);
+ delete shmemData;
+ return NULL;
+ }
+ shmemData->size = size;
+ init = needInit;
+ SHMem *memseg;
+
+ memseg = new SHMem();
+ if (memseg) {
+ memseg->shmemData = shmemData;
+ }
+ return memseg;
+}
+
+SHMem::~SHMem()
+{
+ if (!shmemData) {
+ return;
+ }
+ if (shmemData->addr) {
+ UnmapViewOfFile(shmemData->addr);
+ }
+ if (shmemData->map) {
+ CloseHandle(shmemData->map);
+ }
+ delete shmemData;
+}
+
+char *
+SHMem::getSHMemAddr()
+{
+ return shmemData ? shmemData->addr : NULL;
+}
+
+int
+SHMem::getSHMemSize()
+{
+ return shmemData ? shmemData->size : 0;
+}
+
+struct OSLockData {
+ CRITICAL_SECTION mutex;
+};
+
+OSLock::OSLock(bool exceptionAllowed)
+{
+ lockData = new OSLockData;
+ if (lockData) {
+ InitializeCriticalSection(&lockData->mutex);
+ }
+ if (exceptionAllowed && !lockData) {
+ throw PKCS11Exception(CKR_HOST_MEMORY, "lock allocation failed");
+ }
+}
+
+OSLock::~OSLock()
+{
+ if (lockData) {
+ DeleteCriticalSection(&lockData->mutex);
+ delete lockData;
+ }
+}
+
+bool OSLock::isValid()
+{
+ return (bool) (lockData != NULL);
+}
+
+void OSLock::getLock()
+{
+ if (lockData) {
+ EnterCriticalSection(&lockData->mutex);
+ }
+}
+
+void OSLock::releaseLock()
+{
+ if (lockData) {
+ LeaveCriticalSection(&lockData->mutex);
+ }
+}
+
+OSTime OSTimeNow(void)
+{
+ return GetTickCount();
+}
+
+void OSSleep(int time)
+{
+ Sleep(time);
+}
+
+#else
+//
+// MAC/Unix functions to grab a named shared memory segment of a specific size,
+// return whether or not it has been initialized, return it's size and address,
+// release it when done.
+//
+#ifdef O_EXLOCK
+#define FULL_CLEANUP
+#else
+/* if we can't lock on open, don't use locking for now */
+#define O_EXLOCK 0
+#endif
+
+#ifndef MAP_INHERIT
+#define MAP_INHERIT 0
+#endif
+
+#ifdef FULL_CLEANUP
+#define RESERVED_OFFSET 256
+#define MEMSEGPATH "/tmp/.pk11ipc"
+#else
+#define RESERVED_OFFSET 0
+#define MEMSEGPATH "/tmp/.pk11ipc1"
+#endif
+
+struct SHMemData {
+ char *path;
+ char *addr;
+ int fd;
+ int size;
+ SHMemData() : path(0), addr(0), fd(-1), size(0) {}
+ ~SHMemData() ;
+};
+
+SHMemData::~SHMemData() {
+ if (addr) {
+ /* memory adder implies the fd and path are valid as well */
+#ifdef FULL_CLEANUP
+ flock(fd,LOCK_EX);
+ unsigned long ref = --(*(unsigned long *)addr);
+ if (ref == 0) {
+ unlink(path);
+ }
+ flock(fd, LOCK_UN);
+#endif
+ munmap(addr,size+RESERVED_OFFSET);
+ }
+ if (fd > 0) {
+ close(fd);
+ }
+ if (path) {
+ delete [] path;
+ }
+}
+
+SHMem::SHMem(): shmemData(0) {}
+
+SHMem *
+SHMem::initSegment(const char *name, int size, bool &init)
+{
+ bool needInit = true;
+
+ init = 0;
+ SHMemData *shmemData = new SHMemData;
+ if (!shmemData ) {
+ // applications know we failed because they will get a NULL address
+ // from getSHMemAddr.
+ return NULL;
+ }
+ int ret = mkdir (MEMSEGPATH, 0755);
+ if ((ret == -1) && (errno != EEXIST)) {
+ delete shmemData;
+ return NULL;
+ }
+ shmemData->path = new char [sizeof(MEMSEGPATH)+strlen(name)+2];
+ if (shmemData->path == NULL) {
+ delete shmemData;
+ return NULL;
+ }
+ memcpy(shmemData->path,MEMSEGPATH, sizeof(MEMSEGPATH));
+ shmemData->path[sizeof(MEMSEGPATH)-1] = '/';
+ strcpy(&shmemData->path[sizeof(MEMSEGPATH)],name);
+ shmemData->fd = open(shmemData->path,
+ O_CREAT|O_RDWR|O_EXCL|O_APPEND|O_EXLOCK, 0700);
+ if (shmemData->fd < 0) {
+ needInit = false;
+ shmemData->fd = open(shmemData->path,O_RDWR|O_EXLOCK, 0700);
+ } else {
+ char *buf;
+ int len = size+RESERVED_OFFSET;
+
+ buf = (char *)calloc(1,len);
+ if (!buf) {
+ unlink(shmemData->path);
+#ifdef FULL_CLEANUP
+ flock(shmemData->fd, LOCK_UN);
+#endif
+ delete shmemData;
+ return NULL;
+ }
+ write(shmemData->fd,buf,len);
+ free(buf);
+ }
+ if (shmemData->fd < 0) {
+ delete shmemData;
+ return NULL;
+ }
+ shmemData->addr = (char *) mmap(0, size+RESERVED_OFFSET,
+ PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED|MAP_INHERIT,
+ shmemData->fd, 0);
+ if (shmemData->addr == NULL) {
+ if (needInit) {
+ unlink(shmemData->path);
+ }
+#ifdef FULL_CLEANUP
+ flock(shmemData->fd, LOCK_UN);
+#endif
+ delete shmemData;
+ return NULL;
+ }
+ shmemData->size = size;
+#ifdef FULL_CLEANUP
+ (*(unsigned long *)shmemData->addr)++;
+ flock(shmemData->fd, LOCK_UN);
+#endif
+ init = needInit;
+ SHMem *memseg;
+
+ memseg = new SHMem();
+ if (!memseg) {
+ delete shmemData;
+ return NULL;
+ }
+ memseg->shmemData = shmemData;
+ return memseg;
+}
+
+SHMem::~SHMem()
+{
+ if (!shmemData) {
+ return;
+ }
+ delete shmemData;
+}
+
+char *
+SHMem::getSHMemAddr()
+{
+ return shmemData ? shmemData->addr+RESERVED_OFFSET : NULL;
+}
+
+int
+SHMem::getSHMemSize()
+{
+ return shmemData ? shmemData->size : 0;
+}
+
+struct OSLockData {
+ pthread_mutex_t mutex;
+};
+
+static pthread_mutexattr_t OSLock_attr;
+static int OSLock_attr_init = 0;
+
+OSLock::OSLock(bool exceptionAllowed)
+{
+ int rc;
+
+ lockData = NULL;
+ if (!OSLock_attr_init) {
+ rc = pthread_mutexattr_init(&OSLock_attr);
+ if (rc < 0) {
+ if (exceptionAllowed) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR, "lock init failed");
+ } else {
+ return;
+ }
+ }
+ OSLock_attr_init = 1;
+ }
+ lockData = new OSLockData;
+ if (lockData) {
+ rc = pthread_mutex_init(&lockData->mutex, &OSLock_attr);
+ if (rc < 0) {
+ delete lockData;
+ lockData = NULL;
+ }
+ }
+ if (exceptionAllowed && !lockData) {
+ throw PKCS11Exception(CKR_HOST_MEMORY, "lock allocation failed");
+ }
+}
+
+OSLock::~OSLock()
+{
+ if (lockData) {
+ pthread_mutex_destroy(&lockData->mutex);
+ delete lockData;
+ }
+}
+
+bool OSLock::isValid()
+{
+ return (bool) (lockData != NULL);
+}
+
+void OSLock::getLock()
+{
+ if (lockData) {
+ pthread_mutex_lock(&lockData->mutex);
+ }
+}
+
+void OSLock::releaseLock()
+{
+ if (lockData) {
+ pthread_mutex_unlock(&lockData->mutex);
+ }
+}
+
+#ifdef USE_CLOCK
+OSTime OSTimeNow(void)
+{
+ OSTime ostime;
+ clock_t time;
+
+#if CLOCKS_PER_SEC < 1000
+ ostime = time * (1000/CLOCKS_PER_SEC);
+#else
+ ostime = time / (CLOCKS_PER_SEC/1000);
+#endif
+ return ostime;
+}
+
+#else
+OSTime OSTimeNow(void)
+{
+ OSTime ostime;
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ ostime = tv.tv_usec/1000 + tv.tv_sec*1000;
+
+ return ostime;
+}
+#endif
+
+void OSSleep(int time)
+{
+ usleep(time);
+}
+#endif /* _WINDOWS */
+
+
diff --git a/src/coolkey/machdep.h b/src/coolkey/machdep.h
new file mode 100644
index 0000000..0f702ad
--- /dev/null
+++ b/src/coolkey/machdep.h
@@ -0,0 +1,57 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_MACHDEP_H
+#define COOLKEY_MACHDEP_H
+/*
+ * abstract away os dependencies in shared memory system
+ */
+
+struct SHMemData;
+
+class SHMem {
+private:
+ SHMemData *shmemData;
+ SHMem();
+public:
+ ~SHMem();
+ char *getSHMemAddr();
+ int getSHMemSize();
+ static SHMem *initSegment(const char *name, int size, bool &init);
+};
+
+struct OSLockData;
+class OSLock {
+private:
+ OSLockData *lockData;
+public:
+ OSLock(bool exceptionAllowed = true);
+ ~OSLock();
+ bool isValid();
+ void getLock();
+ void releaseLock();
+};
+
+typedef unsigned long OSTime;
+OSTime OSTimeNow(void);
+
+void OSSleep(int time);
+
+#define USE_SHMEM
+#endif
diff --git a/src/coolkey/manifest.mn b/src/coolkey/manifest.mn
new file mode 100644
index 0000000..3f434be
--- /dev/null
+++ b/src/coolkey/manifest.mn
@@ -0,0 +1,46 @@
+# ***** BEGIN COPYRIGHT BLOCK *****
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation version
+# 2.1 of the License.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ***** END COPYRIGHT BLOCK *****
+
+CORE_DEPTH = ../..
+
+MODULE = coolkeypk11
+
+REQUIRES = ckyapplet zlib
+
+USE_STATIC_RTL=1
+
+BASE_LIBRARY_NAME = coolkeypk11
+LIBRARY_NAME = $(BASE_LIBRARY_NAME)
+MAPFILE = $(OBJDIR)/coolkeypk11.def
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \
+ -DPKCS11_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
+
+DEFINES += -DNSS_HIDE_NONSTANDARD_OBJECTS=1
+
+CPPSRCS = \
+ coolkey.cpp \
+ dllmain.cpp \
+ locking.cpp \
+ log.cpp \
+ machdep.cpp \
+ object.cpp \
+ PKCS11Exception.cpp \
+ slot.cpp \
+ $(NULL)
diff --git a/src/coolkey/mypkcs11.h b/src/coolkey/mypkcs11.h
new file mode 100644
index 0000000..33613ac
--- /dev/null
+++ b/src/coolkey/mypkcs11.h
@@ -0,0 +1,52 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_MYPKCS11_H
+#define COOLKEY_MYPKCS11_H
+
+#if defined(_WIN32)
+#define CK_PTR *
+#define CK_DECLARE_FUNCTION(rv,func) rv __declspec(dllexport) func
+#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (* func)
+#define CK_CALLBACK_FUNCTION(rv,func) rv (* func)
+#define CK_NULL_PTR 0
+#else
+#define CK_PTR *
+#define CK_DECLARE_FUNCTION(rv,func) rv func
+#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (* func)
+#define CK_CALLBACK_FUNCTION(rv,func) rv (* func)
+#define CK_NULL_PTR 0
+#endif
+
+#if defined(_WIN32)
+#pragma warning(disable:4103)
+#pragma pack(push, cryptoki, 1)
+#endif
+
+#include "pkcs11.h"
+
+#include "pkcs11n.h"
+
+#if defined (_WIN32)
+#pragma warning(disable:4103)
+#pragma pack(pop, cryptoki)
+#endif
+
+
+#endif
diff --git a/src/coolkey/object.cpp b/src/coolkey/object.cpp
new file mode 100644
index 0000000..d471c6e
--- /dev/null
+++ b/src/coolkey/object.cpp
@@ -0,0 +1,1065 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include "mypkcs11.h"
+#include "PKCS11Exception.h"
+#include "object.h"
+#include <algorithm>
+
+using std::find_if;
+
+
+bool AttributeMatch::operator()(const PKCS11Attribute& cmp)
+{
+ return (attr->type == cmp.getType()) &&
+ CKYBuffer_DataIsEqual(cmp.getValue(),
+ (const CKYByte *)attr->pValue, attr->ulValueLen);
+}
+
+class AttributeTypeMatch
+{
+ private:
+ CK_ATTRIBUTE_TYPE type;
+ public:
+ AttributeTypeMatch(CK_ATTRIBUTE_TYPE type_) : type(type_) { }
+ bool operator()(const PKCS11Attribute& cmp) {
+ return cmp.getType() == type;
+ }
+};
+
+PKCS11Object::PKCS11Object(unsigned long muscleObjID_,CK_OBJECT_HANDLE handle_)
+ : muscleObjID(muscleObjID_), handle(handle_), label(NULL), name(NULL)
+{
+ CKYBuffer_InitEmpty(&pubKey);
+}
+
+PKCS11Object::PKCS11Object(unsigned long muscleObjID_, const CKYBuffer *data,
+ CK_OBJECT_HANDLE handle_) : muscleObjID(muscleObjID_), handle(handle_),
+ label(NULL), name(NULL)
+{
+ CKYBuffer_InitEmpty(&pubKey);
+
+ CKYByte type = CKYBuffer_GetChar(data,0);
+ // verify object ID is what we think it is
+ if( CKYBuffer_GetLong(data,1) != muscleObjID ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "PKCS #11 actual object id does not match stated id");
+ }
+ if (type == 0) {
+ parseOldObject(data);
+ } else if (type == 1) {
+ parseNewObject(data);
+ }
+}
+
+void
+PKCS11Object::parseOldObject(const CKYBuffer *data)
+{
+ if( CKYBuffer_Size(data) < 7 ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid PKCS#11 object size %d", CKYBuffer_Size(data));
+ }
+
+ // get the amount of attribute data, make sure it makes sense
+ unsigned int attrDataLen = CKYBuffer_GetShort(data, 5);
+ if( CKYBuffer_Size(data) != attrDataLen + 7 ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "PKCS #11 actual attribute data length %d does not match"
+ " stated length %d", CKYBuffer_Size(data)-7, attrDataLen);
+ }
+
+ unsigned int idx = 7;
+ while( idx < CKYBuffer_Size(data) ) {
+ if( idx - CKYBuffer_Size(data) < 6 ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Error parsing attribute");
+ }
+ PKCS11Attribute attrib;
+ attrib.setType(CKYBuffer_GetLong(data, idx));
+ idx += 4;
+ unsigned int attrLen = CKYBuffer_GetShort(data, idx);
+ idx += 2;
+ if( attrLen > CKYBuffer_Size(data)
+ || (idx + attrLen > CKYBuffer_Size(data)) ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid attribute length %d\n", attrLen);
+ }
+ /* these two types are ints, read them back from
+ * the card in host order */
+ if ((attrib.getType() == CKA_CLASS) ||
+ (attrib.getType() == CKA_CERTIFICATE_TYPE) ||
+ (attrib.getType() == CKA_KEY_TYPE)) {
+ if (attrLen != sizeof (CK_ULONG)) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid attribute length %d\n", attrLen);
+ }
+ CK_ULONG value = makeLEUInt(data,idx);
+
+ attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
+ } else {
+ attrib.setValue(CKYBuffer_Data(data)+idx, attrLen);
+ }
+ idx += attrLen;
+ attributes.push_back(attrib);
+ }
+
+}
+
+//
+// masks which determine the valid flag bits for specific objects
+//
+// objects are : flags are:
+// 0 CKO_DATA PRIVATE, MODIFIABLE, TOKEN
+// 1 CKO_CERTIFICATE PRIVATE, MODIFIABLE, TOKEN
+// 2 CKO_PUBLIC_KEY PRIVATE, MODIFIABLE, TOKEN
+// DERIVE, LOCAL, ENCRYPT, WRAP
+// VERIFY, VERIFY_RECOVER
+// 3 CKO_PRIVATE_KEY PRIVATE, MODIFIABLE, TOKEN
+// DERIVE, LOCAL, DECRYPT, UNWRAP
+// SIGN, SIGN_RECOVER, SENSITIVE,
+// ALWAYS_SENSITIVE, EXTRACTABLE,
+// NEVER_EXTRACTABLE
+// 4 CKO_SECRET_KEY PRIVATE, MODIFIABLE, TOKEN
+// DERIVE, LOCAL, ENCRYPT, DECRYPT,
+// WRAP, UNWRAP, SIGN, VERIFY,
+// SENSITIVE, ALWAYS_SENSITIVE,
+// EXTRACTABLE, NEVER_EXTRACTABLE
+// 5-7 RESERVED NONE
+//
+const unsigned long boolMask[8] =
+{
+ 0x00000380, 0x00000380,
+ 0x000c5f80, 0x00f3af80,
+ 0x00f5ff80, 0x00000000,
+ 0x00000000, 0x00000000
+};
+
+//
+// map a mask bit position to CKA_ flag value.
+//
+const CK_ATTRIBUTE_TYPE boolType[32] =
+{
+ 0, 0, 0, 0,
+ 0, 0, 0, CKA_TOKEN,
+ CKA_PRIVATE, CKA_MODIFIABLE, CKA_DERIVE, CKA_LOCAL,
+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP,
+ CKA_SIGN, CKA_SIGN_RECOVER, CKA_VERIFY, CKA_VERIFY_RECOVER,
+ CKA_SENSITIVE, CKA_ALWAYS_SENSITIVE, CKA_EXTRACTABLE, CKA_NEVER_EXTRACTABLE,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+
+void
+PKCS11Object::expandAttributes(unsigned long fixedAttrs)
+{
+ CKYByte cka_id = (CKYByte) (fixedAttrs & 0xf);
+ CK_OBJECT_CLASS objectType = (fixedAttrs >> 4) & 0x7;
+ unsigned long mask = boolMask[objectType];
+ unsigned long i;
+
+ if (!attributeExists(CKA_ID)) {
+ PKCS11Attribute attrib;
+ attrib.setType(CKA_ID);
+ attrib.setValue(&cka_id, 1);
+ attributes.push_back(attrib);
+ }
+ /* unpack the class */
+ if (!attributeExists(CKA_CLASS)) {
+ PKCS11Attribute attrib;
+ attrib.setType(CKA_CLASS);
+ attrib.setValue((CKYByte *)&objectType, 4);
+ attributes.push_back(attrib);
+ }
+
+ /* unpack the boolean flags. Note, the default mask is based on
+ * the class specified in fixedAttrs, not on the real class */
+ for (i=1; i < sizeof(unsigned long)*8; i++) {
+ unsigned long iMask = 1<< i;
+ if ((mask & iMask) == 0) {
+ continue;
+ }
+ if (attributeExists(boolType[i])) {
+ continue;
+ }
+ PKCS11Attribute attrib;
+ CKYByte bVal = (fixedAttrs & iMask) != 0;
+ attrib.setType(boolType[i]);
+ attrib.setValue(&bVal, 1);
+ attributes.push_back(attrib);
+ }
+}
+
+void
+PKCS11Object::parseNewObject(const CKYBuffer *data)
+{
+ if( CKYBuffer_Size(data) < 11 ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid PKCS#11 object size %d", CKYBuffer_Size(data));
+ }
+ unsigned short attributeCount = CKYBuffer_GetShort(data, 9);
+ unsigned long fixedAttrs = CKYBuffer_GetLong(data, 5);
+ unsigned long offset = 11;
+ CKYSize size = CKYBuffer_Size(data);
+ int j;
+
+ // load up the explicit attributes first
+ for (j=0, offset = 11; j < attributeCount && offset < size; j++) {
+ PKCS11Attribute attrib;
+ CKYByte attributeDataType = CKYBuffer_GetChar(data, offset+4);
+ unsigned int attrLen = 0;
+ attrib.setType(CKYBuffer_GetLong(data, offset));
+ offset += 5;
+
+ switch(attributeDataType) {
+ case DATATYPE_STRING:
+ attrLen = CKYBuffer_GetShort(data, offset);
+ offset += 2;
+ if (attrLen > CKYBuffer_Size(data)
+ || (offset + attrLen > CKYBuffer_Size(data)) ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid attribute length %d\n", attrLen);
+ }
+ attrib.setValue(CKYBuffer_Data(data)+offset, attrLen);
+ break;
+ case DATATYPE_BOOL_FALSE:
+ case DATATYPE_BOOL_TRUE:
+ {
+ CKYByte bval = attributeDataType & 1;
+ attrib.setValue(&bval, 1);
+ }
+ break;
+ case DATATYPE_INTEGER:
+ {
+ CK_ULONG value = CKYBuffer_GetLong(data, offset);
+ attrLen = 4;
+ attrib.setValue((const CKYByte *)&value, sizeof(CK_ULONG));
+ }
+ break;
+ default:
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid attribute Data Type %d\n", attributeDataType);
+ }
+ offset += attrLen;
+ attributes.push_back(attrib);
+ }
+ expandAttributes(fixedAttrs);
+}
+
+#if defined( NSS_HIDE_NONSTANDARD_OBJECTS )
+
+static const CK_OBJECT_CLASS rdr_class = CKO_MOZ_READER;
+static const CK_BBOOL rdr_true = TRUE;
+static const CK_ATTRIBUTE rdr_template[] = {
+ {CKA_CLASS, (void *)&rdr_class, sizeof rdr_class },
+ {CKA_MOZ_IS_COOL_KEY, (void *)&rdr_true, sizeof rdr_true }
+};
+#endif
+
+bool
+PKCS11Object::matchesTemplate(const CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+ const
+{
+ unsigned int i;
+
+ typedef std::list<PKCS11Attribute>::const_iterator iterator;
+
+#if defined( NSS_HIDE_NONSTANDARD_OBJECTS )
+ if (!ulCount) {
+ // exclude MOZ reader objects from searches for all objects.
+ // To find an MOZ reader object, one must search for it by
+ // some matching attribute, such as class.
+ iterator iter = find_if(attributes.begin(), attributes.end(),
+ AttributeMatch(&rdr_template[0]));
+ return (iter == attributes.end()) ? true : false;
+ }
+#endif
+
+ // loop over all attributes in the template
+ for( i = 0; i < ulCount; ++i ) {
+ // lookup this attribute in our object
+ iterator iter = find_if(attributes.begin(), attributes.end(),
+ AttributeMatch(pTemplate+i));
+ if( iter == attributes.end() ) {
+ // attribute not found. Template does not match.
+ return false;
+ }
+ }
+
+ // all attributes found. template matches.
+ return true;
+}
+
+bool
+PKCS11Object::attributeExists(CK_ATTRIBUTE_TYPE type) const
+{
+ // find matching attribute
+ AttributeConstIter iter = find_if(attributes.begin(), attributes.end(),
+ AttributeTypeMatch(type));
+ return (bool)(iter != attributes.end());
+}
+
+const CKYBuffer *
+PKCS11Object::getAttribute(CK_ATTRIBUTE_TYPE type) const
+{
+ AttributeConstIter iter = find_if(attributes.begin(), attributes.end(),
+ AttributeTypeMatch(type));
+
+ if( iter == attributes.end() ) {
+ return NULL;
+ }
+ return iter->getValue();
+}
+
+void
+PKCS11Object::getAttributeValue(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ Log* log) const
+{
+ // keep track if these error conditions are true for any attribute
+ bool attrTypeInvalid = false;
+ bool bufferTooSmall = false;
+
+ unsigned int i;
+ // loop over all attributes in the template
+ for( i = 0; i < ulCount; ++i ) {
+
+ // find matching attribute
+ AttributeConstIter iter = find_if(attributes.begin(), attributes.end(),
+ AttributeTypeMatch(pTemplate[i].type));
+
+ if( iter == attributes.end() ) {
+ // no attribute of this type
+ attrTypeInvalid = true;
+ log->log("GetAttributeValue: invalid type 0x%08x on object %x\n",
+ pTemplate[i].type, muscleObjID);
+ pTemplate[i].ulValueLen = (CK_ULONG)-1;
+ continue;
+ }
+
+ if( pTemplate[i].pValue == NULL ) {
+ // Buffer not supplied for this attribute. We just set the length.
+ pTemplate[i].ulValueLen = CKYBuffer_Size(iter->getValue());
+ continue;
+ }
+
+ if( pTemplate[i].ulValueLen < CKYBuffer_Size(iter->getValue()) ) {
+ // supplied buffer is not large enough.
+ pTemplate[i].ulValueLen = (CK_ULONG)-1;
+ bufferTooSmall = true;
+ continue;
+ }
+
+ // the buffer is large enough. return the value and set the exact
+ // length.
+ memcpy(pTemplate[i].pValue, CKYBuffer_Data(iter->getValue()),
+ CKYBuffer_Size(iter->getValue()));
+ pTemplate[i].ulValueLen = CKYBuffer_Size(iter->getValue());
+ }
+
+ if( attrTypeInvalid ) {
+ // At least one of the attribute types was invalid.
+ // Return CKR_ATTRIBUTE_TYPE_INVALID. This is not really an
+ // error condition.
+ throw PKCS11Exception(CKR_ATTRIBUTE_TYPE_INVALID);
+ }
+
+ if( bufferTooSmall ) {
+ // At least one of the supplied buffers was too small.
+ // Return CKR_BUFFER_TOO_SMALL. This is not really an error
+ // condition.
+ throw PKCS11Exception(CKR_BUFFER_TOO_SMALL);
+ }
+
+ // no problems, just return CKR_OK
+}
+
+const char *
+PKCS11Object::getLabel()
+{
+ // clean up old one
+ if (label) {
+ delete label;
+ label = NULL;
+ }
+ // find matching attribute
+ AttributeConstIter iter = find_if(attributes.begin(), attributes.end(),
+ AttributeTypeMatch(CKA_LABEL));
+
+ // none found
+ if( iter == attributes.end() ) {
+ return "";
+ }
+
+ int size = CKYBuffer_Size(iter->getValue());
+
+ label = new char [ size + 1 ];
+ if (!label) {
+ return "";
+ }
+ memcpy(label, CKYBuffer_Data(iter->getValue()), size);
+ label[size] = 0;
+
+ return label;
+}
+
+CK_OBJECT_CLASS
+PKCS11Object::getClass()
+{
+ CK_OBJECT_CLASS objClass;
+ // find matching attribute
+ AttributeConstIter iter = find_if(attributes.begin(), attributes.end(),
+ AttributeTypeMatch(CKA_CLASS));
+
+ // none found */
+ if( iter == attributes.end() ) {
+ return (CK_OBJECT_CLASS) -1;
+ }
+
+ int size = CKYBuffer_Size(iter->getValue());
+
+ if (size != sizeof(objClass)) {
+ return (CK_OBJECT_CLASS) -1;
+ }
+
+ memcpy(&objClass, CKYBuffer_Data(iter->getValue()), size);
+
+ return objClass;
+}
+
+void
+PKCS11Object::setAttribute(CK_ATTRIBUTE_TYPE type, const CKYBuffer *value)
+{
+ AttributeIter iter;
+
+ iter = find_if(attributes.begin(), attributes.end(),
+ AttributeTypeMatch(type));
+ if( iter != attributes.end() ) {
+ iter->setValue( CKYBuffer_Data(value), CKYBuffer_Size(value));
+ } else {
+ attributes.push_back(PKCS11Attribute(type, value));
+ }
+}
+
+void
+PKCS11Object::setAttribute(CK_ATTRIBUTE_TYPE type, const char *string)
+{
+ CKYBuffer buf;
+ CKYBuffer_InitFromData(&buf, (const CKYByte *)string, strlen(string));
+
+ setAttribute(type, &buf);
+ CKYBuffer_FreeData(&buf);
+}
+
+void
+PKCS11Object::setAttributeBool(CK_ATTRIBUTE_TYPE type, CK_BBOOL value)
+{
+ CKYBuffer buf;
+ CKYBuffer_InitFromData(&buf, &value, sizeof(CK_BBOOL));
+
+ setAttribute(type,&buf);
+ CKYBuffer_FreeData(&buf);
+}
+
+void
+PKCS11Object::setAttributeULong(CK_ATTRIBUTE_TYPE type, CK_ULONG value)
+{
+ CKYBuffer buf;
+ CKYBuffer_InitFromData(&buf, (const CKYByte *)&value, sizeof(CK_ULONG));
+
+ setAttribute(type, &buf);
+ CKYBuffer_FreeData(&buf);
+}
+
+typedef struct {
+ const CKYByte*data;
+ unsigned int len;
+} CCItem;
+
+typedef enum {
+ SECSuccess=0,
+ SECFailure=1
+} SECStatus;
+
+static const CKYByte*
+dataStart(const CKYByte *buf, unsigned int length,
+ unsigned int *data_length, bool includeTag) {
+ unsigned char tag;
+ unsigned int used_length= 0;
+
+ tag = buf[used_length++];
+
+ /* blow out when we come to the end */
+ if (tag == 0) {
+ return NULL;
+ }
+
+ *data_length = buf[used_length++];
+
+ if (*data_length&0x80) {
+ int len_count = *data_length & 0x7f;
+
+ *data_length = 0;
+
+ while (len_count-- > 0) {
+ *data_length = (*data_length << 8) | buf[used_length++];
+ }
+ }
+
+ if (*data_length > (length-used_length) ) {
+ *data_length = length-used_length;
+ return NULL;
+ }
+ if (includeTag) *data_length += used_length;
+
+ return (buf + (includeTag ? 0 : used_length));
+}
+
+static const CKYByte *
+unwrapBitString(const CKYByte *buf, unsigned int len, unsigned int *retLen)
+{
+ /* for RSA, bit string always has byte number of bits */
+ if (buf[0] != 0) {
+ return NULL;
+ }
+ if (len < 1) {
+ return NULL;
+ }
+ *retLen = len -1;
+ return buf+1;
+}
+
+static SECStatus
+GetKeyFieldItems(const CKYByte *spki_data,unsigned int spki_length,
+ CCItem *modulus, CCItem *exponent)
+{
+ const CKYByte *buf = spki_data;
+ unsigned int buf_length = spki_length;
+ const CKYByte*dummy;
+ unsigned int dummylen;
+
+ /* skip past the algorithm id */
+ dummy = dataStart(buf,buf_length,&dummylen,false);
+ if (dummy == NULL) return SECFailure;
+ buf_length -= (dummy-buf) + dummylen;
+ buf = dummy + dummylen;
+
+ /* unwrap the public key info */
+ buf = dataStart(buf,buf_length,&buf_length,false);
+ if (buf == NULL) return SECFailure;
+ buf = unwrapBitString(buf,buf_length,&buf_length);
+ if (buf == NULL) return SECFailure;
+ buf = dataStart(buf,buf_length,&buf_length, false);
+ if (buf == NULL) return SECFailure;
+
+ /* read the modulus */
+ modulus->data = dataStart(buf,buf_length,&modulus->len,false);
+ if (modulus->data == NULL) return SECFailure;
+ buf_length -= (modulus->data-buf) + modulus->len;
+ buf = modulus->data + modulus->len;
+
+ /* read the exponent */
+ exponent->data = dataStart(buf,buf_length,&exponent->len,false);
+ if (exponent->data == NULL) return SECFailure;
+ buf_length -= (exponent->data-buf) + exponent->len;
+ buf = exponent->data + exponent->len;
+
+ return SECSuccess;
+}
+
+static void
+GetKeyFields(const CKYBuffer *spki, CKYBuffer *modulus, CKYBuffer *exponent)
+{
+ SECStatus rv;
+ CCItem modulusItem, exponentItem;
+
+ rv = GetKeyFieldItems(CKYBuffer_Data(spki), CKYBuffer_Size(spki),
+ &modulusItem, &exponentItem);
+
+ if( rv != SECSuccess ) {
+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
+ "Failed to decode certificate Subject Public Key Info");
+ }
+
+ CKYBuffer_Replace(modulus, 0, modulusItem.data, modulusItem.len);
+ CKYBuffer_Replace(exponent, 0, exponentItem.data, exponentItem.len);
+}
+
+Key::Key(unsigned long muscleObjID, const CKYBuffer *data,
+ CK_OBJECT_HANDLE handle) : PKCS11Object(muscleObjID, data, handle)
+{
+ // infer key attributes
+ CK_OBJECT_CLASS objClass = getClass();
+ CKYBuffer empty;
+ CKYBuffer_InitEmpty(&empty);
+
+ if ((objClass == CKO_PUBLIC_KEY) || (objClass == CKO_PRIVATE_KEY)) {
+ /* only CKK_RSA is supported */
+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
+ } else if (objClass == CKO_SECRET_KEY) {
+ if (!attributeExists(CKA_LABEL)) {
+ setAttribute(CKA_LABEL, &empty);
+ }
+ if (!attributeExists(CKA_KEY_TYPE)) {
+ /* default to DES3 */
+ setAttributeULong(CKA_KEY_TYPE, CKK_DES3);
+ }
+ }
+ if (!attributeExists(CKA_START_DATE)) {
+ setAttribute(CKA_START_DATE, &empty);
+ }
+ if (!attributeExists(CKA_END_DATE)) {
+ setAttribute(CKA_END_DATE, &empty);
+ }
+}
+
+void
+Key::completeKey(const PKCS11Object &cert)
+{
+ // infer key attributes from cert
+ bool modulusExists, exponentExists;
+ CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
+ CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
+
+ if (!attributeExists(CKA_LABEL)) {
+ setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
+ }
+ try {
+ modulusExists = attributeExists(CKA_MODULUS);
+ exponentExists = attributeExists(CKA_PUBLIC_EXPONENT);
+ if (!modulusExists || !exponentExists) {
+ const CKYBuffer *key = cert.getPubKey();
+ GetKeyFields(key, &modulus, &exponent);
+ if (!modulusExists) {
+ setAttribute(CKA_MODULUS, &modulus);
+ }
+ if (!exponentExists) {
+ setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
+ }
+ }
+ } catch (PKCS11Exception &e) {
+ CKYBuffer_FreeData(&modulus);
+ CKYBuffer_FreeData(&exponent);
+ throw e;
+ }
+ CKYBuffer_FreeData(&modulus);
+ CKYBuffer_FreeData(&exponent);
+}
+
+static SECStatus
+GetCertFieldItems(const CKYByte *dercert,unsigned int cert_length,
+ CCItem *issuer, CCItem *serial, CCItem *derSN, CCItem *subject,
+ CCItem *valid, CCItem *subjkey)
+{
+ const CKYByte *buf;
+ unsigned int buf_length;
+ const CKYByte*dummy;
+ unsigned int dummylen;
+
+ /* get past the signature wrap */
+ buf = dataStart(dercert,cert_length,&buf_length, false);
+ if (buf == NULL) return SECFailure;
+
+ /* get into the raw cert data */
+ buf = dataStart(buf,buf_length,&buf_length,false);
+ if (buf == NULL) return SECFailure;
+
+ /* skip past any optional version number */
+ if ((buf[0] & 0xa0) == 0xa0) {
+ dummy = dataStart(buf,buf_length,&dummylen,false);
+ if (dummy == NULL) return SECFailure;
+ buf_length -= (dummy-buf) + dummylen;
+ buf = dummy + dummylen;
+ }
+
+ /* serial number */
+ if (derSN) {
+ derSN->data=dataStart(buf,buf_length,&derSN->len,true);
+ }
+ serial->data = dataStart(buf,buf_length,&serial->len,false);
+ if (serial->data == NULL) return SECFailure;
+ buf_length -= (serial->data-buf) + serial->len;
+ buf = serial->data + serial->len;
+
+ /* skip the OID */
+ dummy = dataStart(buf,buf_length,&dummylen,false);
+ if (dummy == NULL) return SECFailure;
+ buf_length -= (dummy-buf) + dummylen;
+ buf = dummy + dummylen;
+
+ /* issuer */
+ issuer->data = dataStart(buf,buf_length,&issuer->len,true);
+ if (issuer->data == NULL) return SECFailure;
+ buf_length -= (issuer->data-buf) + issuer->len;
+ buf = issuer->data + issuer->len;
+
+ /* validity */
+ valid->data = dataStart(buf,buf_length,&valid->len,false);
+ if (valid->data == NULL) return SECFailure;
+ buf_length -= (valid->data-buf) + valid->len;
+ buf = valid->data + valid->len;
+
+ /*subject */
+ subject->data=dataStart(buf,buf_length,&subject->len,true);
+ if (subject->data == NULL) return SECFailure;
+ buf_length -= (subject->data-buf) + subject->len;
+ buf = subject->data + subject->len;
+
+ /* subject key info */
+ subjkey->data=dataStart(buf,buf_length,&subjkey->len,false);
+ if (subjkey->data == NULL) return SECFailure;
+ buf_length -= (subjkey->data-buf) + subjkey->len;
+ buf = subjkey->data + subjkey->len;
+ return SECSuccess;
+}
+
+static void
+GetCertFields(const CKYBuffer *derCert, CKYBuffer *derSerial,
+ CKYBuffer *derSubject, CKYBuffer *derIssuer, CKYBuffer *subjectKey)
+{
+ SECStatus rv;
+ CCItem issuerItem, serialItem, derSerialItem, subjectItem,
+ validityItem, subjectKeyItem;
+
+ rv = GetCertFieldItems(CKYBuffer_Data(derCert), CKYBuffer_Size(derCert),
+ &issuerItem, &serialItem, &derSerialItem, &subjectItem, &validityItem,
+ &subjectKeyItem);
+
+ if( rv != SECSuccess ) {
+ throw PKCS11Exception(CKR_FUNCTION_FAILED,
+ "Failed to decode DER certificate");
+ }
+
+ CKYBuffer_Replace(derSerial, 0, derSerialItem.data, derSerialItem.len);
+ CKYBuffer_Replace(derIssuer, 0, issuerItem.data, issuerItem.len);
+ CKYBuffer_Replace(derSubject, 0, subjectItem.data, subjectItem.len);
+ CKYBuffer_Replace(subjectKey, 0, subjectKeyItem.data, subjectKeyItem.len);
+}
+
+Cert::Cert(unsigned long muscleObjID, const CKYBuffer *data,
+ CK_OBJECT_HANDLE handle, const CKYBuffer *derCert)
+ : PKCS11Object(muscleObjID, data, handle)
+{
+ CKYBuffer derSerial; CKYBuffer_InitEmpty(&derSerial);
+ CKYBuffer derSubject; CKYBuffer_InitEmpty(&derSubject);
+ CKYBuffer derIssuer; CKYBuffer_InitEmpty(&derIssuer);
+ CKYBuffer certType;
+ CK_ULONG certTypeValue = CKC_X_509;
+
+ CKYBuffer_InitFromData(&certType, (CKYByte *)&certTypeValue,
+ sizeof(certTypeValue));
+ CKYBuffer_Resize(&pubKey,0);
+
+ try {
+ setAttribute(CKA_CERTIFICATE_TYPE, &certType);
+
+ if (!attributeExists(CKA_VALUE)) {
+ if (derCert) {
+ setAttribute(CKA_VALUE, derCert);
+ } else {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Missing certificate data from token");
+ }
+ }
+
+ if (!derCert) {
+ derCert = getAttribute(CKA_VALUE);
+ if (!derCert) {
+ // paranoia, should never happen since we verify the
+ // attribute exists above
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Missing certificate data from token");
+ }
+ }
+
+ // infer cert attributes
+
+ GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
+
+ if (!attributeExists(CKA_SERIAL_NUMBER)) {
+ setAttribute(CKA_SERIAL_NUMBER, &derSerial);
+ }
+ if (!attributeExists(CKA_SUBJECT)) {
+ setAttribute(CKA_SUBJECT, &derSubject);
+ }
+ if (!attributeExists(CKA_ISSUER)) {
+ setAttribute(CKA_ISSUER, &derIssuer);
+ }
+ } catch (PKCS11Exception &e) {
+ CKYBuffer_FreeData(&certType);
+ CKYBuffer_FreeData(&derSerial);
+ CKYBuffer_FreeData(&derSubject);
+ CKYBuffer_FreeData(&derIssuer);
+ throw e;
+ }
+ CKYBuffer_FreeData(&certType);
+ CKYBuffer_FreeData(&derSerial);
+ CKYBuffer_FreeData(&derSubject);
+ CKYBuffer_FreeData(&derIssuer);
+}
+
+Reader::Reader(unsigned long muscleObjID, CK_OBJECT_HANDLE handle,
+ const char *reader, const CKYBuffer *cardATR, bool isCoolkey) :
+ PKCS11Object(muscleObjID, handle)
+{
+ setAttributeULong(CKA_CLASS, CKO_MOZ_READER);
+ setAttribute(CKA_LABEL, reader);
+ setAttributeBool(CKA_TOKEN, TRUE);
+ setAttributeBool(CKA_PRIVATE, FALSE);
+ setAttributeBool(CKA_MODIFIABLE, FALSE);
+ setAttributeBool(CKA_MOZ_IS_COOL_KEY, isCoolkey ? TRUE : FALSE);
+ setAttribute(CKA_MOZ_ATR, cardATR);
+}
+
+CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert) :
+ PKCS11Object( ((int)'k') << 24 | ((int)instance+'0') << 16,
+ instance | 0x400)
+{
+ CKYBuffer id;
+ CKYBuffer empty;
+ CK_BBOOL decrypt = FALSE;
+
+ /* So we know what the key is supposed to be used for based on
+ * the instance */
+ if (instance == 2) {
+ decrypt = TRUE;
+ }
+
+ CKYBuffer_InitEmpty(&empty);
+ setAttributeULong(CKA_CLASS, CKO_PRIVATE_KEY);
+ setAttributeBool(CKA_TOKEN, TRUE);
+ setAttributeBool(CKA_PRIVATE, FALSE);
+ setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
+ setAttributeBool(CKA_MODIFIABLE, FALSE);
+ CKYBuffer_InitFromLen(&id, 1);
+ CKYBuffer_SetChar(&id, 1, instance+1);
+ setAttribute(CKA_ID, &id);
+ CKYBuffer_FreeData(&id);
+ setAttribute(CKA_START_DATE, &empty);
+ setAttribute(CKA_END_DATE, &empty);
+ setAttributeBool(CKA_DERIVE, FALSE);
+ setAttributeBool(CKA_LOCAL, TRUE);
+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
+
+ setAttributeBool(CKA_DECRYPT, decrypt);
+ setAttributeBool(CKA_SIGN, !decrypt);
+ setAttributeBool(CKA_SIGN_RECOVER, !decrypt);
+ setAttributeBool(CKA_UNWRAP, FALSE);
+ setAttributeBool(CKA_SENSITIVE, TRUE);
+ setAttributeBool(CKA_EXTRACTABLE, FALSE);
+
+ CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
+ CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
+
+ try {
+ const CKYBuffer *key = cert.getPubKey();
+ GetKeyFields(key, &modulus, &exponent);
+ setAttribute(CKA_MODULUS, &modulus);
+ setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
+ } catch (PKCS11Exception &e) {
+ CKYBuffer_FreeData(&modulus);
+ CKYBuffer_FreeData(&exponent);
+ throw e;
+ }
+ CKYBuffer_FreeData(&modulus);
+ CKYBuffer_FreeData(&exponent);
+}
+
+CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert) :
+ PKCS11Object( ((int)'k') << 24 | ((int)(instance+'5')) << 16,
+ instance | 0x500)
+{
+ CKYBuffer id;
+ CKYBuffer empty;
+ CK_BBOOL encrypt = FALSE;
+
+ /* So we know what the key is supposed to be used for based on
+ * the instance */
+ if (instance == 2) {
+ encrypt = TRUE;
+ }
+
+ CKYBuffer_InitEmpty(&empty);
+ setAttributeULong(CKA_CLASS, CKO_PUBLIC_KEY);
+ setAttributeBool(CKA_TOKEN, TRUE);
+ setAttributeBool(CKA_PRIVATE, FALSE);
+ setAttribute(CKA_LABEL, cert.getAttribute(CKA_LABEL));
+ setAttributeBool(CKA_MODIFIABLE, FALSE);
+ CKYBuffer_InitFromLen(&id, 1);
+ CKYBuffer_SetChar(&id, 1, instance+1);
+ setAttribute(CKA_ID, &id);
+ CKYBuffer_FreeData(&id);
+ setAttribute(CKA_START_DATE, &empty);
+ setAttribute(CKA_END_DATE, &empty);
+ setAttributeBool(CKA_DERIVE, FALSE);
+ setAttributeBool(CKA_LOCAL, TRUE);
+ setAttributeULong(CKA_KEY_TYPE, CKK_RSA);
+
+ setAttributeBool(CKA_ENCRYPT, encrypt);
+ setAttributeBool(CKA_VERIFY, !encrypt);
+ setAttributeBool(CKA_VERIFY_RECOVER, !encrypt);
+ setAttributeBool(CKA_WRAP, FALSE);
+
+ CKYBuffer modulus; CKYBuffer_InitEmpty(&modulus);
+ CKYBuffer exponent; CKYBuffer_InitEmpty(&exponent);
+
+ try {
+ const CKYBuffer *key = cert.getPubKey();
+ GetKeyFields(key, &modulus, &exponent);
+ setAttribute(CKA_MODULUS, &modulus);
+ setAttribute(CKA_PUBLIC_EXPONENT, &exponent);
+ } catch (PKCS11Exception &e) {
+ CKYBuffer_FreeData(&modulus);
+ CKYBuffer_FreeData(&exponent);
+ throw e;
+ }
+ CKYBuffer_FreeData(&modulus);
+ CKYBuffer_FreeData(&exponent);
+}
+
+static const char *CAC_Label[] = {
+ "CAC ID Certificate",
+ "CAC Email Signature Certificate",
+ "CAC Email Encryption Certificate",
+};
+
+static const unsigned char CN_DATA[] = { 0x55, 0x4, 0x3 };
+const unsigned int CN_LENGTH = sizeof(CN_DATA);
+
+static SECStatus
+GetCN(const CKYByte *dn, unsigned int dn_length, CCItem *cn)
+{
+ const CKYByte *buf;
+ unsigned int buf_length;
+
+ /* unwrap the sequence */
+ buf = dataStart(dn,dn_length,&buf_length, false);
+ if (buf == NULL) return SECFailure;
+
+ while (buf_length) {
+ const CKYByte *name;
+ unsigned int name_length;
+ const CKYByte *oid;
+ unsigned int oid_length;
+
+ /* unwrap the set */
+ name = dataStart(buf, buf_length, &name_length, false);
+
+ /* advance to next set */
+ buf_length -= (name-buf) + name_length;
+ buf = name + name_length;
+
+ /* unwrap the Sequence */
+ name = dataStart(name, name_length, &name_length, false);
+
+ /* unwrap the oid */
+ oid = dataStart(name, name_length, &oid_length, false);
+
+ /* test the oid */
+ if (oid_length != CN_LENGTH) {
+ continue;
+ }
+ if (memcmp(oid, CN_DATA, CN_LENGTH) != 0) {
+ continue;
+ }
+
+ /* advance to CN */
+ name_length -= (oid-name) + oid_length;
+ name = oid + oid_length;
+
+ /* unwrap the CN */
+ cn->data = dataStart(name, name_length, &cn->len, false);
+ return SECSuccess;
+ }
+ return SECFailure;
+}
+
+static char *
+GetUserName(const CKYBuffer *dn)
+{
+ SECStatus rv;
+ CCItem cn;
+ char *string;
+
+ rv = GetCN(CKYBuffer_Data(dn), CKYBuffer_Size(dn) , &cn);
+
+ if( rv != SECSuccess ) {
+ return NULL;
+ }
+ string = new char [ cn.len + 1 ];
+ if (string == NULL) {
+ return NULL;
+ }
+ memcpy(string, cn.data, cn.len);
+ string[cn.len] = 0;
+ return string;
+}
+
+CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert) :
+ PKCS11Object( ((int)'c') << 24 | ((int)instance+'0') << 16,
+ instance | 0x600)
+{
+ CKYBuffer id;
+ CKYBuffer empty;
+ CK_BBOOL decrypt = FALSE;
+
+ /* So we know what the key is supposed to be used for based on
+ * the instance */
+ if (instance == 2) {
+ decrypt = TRUE;
+ }
+
+ CKYBuffer_InitEmpty(&empty);
+ setAttributeULong(CKA_CLASS, CKO_CERTIFICATE);
+ setAttributeBool(CKA_TOKEN, TRUE);
+ setAttributeBool(CKA_PRIVATE, FALSE);
+ setAttributeBool(CKA_MODIFIABLE, FALSE);
+ CKYBuffer_InitFromLen(&id, 1);
+ CKYBuffer_SetChar(&id, 1, instance+1);
+ setAttribute(CKA_ID, &id);
+ CKYBuffer_FreeData(&id);
+ setAttributeULong(CKA_CERTIFICATE_TYPE, CKC_X_509);
+ setAttribute(CKA_LABEL, CAC_Label[instance]);
+
+ CKYBuffer derSerial; CKYBuffer_InitEmpty(&derSerial);
+ CKYBuffer derSubject; CKYBuffer_InitEmpty(&derSubject);
+ CKYBuffer derIssuer; CKYBuffer_InitEmpty(&derIssuer);
+
+ CKYBuffer_Resize(&pubKey,0);
+
+ try {
+ setAttribute(CKA_VALUE, derCert);
+ // infer cert attributes
+
+ GetCertFields(derCert, &derSerial, &derSubject, &derIssuer, &pubKey);
+
+ setAttribute(CKA_SERIAL_NUMBER, &derSerial);
+ setAttribute(CKA_SUBJECT, &derSubject);
+ setAttribute(CKA_ISSUER, &derIssuer);
+ } catch (PKCS11Exception &e) {
+ CKYBuffer_FreeData(&derSerial);
+ CKYBuffer_FreeData(&derSubject);
+ CKYBuffer_FreeData(&derIssuer);
+ throw e;
+ }
+
+ name = GetUserName(&derSubject); /* adopt */
+ CKYBuffer_FreeData(&derSerial);
+ CKYBuffer_FreeData(&derSubject);
+ CKYBuffer_FreeData(&derIssuer);
+}
diff --git a/src/coolkey/object.h b/src/coolkey/object.h
new file mode 100644
index 0000000..9131b1e
--- /dev/null
+++ b/src/coolkey/object.h
@@ -0,0 +1,205 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_OBJECT_H
+#define COOLKEY_OBJECT_H
+
+#include "mypkcs11.h"
+#include "cky_base.h"
+#include <list>
+#include "log.h"
+
+using std::list;
+
+class PKCS11Attribute {
+ private:
+ CK_ATTRIBUTE_TYPE type;
+ CKYBuffer value;
+
+ public:
+ const CKYBuffer *getValue() const { return &value; }
+ CK_ATTRIBUTE_TYPE getType() const {return type; }
+ void setValue(const CKYByte *data, CKYSize size) {
+ CKYBuffer_Replace(&value, 0, data, size);
+ }
+ void setType(CK_ATTRIBUTE_TYPE type_) { type = type_; }
+ PKCS11Attribute(const PKCS11Attribute &cpy) {
+ type = cpy.type;
+ CKYBuffer_InitFromCopy(&value, &cpy.value);
+ }
+ PKCS11Attribute &operator=(PKCS11Attribute &cpy) {
+ type = cpy.type;
+ CKYBuffer_Replace(&value, 0, CKYBuffer_Data(&cpy.value),
+ CKYBuffer_Size(&cpy.value));
+ return *this;
+ }
+ PKCS11Attribute() { CKYBuffer_InitEmpty(&value); }
+ PKCS11Attribute(CK_ATTRIBUTE_TYPE type_, const CKYBuffer *value_)
+ : type(type_) { CKYBuffer_InitFromCopy(&value, value_); }
+ ~PKCS11Attribute() { CKYBuffer_FreeData(&value); }
+};
+
+class PKCS11Object {
+ public:
+
+ typedef list<PKCS11Attribute> AttributeList;
+ typedef AttributeList::iterator AttributeIter;
+ typedef AttributeList::const_iterator AttributeConstIter;
+
+ private:
+ AttributeList attributes;
+ unsigned long muscleObjID;
+ CK_OBJECT_HANDLE handle;
+ char *label;
+
+ void parseOldObject(const CKYBuffer *data);
+ void parseNewObject(const CKYBuffer *data);
+ void expandAttributes(unsigned long fixedAttrs);
+
+ PKCS11Object &operator=(PKCS11Object &cpy) { return *this; } //Disallow
+
+ protected :
+ CKYBuffer pubKey;
+ char *name;
+
+ public:
+ PKCS11Object(unsigned long muscleObjID, CK_OBJECT_HANDLE handle);
+ PKCS11Object(unsigned long muscleObjID, const CKYBuffer *data,
+ CK_OBJECT_HANDLE handle);
+ ~PKCS11Object() { delete label; delete name; CKYBuffer_FreeData(&pubKey); }
+
+ PKCS11Object(const PKCS11Object& cpy) :
+ attributes(cpy.attributes), muscleObjID(cpy.muscleObjID),
+ handle(cpy.handle), label(NULL), name(NULL) {
+ CKYBuffer_InitFromCopy(&pubKey,&cpy.pubKey); }
+
+
+ unsigned long getMuscleObjID() const { return muscleObjID; }
+ const CK_OBJECT_HANDLE getHandle() const { return handle; }
+
+ /* PKCS11Attribute* getAttribute(CK_ATTRIBUTE_TYPE type); */
+ const char *getLabel();
+ CK_OBJECT_CLASS getClass();
+ const char *getName() { return name; }
+
+ void setAttribute(CK_ATTRIBUTE_TYPE type, const CKYBuffer *value);
+ void setAttribute(CK_ATTRIBUTE_TYPE type, const char *);
+ /* bools and ulongs are too close, don't abuse function overloading
+ * for these cases */
+ void setAttributeBool(CK_ATTRIBUTE_TYPE type, CK_BBOOL);
+ void setAttributeULong(CK_ATTRIBUTE_TYPE type, CK_ULONG);
+
+ void removeAttribute(CK_ATTRIBUTE_TYPE type);
+
+ bool matchesTemplate(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG count) const;
+
+ const CKYBuffer *getAttribute(CK_ATTRIBUTE_TYPE type) const;
+ void getAttributeValue(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ Log* log) const;
+ bool attributeExists(CK_ATTRIBUTE_TYPE type) const;
+ const CKYBuffer *getPubKey(void) const {
+ return &pubKey;
+ }
+};
+
+class Key : public PKCS11Object {
+
+ public:
+ Key(unsigned long muscleObjID, const CKYBuffer *data, CK_OBJECT_HANDLE handle);
+ void completeKey(const PKCS11Object &cert);
+
+};
+
+class Cert : public PKCS11Object {
+ public:
+ Cert(unsigned long muscleObjID, const CKYBuffer *data,
+ CK_OBJECT_HANDLE handle, const CKYBuffer *derCert);
+};
+
+class CACPrivKey : public PKCS11Object {
+ public:
+ CACPrivKey(CKYByte instance, const PKCS11Object &cert);
+};
+
+class CACPubKey : public PKCS11Object {
+ public:
+ CACPubKey(CKYByte instance, const PKCS11Object &cert);
+};
+
+class CACCert : public PKCS11Object {
+ public:
+ CACCert(CKYByte instance, const CKYBuffer *derCert);
+};
+
+class Reader : public PKCS11Object {
+ public:
+ Reader(unsigned long muscleObjID, CK_OBJECT_HANDLE handle,
+ const char *reader, const CKYBuffer *cardATR, bool isCoolkey);
+};
+
+class AttributeMatch {
+
+ private:
+ const CK_ATTRIBUTE *attr;
+ public:
+ AttributeMatch( const CK_ATTRIBUTE *attr_) : attr(attr_) { }
+
+ bool operator()(const PKCS11Attribute& cmp);
+};
+
+inline unsigned int
+makeLEUInt(const CKYBuffer *buf, unsigned int offset)
+{
+ /* assert( offset + 4 <= CKYBuffer_Size(buf) ); */
+ const CKYByte *b = CKYBuffer_Data(buf);
+
+ return (b[offset+3] << 24) |
+ (b[offset+2] << 16) |
+ (b[offset+1] << 8) |
+ (b[offset+0] << 0) ;
+}
+
+// fixed object ID constants
+#define READER_ID 0x72300000 /* 'r0\0\0' */
+#define COMBINED_ID 0x7a300000 /* 'z0\0\0' */
+
+const CKYByte COMP_NONE=0;
+const CKYByte COMP_ZLIB=1;
+const CKYByte DATATYPE_STRING=0;
+const CKYByte DATATYPE_INTEGER=1;
+const CKYByte DATATYPE_BOOL_FALSE=2;
+const CKYByte DATATYPE_BOOL_TRUE=3;
+
+// relative to the header
+const CKYOffset OBJ_FORMAT_VERSION_OFFSET = 0;
+const CKYOffset OBJ_OBJECT_VERSION_OFFSET = 2;
+const CKYOffset OBJ_CUID_OFFSET = 4;
+const CKYSize OBJ_CUID_SIZE = 10;
+const CKYOffset OBJ_COMP_TYPE_OFFSET = 14;
+const CKYOffset OBJ_COMP_SIZE_OFFSET = 16;
+const CKYOffset OBJ_COMP_OFFSET_OFFSET = 18;
+const CKYSize OBJ_HEADER_SIZE = 20;
+
+// relative to the start of the decompressed block
+const CKYOffset OBJ_OBJECT_OFFSET_OFFSET = 0;
+const CKYOffset OBJ_OBJECT_COUNT_OFFSET = 2;
+const CKYOffset OBJ_TOKENNAME_SIZE_OFFSET = 4;
+const CKYOffset OBJ_TOKENNAME_OFFSET = 5;
+
+#endif
diff --git a/src/coolkey/params.h b/src/coolkey/params.h
new file mode 100644
index 0000000..a5a7e12
--- /dev/null
+++ b/src/coolkey/params.h
@@ -0,0 +1,49 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_PARAMS_H
+#define COOLKEY_PARAMS_H
+
+
+class Params {
+
+private:
+ static char *params;
+public:
+ static void SetParams(const char *_params) {
+ ClearParams();
+ params = strdup(_params);
+ };
+ static void ClearParams() {
+ if (params) free (params);
+ params = NULL;
+ };
+ static char *hasParam(const char *key) {
+ char * index;
+ if (!params) return NULL;
+ index = strstr(params, key);
+ if (!index) return NULL;
+ index += strlen(key);
+ if (*index == '=') {
+ return index+1;
+ }
+ return NULL;
+ };
+};
+#endif
diff --git a/src/coolkey/pkcs11.h b/src/coolkey/pkcs11.h
new file mode 100644
index 0000000..61cb147
--- /dev/null
+++ b/src/coolkey/pkcs11.h
@@ -0,0 +1,302 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+/* pkcs11.h include file for PKCS #11. 2001 June 25 */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set. The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this. You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name. It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * )
+ * {
+ * ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y) x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/coolkey/pkcs11f.h b/src/coolkey/pkcs11f.h
new file mode 100644
index 0000000..7d17ced
--- /dev/null
+++ b/src/coolkey/pkcs11f.h
@@ -0,0 +1,917 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+/* pkcs11f.h include file for PKCS #11. 2001 June 25 */
+
+/* This function contains pretty much everything about all the */
+/* Cryptoki function prototypes. Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list */
+);
+#endif
+
+
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens? */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session
+ * handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen
+ * mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
+ * for pub.
+ * key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
+ * attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
+ * for priv.
+ * key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
+ * attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
+ * key
+ * handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
+ * priv. key
+ * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
diff --git a/src/coolkey/pkcs11n.h b/src/coolkey/pkcs11n.h
new file mode 100644
index 0000000..c4eadc5
--- /dev/null
+++ b/src/coolkey/pkcs11n.h
@@ -0,0 +1,76 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef _PKCS11N_H_
+#define _PKCS11N_H_
+
+#ifdef DEBUG
+static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
+#endif /* DEBUG */
+
+/*
+ * pkcs11n.h
+ *
+ * This file contains the NSS-specific type definitions for Cryptoki
+ * (PKCS#11).
+ */
+
+/*
+ * NSSCK_VENDOR_NETSCAPE
+ *
+ * Cryptoki reserves the high half of all the number spaces for
+ * vendor-defined use. I'd like to keep all of our Netscape-
+ * specific values together, but not in the oh-so-obvious
+ * 0x80000001, 0x80000002, etc. area. So I've picked an offset,
+ * and constructed values for the beginnings of our spaces.
+ *
+ * Note that some "historical" Netscape values don't fall within
+ * this range.
+ */
+#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */
+
+/*
+ * Netscape-defined object classes
+ *
+ */
+#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKO_MOZ_READER (CKO_NETSCAPE + 5)
+
+/*
+ * Netscape-defined object attributes
+ *
+ */
+#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
+#define CKA_MOZ_IS_COOL_KEY (CKA_NETSCAPE + 24)
+#define CKA_MOZ_ATR (CKA_NETSCAPE + 25)
+#define CKA_MOZ_TPS_URL (CKA_NETSCAPE + 26)
+
+#endif /* _PKCS11N_H_ */
diff --git a/src/coolkey/pkcs11t.h b/src/coolkey/pkcs11t.h
new file mode 100644
index 0000000..da5200e
--- /dev/null
+++ b/src/coolkey/pkcs11t.h
@@ -0,0 +1,1354 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+/* pkcs11t.h include file for PKCS #11. 2001 June 25 */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+
+ /* libraryDescription and libraryVersion are new for v2.0 */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0
+
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ /* hardwareVersion and firmwareVersion are new for v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
+#define CKF_HW_SLOT 0x00000004 /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+ * changed from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+
+ /* hardwareVersion, firmwareVersion, and time are new for
+ * v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001 /* has random #
+ * generator */
+#define CKF_WRITE_PROTECTED 0x00000002 /* token is
+ * write-
+ * protected */
+#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
+ * login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
+ * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN 0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0
+/* Normal user */
+#define CKU_USER 1
+
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_STATE;
+#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
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+
+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002 /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes. It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+#define CKO_DATA 0x00000000
+#define CKO_CERTIFICATE 0x00000001
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKO_SECRET_KEY 0x00000004
+#define CKO_HW_FEATURE 0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_VENDOR_DEFINED 0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+#define CKH_MONOTONIC_COUNTER 0x00000001
+#define CKH_CLOCK 0x00000002
+#define CKH_VENDOR_DEFINED 0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000
+#define CKK_DSA 0x00000001
+#define CKK_DH 0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA 0x00000003
+#define CKK_EC 0x00000003
+#define CKK_X9_42_DH 0x00000004
+#define CKK_KEA 0x00000005
+
+#define CKK_GENERIC_SECRET 0x00000010
+#define CKK_RC2 0x00000011
+#define CKK_RC4 0x00000012
+#define CKK_DES 0x00000013
+#define CKK_DES2 0x00000014
+#define CKK_DES3 0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST 0x00000016
+#define CKK_CAST3 0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5 0x00000018
+#define CKK_CAST128 0x00000018
+#define CKK_RC5 0x00000019
+#define CKK_IDEA 0x0000001A
+#define CKK_SKIPJACK 0x0000001B
+#define CKK_BATON 0x0000001C
+#define CKK_JUNIPER 0x0000001D
+#define CKK_CDMF 0x0000001E
+#define CKK_AES 0x0000001F
+
+#define CKK_VENDOR_DEFINED 0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+#define CKC_X_509 0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000
+#define CKA_TOKEN 0x00000001
+#define CKA_PRIVATE 0x00000002
+#define CKA_LABEL 0x00000003
+#define CKA_APPLICATION 0x00000010
+#define CKA_VALUE 0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012
+
+#define CKA_CERTIFICATE_TYPE 0x00000080
+#define CKA_ISSUER 0x00000081
+#define CKA_SERIAL_NUMBER 0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083
+#define CKA_OWNER 0x00000084
+#define CKA_ATTR_TYPES 0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086
+
+#define CKA_KEY_TYPE 0x00000100
+#define CKA_SUBJECT 0x00000101
+#define CKA_ID 0x00000102
+#define CKA_SENSITIVE 0x00000103
+#define CKA_ENCRYPT 0x00000104
+#define CKA_DECRYPT 0x00000105
+#define CKA_WRAP 0x00000106
+#define CKA_UNWRAP 0x00000107
+#define CKA_SIGN 0x00000108
+#define CKA_SIGN_RECOVER 0x00000109
+#define CKA_VERIFY 0x0000010A
+#define CKA_VERIFY_RECOVER 0x0000010B
+#define CKA_DERIVE 0x0000010C
+#define CKA_START_DATE 0x00000110
+#define CKA_END_DATE 0x00000111
+#define CKA_MODULUS 0x00000120
+#define CKA_MODULUS_BITS 0x00000121
+#define CKA_PUBLIC_EXPONENT 0x00000122
+#define CKA_PRIVATE_EXPONENT 0x00000123
+#define CKA_PRIME_1 0x00000124
+#define CKA_PRIME_2 0x00000125
+#define CKA_EXPONENT_1 0x00000126
+#define CKA_EXPONENT_2 0x00000127
+#define CKA_COEFFICIENT 0x00000128
+#define CKA_PRIME 0x00000130
+#define CKA_SUBPRIME 0x00000131
+#define CKA_BASE 0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133
+#define CKA_SUB_PRIME_BITS 0x00000134
+
+#define CKA_VALUE_BITS 0x00000160
+#define CKA_VALUE_LEN 0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE 0x00000162
+#define CKA_LOCAL 0x00000163
+#define CKA_NEVER_EXTRACTABLE 0x00000164
+#define CKA_ALWAYS_SENSITIVE 0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166
+
+#define CKA_MODIFIABLE 0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS 0x00000180
+#define CKA_EC_PARAMS 0x00000180
+
+#define CKA_EC_POINT 0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_SECONDARY_AUTH 0x00000200
+#define CKA_AUTH_PIN_FLAGS 0x00000201
+#define CKA_HW_FEATURE_TYPE 0x00000300
+#define CKA_RESET_ON_INIT 0x00000301
+#define CKA_HAS_RESET 0x00000302
+
+#define CKA_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+
+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
+#define CKM_RSA_PKCS 0x00000001
+#define CKM_RSA_9796 0x00000002
+#define CKM_RSA_X_509 0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0. They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS 0x00000004
+#define CKM_MD5_RSA_PKCS 0x00000005
+#define CKM_SHA1_RSA_PKCS 0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008
+#define CKM_RSA_PKCS_OAEP 0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
+#define CKM_RSA_X9_31 0x0000000B
+#define CKM_SHA1_RSA_X9_31 0x0000000C
+#define CKM_RSA_PKCS_PSS 0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010
+#define CKM_DSA 0x00000011
+#define CKM_DSA_SHA1 0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
+#define CKM_DH_PKCS_DERIVE 0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
+#define CKM_X9_42_DH_DERIVE 0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
+#define CKM_X9_42_MQV_DERIVE 0x00000033
+
+#define CKM_RC2_KEY_GEN 0x00000100
+#define CKM_RC2_ECB 0x00000101
+#define CKM_RC2_CBC 0x00000102
+#define CKM_RC2_MAC 0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL 0x00000104
+#define CKM_RC2_CBC_PAD 0x00000105
+
+#define CKM_RC4_KEY_GEN 0x00000110
+#define CKM_RC4 0x00000111
+#define CKM_DES_KEY_GEN 0x00000120
+#define CKM_DES_ECB 0x00000121
+#define CKM_DES_CBC 0x00000122
+#define CKM_DES_MAC 0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL 0x00000124
+#define CKM_DES_CBC_PAD 0x00000125
+
+#define CKM_DES2_KEY_GEN 0x00000130
+#define CKM_DES3_KEY_GEN 0x00000131
+#define CKM_DES3_ECB 0x00000132
+#define CKM_DES3_CBC 0x00000133
+#define CKM_DES3_MAC 0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL 0x00000135
+#define CKM_DES3_CBC_PAD 0x00000136
+#define CKM_CDMF_KEY_GEN 0x00000140
+#define CKM_CDMF_ECB 0x00000141
+#define CKM_CDMF_CBC 0x00000142
+#define CKM_CDMF_MAC 0x00000143
+#define CKM_CDMF_MAC_GENERAL 0x00000144
+#define CKM_CDMF_CBC_PAD 0x00000145
+
+#define CKM_MD2 0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC 0x00000201
+#define CKM_MD2_HMAC_GENERAL 0x00000202
+
+#define CKM_MD5 0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC 0x00000211
+#define CKM_MD5_HMAC_GENERAL 0x00000212
+
+#define CKM_SHA_1 0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230
+#define CKM_RIPEMD128_HMAC 0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
+#define CKM_RIPEMD160 0x00000240
+#define CKM_RIPEMD160_HMAC 0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN 0x00000300
+#define CKM_CAST_ECB 0x00000301
+#define CKM_CAST_CBC 0x00000302
+#define CKM_CAST_MAC 0x00000303
+#define CKM_CAST_MAC_GENERAL 0x00000304
+#define CKM_CAST_CBC_PAD 0x00000305
+#define CKM_CAST3_KEY_GEN 0x00000310
+#define CKM_CAST3_ECB 0x00000311
+#define CKM_CAST3_CBC 0x00000312
+#define CKM_CAST3_MAC 0x00000313
+#define CKM_CAST3_MAC_GENERAL 0x00000314
+#define CKM_CAST3_CBC_PAD 0x00000315
+#define CKM_CAST5_KEY_GEN 0x00000320
+#define CKM_CAST128_KEY_GEN 0x00000320
+#define CKM_CAST5_ECB 0x00000321
+#define CKM_CAST128_ECB 0x00000321
+#define CKM_CAST5_CBC 0x00000322
+#define CKM_CAST128_CBC 0x00000322
+#define CKM_CAST5_MAC 0x00000323
+#define CKM_CAST128_MAC 0x00000323
+#define CKM_CAST5_MAC_GENERAL 0x00000324
+#define CKM_CAST128_MAC_GENERAL 0x00000324
+#define CKM_CAST5_CBC_PAD 0x00000325
+#define CKM_CAST128_CBC_PAD 0x00000325
+#define CKM_RC5_KEY_GEN 0x00000330
+#define CKM_RC5_ECB 0x00000331
+#define CKM_RC5_CBC 0x00000332
+#define CKM_RC5_MAC 0x00000333
+#define CKM_RC5_MAC_GENERAL 0x00000334
+#define CKM_RC5_CBC_PAD 0x00000335
+#define CKM_IDEA_KEY_GEN 0x00000340
+#define CKM_IDEA_ECB 0x00000341
+#define CKM_IDEA_CBC 0x00000342
+#define CKM_IDEA_MAC 0x00000343
+#define CKM_IDEA_MAC_GENERAL 0x00000344
+#define CKM_IDEA_CBC_PAD 0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
+#define CKM_XOR_BASE_AND_DATA 0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
+
+#define CKM_SSL3_MD5_MAC 0x00000380
+#define CKM_SSL3_SHA1_MAC 0x00000381
+#define CKM_MD5_KEY_DERIVATION 0x00000390
+#define CKM_MD2_KEY_DERIVATION 0x00000391
+#define CKM_SHA1_KEY_DERIVATION 0x00000392
+#define CKM_PBE_MD2_DES_CBC 0x000003A0
+#define CKM_PBE_MD5_DES_CBC 0x000003A1
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
+#define CKM_PBE_SHA1_RC4_128 0x000003A6
+#define CKM_PBE_SHA1_RC4_40 0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
+#define CKM_KEY_WRAP_LYNKS 0x00000400
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN 0x00001000
+#define CKM_SKIPJACK_ECB64 0x00001001
+#define CKM_SKIPJACK_CBC64 0x00001002
+#define CKM_SKIPJACK_OFB64 0x00001003
+#define CKM_SKIPJACK_CFB64 0x00001004
+#define CKM_SKIPJACK_CFB32 0x00001005
+#define CKM_SKIPJACK_CFB16 0x00001006
+#define CKM_SKIPJACK_CFB8 0x00001007
+#define CKM_SKIPJACK_WRAP 0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
+#define CKM_SKIPJACK_RELAYX 0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010
+#define CKM_KEA_KEY_DERIVE 0x00001011
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020
+#define CKM_BATON_KEY_GEN 0x00001030
+#define CKM_BATON_ECB128 0x00001031
+#define CKM_BATON_ECB96 0x00001032
+#define CKM_BATON_CBC128 0x00001033
+#define CKM_BATON_COUNTER 0x00001034
+#define CKM_BATON_SHUFFLE 0x00001035
+#define CKM_BATON_WRAP 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
+#define CKM_EC_KEY_PAIR_GEN 0x00001040
+
+#define CKM_ECDSA 0x00001041
+#define CKM_ECDSA_SHA1 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE 0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
+#define CKM_ECMQV_DERIVE 0x00001052
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060
+#define CKM_JUNIPER_ECB128 0x00001061
+#define CKM_JUNIPER_CBC128 0x00001062
+#define CKM_JUNIPER_COUNTER 0x00001063
+#define CKM_JUNIPER_SHUFFLE 0x00001064
+#define CKM_JUNIPER_WRAP 0x00001065
+#define CKM_FASTHASH 0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN 0x00001080
+#define CKM_AES_ECB 0x00001081
+#define CKM_AES_CBC 0x00001082
+#define CKM_AES_MAC 0x00001083
+#define CKM_AES_MAC_GENERAL 0x00001084
+#define CKM_AES_CBC_PAD 0x00001085
+#define CKM_DSA_PARAMETER_GEN 0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
+
+#define CKM_VENDOR_DEFINED 0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+
+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001 /* performed by HW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0. They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100
+#define CKF_DECRYPT 0x00000200
+#define CKF_DIGEST 0x00000400
+#define CKF_SIGN 0x00000800
+#define CKF_SIGN_RECOVER 0x00001000
+#define CKF_VERIFY 0x00002000
+#define CKF_VERIFY_RECOVER 0x00004000
+#define CKF_GENERATE 0x00008000
+#define CKF_GENERATE_KEY_PAIR 0x00010000
+#define CKF_WRAP 0x00020000
+#define CKF_UNWRAP 0x00040000
+#define CKF_DERIVE 0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P 0x00100000
+#define CKF_EC_F_2M 0x00200000
+#define CKF_EC_ECPARAMETERS 0x00400000
+#define CKF_EC_NAMEDCURVE 0x00800000
+#define CKF_EC_UNCOMPRESS 0x01000000
+#define CKF_EC_COMPRESS 0x02000000
+
+#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000
+#define CKR_CANCEL 0x00000001
+#define CKR_HOST_MEMORY 0x00000002
+#define CKR_SLOT_ID_INVALID 0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR 0x00000005
+#define CKR_FUNCTION_FAILED 0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD 0x00000007
+#define CKR_NO_EVENT 0x00000008
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009
+#define CKR_CANT_LOCK 0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
+#define CKR_DATA_INVALID 0x00000020
+#define CKR_DATA_LEN_RANGE 0x00000021
+#define CKR_DEVICE_ERROR 0x00000030
+#define CKR_DEVICE_MEMORY 0x00000031
+#define CKR_DEVICE_REMOVED 0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
+#define CKR_FUNCTION_CANCELED 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE 0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED 0x00000064
+#define CKR_KEY_CHANGED 0x00000065
+#define CKR_KEY_NEEDED 0x00000066
+#define CKR_KEY_INDIGESTIBLE 0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069
+#define CKR_KEY_UNEXTRACTABLE 0x0000006A
+
+#define CKR_MECHANISM_INVALID 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082
+#define CKR_OPERATION_ACTIVE 0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
+#define CKR_PIN_INCORRECT 0x000000A0
+#define CKR_PIN_INVALID 0x000000A1
+#define CKR_PIN_LEN_RANGE 0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED 0x000000A3
+#define CKR_PIN_LOCKED 0x000000A4
+
+#define CKR_SESSION_CLOSED 0x000000B0
+#define CKR_SESSION_COUNT 0x000000B1
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
+#define CKR_SESSION_READ_ONLY 0x000000B5
+#define CKR_SESSION_EXISTS 0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
+
+#define CKR_SIGNATURE_INVALID 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
+#define CKR_USER_NOT_LOGGED_IN 0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
+#define CKR_USER_TYPE_INVALID 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
+#define CKR_USER_TOO_MANY_TYPES 0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG 0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL 0x00000150
+#define CKR_SAVED_STATE_INVALID 0x00000160
+#define CKR_INFORMATION_SENSITIVE 0x00000170
+#define CKR_STATE_UNSAVEABLE 0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
+#define CKR_MUTEX_BAD 0x000001A0
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1
+
+#define CKR_VENDOR_DEFINED 0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR LibraryParameters;
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK 0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+#define CKG_MGF1_SHA1 0x00000001
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+ CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+#endif
diff --git a/src/coolkey/slot.cpp b/src/coolkey/slot.cpp
new file mode 100644
index 0000000..fae592a
--- /dev/null
+++ b/src/coolkey/slot.cpp
@@ -0,0 +1,3192 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include <string>
+#include "mypkcs11.h"
+#include <stdio.h>
+#include <assert.h>
+#include "log.h"
+#include "PKCS11Exception.h"
+#include <winscard.h>
+#include "slot.h"
+#include <memory.h>
+#include "zlib.h"
+#include "params.h"
+
+#include "machdep.h"
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+using std::auto_ptr;
+
+
+#ifdef DEBUG
+#define PRINTF(args) printf args
+#else
+#define PRINTF(args)
+#endif
+// #define DISPLAY_WHOLE_GET_DATA 1
+
+
+// The Cyberflex Access 32k egate ATR
+const CKYByte ATR[] =
+{ 0x3b, 0x75, 0x94, 0x00, 0x00, 0x62, 0x02, 0x02, 0x02, 0x01 };
+const CKYByte ATR1[] =
+{ 0x3b, 0x75, 0x94, 0x00, 0x00, 0x62, 0x02, 0x02, 0x03, 0x01 };
+const CKYByte ATR3[] =
+{ 0x3b, 0x76, 0x94, 0x00, 0x00, 0xff, 0x62, 0x76, 0x01, 0x00, 0x00 };
+/* RSA SecurID */
+const CKYByte ATR2[] =
+{ 0x3B, 0x6F, 0x00, 0xFF, 0x52, 0x53, 0x41, 0x53, 0x65, 0x63, 0x75, 0x72,
+ 0x49, 0x44, 0x28, 0x52, 0x29, 0x31, 0x30 };
+
+SlotList::SlotList(Log *log_) : log(log_)
+{
+ // initialize things to NULL so we can recover from an exception
+ slots = NULL;
+ numSlots = 0;
+ readerStates = NULL;
+ numReaders = 0;
+ context = NULL;
+ shuttingDown = FALSE;
+
+ try {
+
+ context = CKYCardContext_Create(SCARD_SCOPE_USER);
+ if( context == NULL) {
+ throw PKCS11Exception(CKR_GENERAL_ERROR,
+ "Failed to create card context\n");
+ }
+ updateSlotList();
+ } catch( PKCS11Exception &) {
+ CKYCardContext_Destroy(context);
+ if (readerStates) {
+ CKYReader_DestroyArray(readerStates, numReaders);
+ }
+ throw;
+ }
+}
+
+SlotList::~SlotList()
+{
+ if( slots ) {
+ assert( numSlots > 0 );
+ for( unsigned int i=0; i < numSlots; ++i ) {
+ delete slots[i];
+ }
+ delete [] slots;
+ slots = NULL;
+ numSlots = 0;
+ }
+ if (readerStates) {
+ CKYReader_DestroyArray(readerStates, numReaders);
+ readerStates = NULL;
+ numReaders = 0;
+ }
+ if (context) {
+ CKYCardContext_Destroy(context);
+ context = NULL;
+ }
+}
+void
+SlotList::shutdown()
+{
+ shuttingDown = TRUE;
+ CKYCardContext_Cancel(context);
+}
+
+void
+SlotList::updateSlotList()
+{
+ Slot **newSlots = NULL;
+ Slot **oldSlots = NULL;
+
+ readerListLock.getLock();
+
+ updateReaderList();
+
+ if (numSlots == numReaders) {
+ readerListLock.releaseLock();
+ return;
+ }
+ assert(numSlots < numReaders);
+ if (numSlots > numReaders) {
+ readerListLock.releaseLock();
+ throw PKCS11Exception(CKR_GENERAL_ERROR,
+ "Reader and slot count inconsistant\n");
+ }
+
+ try {
+ newSlots = new Slot*[numReaders];
+ if (newSlots == NULL )
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ memset(newSlots, 0, numReaders*sizeof(Slot*));
+
+ memcpy(newSlots, slots, sizeof(slots[0]) * numSlots);
+
+ for (unsigned int i=numSlots; i < numReaders; i++) {
+ newSlots[i] = new
+ Slot(CKYReader_GetReaderName(&readerStates[i]), log, context);
+ }
+
+ oldSlots = slots;
+ slots = newSlots; // update the pointer first
+ numSlots = numReaders; // now update the count
+ if (oldSlots) { // ok we can free the old value now
+ delete [] oldSlots;
+ }
+ } catch( PKCS11Exception &) {
+ // Recover by deleting everything that was created.
+ if( newSlots ) {
+ assert(numSlots < numReaders );
+ for( unsigned int i=numSlots; i < numReaders; ++i ) {
+ if( newSlots[i] ) {
+ delete newSlots[i];
+ }
+ }
+ delete [] newSlots;
+ }
+ readerListLock.releaseLock();
+ throw;
+ }
+ readerListLock.releaseLock();
+
+}
+
+bool
+SlotList::readerExists(const char *readerName, unsigned int *hint)
+{
+ unsigned int start = 0;
+ unsigned int i;
+
+ if (hint && (*hint < numReaders)) {
+ start = *hint;
+ }
+
+ /*
+ * We use 'hint' as a way of deciding where to
+ * start. This way we can handle the normal case where the name list
+ * and the readerState matches one for one with a single string compare.
+ */
+ for (i=start; i < numReaders; i++) {
+ if (strcmp(CKYReader_GetReaderName(&readerStates[i]),readerName) == 0) {
+ if (hint) {
+ *hint = i+1;
+ }
+ return TRUE;
+ }
+ }
+ /* we guessed wrong, check the first part of the reader states */
+ for (i=0; i < start; i++) {
+ if (strcmp(CKYReader_GetReaderName(&readerStates[i]),readerName) == 0) {
+ if (hint) {
+ *hint = i+1;
+ }
+ return TRUE;
+ }
+ }
+ /* OK, we've found a genuinely new reader */
+ return FALSE;
+}
+
+/*
+ * you need to hold the ReaderList Lock before you can update the ReaderList
+ */
+#define MAX_READER_DELTA 4
+void
+SlotList::updateReaderList()
+{
+ CKYReaderNameList readerNames = NULL;
+
+ CKYStatus status = CKYCardContext_ListReaders(context, &readerNames);
+ if ( status != CKYSUCCESS ) {
+ throw PKCS11Exception(CKR_GENERAL_ERROR,
+ "Failed to list readers: 0x%x\n",
+ CKYCardContext_GetLastError(context));
+ }
+
+ if (!readerStates) {
+ /* fresh Reader State list, just create it */
+ readerStates = CKYReader_CreateArray(readerNames, (CKYSize *)&numReaders);
+
+ /* if we have no readers, make sure we have at least one to keep things
+ * happy */
+ if (readerStates == NULL &&
+ CKYReaderNameList_GetCount(readerNames) == 0) {
+ readerStates = (SCARD_READERSTATE *)
+ malloc(sizeof(SCARD_READERSTATE));
+ if (readerStates) {
+ CKYReader_Init(readerStates);
+ status = CKYReader_SetReaderName(readerStates, "E-Gate 0 0");
+ if (status != CKYSUCCESS) {
+ CKYReader_DestroyArray(readerStates, 1);
+ readerStates = NULL;
+ } else {
+ numReaders = 1;
+ }
+ }
+ }
+ CKYReaderNameList_Destroy(readerNames);
+
+ if (readerStates == NULL) {
+ throw PKCS11Exception(CKR_HOST_MEMORY,
+ "Failed to allocate ReaderStates\n");
+ }
+ return;
+ }
+
+ /* it would be tempting at this point just to see if we have more readers
+ * then specified previously. The problem with this is it is possible that
+ * some readers have been deleted, so the only way to tell if we have
+ * new readers is to see if there are any readers on the list that we
+ * don't recognize.
+ */
+
+ const char *newReadersData[MAX_READER_DELTA];
+ const char **newReaders = &newReadersData[0];
+ unsigned int newReaderCount = 0;
+ unsigned int hint = 0;
+
+ try {
+ CKYReaderNameIterator iter;
+
+ for (iter = CKYReaderNameList_GetIterator(readerNames);
+ !CKYReaderNameIterator_End(iter);
+ iter = CKYReaderNameIterator_Next(iter)) {
+ const char *thisReaderName = CKYReaderNameIterator_GetValue(iter);
+ if (!readerExists(thisReaderName, &hint)) {
+ if (newReaderCount == MAX_READER_DELTA) {
+ /* oops, we overflowed our buffer, alloc a new one right
+ * quick. This code is very unlikely, so it's not fast,
+ * but it's meant to keep working, even in this weird
+ * condition. NOTE: it assumes that we can't have any
+ * more new readers than candidate readers we are
+ * checking */
+ int maxReaders = CKYReaderNameList_GetCount(readerNames);
+ assert(maxReaders > MAX_READER_DELTA);
+ newReaders = new const char *[maxReaders];
+ if (!newReaders) {
+ throw PKCS11Exception(CKR_HOST_MEMORY,
+ "Could allocate space for %d new readers\n",
+ maxReaders);
+ }
+ memcpy(newReaders, newReadersData,
+ MAX_READER_DELTA*sizeof(newReadersData[0]));
+ }
+ newReaders[newReaderCount++] = thisReaderName;
+ }
+ }
+ /* OK, we haven't added any new readers, blow out now */
+ if (newReaderCount == 0) {
+ CKYReaderNameList_Destroy(readerNames);
+ return;
+ }
+
+ status = CKYReader_AppendArray(&readerStates, numReaders,
+ newReaders, newReaderCount);
+ if (status != CKYSUCCESS) {
+ throw PKCS11Exception(CKR_GENERAL_ERROR,
+ "Couldn't append %d new reader states\n",
+ newReaderCount);
+ }
+ numReaders += newReaderCount;
+
+ CKYReaderNameList_Destroy(readerNames);
+ /* free newReaders if w were forced to alloc it */
+ if (newReaders != &newReadersData[0]) {
+ delete [] newReaders;
+ }
+ return;
+
+ } catch( PKCS11Exception &) {
+ CKYReaderNameList_Destroy(readerNames);
+ /* free newReaders if w were forced to alloc it */
+ if (newReaders != &newReadersData[0]) {
+ delete [] newReaders;
+ }
+
+ throw;
+ }
+}
+
+
+Slot::Slot(const char *readerName_, Log *log_, CKYCardContext* context_)
+ : log(log_), readerName(NULL), personName(NULL), manufacturer(NULL),
+ slotInfoFound(false), context(context_), conn(NULL), state(UNKNOWN),
+ isVersion1Key(false), needLogin(false), fullTokenName(false),
+ mCoolkey(false),
+#ifdef USE_SHMEM
+ shmem(readerName_),
+#endif
+ sessionHandleCounter(1), objectHandleCounter(1)
+{
+
+ tokenFWVersion.major = 0;
+ tokenFWVersion.minor = 0;
+
+
+ try {
+ conn = CKYCardConnection_Create(context);
+ if( conn == 0 ) {
+ throw PKCS11Exception(CKR_GENERAL_ERROR);
+ }
+ hwVersion.major = 255;
+ hwVersion.minor = 255;
+
+ //Initialize login state for both Version 1 keys and older keys
+ reverify = false;
+ nonceValid = false;
+ loggedIn = false;
+ pinCache.invalidate();
+ pinCache.clearPin();
+ //readSlotInfo();
+ manufacturer = strdup("Unknown");
+ if (!manufacturer) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+ readerName = strdup(readerName_);
+ if (!readerName) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+ CKYStatus ret = CKYBuffer_InitFromLen(&nonce, NONCE_SIZE);
+ if (ret != CKYSUCCESS) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+ CKYBuffer_InitEmpty(&cardATR);
+ CKYBuffer_InitEmpty(&mCUID);
+ } catch(PKCS11Exception &) {
+ if (conn) {
+ CKYCardConnection_Destroy(conn);
+ }
+ if (manufacturer) {
+ free(manufacturer);
+ }
+ if (readerName) {
+ free(readerName);
+ }
+ throw;
+ }
+}
+
+void
+Slot::readSlotInfo(void)
+{
+#ifdef WIN32 /* Mac doesn't have the SCardGetAttrib function */
+ CKYStatus status;
+ CKYBuffer attrBuf;
+
+ CKYBuffer_InitEmpty(&attrBuf);
+ status = CKYCardConnection_GetAttribute(conn,
+ SCARD_ATTR_VENDOR_IFD_VERSION, &attrBuf);
+ if (status == CKYSUCCESS) {
+ const CKYByte *type = CKYBuffer_Data(&attrBuf);
+
+ if (CKYBuffer_Size(&attrBuf) == sizeof(unsigned long)) {
+ /* buffer data is returned in machine order, not network or
+ * applet order */
+ unsigned long version = *(unsigned long *)type;
+ hwVersion.major = (CK_BYTE) (version >> 24) & 0xff;
+ hwVersion.minor = (CK_BYTE) (version >> 16) & 0xff;
+ }
+ status = CKYCardConnection_GetAttribute(conn,
+ SCARD_ATTR_VENDOR_NAME, &attrBuf);
+ if (status == CKYSUCCESS) {
+ free(manufacturer);
+ /* make sure manufacturer is NULL terminated */
+ CKYBuffer_AppendChar(&attrBuf,0);
+ manufacturer = strdup((const char *)CKYBuffer_Data(&attrBuf));
+ slotInfoFound = true;
+ }
+ } else {
+ PRINTF(("readSlotInfo failed\n"));
+ }
+ CKYBuffer_FreeData(&attrBuf);
+#endif /* WIN32 */
+}
+
+Slot::~Slot()
+{
+ if (conn) {
+ CKYCardConnection_Destroy(conn);
+ }
+ if (readerName) {
+ free(readerName);
+ }
+ if (personName) {
+ free(personName);
+ }
+ if (manufacturer) {
+ free(manufacturer);
+ }
+ CKYBuffer_FreeData(&nonce);
+ CKYBuffer_FreeData(&cardATR);
+ CKYBuffer_FreeData(&mCUID);
+}
+
+template <class C>
+class ArrayFreer {
+ private:
+ C *ptr;
+ public:
+ ArrayFreer(C* cptr) : ptr(cptr) { }
+ ~ArrayFreer() {
+ if( ptr ) {
+ delete [] ptr;
+ }
+ }
+ void release() { ptr = NULL; }
+};
+
+CK_RV
+SlotList::getSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount)
+{
+ CK_RV rv = CKR_OK;
+ unsigned int i;
+
+ if( pulCount == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+
+ if (pSlotList == NULL) {
+ updateSlotList();
+ }
+
+ //
+ // first, figure out which slots have tokens present
+ //
+ bool * tokenIsPresent = new bool[numSlots];
+ if( tokenIsPresent == NULL ) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+ ArrayFreer<bool> deleteTokIsPres(tokenIsPresent);
+
+ unsigned int numPresent = 0;
+ for( i = 0; i < numSlots; ++i ) {
+ tokenIsPresent[i] = slots[i]->isTokenPresent();
+ numPresent += tokenIsPresent[i];
+ }
+
+ //
+ // now fill in the slot list if it was supplied
+ //
+ if( pSlotList != NULL ) {
+ if( tokenPresent ) {
+ // only slots with tokens present
+ if( *pulCount >= numPresent ) {
+ // we have enough space to copy the slot IDs
+ unsigned int j;
+ for( i=0, j=0; i < numSlots; ++i ) {
+ if( tokenIsPresent[i] ) {
+ assert(j < numPresent);
+ pSlotList[j++] = slotIndexToID(i);
+ }
+ }
+ assert( j == numPresent );
+ } else {
+ // not enough space
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
+ } else {
+ // all slots, even without tokens present
+ if( *pulCount >= numSlots ) {
+ // we have enough space to copy the slot IDs
+ for( i=0; i < numSlots; ++i ) {
+ pSlotList[i] = slotIndexToID(i);
+ }
+ } else {
+ // not enough space
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
+ }
+ }
+
+ // set the number of slots
+ if( tokenPresent ) {
+ *pulCount = numPresent;
+ } else {
+ *pulCount = numSlots;
+ }
+
+ return rv;
+}
+
+void
+Slot::connectToToken()
+{
+ CKYStatus status;
+ OSTime time = OSTimeNow();
+
+ mCoolkey = 0;
+
+ // try to connect to the card
+ if( ! CKYCardConnection_IsConnected(conn) ) {
+ status = CKYCardConnection_Connect(conn, readerName);
+ if( status != CKYSUCCESS ) {
+ log->log("Unable to connect to token\n");
+ state = UNKNOWN;
+ return;
+ }
+ }
+ log->log("time connect: Connect Time %d ms\n", OSTimeNow() - time);
+ if (!slotInfoFound) {
+ readSlotInfo();
+ }
+ log->log("time connect: Read Slot %d ms\n", OSTimeNow() - time);
+
+ // Get card state. See if it is present, and if the ATR matches
+ unsigned long cardState;
+ status = CKYCardConnection_GetStatus(conn, &cardState, &cardATR);
+ if( status != CKYSUCCESS ) {
+ disconnect();
+ return;
+ }
+ log->log("time connect: connection status %d ms\n", OSTimeNow() - time);
+ if( cardState & SCARD_PRESENT ) {
+ state = CARD_PRESENT;
+ }
+
+ if ( CKYBuffer_DataIsEqual(&cardATR, ATR, sizeof (ATR)) ||
+ CKYBuffer_DataIsEqual(&cardATR, ATR1, sizeof(ATR1)) ||
+ CKYBuffer_DataIsEqual(&cardATR, ATR2, sizeof(ATR2)) ) {
+
+ if (Params::hasParam("noAppletOK"))
+ {
+ state |= APPLET_SELECTABLE;
+ mCoolkey = 1;
+ }
+ }
+
+ /* support CAC card. identify the card based on applets, not the ATRS */
+ state |= ATR_MATCH;
+
+ /* our production cards should "ALWAYS" have an applet, even if it
+ * doesn't exit */
+ if ( CKYBuffer_DataIsEqual(&cardATR, ATR3, sizeof (ATR3)) ) {
+ state |= ATR_MATCH | APPLET_SELECTABLE;
+ mCoolkey = 1;
+
+ }
+
+ Transaction trans;
+ trans.begin(conn);
+
+ // see if the applet is selectable
+
+ log->log("time connnect: Begin transaction %d ms\n", OSTimeNow() - time);
+ status = CKYApplet_SelectCoolKeyManager(conn, NULL);
+ if (status != CKYSUCCESS) {
+ status = CACApplet_SelectPKI(conn, 0, NULL);
+ if (status != CKYSUCCESS) {
+ if (status == CKYSCARDERR) {
+ disconnect();
+ }
+ return;
+ }
+ state |= CAC_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED;
+ /* ARG CAC is evil. once you've selected an applet, you cannot
+ * select the card manager unless you reset the card...
+ * ... even removing and reinserting the card does not change the
+ * applet selection,
+ * do so reset the card now so we can get the CUID
+ * this will cause other apps to loose login state! */
+ CKYCardConnection_Reset(conn);
+ readCUID(); /* get the CUID before we loose the ability to */
+ isVersion1Key = 0;
+ needLogin = 1;
+
+ return;
+ }
+ mCoolkey = 1;
+ log->log("time connect: Select Applet %d ms\n", OSTimeNow() - time);
+
+ state |= APPLET_SELECTABLE;
+
+ // now see if the applet is personalized
+ CKYAppletRespGetLifeCycleV2 lifeCycleV2;
+ status = CKYApplet_GetLifeCycleV2(conn, &lifeCycleV2, NULL);
+ if (status != CKYSUCCESS) {
+ if (status == CKYSCARDERR) {
+ disconnect();
+ }
+ return;
+ }
+ log->log("time connect: Get Personalization %d ms\n", OSTimeNow() - time);
+ if (lifeCycleV2.lifeCycle == CKY_APPLICATION_PERSONALIZED )
+ {
+ state |= APPLET_PERSONALIZED;
+ }
+ isVersion1Key = (lifeCycleV2.protocolMajorVersion == 1);
+ needLogin = (lifeCycleV2.pinCount != 0);
+ tokenFWVersion.major = lifeCycleV2.protocolMajorVersion;
+ tokenFWVersion.minor = lifeCycleV2.protocolMinorVersion;
+}
+
+bool
+Slot::cardStateMayHaveChanged()
+{
+ CKYStatus status;
+
+log->log("calling IsConnected\n");
+ if( !CKYCardConnection_IsConnected(conn) ) {
+ return true;
+ }
+log->log("IsConnected returned false\n");
+
+ // If the card has been removed or reset, this call will fail.
+ unsigned long cardState;
+ CKYBuffer aid;
+ CKYBuffer_InitEmpty(&aid);
+ status = CKYCardConnection_GetStatus(conn, &cardState, &aid);
+ CKYBuffer_FreeData(&aid);
+ if( status != CKYSUCCESS ) {
+ disconnect();
+ return true;
+ }
+ return false;
+}
+
+void
+Slot::invalidateLogin(bool hard)
+{
+ if (isVersion1Key) {
+ if (hard) {
+ nonceValid = false;
+ CKYBuffer_Zero(&nonce);
+ CKYBuffer_Resize(&nonce,8);
+ } else {
+ reverify = true;
+ }
+ } else {
+ loggedIn = false;
+ if (hard) {
+ pinCache.invalidate();
+ pinCache.clearPin();
+ }
+ }
+}
+
+void
+Slot::disconnect()
+{
+ CKYCardConnection_Disconnect(conn);
+ state = UNKNOWN;
+ closeAllSessions();
+ invalidateLogin(false);
+}
+
+void
+Slot::refreshTokenState()
+{
+ if( cardStateMayHaveChanged() ) {
+log->log("card changed\n");
+ invalidateLogin(true);
+ closeAllSessions();
+ unloadObjects();
+ connectToToken();
+
+
+ if( state & APPLET_PERSONALIZED ) {
+ try {
+ loadObjects();
+ } catch(PKCS11Exception&) {
+ log->log("refreshTokenState: Failed to load objects.\n");
+ unloadObjects();
+ }
+ } else if (state & APPLET_SELECTABLE) {
+ initEmpty();
+ }
+
+ }
+}
+
+bool
+Slot::isTokenPresent()
+{
+ refreshTokenState();
+ log->log("isTokenPresent, card state is 0x%x\n", state);
+ return (state & APPLET_SELECTABLE) != 0;
+}
+
+CK_SESSION_HANDLE
+makeSessionHandle(CK_SLOT_ID slotID, SessionHandleSuffix suffix)
+{
+ assert( (slotID & 0x000000ff) == slotID );
+ return (slotID << 24) | suffix;
+}
+
+void
+SlotList::decomposeSessionHandle(CK_SESSION_HANDLE hSession, CK_SLOT_ID& slotID,
+ SessionHandleSuffix& suffix) const
+{
+ slotID = hSession >> 24;
+ suffix = SessionHandleSuffix(hSession);
+ try {
+ validateSlotID(slotID);
+ } catch(PKCS11Exception&) {
+ log->log("Invalid slotID %d pulled from session handle 0x%08x\n",
+ slotID, hSession);
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+}
+
+void
+SlotList::openSession(Session::Type type, CK_SLOT_ID slotID,
+ CK_SESSION_HANDLE_PTR phSession)
+{
+ validateSlotID(slotID);
+
+ SessionHandleSuffix suffix =
+ slots[slotIDToIndex(slotID)]->openSession(type);
+
+ *phSession = makeSessionHandle(slotID, suffix);
+}
+
+void
+SlotList::closeSession(CK_SESSION_HANDLE hSession)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->closeSession(suffix);
+}
+
+
+SessionHandleSuffix
+Slot::openSession(Session::Type type)
+{
+ ensureTokenPresent();
+ return generateNewSession(type);
+}
+
+class SessionHandleSuffixMatch {
+ private:
+ SessionHandleSuffix suffix;
+ public:
+ explicit SessionHandleSuffixMatch(SessionHandleSuffix s) : suffix(s) { }
+ bool operator()(const Session& session) {
+ return session.getHandleSuffix() == suffix;
+ }
+};
+
+bool
+Slot::isValidSession(SessionHandleSuffix handleSuffix) const
+{
+ SessionConstIter iter;
+ iter = findConstSession(handleSuffix);
+ return (iter != sessions.end());
+}
+
+void
+Slot::closeSession(SessionHandleSuffix handleSuffix)
+{
+ refreshTokenState();
+
+ SessionIter iter;
+ iter = findSession(handleSuffix);
+ if( iter == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID,
+ "Invalid session handle suffix 0x%08x passed to closeSession\n",
+ (unsigned long)handleSuffix);
+ } else {
+ log->log("Closed session 0x%08x\n", (unsigned long)handleSuffix);
+ sessions.erase(iter);
+ }
+}
+
+CK_RV
+Slot::getSlotInfo(CK_SLOT_INFO_PTR pSlotInfo)
+{
+ static CK_VERSION firmwareVersion = {0,0};
+
+ if( pSlotInfo == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ pSlotInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
+ /*pSlotInfo->flags = CKF_REMOVABLE_DEVICE; */
+ if( isTokenPresent() )
+ pSlotInfo->flags |= CKF_TOKEN_PRESENT;
+ memset(pSlotInfo->slotDescription, ' ', 64);
+ memcpy(pSlotInfo->slotDescription, readerName,
+ MIN(64, strlen(readerName)) );
+ memset(pSlotInfo->manufacturerID, ' ', 32);
+ memcpy(pSlotInfo->manufacturerID, manufacturer,
+ MIN(32, strlen(manufacturer)) );
+ pSlotInfo->hardwareVersion = hwVersion;
+ pSlotInfo->firmwareVersion = firmwareVersion;
+
+ return CKR_OK;
+}
+
+inline unsigned char
+hex(unsigned long digit)
+{
+ return (digit > 9 )? (char)(digit+'a'-10) : (char)(digit+'0');
+}
+
+void
+Slot::makeCUIDString(char *serialNumber, int maxSize,
+ const unsigned char *cuids)
+{
+ signed int i; // must be signed or for loop won't exit!
+ char *cp;
+
+ memset(serialNumber, ' ', maxSize);
+ // CUID is an 8 digit hex number with leading zeros.
+ // we count down from 8 stripping hex digits. If there is not
+ // enough space, we truncate the top digits
+ unsigned long cuid =
+ ((unsigned long) cuids[6]) << 24 |
+ ((unsigned long) cuids[7]) << 16 |
+ ((unsigned long) cuids[8]) << 8 |
+ ((unsigned long) cuids[9]) ;
+
+ for (i = MIN(maxSize,8)-1, cp= serialNumber; i >= 0;
+ cp++, i--) {
+ unsigned long digit = cuid >> (i*4);
+ // if we truncated the beginning. show that with a '*'
+ *cp = (digit > 0xf) ? '*' : hex(digit);
+ cuid -= digit << (i*4);
+ }
+}
+
+
+void
+Slot::makeSerialString(char *serialNumber, int maxSize,
+ const unsigned char *cuid)
+{
+ memset(serialNumber, ' ', maxSize);
+
+ // otherwise we use the eepromSerialNumber as a hex value
+ if (cuid) {
+ makeCUIDString(serialNumber, maxSize, cuid);
+ }
+ return;
+}
+
+void
+Slot::makeLabelString(char *label, int maxSize, const unsigned char *cuid)
+{
+ int personLen;
+ memset(label, ' ', maxSize);
+ if (fullTokenName) {
+ personLen = strlen(personName);
+ memcpy(label, personName, MIN(personLen, maxSize));
+ // UTF8 Truncate fixup! don't drop halfway through a UTF8 character
+ return;
+ }
+
+//
+// Legacy tokens only 'speak' english.
+//
+#define COOLKEY "CoolKey"
+#define POSSESSION " for "
+ if (!personName || personName == "") {
+ const int coolKeySize = sizeof(COOLKEY) ;
+ memcpy(label, COOLKEY, coolKeySize-1);
+ makeSerialString(&label[coolKeySize], maxSize-coolKeySize, cuid);
+ return;
+ }
+ const int prefixSize = sizeof (COOLKEY POSSESSION )-1;
+ memcpy(label, COOLKEY POSSESSION, prefixSize);
+ personLen = strlen(personName);
+ memcpy(&label[prefixSize], personName,
+ MIN(personLen, maxSize-prefixSize));
+
+}
+
+void
+Slot::makeModelString(char *model, int maxSize, const unsigned char *cuid)
+{
+ char *cp = model;
+ memset(model, ' ', maxSize);
+ assert(maxSize >= 8);
+
+ if (!cuid) {
+ return;
+ }
+
+ *cp++ = hex(cuid[2] >> 4);
+ *cp++ = hex(cuid[2] & 0xf);
+ *cp++ = hex(cuid[3] >> 4);
+ *cp++ = hex(cuid[3] & 0xf);
+ *cp++ = hex(cuid[4] >> 4);
+ *cp++ = hex(cuid[4] & 0xf);
+ *cp++ = hex(cuid[5] >> 4);
+ *cp++ = hex(cuid[5] & 0xf);
+ makeCUIDString(&model[8],maxSize -8, cuid);
+
+ return;
+}
+
+struct _manList {
+ unsigned short type;
+ char *string;
+};
+
+static const struct _manList manList[] = {
+ { 0x4090, "Axalto" },
+ { 0x2050, "Oberthur" },
+ { 0x4780, "RSA" }
+};
+
+static int manListSize = sizeof(manList)/sizeof(manList[0]);
+
+void
+Slot::makeManufacturerString(char *man, int maxSize, const unsigned char *cuid)
+{
+ char *cp = man;
+ memset(man, ' ', maxSize);
+
+ if (!cuid) {
+ return;
+ }
+ unsigned short fabricator = ((unsigned short)cuid[0]) << 8 | cuid[1];
+
+ assert(maxSize >=4 );
+
+ /* first give the raw manufacture ID for CUID calculations */
+ *cp++ = hex(cuid[0] >> 4);
+ *cp++ = hex(cuid[0] & 0xf);
+ *cp++ = hex(cuid[1] >> 4);
+ *cp++ = hex(cuid[1] & 0xf);
+ cp++; /* leave a space */
+
+
+ for (int i=0; i < manListSize; i++) {
+ if (fabricator == manList[i].type) {
+ int len = strlen(manList[i].string);
+ memcpy(cp,manList[i].string, MIN(len,maxSize-5));
+ break;
+ }
+ }
+ /* just leave the number bare if we don't recognize it */
+}
+
+CK_RV
+Slot::getTokenInfo(CK_TOKEN_INFO_PTR pTokenInfo)
+{
+ if(pTokenInfo == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ ensureTokenPresent();
+ const unsigned char *cuid = CKYBuffer_Data(&mCUID);
+
+ /// format the token string
+ makeLabelString((char *)pTokenInfo->label, sizeof(pTokenInfo->label),cuid);
+ makeSerialString((char *)pTokenInfo->serialNumber,
+ sizeof(pTokenInfo->serialNumber), cuid);
+ makeModelString((char *)pTokenInfo->model,
+ sizeof(pTokenInfo->model), cuid);
+ makeManufacturerString((char *)pTokenInfo->manufacturerID,
+ sizeof(pTokenInfo->manufacturerID), cuid);
+
+ pTokenInfo->flags = CKF_WRITE_PROTECTED;
+ if (state & APPLET_PERSONALIZED) {
+ pTokenInfo->flags |= CKF_TOKEN_INITIALIZED;
+ if (needLogin) {
+ pTokenInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
+ }
+ }
+ pTokenInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ pTokenInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
+ pTokenInfo->ulMaxRwSessionCount = 0;
+ pTokenInfo->ulMaxPinLen = 32;
+ pTokenInfo->ulMinPinLen = 0;
+ pTokenInfo->ulTotalPublicMemory = publicTotal;
+ pTokenInfo->ulFreePublicMemory = publicFree;
+ pTokenInfo->ulTotalPrivateMemory = CK_EFFECTIVELY_INFINITE;
+ pTokenInfo->ulFreePrivateMemory = privateFree;
+ pTokenInfo->hardwareVersion.major = cuid ? cuid[4] : 0;
+ pTokenInfo->hardwareVersion.minor = cuid ? cuid[5] : 0;
+ pTokenInfo->firmwareVersion = tokenFWVersion;
+
+
+ return CKR_OK;
+}
+
+void
+SlotList::validateSlotID(CK_SLOT_ID slotID) const
+{
+ if( slotID < 1 || slotID > numSlots ) {
+ throw PKCS11Exception(CKR_SLOT_ID_INVALID);
+ }
+}
+
+#define PKCS11_WAIT_LATENCY 500 /* 500 msec or 1/2 sec */
+#define PKCS11_CARD_ERROR_LATENCY 300
+void
+SlotList::waitForSlotEvent(CK_FLAGS flag, CK_SLOT_ID_PTR slotp, CK_VOID_PTR res)
+{
+ unsigned long timeout = (flag ==CKF_DONT_BLOCK) ? 0 : PKCS11_WAIT_LATENCY;
+ unsigned int i;
+ bool found = FALSE;
+ CKYStatus status;
+ SCARD_READERSTATE *myReaderStates = NULL;
+ unsigned int myNumReaders = 0;
+#ifndef notdef
+ do {
+ readerListLock.getLock();
+ try {
+ updateReaderList();
+ } catch(PKCS11Exception&) {
+ readerListLock.releaseLock();
+ if (myReaderStates) {
+ delete [] myReaderStates;
+ }
+ throw;
+ }
+ if (myNumReaders != numReaders) {
+ if (myReaderStates) {
+ delete [] myReaderStates;
+ }
+ myReaderStates = new SCARD_READERSTATE [numReaders];
+ }
+ memcpy(myReaderStates, readerStates,
+ sizeof(SCARD_READERSTATE)*numReaders);
+ myNumReaders = numReaders;
+ readerListLock.releaseLock();
+ status = CKYCardContext_WaitForStatusChange(context,
+ myReaderStates, myNumReaders, timeout);
+ if (status == CKYSUCCESS) {
+ for (i=0; i < myNumReaders; i++) {
+ SCARD_READERSTATE *rsp = &myReaderStates[i];
+ unsigned long eventState = CKYReader_GetEventState(rsp);
+ if (eventState & SCARD_STATE_CHANGED) {
+ readerListLock.getLock();
+ CKYReader_SetKnownState(&readerStates[i], eventState & ~SCARD_STATE_CHANGED);
+ readerListLock.releaseLock();
+ *slotp = slotIndexToID(i);
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ if (found || (flag == CKF_DONT_BLOCK) || shuttingDown) {
+ break;
+ }
+
+ #ifndef WIN32
+ if (status != CKYSUCCESS) {
+
+ if ( (CKYCardContext_GetLastError(context) ==
+ SCARD_E_READER_UNAVAILABLE) ||
+ (CKYCardContext_GetLastError(context) == SCARD_E_TIMEOUT))
+ {
+ OSSleep(timeout*PKCS11_CARD_ERROR_LATENCY);
+ }
+
+
+ }
+ #endif
+ } while ((status == CKYSUCCESS) ||
+ (CKYCardContext_GetLastError(context) == SCARD_E_TIMEOUT) ||
+ ( CKYCardContext_GetLastError(context) == SCARD_E_READER_UNAVAILABLE));
+#else
+ do {
+ OSSleep(100);
+ } while ((flag != CKF_DONT_BLOCK) && !shuttingDown);
+#endif
+
+ if (myReaderStates) {
+ delete [] myReaderStates;
+ }
+
+ if (!found) {
+ throw PKCS11Exception(CKR_NO_EVENT);
+ }
+ return;
+}
+
+void
+Slot::handleConnectionError()
+{
+ long error = CKYCardConnection_GetLastError(conn);
+
+ // Force a reconnect after a token operation fails. The most
+ // common reason for it to fail is that it has been removed, but
+ // it doesn't hurt to do it in other cases either (such as a reset).
+ disconnect();
+
+ // Convert the PCSC error to a PKCS #11 error, and throw the exception.
+ CK_RV ckrv;
+ switch( error ) {
+ case SCARD_E_NO_SMARTCARD:
+ case SCARD_W_RESET_CARD:
+ case SCARD_W_REMOVED_CARD:
+ ckrv = CKR_DEVICE_REMOVED;
+ break;
+ default:
+ ckrv = CKR_DEVICE_ERROR;
+ break;
+ }
+ throw PKCS11Exception(ckrv);
+}
+
+list<ListObjectInfo>
+Slot::getObjectList()
+{
+ list<ListObjectInfo> objInfoList;
+
+ while(true) {
+ CKYISOStatus result;
+ ListObjectInfo info;
+ CKYByte seq = objInfoList.size() == 0 ? CKY_LIST_RESET : CKY_LIST_NEXT;
+ CKYStatus status=CKYApplet_ListObjects(conn, seq, &info.obj, &result);
+ if (status != CKYSUCCESS) {
+ // we failed because of a connection error
+ if (status == CKYSCARDERR) {
+ handleConnectionError();
+ }
+ // we failed simply because we hit the end of the list
+ // (in which case we are done)
+ if ((result == CKYISO_SUCCESS) || (result == CKYISO_SEQUENCE_END)) {
+ break;
+ }
+ // we failed fror some other reason...
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+
+ log->log("===Object\n");
+ log->log("===id: 0x%04x\n", info.obj.objectID);
+ log->log("===size: %d\n", info.obj.objectSize);
+ log->log("===acl: 0x%02x,0x%02x,0x%02x\n", info.obj.readACL,
+ info.obj.writeACL, info.obj.deleteACL);
+ log->log("\n");
+
+ objInfoList.push_back(info);
+ }
+
+ return objInfoList;
+}
+
+// Should already have a transaction
+void
+Slot::selectApplet()
+{
+ CKYStatus status;
+ status = CKYApplet_SelectCoolKeyManager(conn, NULL);
+ if ( status == CKYSCARDERR ) handleConnectionError();
+ if ( status != CKYSUCCESS) {
+ // could not select applet: this just means it's not there
+ disconnect();
+ throw PKCS11Exception(CKR_DEVICE_REMOVED);
+ }
+}
+
+void
+Slot::selectCACApplet(CKYByte instance)
+{
+ CKYStatus status;
+ status = CACApplet_SelectPKI(conn, instance, NULL);
+ if ( status == CKYSCARDERR ) handleConnectionError();
+ if ( status != CKYSUCCESS) {
+ // could not select applet: this just means it's not there
+ disconnect();
+ throw PKCS11Exception(CKR_DEVICE_REMOVED);
+ }
+}
+// assume we are already in a transaction
+void
+Slot::readMuscleObject(CKYBuffer *data, unsigned long objectID,
+ unsigned int objSize)
+{
+ CKYStatus status;
+
+ status = CKYApplet_ReadObjectFull(conn, objectID, 0, objSize,
+ getNonce(), data, NULL);
+ if (status == CKYSCARDERR) {
+ handleConnectionError();
+ }
+ if (status != CKYSUCCESS) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+ return;
+}
+
+
+class DERCertObjIDMatch {
+ private:
+ unsigned short certnum;
+ const Slot &slot;
+ public:
+ DERCertObjIDMatch(unsigned short cn, const Slot &s) :
+ certnum(cn), slot(s) { }
+
+ bool operator()(const ListObjectInfo& info) {
+ return (slot.getObjectClass(info.obj.objectID) == 'C')
+ && ( slot.getObjectIndex(info.obj.objectID) == certnum );
+ }
+};
+
+class ObjectHandleMatch {
+ private:
+ CK_OBJECT_HANDLE handle;
+ public:
+ ObjectHandleMatch(CK_OBJECT_HANDLE handle_) : handle(handle_) { }
+ bool operator()(const PKCS11Object& obj) {
+ return obj.getHandle() == handle;
+ }
+};
+
+class ObjectCertCKAIDMatch {
+ private:
+ CKYByte cka_id;
+ public:
+ ObjectCertCKAIDMatch(CKYByte cka_id_) : cka_id(cka_id_) {}
+ bool operator()(const PKCS11Object& obj) {
+ const CKYBuffer *id;
+ const CKYBuffer *objClass;
+ CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
+ objClass = obj.getAttribute(CKA_CLASS);
+ if (objClass == NULL || !CKYBuffer_DataIsEqual(objClass,
+ (CKYByte *)&certClass, sizeof(certClass))) {
+ return false;
+ }
+ id = obj.getAttribute(CKA_ID);
+ return (id != NULL && CKYBuffer_DataIsEqual(id,&cka_id, 1))
+ ? true : false;
+ }
+};
+
+CK_OBJECT_HANDLE
+Slot::generateUnusedObjectHandle()
+{
+ CK_OBJECT_HANDLE handle;
+ ObjectConstIter iter;
+ do {
+ handle = ++objectHandleCounter;
+ iter = find_if(tokenObjects.begin(), tokenObjects.end(),
+ ObjectHandleMatch(handle));
+ } while( handle == CK_INVALID_HANDLE || iter != tokenObjects.end() );
+ return handle;
+}
+
+void
+Slot::addKeyObject(list<PKCS11Object>& objectList, const ListObjectInfo& info,
+ CK_OBJECT_HANDLE handle, bool isCombined)
+{
+ ObjectConstIter iter;
+ Key keyObj(info.obj.objectID, &info.data, handle);
+ CK_OBJECT_CLASS objClass = keyObj.getClass();
+ const CKYBuffer *id;
+
+
+ if (isCombined &&
+ ((objClass == CKO_PUBLIC_KEY) || (objClass == CKO_PRIVATE_KEY))) {
+ id = keyObj.getAttribute(CKA_ID);
+ if ((!id) || (CKYBuffer_Size(id) != 1)) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Missing or invalid CKA_ID value");
+ }
+ iter = find_if(objectList.begin(), objectList.end(),
+ ObjectCertCKAIDMatch(CKYBuffer_GetChar(id,0)));
+ if ( iter == objectList.end() ) {
+ // We failed to find a cert with a matching CKA_ID. This
+ // can happen if the cert is not present on the token, or
+ // the der encoded cert stored on the token was corrupted.
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Failed to find cert with matching CKA_ID value");
+ }
+ keyObj.completeKey(*iter);
+ }
+ objectList.push_back(keyObj);
+
+}
+
+void
+Slot::addObject(list<PKCS11Object>& objectList, const ListObjectInfo& info,
+ CK_OBJECT_HANDLE handle)
+{
+ objectList.push_back(PKCS11Object(info.obj.objectID, &info.data, handle));
+}
+
+void
+Slot::addCertObject(list<PKCS11Object>& objectList,
+ const ListObjectInfo& certAttrs,
+ const CKYBuffer *derCert, CK_OBJECT_HANDLE handle)
+{
+ Cert certObj(certAttrs.obj.objectID,
+ &certAttrs.data, handle, derCert);
+ if (personName == NULL) {
+ personName = strdup(certObj.getLabel());
+ fullTokenName = false;
+ }
+
+ objectList.push_back(certObj);
+}
+void
+Slot::unloadObjects()
+{
+ tokenObjects.clear();
+ free(personName);
+ personName = NULL;
+ fullTokenName = false;
+}
+
+#ifdef USE_SHMEM
+
+// The shared memory segment is used to cache the raw token objects from
+// the card so mupltiple instances do not need to read all the data in
+// by themselves. It also allows us to recover data from a token on
+// reinsertion if that token is inserted into the same 'slot' as it was
+// originally.
+//
+// There is one memory segment for each slot.
+//
+// The process that creates the shared memory segment will initialize the
+// valid byte to '0'. Otherwise the Memory Segment must be accessed while
+// in a transaction for the connection to a reader that the memory segment
+// represents is held.
+//
+// If the memory segment is not valid, does not match the CUID of the
+// current token, or does not match the current data version, the current
+// process will read the object data out of the card and into shared memory.
+// Since access to the shared memory is protected by the interprocess
+// transaction lock on the reader, data consistancy is
+// maintained.
+//
+// shared memory is layed out as follows:
+//
+// Header:
+// 1 short (version) shared mem layout version number (currrent 1,0)
+// 1 short (header size) size in bytes of the shared memory header
+// 1 byte (valid) segment is valid or not (valid =1; not valid =0 )
+// 1 byte (reserved) (set to zero)
+// 10 bytes (CUID) Unique card identifier.
+// 1 short (reserved) (set to zero)
+// 1 short (data version) version number of the embeded data
+// 1 short (header offset) offset to the card's data header.
+// 1 short (data offset) offset to the uncompressed card data.
+// 1 long (header size) size in bytes of the card's data header.
+// 1 long (data size) size in bytes of the uncompressed data.
+// .
+// .
+// DataHeader:
+// n bytes DataHeader.
+// .
+// .
+// Data:
+// n bytes Data.
+//
+// All data in the shared memory header is stored in machine order, packing,
+// and size. Data in the DataHeader and Data sections are stored in applet
+// byte order.
+//
+// Shared memory segments are fixed size (equal to the object memory size of
+// the token).
+//
+
+struct SlotSegmentHeader {
+ unsigned short version;
+ unsigned short headerSize;
+ unsigned char valid;
+ unsigned char reserved;
+ unsigned char cuid[10];
+ unsigned short reserved2;
+ unsigned short dataVersion;
+ unsigned short dataHeaderOffset;
+ unsigned short dataOffset;
+ unsigned long dataHeaderSize;
+ unsigned long dataSize;
+ unsigned long cert2Offset;
+ unsigned long cert2Size;
+};
+
+#define MAX_OBJECT_STORE_SIZE 15000
+//
+// previous development versions used a segment prefix of
+// "coolkeypk11s"
+//
+#define SEGMENT_PREFIX "coolkeypk11s"
+#define CAC_FAKE_CUID "CAC Certs"
+SlotMemSegment::SlotMemSegment(const char *readerName):
+ segmentAddr(NULL), segmentSize(0), segment(NULL)
+{
+ bool needInit;
+ char *segName;
+
+ segName = new char[strlen(readerName)+sizeof(SEGMENT_PREFIX)+1];
+ if (!segName) {
+ // just run without shared memory
+ return;
+ }
+ sprintf(segName,SEGMENT_PREFIX"%s",readerName);
+ segment = SHMem::initSegment(segName, MAX_OBJECT_STORE_SIZE, needInit);
+ delete segName;
+ if (!segment) {
+ // just run without shared memory
+ return;
+ }
+ segmentAddr = segment->getSHMemAddr();
+ assert(segmentAddr);
+ // paranoia, shouldn't happen..
+ if (!segmentAddr) {
+ delete segment;
+ segment = NULL;
+ return;
+ }
+
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ if (needInit) {
+ segmentHeader->valid = 0;
+ }
+ segmentSize = segment->getSHMemSize();
+}
+
+SlotMemSegment::~SlotMemSegment()
+{
+ if (segment) {
+ delete segment;
+ }
+}
+
+bool
+SlotMemSegment::CUIDIsEqual(const CKYBuffer *cuid) const
+{
+ if (!segment) {
+ return false;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+
+ return
+ CKYBuffer_DataIsEqual(cuid, (CKYByte *)segmentHeader->cuid,
+ sizeof(segmentHeader->cuid)) ? true : false;
+}
+
+void
+SlotMemSegment::setCUID(const CKYBuffer *cuid)
+{
+ if (!segment) {
+ return;
+ }
+
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+
+ if (CKYBuffer_Size(cuid) != sizeof(segmentHeader->cuid)) {
+ // should throw and exception?
+ return;
+ }
+ memcpy (segmentHeader->cuid, CKYBuffer_Data(cuid),
+ sizeof(segmentHeader->cuid));
+}
+
+const unsigned char *
+SlotMemSegment::getCUID() const
+{
+ if (!segment) {
+ return NULL;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ return segmentHeader->cuid;
+}
+
+unsigned short
+SlotMemSegment::getVersion() const
+{
+ if (!segment) {
+ return 0;
+ }
+
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ return segmentHeader->version;
+}
+
+unsigned short
+SlotMemSegment::getDataVersion() const
+{
+ if (!segment) {
+ return 0;
+ }
+
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ return segmentHeader->dataVersion;
+}
+
+void
+SlotMemSegment::setVersion(unsigned short version)
+{
+ if (!segment) {
+ return;
+ }
+
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ segmentHeader->version = version;
+}
+
+
+void
+SlotMemSegment::setDataVersion(unsigned short version)
+{
+ if (!segment) {
+ return;
+ }
+
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ segmentHeader->dataVersion = version;
+}
+
+bool
+SlotMemSegment::isValid() const
+{
+ if (!segment) {
+ return false;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ return segmentHeader->valid == 1;
+}
+
+void
+SlotMemSegment::readHeader(CKYBuffer *dataHeader) const
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ int size = segmentHeader->dataHeaderSize;
+ CKYByte *data = (CKYByte *) &segmentAddr[segmentHeader->dataHeaderOffset];
+ CKYBuffer_Replace(dataHeader, 0, data, size);
+}
+
+void
+SlotMemSegment::readData(CKYBuffer *objData) const
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ int size = segmentHeader->dataSize;
+ CKYByte *data = (CKYByte *) &segmentAddr[segmentHeader->dataOffset];
+ CKYBuffer_Replace(objData, 0, data, size);
+}
+
+
+void
+SlotMemSegment::writeHeader(const CKYBuffer *dataHeader)
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ int size = CKYBuffer_Size(dataHeader);
+ segmentHeader->headerSize = sizeof *segmentHeader;
+ segmentHeader->dataHeaderSize = size;
+ segmentHeader->dataHeaderOffset = sizeof *segmentHeader;
+ segmentHeader->dataOffset = segmentHeader->dataHeaderOffset + size;
+ CKYByte *data = (CKYByte *) &segmentAddr[segmentHeader->dataHeaderOffset];
+ memcpy(data, CKYBuffer_Data(dataHeader), size);
+}
+
+void
+SlotMemSegment::writeData(const CKYBuffer *objData)
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ int size = CKYBuffer_Size(objData);
+ segmentHeader->dataSize = size;
+ CKYByte *data = (CKYByte *) &segmentAddr[segmentHeader->dataOffset];
+ memcpy(data, CKYBuffer_Data(objData), size);
+}
+
+void
+SlotMemSegment::readCACCert(CKYBuffer *objData, CKYByte instance) const
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ int size;
+ CKYByte *data;
+
+ switch (instance) {
+ case 0:
+ data = (CKYByte *) &segmentAddr[segmentHeader->dataHeaderOffset];
+ size = segmentHeader->dataHeaderSize;
+ break;
+ case 1:
+ data = (CKYByte *) &segmentAddr[segmentHeader->dataOffset];
+ size = segmentHeader->dataSize;
+ break;
+ case 2:
+ data = (CKYByte *) &segmentAddr[segmentHeader->cert2Offset];
+ size = segmentHeader->cert2Size;
+ break;
+ default:
+ CKYBuffer_Resize(objData, 0);
+ return;
+ }
+ CKYBuffer_Replace(objData, 0, data, size);
+}
+
+
+void
+SlotMemSegment::writeCACCert(const CKYBuffer *data, CKYByte instance)
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ int size = CKYBuffer_Size(data);
+ CKYByte *shmData;
+ switch (instance) {
+ case 0:
+ segmentHeader->headerSize = sizeof *segmentHeader;
+ segmentHeader->dataHeaderOffset = sizeof *segmentHeader;
+ segmentHeader->dataHeaderSize = size;
+ segmentHeader->dataOffset = segmentHeader->dataHeaderOffset + size;
+ segmentHeader->dataSize = 0;
+ shmData = (CKYByte *) &segmentAddr[segmentHeader->dataHeaderOffset];
+ break;
+ case 1:
+ segmentHeader->dataSize = size;
+ segmentHeader->cert2Offset = segmentHeader->dataOffset + size;
+ segmentHeader->cert2Size = 0;
+ shmData = (CKYByte *) &segmentAddr[segmentHeader->dataOffset];
+ break;
+ case 2:
+ segmentHeader->cert2Size = size;
+ shmData = (CKYByte *) &segmentAddr[segmentHeader->cert2Offset];
+ break;
+ default:
+ return;
+ }
+ memcpy(shmData, CKYBuffer_Data(data), size);
+}
+
+void
+SlotMemSegment::clearValid(CKYByte instance)
+{
+
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ switch (instance) {
+ case 0:
+ segmentHeader->headerSize = 0;
+ segmentHeader->dataHeaderSize = 0;
+ /* fall through */
+ case 1:
+ segmentHeader->dataSize = 0;
+ }
+ segmentHeader->valid = 0;
+}
+
+void
+SlotMemSegment::setValid()
+{
+ if (!segment) {
+ return;
+ }
+ SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
+ segmentHeader->valid = 1;
+}
+
+#endif
+
+void
+Slot::initEmpty(void)
+{
+ // check the shared memory area first
+ // shared memory is protected by our transaction call on the card
+ //
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS ) {
+ handleConnectionError();
+ }
+
+ loadReaderObject();
+ readCUID();
+}
+
+void
+Slot::readCUID(void)
+{
+ // check the shared memory area first
+ // shared memory is protected by our transaction call on the card
+ //
+ CKYStatus status;
+ if (state & CAC_CARD) {
+ status = CACApplet_SelectCardManager(conn, NULL);
+ } else {
+ status = CKYApplet_SelectCardManager(conn, NULL);
+ }
+ CKYBuffer_Resize(&mCUID, 0);
+ if (status == CKYSCARDERR) {
+ handleConnectionError();
+ }
+ status = CKYApplet_GetCUID(conn, &mCUID, NULL);
+ if (status == CKYSCARDERR) {
+ handleConnectionError();
+ }
+}
+
+list<ListObjectInfo>
+Slot::fetchSeparateObjects()
+{
+ int i;
+
+ list<ListObjectInfo> objInfoList;
+ std::list<ListObjectInfo>::iterator iter;
+
+ OSTime time = OSTimeNow();
+ readCUID();
+ selectApplet();
+ log->log(
+ "time fetch separate: getting cuid & applet select (again) %d ms\n",
+ OSTimeNow() - time);
+
+#ifdef USE_SHMEM
+ shmem.clearValid(0);
+#endif
+
+ //
+ // get the list of objects on the muscle token
+ //
+ objInfoList = getObjectList();
+
+
+ log->log("time fetch separate: getObjectList %d ms\n",OSTimeNow() - time);
+ //
+ // get the content of each object
+ //
+ for (i=0, iter = objInfoList.begin(); iter != objInfoList.end();
+ ++iter, i++) {
+ // check the ACL to make sure this will succeed.
+ unsigned short readPerm = iter->obj.readACL;
+
+ log->log("Object has read perm 0x%04x\n", readPerm);
+ if ( (!isVersion1Key && ((readPerm & 0x2) == readPerm)) ||
+ (isVersion1Key && ((readPerm & 0x1))) ) {
+ readMuscleObject(&iter->data, iter->obj.objectID,
+ iter->obj.objectSize);
+ log->log("Object:\n");
+ log->dump(&iter->data);
+ }
+ }
+ log->log("time fetch separate: readObjects %dms\n", OSTimeNow() - time);
+ return objInfoList;
+}
+
+list<ListObjectInfo>
+Slot::fetchCombinedObjects(const CKYBuffer *header)
+{
+ CKYBuffer objBuffer;
+ CKYStatus status;
+
+ list<ListObjectInfo> objInfoList;
+ CKYBuffer_InitEmpty(&objBuffer);
+ unsigned short compressedOffset = CKYBuffer_GetShort(
+ header, OBJ_COMP_OFFSET_OFFSET);
+ unsigned short compressedSize = CKYBuffer_GetShort(
+ header, OBJ_COMP_SIZE_OFFSET);
+ OSTime time = OSTimeNow();
+
+#ifdef USE_SHMEM
+
+ // check the shared memory area first
+ // shared memory is protected by our transaction call on the card
+ //
+ CKYBuffer_Resize(&mCUID,0);
+ CKYBuffer_AppendBuffer(&mCUID, header, OBJ_CUID_OFFSET, OBJ_CUID_SIZE);
+ unsigned short dataVersion = CKYBuffer_GetShort(
+ header, OBJ_OBJECT_VERSION_OFFSET);
+
+ if (shmem.isValid() && shmem.CUIDIsEqual(&mCUID) &&
+ shmem.getDataVersion() == dataVersion) {
+ shmem.readData(&objBuffer);
+ } else {
+ shmem.clearValid(0);
+ shmem.setCUID(&mCUID);
+ shmem.setVersion(SHMEM_VERSION);
+ shmem.setDataVersion(dataVersion);
+ CKYBuffer dataHeader;
+ CKYBuffer_InitFromBuffer(&dataHeader, header, 0,
+ (CKYSize) compressedOffset);
+
+ shmem.writeHeader(&dataHeader);
+ CKYBuffer_FreeData(&dataHeader);
+ log->log("time fetch combined: play with shared memory %d ms\n",
+ OSTimeNow() - time);
+#endif
+ CKYBuffer_Reserve(&objBuffer, compressedSize);
+ CKYSize headerSize = CKYBuffer_Size(header);
+ CKYSize headerBytes = headerSize - compressedOffset;
+
+
+ CKYBuffer_AppendBuffer(&objBuffer,header,compressedOffset,headerBytes);
+ log->log("time fetch combined: "
+ "headerbytes = %d compressedOffset = %d compressedSize = %d\n",
+ headerBytes, compressedOffset, compressedSize);
+ status = CKYApplet_ReadObjectFull(conn, COMBINED_ID,
+ headerSize, compressedSize - headerBytes, getNonce(),
+ &objBuffer, NULL);
+ log->log("time fetch combined: read status = %d objectBuffSize = %d\n",
+ status, CKYBuffer_Size(&objBuffer));
+ if (status == CKYSCARDERR) {
+ CKYBuffer_FreeData(&objBuffer);
+ handleConnectionError();
+ }
+ log->log("time fetch combined: "
+ "Read Object Data %d ms (object size = %d bytes)\n",
+ OSTimeNow() - time, compressedSize);
+ if (CKYBuffer_GetShort(header, OBJ_COMP_TYPE_OFFSET) == COMP_ZLIB) {
+ CKYBuffer compBuffer;
+ CKYSize guessFinalSize = CKYBuffer_Size(&objBuffer);
+ CKYSize objSize = 0;
+ int zret = Z_MEM_ERROR;
+
+ CKYBuffer_InitFromCopy(&compBuffer,&objBuffer);
+ do {
+ guessFinalSize *= 2;
+ status = CKYBuffer_Resize(&objBuffer, guessFinalSize);
+ if (status != CKYSUCCESS) {
+ break;
+ }
+ objSize = guessFinalSize;
+ zret = uncompress((Bytef *)CKYBuffer_Data(&objBuffer),&objSize,
+ CKYBuffer_Data(&compBuffer), CKYBuffer_Size(&compBuffer));
+ } while (zret == Z_BUF_ERROR);
+ log->log("time fetch combined: "
+ "uncompress objects %d ms (object size = %d bytes)\n",
+ OSTimeNow() - time, objSize);
+
+ CKYBuffer_FreeData(&compBuffer);
+ if (zret != Z_OK) {
+ CKYBuffer_FreeData(&objBuffer);
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Corrupted compressed object Data");
+ }
+ CKYBuffer_Resize(&objBuffer,objSize);
+ }
+
+ // uncompress...
+#ifdef USE_SHMEM
+ shmem.writeData(&objBuffer);
+ shmem.setDataVersion(dataVersion);
+ shmem.setValid();
+ }
+#endif
+
+ //
+ // now pull apart the objects
+ //
+ unsigned short offset =
+ CKYBuffer_GetShort(&objBuffer, OBJ_OBJECT_OFFSET_OFFSET);
+ unsigned short objectCount = CKYBuffer_GetShort(
+ &objBuffer, OBJ_OBJECT_COUNT_OFFSET);
+ int tokenNameSize = CKYBuffer_GetChar(&objBuffer,OBJ_TOKENNAME_SIZE_OFFSET);
+ int i;
+ CKYSize size = CKYBuffer_Size(&objBuffer);
+
+ if (offset < tokenNameSize+OBJ_TOKENNAME_OFFSET) {
+ CKYBuffer_FreeData(&objBuffer);
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Tokenname/object Data overlap");
+ }
+ if (personName) {
+ free(personName);
+ }
+ personName = (char *)malloc(tokenNameSize+1);
+ memcpy(personName,CKYBuffer_Data(&objBuffer)+OBJ_TOKENNAME_OFFSET,
+ tokenNameSize);
+ personName[tokenNameSize] = 0;
+ fullTokenName = true;
+
+ for (i=0; i < objectCount && offset < size; i++) {
+ ListObjectInfo info;
+ unsigned long objectID = CKYBuffer_GetLong(&objBuffer, offset);
+ unsigned long attrsCount= CKYBuffer_GetShort(&objBuffer, offset+8);
+ unsigned long start = offset;
+ unsigned int j;
+
+ info.obj.objectID = objectID;
+ offset +=10;
+
+ /* get the length of the attribute block */
+ for (j=0; j < attrsCount; j++) {
+ CKYByte attributeDataType=CKYBuffer_GetChar(&objBuffer, offset +4);
+
+ offset += 5;
+
+ switch (attributeDataType) {
+ case DATATYPE_STRING:
+ offset += CKYBuffer_GetShort(&objBuffer, offset) + 2;
+ break;
+ case DATATYPE_BOOL_FALSE:
+ case DATATYPE_BOOL_TRUE:
+ break;
+ case DATATYPE_INTEGER:
+ offset += 4;
+ break;
+ }
+ }
+ if (offset > size) {
+ CKYBuffer_FreeData(&objBuffer);
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Inconsistant combined object data");
+ }
+ CKYSize objSize = offset - start;
+ CKYBuffer_Reserve(&info.data, objSize +1);
+ // tell the object parsing code that this is a new, compact type
+ CKYBuffer_AppendChar(&info.data,1);
+ // copy the object
+ CKYBuffer_AppendBuffer(&info.data, &objBuffer, start, objSize);
+ objInfoList.push_back(info);
+ }
+ CKYBuffer_FreeData(&objBuffer);
+ log->log("fetch combined: format objects %d ms\n", OSTimeNow() - time);
+ return objInfoList;
+}
+
+void
+Slot::loadCACCert(CKYByte instance)
+{
+ CKYISOStatus apduRC;
+ CKYStatus status;
+ CKYBuffer cert;
+ CKYBuffer rawCert;
+ CKYBuffer shmCert;
+ CKYSize nextSize;
+
+ OSTime time = OSTimeNow();
+
+ CKYBuffer_InitEmpty(&cert);
+ CKYBuffer_InitEmpty(&rawCert);
+ CKYBuffer_InitEmpty(&shmCert);
+ selectCACApplet(instance);
+
+ log->log("CAC Cert %d: select CAC applet: %d ms\n",
+ instance, OSTimeNow() - time);
+
+ if (instance == 0) {
+ /* get the first 100 bytes of the cert */
+ status = CACApplet_GetCertificateFirst(conn, &rawCert,
+ &nextSize, &apduRC);
+ if (status != CKYSUCCESS) {
+ handleConnectionError();
+ }
+ log->log("CAC Cert %d: fetch CAC Cert: %d ms\n",
+ instance, OSTimeNow() - time);
+ }
+
+ unsigned short dataVersion = 1;
+ CKYBool needRead = 1;
+
+ /* see if it matches the shared memory */
+ if (shmem.isValid() && shmem.CUIDIsEqual(&mCUID) &&
+ shmem.getDataVersion() == dataVersion) {
+ shmem.readCACCert(&shmCert, instance);
+ CKYSize certSize = CKYBuffer_Size(&rawCert);
+ CKYSize shmCertSize = CKYBuffer_Size(&shmCert);
+ const CKYByte *shmData = CKYBuffer_Data(&shmCert);
+
+ if (instance != 0) {
+ needRead = 0;
+ }
+
+ if (shmCertSize >= certSize) {
+ if (memcmp(shmData, CKYBuffer_Data(&rawCert), certSize) == 0) {
+ /* yes it does, no need to read the rest of the cert, use
+ * the cache */
+ CKYBuffer_Replace(&rawCert, 0, shmData, shmCertSize);
+ needRead = 0;
+ }
+ }
+ }
+ CKYBuffer_FreeData(&shmCert);
+
+ if (needRead) {
+ /* it doesn't, read the new cert and update the cache */
+ if (instance == 0) {
+ shmem.clearValid(0);
+ shmem.setCUID(&mCUID);
+ shmem.setVersion(SHMEM_VERSION);
+ shmem.setDataVersion(dataVersion);
+ } else {
+ status = CACApplet_GetCertificateFirst(conn, &rawCert,
+ &nextSize, &apduRC);
+
+ if (status != CKYSUCCESS) {
+ handleConnectionError();
+ }
+ }
+
+ if (nextSize) {
+ status = CACApplet_GetCertificateAppend(conn, &rawCert,
+ nextSize, &apduRC);
+ }
+ log->log("CAC Cert %d: Fetch rest : %d ms\n",
+ instance, OSTimeNow() - time);
+ if (status != CKYSUCCESS) {
+ handleConnectionError();
+ }
+ shmem.writeCACCert(&rawCert, instance);
+ if (instance == 2) {
+ shmem.setValid();
+ }
+ }
+
+
+ log->log("CAC Cert %d: Cert has been read: %d ms\n",
+ instance, OSTimeNow() - time);
+ if (CKYBuffer_GetChar(&rawCert,0) == 1) {
+ CKYSize guessFinalSize = CKYBuffer_Size(&rawCert);
+ CKYSize certSize = 0;
+ int zret = Z_MEM_ERROR;
+
+ do {
+ guessFinalSize *= 2;
+ status = CKYBuffer_Resize(&cert, guessFinalSize);
+ if (status != CKYSUCCESS) {
+ break;
+ }
+ certSize = guessFinalSize;
+ zret = uncompress((Bytef *)CKYBuffer_Data(&cert),&certSize,
+ CKYBuffer_Data(&rawCert)+1, CKYBuffer_Size(&rawCert)-1);
+ } while (zret == Z_BUF_ERROR);
+
+ if (zret != Z_OK) {
+ CKYBuffer_FreeData(&rawCert);
+ CKYBuffer_FreeData(&cert);
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Corrupted compressed CAC Cert");
+ }
+ CKYBuffer_Resize(&cert,certSize);
+ } else {
+ CKYBuffer_InitFromBuffer(&cert,&rawCert,1,CKYBuffer_Size(&rawCert)-1);
+ }
+ CKYBuffer_FreeData(&rawCert);
+ log->log("CAC Cert %d: Cert has been uncompressed: %d ms\n",
+ instance, OSTimeNow() - time);
+
+ CACCert certObj(instance, &cert);
+ CACPrivKey privKey(instance, certObj);
+ CACPubKey pubKey(instance, certObj);
+ tokenObjects.push_back(privKey);
+ tokenObjects.push_back(pubKey);
+ tokenObjects.push_back(certObj);
+
+ if (personName == NULL) {
+ const char *name = certObj.getName();
+ if (name) {
+ personName = strdup(name);
+ fullTokenName = true;
+ }
+ }
+}
+
+void
+Slot::loadObjects()
+{
+ // throw away all token objects!
+
+ Transaction trans;
+ CKYBuffer header;
+ CKYBuffer_InitEmpty(&header);
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS ) {
+ handleConnectionError();
+ }
+ OSTime time = OSTimeNow();
+
+
+ list<ListObjectInfo> objInfoList;
+ std::list<ListObjectInfo>::iterator iter;
+
+ if (state & CAC_CARD) {
+ loadCACCert(0);
+ loadCACCert(1);
+ loadCACCert(2);
+ status = trans.end();
+ loadReaderObject();
+ return;
+ }
+
+ selectApplet();
+ log->log("time load object: Select Applet (again) %d ms\n",
+ OSTimeNow() - time);
+
+
+ status = CKYApplet_ReadObjectFull(conn, COMBINED_ID, 0,
+ CKY_MAX_READ_CHUNK_SIZE, getNonce(), &header, NULL);
+ log->log("time load object: ReadCombined Header %d ms\n",
+ OSTimeNow() - time);
+ if (status == CKYSCARDERR) {
+ CKYBuffer_FreeData(&header);
+ handleConnectionError();
+ }
+ bool isCombined = (status == CKYSUCCESS) ? true : false;
+ try {
+ objInfoList = isCombined ? fetchCombinedObjects(&header)
+ : fetchSeparateObjects();
+ } catch(PKCS11Exception& e) {
+ CKYBuffer_FreeData(&header);
+ throw(e);
+ }
+ log->log("time load object: Fetch %d ms\n", OSTimeNow() - time);
+ CKYBuffer_FreeData(&header);
+ status = trans.end();
+
+ //
+ // load up the keys, certs and others.
+ //
+ for( iter = objInfoList.begin(); iter != objInfoList.end(); ++iter ) {
+ CKYByte type = getObjectClass(iter->obj.objectID);
+ if( type == 'k' ) {
+ CK_OBJECT_HANDLE handle = generateUnusedObjectHandle();
+ addKeyObject(tokenObjects, *iter, handle, isCombined);
+ } else if( type == 'c' ) {
+ // cert attribute object. find the DER encoding
+ unsigned short certnum = getObjectIndex(iter->obj.objectID);
+ if( certnum > 9 ) {
+ //invalid object id
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Invalid object id %08x",iter->obj.objectID);
+ }
+ std::list<ListObjectInfo>::iterator derCert;
+ /*
+ * Old tokens stored certs separately from the attributes
+ */
+ if (!isCombined) {
+ derCert = find_if(objInfoList.begin(), objInfoList.end(),
+ DERCertObjIDMatch(certnum, *this));
+ if( derCert == objInfoList.end() ) {
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "No DER cert object for cert %d\n", certnum);
+ }
+ }
+ CK_OBJECT_HANDLE handle = generateUnusedObjectHandle();
+ addCertObject(tokenObjects, *iter,
+ isCombined ? NULL : &derCert->data, handle);
+ } else if ( type == 'C' ) {
+ // This is a DER Cert object (as opposed to a cert attribute
+ // object, 'c' above). skip it.
+ } else if (type == 'd') {
+ CK_OBJECT_HANDLE handle = generateUnusedObjectHandle();
+ addObject(tokenObjects, *iter, handle);
+ } else {
+ log->log("Ignoring unknown object %08x\n",iter->obj.objectID);
+ }
+ }
+ log->log("time load objects: Process %d ms\n", OSTimeNow() - time);
+
+ loadReaderObject();
+}
+
+void
+Slot::loadReaderObject(void)
+{
+ // now generate an Moz "reader" object.
+ CK_OBJECT_HANDLE handle = generateUnusedObjectHandle();
+ Reader rdr(READER_ID, handle, readerName, &cardATR, mCoolkey);
+ tokenObjects.push_back(rdr);
+}
+
+void
+Slot::closeAllSessions()
+{
+ sessions.clear();
+ log->log("cleared all sessions\n");
+}
+
+SessionHandleSuffix
+Slot::generateNewSession(Session::Type type)
+{
+ SessionHandleSuffix suffix;
+ SessionIter iter;
+
+ do {
+ suffix = (++sessionHandleCounter) & 0x00ffffff;
+ iter = findSession(suffix);
+ } while( iter != sessions.end() );
+
+ sessions.push_back(Session(suffix, type));
+
+ return suffix;
+}
+
+void
+SlotList::getSessionInfo(CK_SESSION_HANDLE hSession,
+ CK_SESSION_INFO_PTR pInfo)
+{
+
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->getSessionInfo(suffix, pInfo);
+
+ pInfo->slotID = slotID;
+}
+
+void
+Slot::ensureTokenPresent()
+{
+ if( ! isTokenPresent() ) {
+ throw PKCS11Exception(CKR_DEVICE_REMOVED);
+ }
+}
+
+SessionIter
+Slot::findSession(SessionHandleSuffix suffix)
+{
+ return find_if(sessions.begin(), sessions.end(),
+ SessionHandleSuffixMatch(suffix));
+}
+
+SessionConstIter
+Slot::findConstSession(SessionHandleSuffix suffix) const
+{
+ return find_if(sessions.begin(), sessions.end(),
+ SessionHandleSuffixMatch(suffix));
+}
+
+void
+Slot::getSessionInfo(SessionHandleSuffix handleSuffix,
+ CK_SESSION_INFO_PTR pInfo)
+{
+ refreshTokenState();
+
+ SessionIter iter = findSession(handleSuffix);
+ if( iter == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID,
+ "Unknown session handle suffix 0x%08x passed to "
+ "getSessionInfo\n", (unsigned long) handleSuffix);
+ } else {
+ if( iter->getType() == Session::RO ) {
+ pInfo->state = isLoggedIn() ?
+ CKS_RO_USER_FUNCTIONS : CKS_RO_PUBLIC_SESSION;
+ pInfo->flags = CKF_SERIAL_SESSION;
+ } else {
+ pInfo->state = isLoggedIn() ?
+ CKS_RW_USER_FUNCTIONS : CKS_RW_PUBLIC_SESSION;
+ pInfo->flags = CKF_RW_SESSION | CKF_SERIAL_SESSION;
+ }
+ pInfo->ulDeviceError = CKYCardConnection_GetLastError(conn);
+ }
+}
+
+void
+SlotList::login(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->login(suffix, pPin, ulPinLen);
+}
+
+void
+Slot::testNonce()
+{
+ reverify = false;
+ if (!nonceValid) {
+ return;
+ }
+#ifdef notdef
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ try {
+ if ( status != CKYSUCCESS ) handleConnectionError();
+
+ selectApplet();
+ } catch (PKCS11Exception &) {
+ invalidateLogin(true);
+ return;
+ }
+
+ CKYBuffer data;
+ CKYBuffer_InitEmpty(&data);
+
+ status = CKYApplet_ReadObject(conn, 0xffffffff, 0, 1, &nonce, &data, NULL);
+ trans.end();
+ CKYBuffer_FreeData(&data);
+ if( status != CKYSUCCESS ) {
+ invalidateLogin(true);
+ return;
+ }
+#else
+ invalidateLogin(true);
+#endif
+}
+
+bool
+Slot::isLoggedIn()
+{
+ if (isVersion1Key) {
+ if (reverify) {
+ testNonce();
+ }
+ return nonceValid;
+ }
+ return loggedIn;
+}
+
+void
+Slot::login(SessionHandleSuffix handleSuffix, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen)
+{
+ refreshTokenState();
+
+ if( ! isValidSession(handleSuffix) ) {
+ log->log("Invalid session handle suffix 0x%08x passed to "
+ "Slot::login\n", (unsigned long) handleSuffix);
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+
+ if (!isVersion1Key) {
+ pinCache.set((const char *)pPin, ulPinLen);
+ } else if (nonceValid) {
+ throw PKCS11Exception(CKR_USER_ALREADY_LOGGED_IN);
+ }
+
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if(status != CKYSUCCESS ) handleConnectionError();
+
+ if (state & CAC_CARD) {
+ selectCACApplet(0);
+ } else {
+ selectApplet();
+ }
+
+ if (isVersion1Key) {
+ attemptLogin((const char *)pPin);
+ } else if (state & CAC_CARD) {
+ attemptCACLogin();
+ } else {
+ oldAttemptLogin();
+ }
+}
+
+void
+Slot::attemptCACLogin()
+{
+ loggedIn = false;
+ pinCache.invalidate();
+
+ CKYStatus status;
+ CKYISOStatus result;
+
+ status = CACApplet_VerifyPIN(conn,
+ (const char *)CKYBuffer_Data(pinCache.get()), &result);
+ if( status == CKYSCARDERR ) {
+ handleConnectionError();
+ }
+ switch( result ) {
+ case CKYISO_SUCCESS:
+ break;
+ case 6981:
+ throw PKCS11Exception(CKR_PIN_LOCKED);
+ default:
+ if ((result & 0xff00) == 0x6300) {
+ throw PKCS11Exception(CKR_PIN_INCORRECT);
+ }
+ throw PKCS11Exception(CKR_DEVICE_ERROR, "Applet returned 0x%04x",
+ result);
+ }
+
+ pinCache.validate();
+ loggedIn = true;
+}
+
+void
+Slot::oldAttemptLogin()
+{
+ loggedIn = false;
+ pinCache.invalidate();
+
+ CKYStatus status;
+ CKYISOStatus result;
+ status = CKYApplet_VerifyPinV0(conn, CKY_OLD_USER_PIN_NUM,
+ (const char *)CKYBuffer_Data(pinCache.get()), &result);
+ if( status == CKYSCARDERR ) {
+ handleConnectionError();
+ }
+ switch( result ) {
+ case CKYISO_SUCCESS:
+ break;
+ case CKYISO_AUTH_FAILED:
+ throw PKCS11Exception(CKR_PIN_INCORRECT);
+ case CKYISO_IDENTITY_BLOCKED:
+ throw PKCS11Exception(CKR_PIN_LOCKED);
+ default:
+ throw PKCS11Exception(CKR_DEVICE_ERROR, "Applet returned 0x%04x",
+ result);
+ }
+
+ pinCache.validate();
+ loggedIn = true;
+}
+
+// should already be in a transaction, and applet selected
+void
+Slot::attemptLogin(const char *pin)
+{
+ CKYStatus status;
+ CKYISOStatus result;
+ status = CKYApplet_VerifyPIN(conn, CKY_USER_PIN_NUM, pin, &nonce, &result);
+ if( status == CKYSCARDERR ) {
+ handleConnectionError();
+ }
+
+ switch( result ) {
+ case CKYISO_SUCCESS:
+ break;
+ case CKYISO_AUTH_FAILED:
+ throw PKCS11Exception(CKR_PIN_INCORRECT);
+ case CKYISO_IDENTITY_BLOCKED:
+ throw PKCS11Exception(CKR_PIN_LOCKED);
+ default:
+ throw PKCS11Exception(CKR_DEVICE_ERROR,
+ "Applet returned 0x%04x", result);
+ }
+ nonceValid = true;
+
+}
+
+void
+SlotList::logout(CK_SESSION_HANDLE hSession)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->logout(suffix);
+}
+
+//
+// The old "logout All" from pre-version 1 CoolKeys.
+//
+void
+Slot::oldLogout()
+{
+ invalidateLogin(true);
+
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS) handleConnectionError();
+
+ selectApplet();
+
+ status = CKYApplet_LogoutAllV0(conn, NULL);
+ if (status != CKYSUCCESS) {
+ if (status == CKYSCARDERR) {
+ handleConnectionError();
+ }
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+}
+
+//
+//
+void
+Slot::CACLogout()
+{
+ /* use get properties which has the side effect of logging out */
+ invalidateLogin(true);
+}
+
+void
+Slot::logout(SessionHandleSuffix suffix)
+{
+ refreshTokenState();
+
+ if( !isValidSession(suffix) ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+
+ if (state & CAC_CARD) {
+ CACLogout();
+ return;
+ }
+
+ if (!isVersion1Key) {
+ oldLogout();
+ return;
+ }
+
+ if (!nonceValid) {
+ throw PKCS11Exception(CKR_USER_NOT_LOGGED_IN);
+ }
+
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS) handleConnectionError();
+
+ status = CKYApplet_Logout(conn, CKY_USER_PIN_NUM, getNonce(), NULL);
+ invalidateLogin(true);
+ if (status != CKYSUCCESS) {
+ if (status == CKYSCARDERR) {
+ handleConnectionError();
+ }
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+
+}
+
+void
+SlotList::findObjectsInit(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->findObjectsInit(suffix, pTemplate, ulCount);
+}
+
+void
+Slot::findObjectsInit(SessionHandleSuffix suffix, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+{
+ refreshTokenState();
+
+ SessionIter session = findSession(suffix);
+ if( session == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+
+ session->foundObjects.clear();
+
+ ObjectConstIter iter;
+ for( iter = tokenObjects.begin(); iter != tokenObjects.end(); ++iter) {
+ if( iter->matchesTemplate(pTemplate, ulCount) ) {
+ log->log("C_FindObjectsInit found matching object 0x%08x\n",
+ iter->getHandle());
+ session->foundObjects.push_back(iter->getHandle());
+ }
+ }
+
+ session->curFoundObject = session->foundObjects.begin();
+}
+
+void
+SlotList::findObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->findObjects(suffix, phObject,
+ ulMaxObjectCount, pulObjectCount);
+}
+
+void
+Slot::findObjects(SessionHandleSuffix suffix, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ refreshTokenState();
+
+ SessionIter session = findSession(suffix);
+ if( session == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+
+ unsigned int objectsReturned = 0;
+ while( objectsReturned < ulMaxObjectCount &&
+ session->curFoundObject != session->foundObjects.end() )
+ {
+ phObject[objectsReturned++] = *(session->curFoundObject++);
+ }
+
+ *pulObjectCount = objectsReturned;
+}
+
+void
+SlotList::getAttributeValue(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+ const
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->getAttributeValue(suffix, hObject,
+ pTemplate, ulCount);
+}
+
+void
+Slot::getAttributeValue(SessionHandleSuffix suffix,
+ CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ refreshTokenState();
+
+ if( ! isValidSession(suffix) ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+
+ ObjectConstIter iter = find_if(tokenObjects.begin(), tokenObjects.end(),
+ ObjectHandleMatch(hObject));
+
+ if( iter == tokenObjects.end() ) {
+ throw PKCS11Exception(CKR_OBJECT_HANDLE_INVALID);
+ }
+
+ iter->getAttributeValue(pTemplate, ulCount, log);
+}
+
+void
+SlotList::signInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->signInit(suffix, pMechanism, hKey);
+}
+
+void
+SlotList::decryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->decryptInit(suffix, pMechanism, hKey);
+}
+
+void
+SlotList::sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->sign(suffix, pData, ulDataLen,
+ pSignature, pulSignatureLen);
+}
+
+void
+SlotList::decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pDecryptedData,
+ CK_ULONG_PTR pulDecryptedDataLen)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->decrypt(suffix, pData, ulDataLen,
+ pDecryptedData, pulDecryptedDataLen);
+}
+
+void
+SlotList::seedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->seedRandom(suffix, pData, ulDataLen);
+}
+
+void
+SlotList::generateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen)
+{
+ CK_SLOT_ID slotID;
+ SessionHandleSuffix suffix;
+
+ decomposeSessionHandle(hSession, slotID, suffix);
+
+ slots[slotIDToIndex(slotID)]->generateRandom(suffix, pData, ulDataLen);
+}
+
+void
+Slot::ensureValidSession(SessionHandleSuffix suffix)
+{
+ if( ! isValidSession(suffix) ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+}
+
+//
+// Looks up an object and pulls the key number from the Muscle Object ID.
+// Keys in Muscle have IDs of the form 'kn ', where 'n' is the key number
+// from 0-9.
+//
+CKYByte
+Slot::objectHandleToKeyNum(CK_OBJECT_HANDLE hKey)
+{
+ ObjectConstIter iter = find_if(tokenObjects.begin(), tokenObjects.end(),
+ ObjectHandleMatch(hKey));
+
+ if( iter == tokenObjects.end() ) {
+ // no such object
+ throw PKCS11Exception(CKR_KEY_HANDLE_INVALID);
+ }
+
+ if( getObjectClass(iter->getMuscleObjID()) != 'k' ) {
+ throw PKCS11Exception(CKR_KEY_HANDLE_INVALID);
+ }
+ unsigned short keyNum = getObjectIndex(iter->getMuscleObjID());
+ if( keyNum > 9 ) {
+ throw PKCS11Exception(CKR_KEY_HANDLE_INVALID);
+ }
+ return keyNum & 0xFF;
+}
+
+void
+Slot::signInit(SessionHandleSuffix suffix, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ refreshTokenState();
+ SessionIter session = findSession(suffix);
+ if( session == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+ session->signatureState.initialize(objectHandleToKeyNum(hKey));
+}
+
+void
+Slot::decryptInit(SessionHandleSuffix suffix, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ refreshTokenState();
+ SessionIter session = findSession(suffix);
+ if( session == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+ session->decryptionState.initialize(objectHandleToKeyNum(hKey));
+}
+
+/**
+ * Padding algorithm defined in RSA's PKCS #1.
+ * to: pre-allocated buffer to receive the padded data
+ * toLen: the length of the buffer. This should be the same as the size
+ * of the RSA modulus. (toLen - 3) > fromLen.
+ * from: data to be padded.
+ * fromLen: size of data to be padded. fromLen < (toLen-3).
+ * Returns: nonzero for success, zero for failure.
+ */
+static void
+padRSAType1(const CKYBuffer *raw, CKYBuffer *padded)
+{
+ int i = 0;
+ unsigned int padLen = CKYBuffer_Size(padded) - 3 - CKYBuffer_Size(raw);
+
+ /* First byte: 00 */
+ CKYBuffer_SetChar(padded, i++, 0x00);
+
+ /* Second Byte: Block Type == 01 */
+ CKYBuffer_SetChar(padded, i++, 0x01);
+
+ /* Padding String, each byte is 0xFF for block type 01 */
+ CKYBuffer_SetChars(padded, i, 0xFF, padLen);
+ i += padLen;
+
+ /* Separator byte: 00 */
+ CKYBuffer_SetChar(padded, i++, 0x00);
+
+ /* Finally, the data */
+ CKYBuffer_Replace(padded, i, CKYBuffer_Data(raw), CKYBuffer_Size(raw));
+}
+
+static void
+stripRSAPadding(CKYBuffer *stripped, const CKYBuffer *padded)
+{
+ unsigned int size = CKYBuffer_Size(padded);
+ if( size < 2 ) {
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID);
+ }
+ if( CKYBuffer_GetChar(padded,0) != 0 ) {
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID);
+ }
+
+ unsigned int dataStart = 3;
+
+ CKYByte blockType = CKYBuffer_GetChar(padded, 1);
+ // There are three block types in PKCS #1 padding: 00, 01, and 02.
+ switch(blockType) {
+ case 0x00:
+ // The padding string is all zeroes. The first nonzero byte
+ // is the beginning of the data.
+ for( ; dataStart < size; ++dataStart ) {
+ if( CKYBuffer_GetChar(padded,dataStart) != 0 ) {
+ break;
+ }
+ }
+ if( dataStart == size ) {
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID);
+ }
+ break;
+ case 0x01:
+ // The padding string is all 0xFF, followed by a 0x00 separator byte,
+ // and then the data.
+ for( ; dataStart < size; ++dataStart ) {
+ if( CKYBuffer_GetChar(padded,dataStart) == 0xff ) {
+ // padding, continue;
+ } else if( CKYBuffer_GetChar(padded,dataStart) == 0x00 ) {
+ // end of padding
+ break;
+ } else {
+ // invalid character
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID);
+ }
+ }
+ if( dataStart == size ) {
+ // we never found the separator byte
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID);
+ }
+ dataStart++; // data starts after separator byte
+ break;
+ case 0x02:
+ // padding is non-zero. First non-zero byte is the separator,
+ // and then the data.
+ for( ; dataStart < size; ++dataStart) {
+ if( CKYBuffer_GetChar(padded,dataStart) == 0x00 ) {
+ break;
+ }
+ }
+ if( dataStart == size ) {
+ // we never found the separator byte
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID);
+ }
+ dataStart++; // data starts after separator byte
+ break;
+ default:
+ throw PKCS11Exception(CKR_ENCRYPTED_DATA_INVALID,
+ "Unknown PKCS#1 block type %x", blockType);
+ }
+
+ CKYStatus status = CKYBuffer_Replace(stripped, 0,
+ CKYBuffer_Data(padded)+dataStart, size-dataStart);
+ if (status != CKYSUCCESS) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+}
+
+class RSASignatureParams : public CryptParams {
+ public:
+ RSASignatureParams(unsigned int keysize) : CryptParams(keysize) { }
+
+ CKYByte getDirection() const { return CKY_DIR_ENCRYPT; }
+
+ CryptOpState& getOpState(Session& session) const {
+ return session.signatureState;
+ }
+
+ void padInput(CKYBuffer *paddedInput, const CKYBuffer *unpaddedInput) const {
+ // RSA_NO_PAD requires RSA PKCS #1 Type 1 padding
+ CKYStatus status = CKYBuffer_Resize(paddedInput,getKeySize()/8);
+ if (status != CKYSUCCESS) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+ padRSAType1(unpaddedInput, paddedInput);
+ return;
+ }
+
+ void
+ unpadOutput(CKYBuffer *unpaddedOutput, const CKYBuffer *paddedOutput) const {
+ // no need to unpad ciphertext
+ CKYBuffer_Replace(unpaddedOutput, 0, CKYBuffer_Data(paddedOutput),
+ CKYBuffer_Size(paddedOutput));
+
+ }
+};
+
+class RSADecryptParams: public CryptParams {
+ public:
+ RSADecryptParams(unsigned int keysize) : CryptParams(keysize) { }
+
+ CKYByte getDirection() const { return CKY_DIR_DECRYPT; }
+
+ CryptOpState& getOpState(Session& session) const {
+ return session.decryptionState;
+ }
+
+ void padInput(CKYBuffer *paddedInput, const CKYBuffer *unpaddedInput) const {
+ // no need to unpad ciphertext
+ CKYBuffer_Replace(paddedInput, 0, CKYBuffer_Data(unpaddedInput),
+ CKYBuffer_Size(unpaddedInput));
+ }
+
+ void
+ unpadOutput(CKYBuffer *unpaddedOutput, const CKYBuffer *paddedOutput) const {
+ // strip off PKCS #1 padding
+ stripRSAPadding( unpaddedOutput, paddedOutput );
+ return;
+ }
+};
+
+void
+Slot::sign(SessionHandleSuffix suffix, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen)
+{
+ cryptRSA(suffix, pData, ulDataLen, pSignature, pulSignatureLen,
+ RSASignatureParams(CryptParams::FIXED_KEY_SIZE));
+}
+
+void
+Slot::decrypt(SessionHandleSuffix suffix, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pDecryptedData,
+ CK_ULONG_PTR pulDecryptedDataLen)
+{
+ cryptRSA(suffix, pData, ulDataLen, pDecryptedData, pulDecryptedDataLen,
+ RSADecryptParams(CryptParams::FIXED_KEY_SIZE));
+}
+
+void
+Slot::cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput,
+ CK_ULONG ulInputLen, CK_BYTE_PTR pOutput,
+ CK_ULONG_PTR pulOutputLen, const CryptParams& params)
+{
+ refreshTokenState();
+ SessionIter session = findSession(suffix);
+ if( session == sessions.end() ) {
+ throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
+ }
+ // version 1 keys may not need login. We catch the error
+ // on the operation. The token will not allow us to sign with
+ // a protected key unless we are logged in.
+ // can be removed when version 0 support is depricated.
+ if (!isVersion1Key && ! isLoggedIn() ) {
+ throw PKCS11Exception(CKR_USER_NOT_LOGGED_IN);
+ }
+ CryptOpState& opState = params.getOpState(*session);
+ CKYBuffer *result = &opState.result;
+ CKYByte keyNum = opState.keyNum;
+
+ if( CKYBuffer_Size(result) == 0 ) {
+ // we haven't already peformed the decryption, so do it now.
+ if( pInput == NULL || ulInputLen == 0) {
+ throw PKCS11Exception(CKR_DATA_LEN_RANGE);
+ }
+ // OK, this is gross. We should get our own C++ like buffer
+ // management at this point. This code has nothing to do with
+ // the applet, it shouldn't be using applet specific buffers.
+ CKYBuffer input;
+ CKYBuffer inputPad;
+ CKYBuffer output;
+ CKYBuffer_InitEmpty(&output);
+ CKYBuffer_InitEmpty(&inputPad);
+ CKYStatus status = CKYBuffer_InitFromData(&input, pInput, ulInputLen);
+ if (status != CKYSUCCESS) {
+ throw PKCS11Exception(CKR_HOST_MEMORY);
+ }
+ try {
+ params.padInput(&inputPad, &input);
+ performRSAOp(&output, &inputPad, keyNum, params.getDirection());
+ params.unpadOutput(result, &output);
+ CKYBuffer_FreeData(&input);
+ CKYBuffer_FreeData(&inputPad);
+ CKYBuffer_FreeData(&output);
+ } catch(PKCS11Exception& e) {
+ CKYBuffer_FreeData(&input);
+ CKYBuffer_FreeData(&inputPad);
+ CKYBuffer_FreeData(&output);
+ throw(e);
+ }
+ }
+
+ if( pulOutputLen == NULL ) {
+ throw PKCS11Exception(CKR_DATA_INVALID,
+ "output length is NULL");
+ }
+
+ if( pOutput != NULL ) {
+ if( *pulOutputLen < CKYBuffer_Size(result) ) {
+ *pulOutputLen = CKYBuffer_Size(result);
+ throw PKCS11Exception(CKR_BUFFER_TOO_SMALL);
+ }
+ memcpy(pOutput, CKYBuffer_Data(result), CKYBuffer_Size(result));
+ }
+ *pulOutputLen = CKYBuffer_Size(result);
+}
+
+const CKYBuffer *
+Slot::getNonce()
+{
+ if (!isVersion1Key) {
+ return NULL;
+ }
+ return &nonce;
+}
+
+void
+Slot::performRSAOp(CKYBuffer *output, const CKYBuffer *input,
+ CKYByte keyNum, CKYByte direction)
+{
+ //
+ // establish a transaction
+ //
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS ) handleConnectionError();
+
+ //
+ // select the applet
+ //
+ if (state & CAC_CARD) {
+ selectCACApplet(keyNum);
+ } else {
+ selectApplet();
+ }
+
+ CKYISOStatus result;
+ int loginAttempted = 0;
+retry:
+ if (state & CAC_CARD) {
+ status = CACApplet_SignDecrypt(conn, input, output, &result);
+ } else {
+ status = CKYApplet_ComputeCrypt(conn, keyNum, CKY_RSA_NO_PAD, direction,
+ input, NULL, output, getNonce(), &result);
+ }
+ if (status != CKYSUCCESS) {
+ if ( status == CKYSCARDERR ) {
+ handleConnectionError();
+ }
+ if (result == CKYISO_DATA_INVALID) {
+ throw PKCS11Exception(CKR_DATA_INVALID);
+ }
+ // version0 keys could be logged out in the middle by someone else,
+ // reauthenticate... This code can go away when we depricate.
+ // version0 applets.
+ if (!isVersion1Key && !loginAttempted &&
+ (result == CKYISO_UNAUTHORIZED)) {
+ // try to reauthenticate
+ try {
+ oldAttemptLogin();
+ } catch(PKCS11Exception& ) {
+ // attemptLogin can throw things like CKR_PIN_INCORRECT
+ // that don't make sense from a crypto operation. This is
+ // a result of pin caching. We will reformat any login
+ // exception to a CKR_DEVICE_ERROR.
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+ loginAttempted = true;
+ goto retry; // easier to understand than a while loop in this case.
+ }
+ throw PKCS11Exception( result == CKYISO_UNAUTHORIZED ?
+ CKR_USER_NOT_LOGGED_IN : CKR_DEVICE_ERROR);
+ }
+}
+
+void
+Slot::seedRandom(SessionHandleSuffix suffix, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen)
+{
+ if (state & CAC_CARD) {
+ /* should throw unsupported */
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS ) handleConnectionError();
+
+ CKYBuffer random;
+ CKYBuffer seed;
+ CKYOffset offset = 0;
+ CKYISOStatus result;
+ int i;
+
+ CKYBuffer_InitEmpty(&random);
+ CKYBuffer_InitFromData(&seed, pData, ulDataLen);
+
+
+ while (ulDataLen) {
+ CKYByte len = (CKYByte) MIN(ulDataLen, 0xff);
+
+ status = CKYApplet_GetRandom(conn, &random, len, &result);
+ if (status != CKYSUCCESS) break;
+
+ for (i=0; i < len ; i++) {
+ CKYBuffer_SetChar(&random, i,
+ CKYBuffer_GetChar(&random,i) ^
+ CKYBuffer_GetChar(&seed,i+offset));
+ }
+ status = CKYApplet_SeedRandom(conn, &random, &result);
+ if (status != CKYSUCCESS) break;
+
+ ulDataLen -= (unsigned char)len;
+ offset += (unsigned char)len;
+ }
+
+ CKYBuffer_FreeData(&random);
+ CKYBuffer_FreeData(&seed);
+
+ if (status != CKYSUCCESS) {
+ if ( status == CKYSCARDERR ) {
+ handleConnectionError();
+ }
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+}
+
+void
+Slot::generateRandom(SessionHandleSuffix suffix, const CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen)
+{
+ if (state & CAC_CARD) {
+ /* should throw unsupported */
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+
+ Transaction trans;
+ CKYStatus status = trans.begin(conn);
+ if( status != CKYSUCCESS ) handleConnectionError();
+
+ CKYBuffer random;
+ CKYBuffer_InitEmpty(&random);
+
+ CKYISOStatus result;
+
+ while (ulDataLen) {
+ CKYByte len = (CKYByte) MIN(ulDataLen, 0xff);
+
+ status = CKYApplet_GetRandomAppend(conn, &random, len, &result);
+ if (status != CKYSUCCESS) break;
+
+ ulDataLen -= (unsigned char)len;
+ }
+ CKYBuffer_FreeData(&random);
+
+ if (status != CKYSUCCESS) {
+ if ( status == CKYSCARDERR ) {
+ handleConnectionError();
+ }
+ throw PKCS11Exception(CKR_DEVICE_ERROR);
+ }
+}
diff --git a/src/coolkey/slot.h b/src/coolkey/slot.h
new file mode 100644
index 0000000..1e2b12e
--- /dev/null
+++ b/src/coolkey/slot.h
@@ -0,0 +1,597 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#ifndef COOLKEY_SLOT_H
+#define COOLKEY_SLOT_H
+
+#include "locking.h"
+#include "log.h"
+#include "cky_applet.h"
+#include <string.h>
+#include <algorithm>
+#include "object.h"
+#include "machdep.h"
+#include <assert.h>
+
+using std::list;
+using std::find;
+using std::find_if;
+
+class Transaction {
+
+private:
+ CKYCardConnection *conn;
+
+ Transaction(const Transaction&) {} // not allowed
+ Transaction& operator=(const Transaction&) {return *this;} // not allowed
+public:
+ Transaction() : conn(0) { }
+ CKYStatus begin(CKYCardConnection *conn_) {
+ CKYStatus status;
+ status = CKYCardConnection_BeginTransaction(conn_);
+ if (status == CKYSUCCESS) {
+ conn = conn_;
+ }
+ return status;
+ }
+ CKYStatus end() {
+ CKYStatus status = CKYSUCCESS;
+ CKYCardConnection *conn_ = conn;
+
+ conn = NULL;
+ if (conn_) {
+ status = CKYCardConnection_EndTransaction(conn_);
+ }
+ return status;
+ }
+ ~Transaction() { if (conn) end(); }
+};
+
+#ifdef USE_SHMEM
+
+#define SHMEM_VERSION 0x0100 // 1.0
+
+class SlotMemSegment {
+private:
+ char *segmentAddr;
+ int segmentSize;
+ SHMem *segment; // machine independed shared memory object
+public:
+ SlotMemSegment(const char *readerName);
+ ~SlotMemSegment();
+
+ bool CUIDIsEqual(const CKYBuffer *cuid) const;
+ unsigned short getVersion() const;
+ unsigned short getDataVersion() const;
+ void setCUID(const CKYBuffer *cuid);
+ void setVersion(unsigned short version);
+ void setDataVersion(unsigned short version);
+ bool isValid() const;
+ int size() const;
+ const unsigned char *getCUID() const;
+ void readHeader(CKYBuffer *data) const;
+ void writeHeader(const CKYBuffer *data);
+ void setSize(int size);
+ void readData(CKYBuffer *data) const;
+ void writeData(const CKYBuffer *data);
+ void readCACCert(CKYBuffer *data, CKYByte instance) const;
+ void writeCACCert(const CKYBuffer *data, CKYByte instance);
+ void clearValid(CKYByte instance);
+ void setValid();
+};
+#endif
+
+struct ListObjectInfo {
+ CKYAppletRespListObjects obj;
+ CKYBuffer data;
+
+ ListObjectInfo(const ListObjectInfo &cpy) {
+ obj = cpy.obj;
+ CKYBuffer_InitFromCopy(&data,&cpy.data);
+ }
+ ListObjectInfo &operator=(const ListObjectInfo& cpy ) {
+ obj = cpy.obj;
+ CKYBuffer_Replace(&data, 0, CKYBuffer_Data(&cpy.data),
+ CKYBuffer_Size(&cpy.data));
+ return *this;
+ }
+ bool operator==(const ListObjectInfo& cmp) const {
+ if( obj.objectID != cmp.obj.objectID )
+ return false;
+ if( obj.objectSize!=cmp.obj.objectSize )
+ return false;
+ if( obj.readACL != cmp.obj.readACL )
+ return false;
+ if( obj.writeACL != cmp.obj.writeACL )
+ return false;
+ if( obj.deleteACL != cmp.obj.deleteACL )
+ return false;
+ if( !CKYBuffer_IsEqual(&data,&cmp.data) )
+ return false;
+ return true;
+ }
+ ListObjectInfo(void) {
+ memset(&obj, 0, sizeof(obj));
+ CKYBuffer_InitEmpty(&data);
+ }
+ ~ListObjectInfo() {
+ CKYBuffer_FreeData(&data);
+ }
+};
+
+//
+// The most significant byte of a session handle is the slot ID.
+// The three most significant bytes, the SessionHandleSuffix, are controlled
+// by the slot itself.
+//
+class SessionHandleSuffix {
+ private:
+ CK_SESSION_HANDLE value;
+ public:
+ SessionHandleSuffix() : value(0) { }
+ SessionHandleSuffix(CK_SESSION_HANDLE val) {
+ value = val & 0x00ffffff;
+ }
+
+ operator CK_SESSION_HANDLE() {
+ return value;
+ }
+
+ SessionHandleSuffix& operator=(CK_SESSION_HANDLE val) {
+ value = val & 0x00ffffff;
+ return *this;
+ }
+
+ bool operator==(const SessionHandleSuffix&cmp) const {
+ return value == cmp.value;
+ }
+};
+
+struct PinCache {
+ private:
+ CKYBuffer cachedPin;
+ bool valid;
+
+ PinCache(const PinCache &cpy) {} // not allowed
+ PinCache &operator=(const PinCache &cpy)
+ { return *this ; } // not allowed
+
+ public:
+ PinCache() : valid(false) { CKYBuffer_InitEmpty(&cachedPin); }
+ ~PinCache() {
+ CKYBuffer_Zero(&cachedPin); /* zero buffer before freeing it so
+ * we don't get passwords on the heap */
+ CKYBuffer_FreeData(&cachedPin); }
+ void set(const char *newPin, unsigned long pinLen) {
+ CKYBuffer_Zero(&cachedPin);
+ CKYBuffer_Replace(&cachedPin, 0, (const CKYByte *)newPin, pinLen);
+ CKYBuffer_AppendChar(&cachedPin, 0);
+ }
+ void clearPin() { CKYBuffer_Zero(&cachedPin); }
+ void invalidate() { valid = false; }
+ void validate() { valid = true; }
+ const CKYBuffer *get() const { return &cachedPin; }
+ bool isValid() const { return valid; }
+};
+
+inline unsigned int slotIDToIndex(CK_SLOT_ID slotID) {
+ return slotID - 1;
+}
+
+inline CK_SLOT_ID slotIndexToID(unsigned int index) {
+ return index + 1;
+}
+
+typedef list<PKCS11Object> ObjectList;
+typedef ObjectList::iterator ObjectIter;
+typedef ObjectList::const_iterator ObjectConstIter;
+
+typedef list<CK_OBJECT_HANDLE> ObjectHandleList;
+typedef ObjectHandleList::iterator ObjectHandleIter;
+
+class CryptOpState {
+ public:
+ enum State { NOT_INITIALIZED, IN_PROCESS, FINALIZED };
+ State state;
+ CKYByte keyNum;
+ CKYBuffer result;
+
+ CryptOpState() : state(NOT_INITIALIZED), keyNum(0)
+ { CKYBuffer_InitEmpty(&result); }
+ CryptOpState(const CryptOpState &cpy) :
+ state(cpy.state), keyNum(cpy.keyNum) {
+ CKYBuffer_InitFromCopy(&result, &cpy.result);
+ }
+ CryptOpState &operator=(const CryptOpState &cpy) {
+ state = cpy.state,
+ keyNum = cpy.keyNum;
+ CKYBuffer_Replace(&result, 0, CKYBuffer_Data(&cpy.result),
+ CKYBuffer_Size(&cpy.result));
+ return *this;
+ }
+ ~CryptOpState() { CKYBuffer_FreeData(&result); }
+ void initialize(CKYByte keyNum) {
+ state = IN_PROCESS;
+ this->keyNum = keyNum;
+ CKYBuffer_Resize(&result, 0);
+ }
+};
+
+class Session {
+ public:
+ enum Type { RO, RW };
+ private:
+ SessionHandleSuffix handleSuffix;
+ Type type;
+
+ public:
+ Session(SessionHandleSuffix h, Type t) : handleSuffix(h), type(t) { }
+ ~Session() { }
+
+ SessionHandleSuffix getHandleSuffix() const { return handleSuffix; }
+ Type getType() const { return type; }
+
+ bool operator==(const Session& cmp) const {
+ return handleSuffix == cmp.handleSuffix;
+ }
+
+ // the results of FindObjectsInit() are stored here and passed out
+ // to FindObjects().
+ ObjectHandleList foundObjects;
+ ObjectHandleIter curFoundObject;
+
+ CryptOpState signatureState;
+ CryptOpState decryptionState;
+};
+
+typedef list<Session> SessionList;
+typedef SessionList::iterator SessionIter;
+typedef SessionList::const_iterator SessionConstIter;
+
+class CryptParams {
+ private:
+ unsigned int keySize; // in bits
+ protected:
+ unsigned int getKeySize() const { return keySize; }
+ public:
+ // !!!XXX hack. The right way to get the key size is to get all the
+ // key information from the token with MSCListKeys, the same way
+ // we get all the object information with MSCListObjects.
+ enum { FIXED_KEY_SIZE = 1024 };
+
+
+ CryptParams(unsigned int keySize_) : keySize(keySize_) { }
+ virtual ~CryptParams() { }
+
+ // returns the Muscle 'direction' constant for the operation,
+ // required for the MSCComputeCrypt command
+ virtual CKYByte getDirection() const = 0;
+
+ // pulls the proper state object out of a session.
+ virtual CryptOpState& getOpState(Session& session) const = 0;
+
+ // performs any padding required on the input to the operation
+ virtual void padInput(CKYBuffer *paddedOutput,
+ const CKYBuffer *unpaddedInput) const = 0;
+
+ // performs any unpadding required on the output from the operation
+ virtual void unpadOutput(CKYBuffer *unpaddedInout,
+ const CKYBuffer *paddedOutput) const = 0;
+};
+
+class Slot {
+
+ public:
+ enum SlotState {
+ UNKNOWN = 0x01,
+ CARD_PRESENT = 0x02,
+ ATR_MATCH = 0x04,
+ APPLET_SELECTABLE = 0x08,
+ APPLET_PERSONALIZED = 0x10,
+ CAC_CARD = 0x20
+ };
+ enum {
+ NONCE_SIZE = 8
+ };
+
+ private:
+ Log *log;
+ char *readerName;
+ char *personName;
+ char *manufacturer;
+ //char *model;
+ CK_VERSION hwVersion;
+ CK_VERSION tokenFWVersion;
+ bool slotInfoFound;
+ CKYCardContext* context;
+ CKYCardConnection* conn;
+ unsigned long state; // = UNKNOWN
+ PinCache pinCache;
+ bool loggedIn;
+ bool reverify;
+ bool nonceValid;
+ CKYBuffer nonce;
+ CKYBuffer cardATR;
+ CKYBuffer mCUID;
+ bool isVersion1Key;
+ bool needLogin;
+ long publicFree;
+ long publicTotal;
+ long privateFree;
+ bool fullTokenName;
+ bool mCoolkey;
+
+ //enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 };
+
+#ifdef USE_SHMEM
+ SlotMemSegment shmem;
+#endif
+
+ SessionList sessions;
+ unsigned int sessionHandleCounter;
+
+ ObjectList tokenObjects;
+ CK_OBJECT_HANDLE objectHandleCounter;
+ CK_OBJECT_HANDLE generateUnusedObjectHandle();
+
+ SessionIter findSession(SessionHandleSuffix suffix);
+ SessionConstIter findConstSession(SessionHandleSuffix suffix) const;
+
+ void closeAllSessions();
+ SessionHandleSuffix generateNewSession(Session::Type type);
+
+ bool cardStateMayHaveChanged();
+ void connectToToken();
+ void refreshTokenState();
+ void disconnect();
+ void handleConnectionError();
+ void ensureTokenPresent();
+ void readSlotInfo();
+ void readCUID();
+ void initEmpty();
+
+ // formatting helpers
+ // data will be formated to fit in the supplied buffers, padded with
+ // ascii blanks. size of the buffers is specifed by maxSize.
+ //
+ void makeLabelString(char *man, int maxSize, const unsigned char *cuid);
+ void makeManufacturerString(char *man, int maxSize,
+ const unsigned char *cuid);
+ void makeModelString(char *man, int maxSize, const unsigned char *cuid);
+ void makeSerialString(char *man, int maxSize, const unsigned char *cuid);
+ void makeCUIDString(char *man, int maxSize, const unsigned char *cuid);
+
+ // login helpers
+ void invalidateLogin(bool hard);
+ const CKYBuffer *getNonce();
+ const CKYBuffer *getATR();
+ bool isLoggedIn();
+ bool needLoggedIn();
+ void testNonce();
+
+ void addKeyObject(list<PKCS11Object>& objectList,
+ const ListObjectInfo& info, CK_OBJECT_HANDLE handle, bool isCombined);
+ void addCertObject(list<PKCS11Object>& objectList,
+ const ListObjectInfo& certAttrs,
+ const CKYBuffer *derCert, CK_OBJECT_HANDLE handle);
+ void addObject(list<PKCS11Object>& objectList,
+ const ListObjectInfo& info, CK_OBJECT_HANDLE handle);
+
+ void ensureValidSession(SessionHandleSuffix suffix);
+
+ list<ListObjectInfo> getObjectList();
+ list<ListObjectInfo> fetchCombinedObjects(const CKYBuffer *header);
+ list<ListObjectInfo> fetchSeparateObjects();
+
+ void selectApplet();
+ void selectCACApplet(CKYByte instance);
+ void unloadObjects();
+ void loadCACObjects();
+ void loadCACCert(CKYByte instance);
+ void loadObjects();
+ void loadReaderObject();
+
+ void attemptLogin(const char *pin);
+ void attemptCACLogin();
+ void oldAttemptLogin();
+ void oldLogout(void);
+ void CACLogout(void);
+
+ void readMuscleObject(CKYBuffer *obj, unsigned long objID,
+ unsigned int objSize);
+
+ void performSignature(CKYBuffer *sig, const CKYBuffer *unpaddedInput,
+ CKYByte keyNum);
+ void performDecryption(CKYBuffer *data, const CKYBuffer *input, CKYByte keyNum);
+
+ void cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput,
+ CK_ULONG ulInputLen, CK_BYTE_PTR pOutput,
+ CK_ULONG_PTR pulOutputLen, const CryptParams& params);
+
+ void performRSAOp(CKYBuffer *out, const CKYBuffer *input, CKYByte keyNum,
+ CKYByte direction);
+
+ void processComputeCrypt(CKYBuffer *result, const CKYAPDU *apdu);
+
+ CKYByte objectHandleToKeyNum(CK_OBJECT_HANDLE hKey);
+ Slot(const Slot &cpy)
+#ifdef USE_SHMEM
+ : shmem(readerName)
+#endif
+ {} // not allowed
+ Slot &operator=(const Slot &cpy) { return *this; } // not allowed
+ public:
+ Slot(const char *readerName, Log *log, CKYCardContext* context);
+ ~Slot();
+
+ // Returns TRUE if the token is present from the point of view of PKCS #11.
+ // This will occur if a card is present, our applet is selectable,
+ // and the applet is in a personalized state.
+ bool isTokenPresent();
+
+ CK_RV getSlotInfo(CK_SLOT_INFO_PTR pSlotInfo);
+ CK_RV getTokenInfo(CK_TOKEN_INFO_PTR pTokenInfo);
+
+ // future versions may have different defintions of object classes
+ // this function may need to look a applet or protocol version
+ // to parse things correctly. Right now the class is a single character
+ // in the top byte of the objectID. the index is the second byte
+ // in bdc ascii (values 0-9).
+ char getObjectClass(unsigned long objectID) const {
+ return (char) (objectID >> 24) & 0xff;
+ }
+ unsigned short getObjectIndex(unsigned long objectID) const {
+ return (char )((objectID >> 16) & 0xff) - '0';
+ }
+
+
+ SessionHandleSuffix openSession(Session::Type type);
+ void closeSession(SessionHandleSuffix handleSuffix);
+
+ bool isValidSession(SessionHandleSuffix handleSuffix) const;
+
+ void getSessionInfo(SessionHandleSuffix handleSuffix,
+ CK_SESSION_INFO_PTR pInfo);
+
+ void login(SessionHandleSuffix handleSuffix, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen);
+
+ void logout(SessionHandleSuffix suffix);
+
+ void findObjectsInit(SessionHandleSuffix handleSuffix,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+
+ void findObjects(SessionHandleSuffix suffix, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount);
+
+ void getAttributeValue(SessionHandleSuffix suffix,
+ CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+
+ void signInit(SessionHandleSuffix suffix, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+ void sign(SessionHandleSuffix suffix, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+
+ void decryptInit(SessionHandleSuffix suffix, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+ void decrypt(SessionHandleSuffix suffix, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pDecryptedData,
+ CK_ULONG_PTR pulDecryptedDataLen);
+
+ void seedRandom(SessionHandleSuffix suffix, CK_BYTE_PTR data,
+ CK_ULONG len);
+ void generateRandom(SessionHandleSuffix suffix, CK_BYTE_PTR data,
+ CK_ULONG len);
+};
+
+class SlotList {
+
+ private:
+ Slot **slots;
+ unsigned int numSlots;
+ Log *log;
+ CKYCardContext *context;
+ SCARD_READERSTATE *readerStates;
+ unsigned int numReaders;
+ OSLock readerListLock;
+ bool shuttingDown;
+
+
+ void decomposeSessionHandle(CK_SESSION_HANDLE hSession, CK_SLOT_ID& slotID,
+ SessionHandleSuffix& suffix) const;
+
+ /* the slot list is the list the outside world sees */
+ void updateSlotList();
+ /* the reader list is the internal list we keep. It is possible that
+ * the reader list has more readers on it than the slot list reflects.
+ * This is because we can only update the slot list if the application
+ * has called 'C_GetSlotList' with a NULL parameter */
+ void updateReaderList();
+
+ bool readerExists(const char *readerName, unsigned int *hint = 0);
+ public:
+ SlotList(Log *log);
+ ~SlotList();
+
+ void shutdown(); // close our connection so waits will return.
+ int getNumSlots() const { return numSlots; }
+ Slot* getSlot(unsigned int index) const {
+ assert( index >= 0 && index < numSlots );
+ return slots[index];
+ }
+ CK_RV getSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount);
+ CK_RV getInfo(CK_SLOT_INFO_PTR pSlotInfo) const;
+
+ void validateSlotID(CK_SLOT_ID id) const;
+
+ void waitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
+ CK_VOID_PTR pReserved);
+
+ void openSession(Session::Type type, CK_SLOT_ID slotID,
+ CK_SESSION_HANDLE_PTR phSession);
+
+ void closeSession(CK_SESSION_HANDLE sessionHandle);
+
+ bool isValidSession(CK_SESSION_HANDLE sessionID) const;
+
+ void getSessionInfo(CK_SESSION_HANDLE sessionHandle,
+ CK_SESSION_INFO_PTR pInfo);
+
+ void login(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen);
+
+ void logout(CK_SESSION_HANDLE hSession);
+
+ void findObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount);
+
+ void findObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount);
+
+ void getAttributeValue(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+ const;
+
+ void signInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+ void sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+
+ void decryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+ void decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pDecryptedData,
+ CK_ULONG_PTR pulDecryptedDataLen);
+
+ void generateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen);
+
+ void seedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen);
+
+
+};
+#endif
diff --git a/src/coolkey/test.cpp b/src/coolkey/test.cpp
new file mode 100644
index 0000000..b0c3aed
--- /dev/null
+++ b/src/coolkey/test.cpp
@@ -0,0 +1,118 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version
+ * 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK *****/
+
+#include "list.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <list>
+#include <string>
+
+using std::list;
+using std::string;
+
+void*
+operator new(unsigned int len)
+{
+ void* p = malloc(len);
+ printf("operator new(%d) returns 0x%08x\n", len, p);
+ return p;
+}
+
+void
+operator delete(void *p)
+{
+ printf("operator delete(0x%08x)\n", p);
+}
+
+void
+mylist()
+{
+ List<int> intlist;
+
+ List<int>::Iterator iter;
+
+ iter = intlist.begin();
+
+ intlist.insert(iter, 5);
+
+ iter++;
+
+ intlist.insert(iter, 7);
+
+ iter = intlist.find_item(intlist.begin(), intlist.end(), 7);
+
+ intlist.insert(iter, 9);
+
+
+ List<string> stringlist;
+
+ List<string>::Iterator siter;
+
+ siter = stringlist.begin();
+
+ string bob("hello, world");
+ bob += "5";
+ stringlist.insert(siter, bob);
+
+ siter = stringlist.begin();
+
+ string boo = *siter;
+
+ printf("boo is %s\n", boo.c_str());
+
+ stringlist.remove(siter);
+
+}
+
+void
+stllist()
+{
+ list<int> intlist;
+
+ std::list<int>::iterator iter;
+
+ iter = intlist.begin();
+
+ intlist.insert(iter, 5);
+
+ iter++;
+
+ intlist.insert(iter, 7);
+
+ intlist.insert(iter, 9);
+
+
+ list<string> stringlist;
+ std::list<string>::iterator siter;
+ siter = stringlist.begin();
+ stringlist.insert(siter, "hello, world");
+
+}
+
+int
+main(int argc, char *argv[])
+{
+ printf("Doing mylist\n");
+ mylist();
+ printf("Doing stllist\n");
+ stllist();
+ return 0;
+}
+