diff options
author | rrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0> | 2006-06-09 18:39:11 +0000 |
---|---|---|
committer | rrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0> | 2006-06-09 18:39:11 +0000 |
commit | d9119ff1fc1e32cdd060f33855c9bb0f1d12edf4 (patch) | |
tree | 4f7f4db50ea1a426fc134ae00c4706b92d807019 | |
parent | b974b595c8d60105667fce51b3e192c08f44a7bd (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.am | 84 | ||||
-rw-r--r-- | src/coolkey/Makefile.in | 726 | ||||
-rw-r--r-- | src/coolkey/PKCS11Exception.cpp | 54 | ||||
-rw-r--r-- | src/coolkey/PKCS11Exception.h | 64 | ||||
-rw-r--r-- | src/coolkey/config.mk | 81 | ||||
-rw-r--r-- | src/coolkey/coolkey.cpp | 641 | ||||
-rw-r--r-- | src/coolkey/coolkeypk11.def | 103 | ||||
-rw-r--r-- | src/coolkey/coolkeypk11.rc | 89 | ||||
-rw-r--r-- | src/coolkey/dllmain.cpp | 43 | ||||
-rw-r--r-- | src/coolkey/locking.cpp | 133 | ||||
-rw-r--r-- | src/coolkey/locking.h | 94 | ||||
-rw-r--r-- | src/coolkey/log.cpp | 83 | ||||
-rw-r--r-- | src/coolkey/log.h | 56 | ||||
-rw-r--r-- | src/coolkey/machdep.cpp | 424 | ||||
-rw-r--r-- | src/coolkey/machdep.h | 57 | ||||
-rw-r--r-- | src/coolkey/manifest.mn | 46 | ||||
-rw-r--r-- | src/coolkey/mypkcs11.h | 52 | ||||
-rw-r--r-- | src/coolkey/object.cpp | 1065 | ||||
-rw-r--r-- | src/coolkey/object.h | 205 | ||||
-rw-r--r-- | src/coolkey/params.h | 49 | ||||
-rw-r--r-- | src/coolkey/pkcs11.h | 302 | ||||
-rw-r--r-- | src/coolkey/pkcs11f.h | 917 | ||||
-rw-r--r-- | src/coolkey/pkcs11n.h | 76 | ||||
-rw-r--r-- | src/coolkey/pkcs11t.h | 1354 | ||||
-rw-r--r-- | src/coolkey/slot.cpp | 3192 | ||||
-rw-r--r-- | src/coolkey/slot.h | 597 | ||||
-rw-r--r-- | src/coolkey/test.cpp | 118 |
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; +} + |