summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d0e9cb6)
raw | patch | inline | side by side (parent: d0e9cb6)
author | Sajesh Kumar Saran <sajesh@ti.com> | |
Fri, 4 Jan 2013 23:35:04 +0000 (18:35 -0500) | ||
committer | Sajesh Kumar Saran <sajesh@ti.com> | |
Fri, 4 Jan 2013 23:35:04 +0000 (18:35 -0500) |
336 files changed:
diff --git a/AUTHORS b/AUTHORS
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,7 @@
+$Id: AUTHORS 6722 2012-10-04 10:26:21Z roland $
+
+* Developers
+
+Rickard Bellgrim (.SE, The Internet Infrastructure Foundation, www.iis.se)
+René Post (XPT Software and Consulting, www.xpt.nl)
+Roland van Rijswijk (SURFnet bv, www.surfnet.nl)
diff --git a/LICENSE b/LICENSE
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+$Id: LICENSE 4954 2011-04-15 08:01:06Z jakob $
+
+Copyright (c) 2010 .SE, The Internet Infrastructure Foundation
+ http://www.iis.se
+
+Copyright (c) 2010 SURFnet bv
+ http://www.surfnet.nl/en
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile.am b/Makefile.am
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,17 @@
+# $Id: Makefile.am 6757 2012-10-22 19:40:31Z rb $
+
+ACLOCAL_AMFLAGS = -I m4
+
+MAINTAINERCLEANFILES = \
+ config.log config.status \
+ $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/config.h.in~ \
+ $(srcdir)/configure \
+ $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \
+ $(srcdir)/depcomp $(srcdir)/aclocal.m4 $(srcdir)/compile \
+ $(srcdir)/config.guess $(srcdir)/config.sub
+
+SUBDIRS = src
+
+EXTRA_DIST = $(srcdir)/m4/*.m4 \
+ $(srcdir)/LICENSE
diff --git a/NEWS b/NEWS
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,8 @@
+$Id: NEWS 4954 2011-04-15 08:01:06Z jakob $
+
+NEWS for SoftHSM -- History of user visible changes
+
+SoftHSM 2.0.0a - 2010-XX-XX
+
+* ...
+* ...
diff --git a/README b/README
--- /dev/null
+++ b/README
@@ -0,0 +1,94 @@
+$Id: README 6773 2012-10-24 16:21:48Z rb $
+
+ SoftHSM is part of the OpenDNSSEC project.
+ Read more at www.opendnssec.org
+
+INTRODUCTION
+
+ OpenDNSSEC handles and stores its cryptographic keys via the PKCS#11
+ interface. This interface specifies how to communicate with cryptographic
+ devices such as HSM:s (Hardware Security Modules) and smart cards. The
+ purpose of these devices is, among others, to generate cryptographic keys
+ and sign information without revealing private-key material to the outside
+ world. They are often designed to perform well on these specific tasks
+ compared to ordinary processes in a normal computer.
+
+ A potential problem with the use of the PKCS#11 interface is that it might
+ limit the wide spread use of OpenDNSSEC, since a potential user might not
+ be willing to invest in a new hardware device. To counter this effect,
+ OpenDNSSEC is providing a software implementation of a generic
+ cryptographic device with a PKCS#11 interface, the SoftHSM. SoftHSM is
+ designed to meet the requirements of OpenDNSSEC, but can also work together
+ with other cryptographic products because of the PKCS#11 interface.
+
+DEPENDENCIES
+
+ SoftHSM depends on a cryptographic library, Botan or OpenSSL.
+ Minimum required versions:
+ * Botan 1.10.0
+ * OpenSSL 0.9.8
+
+ There is a migration tool for converting token databases from SoftHSMv1
+ into the new type of tokens. If this tool is built, then SQLite3 is
+ required (>= 3.4.2).
+
+INSTALLING
+
+ 1. Configure the installation/compilation scripts.
+
+ ./configure
+
+ Options:
+
+ --disable-non-paged-memory
+ Disable non-paged memory for secure storage
+ (default enabled)
+ --with-crypto-backend Select crypto backend (openssl|botan)
+ --with-openssl=PATH Specify prefix of path of OpenSSL
+ --with-botan=PATH Specify prefix of path of Botan
+ --with-loglevel=INT The log level. 0=No log 1=Error 2=Warning 3=Info
+ 4=Debug (default INT=3)
+ --with-migrate Build the migration tool. Used when migrating
+ a SoftHSM v1 token database. Requires SQLite3.
+ --with-sqlite3=PATH Specify prefix of path of SQLite3
+
+ For more options:
+
+ ./configure --help
+
+ 2. Compile the source code.
+
+ make
+
+ 3. Install the library.
+
+ sudo make install
+
+ 4. Location of the configuration file.
+
+ The default location of the config file is /etc/softhsm2.conf
+ This location can be change by setting the environment variable.
+
+ export SOFTHSM2_CONF=/home/user/config.file
+
+ Details on the configuration can be found in "man softhsm2.conf".
+
+ 5. Initialize your tokens.
+
+ Use either softhsm-util or the PKCS#11 interface. The SO PIN can e.g.
+ be used to re-initialize the token and the user PIN is handed out to the
+ application so it can interact with the token.
+
+ softhsm-util --init-token --slot 0 --label "My token 1"
+
+ Type in SO PIN and user PIN.
+
+ Once a token has been initialized, more slots will be added automatically
+ with a new uninitialized token.
+
+ 6. Link to this library and use the PKCS#11 interface.
+
+BACKUP
+
+ All of the tokens and their objects are stored in the location given by
+ softhsm2.conf. Backup can thus be done as a regular file copy.
diff --git a/README.svn b/README.svn
--- /dev/null
+++ b/README.svn
@@ -0,0 +1,10 @@
+$Id: README.svn 4954 2011-04-15 08:01:06Z jakob $
+
+If the code is downloaded directly from the SVN, then you have to prepare the
+configuration scripts before continuing with the real README.
+
+1. You need to install automake, autoconf, libtool, etc.
+
+2. Run the command 'sh autogen.sh'
+
+3. Continue reading in the file README.
diff --git a/README.txt b/README.txt
--- a/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-Initial temporary file
diff --git a/autogen.sh b/autogen.sh
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+#
+# $Id: autogen.sh 4954 2011-04-15 08:01:06Z jakob $
+
+autoreconf --install --force
diff --git a/configure.ac b/configure.ac
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,186 @@
+dnl
+dnl $Id: configure.ac 6757 2012-10-22 19:40:31Z rb $
+dnl
+
+##################
+# #
+# Version #
+# #
+################
+
+# Program version
+
+define([SOFTHSM_VERSION_MAJOR], [2])
+define([SOFTHSM_VERSION_MINOR], [0])
+define([SOFTHSM_VERSION_FIX], [0])
+define([PACKAGE_SUFFIX], [a1])
+
+# Library version
+
+# Code changed: SOFTHSM_VERSION_REVISION++
+# Interface added/removed/changed: SOFTHSM_VERSION_CURRENT++, SOFTHSM_VERSION_REVISION=0
+# Interface added: SOFTHSM_VERSION_AGE++
+# Interface removed: SOFTHSM_VERSION_AGE=0
+
+define([SOFTHSM_VERSION_CURRENT], [2])
+define([SOFTHSM_VERSION_AGE], [1])
+define([SOFTHSM_VERSION_REVISION], [0])
+
+##################
+# #
+# Configure code #
+# #
+##################
+
+# Init
+AC_PREREQ(2.61)
+AC_INIT([SoftHSM],[SOFTHSM_VERSION_MAJOR.SOFTHSM_VERSION_MINOR.SOFTHSM_VERSION_FIX[]PACKAGE_SUFFIX])
+AC_CONFIG_HEADER([config.h])
+AC_CONFIG_SRCDIR([src/Makefile.am])
+AC_CONFIG_MACRO_DIR([m4])
+AM_INIT_AUTOMAKE(foreign)
+ACX_PREFIXHACK
+
+# Version info for the library
+VERSION_INFO="SOFTHSM_VERSION_CURRENT:SOFTHSM_VERSION_REVISION:SOFTHSM_VERSION_AGE"
+AC_SUBST(VERSION_INFO)
+
+# Checks for compilers
+AC_PROG_CC
+AC_PROG_CXX
+
+# Compiler flags
+ACX_PEDANTIC
+ACX_STRICT
+
+# What crypto backend to use and if we want to have support GOST
+ACX_CRYPTO_BACKEND
+
+# Non-paged memory for secure storage
+ACX_NON_PAGED_MEMORY
+
+# Log level
+AC_ARG_WITH(
+ [loglevel],
+ [AS_HELP_STRING([--with-loglevel=INT],[The log level. 0=No log 1=Error 2=Warning 3=Info 4=Debug (default INT=3)])],
+ [SOFTLOGLEVEL="$withval"],
+ [SOFTLOGLEVEL=3]
+)
+
+# If the user want to have the migration tool
+# Requires SQLite3
+AC_ARG_WITH(migrate,
+ AC_HELP_STRING([--with-migrate],
+ [Build the migration tool. Requires SQLite3.]
+ ),
+ [build_migrate="${withval}"],
+ [build_migrate="no"]
+)
+AC_MSG_CHECKING(if building with softhsm-migrate)
+if test "x${build_migrate}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ ACX_SQLITE3
+ ACX_YIELD
+else
+ AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL([BUILD_MIGRATE], [test "x${build_migrate}" = "xyes"])
+
+# Check for libraries
+ACX_DLOPEN
+ACX_SEMAPHORE
+
+# Check for headers
+AC_CHECK_HEADERS([pthread.h])
+
+# Set full directory paths
+full_sysconfdir=`eval eval eval eval eval echo "${sysconfdir}" | sed "s#NONE#${prefix}#" | sed "s#NONE#${ac_default_prefix}#"`
+full_localstatedir=`eval eval eval eval eval echo "${localstatedir}" | sed "s#NONE#${prefix}#" | sed "s#NONE#${ac_default_prefix}#"`
+full_libdir=`eval eval eval eval eval echo "${libdir}" | sed "s#NONE#${prefix}#" | sed "s#NONE#${ac_default_prefix}#"`
+default_softhsm2_conf="`eval echo ${full_sysconfdir} | sed s,NONE,$ac_default_prefix,g`/softhsm2.conf"
+softhsmtokendir=${full_localstatedir}/lib/softhsm/tokens/
+
+# Install the library in a sub-directory
+full_libdir="$full_libdir/softhsm"
+libdir=$full_libdir
+
+# Define some variables for the code
+AC_DEFINE_UNQUOTED(
+ [VERSION_MAJOR],
+ [SOFTHSM_VERSION_MAJOR],
+ [SoftHSM major version number via PKCS#11]
+)
+AC_DEFINE_UNQUOTED(
+ [VERSION_MINOR],
+ [SOFTHSM_VERSION_MINOR],
+ [SoftHSM minor version number via PKCS#11]
+)
+AC_DEFINE_UNQUOTED(
+ [SOFTLOGLEVEL],
+ [$SOFTLOGLEVEL],
+ [The log level set by the user]
+)
+AC_DEFINE_UNQUOTED(
+ [MAX_PIN_LEN],
+ [255],
+ [Maximum PIN length]
+)
+AC_DEFINE_UNQUOTED(
+ [MIN_PIN_LEN],
+ [4],
+ [Minimum PIN length]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_SOFTHSM2_CONF],
+ ["$default_softhsm2_conf"],
+ [The default location of softhsm2.conf]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_TOKENDIR],
+ ["$softhsmtokendir"],
+ [The default location of the token directory]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_PKCS11_LIB],
+ ["$full_libdir/libsofthsm.so"],
+ [The default PKCS#11 library]
+)
+
+AC_SUBST([softhsmtokendir])
+AC_SUBST([default_softhsm2_conf])
+
+# Generate the libtool script and install script
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+# Generate the makefiles
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ src/lib/Makefile
+ src/lib/common/Makefile
+ src/lib/common/softhsm2.conf
+ src/lib/common/softhsm2.conf.5
+ src/lib/crypto/Makefile
+ src/lib/crypto/test/Makefile
+ src/lib/data_mgr/Makefile
+ src/lib/data_mgr/test/Makefile
+ src/lib/object_store/Makefile
+ src/lib/object_store/test/Makefile
+ src/lib/session_mgr/Makefile
+ src/lib/session_mgr/test/Makefile
+ src/lib/slot_mgr/Makefile
+ src/lib/slot_mgr/test/Makefile
+ src/lib/handle_mgr/Makefile
+ src/lib/handle_mgr/test/Makefile
+ src/lib/test/Makefile
+ src/lib/test/softhsm2.conf
+ src/lib/test/tokens/dummy
+ src/bin/Makefile
+ src/bin/common/Makefile
+ src/bin/keyconv/Makefile
+ src/bin/migrate/Makefile
+ src/bin/util/Makefile
+])
+
+AC_OUTPUT
diff --git a/m4/acx_botan.m4 b/m4/acx_botan.m4
--- /dev/null
+++ b/m4/acx_botan.m4
@@ -0,0 +1,54 @@
+# $Id$
+
+AC_DEFUN([ACX_BOTAN],[
+ AC_ARG_WITH(botan,
+ AC_HELP_STRING([--with-botan=PATH],[Specify prefix of path of Botan]),
+ [
+ BOTAN_PATH="$withval"
+ ],
+ [
+ BOTAN_PATH="/usr/local"
+ ])
+
+ AC_MSG_CHECKING(what are the Botan includes)
+ BOTAN_INCLUDES="-I$BOTAN_PATH/include/botan-1.10"
+ AC_MSG_RESULT($BOTAN_INCLUDES)
+
+ AC_MSG_CHECKING(what are the Botan libs)
+ BOTAN_LIBS="-L$BOTAN_PATH/lib -lbotan-1.10"
+ AC_MSG_RESULT($BOTAN_LIBS)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $BOTAN_INCLUDES"
+ LIBS="$LIBS $BOTAN_LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <botan/init.h>
+ #include <botan/pipe.h>
+ #include <botan/filters.h>
+ #include <botan/hex.h>
+ #include <botan/sha2_32.h>
+ #include <botan/emsa3.h>
+ #include <botan/version.h>],
+ [using namespace Botan;
+ LibraryInitializer::initialize();
+ new EMSA3_Raw();
+ #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR($1,$2,$3)
+ #error "Botan version too old";
+ #endif])],
+ [AC_MSG_RESULT([checking for Botan >= v$1.$2.$3 ... yes])],
+ [AC_MSG_RESULT([checking for Botan >= v$1.$2.$3 ... no])
+ AC_MSG_ERROR([Missing the correct version of the Botan library])]
+ )
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+
+ AC_SUBST(BOTAN_INCLUDES)
+ AC_SUBST(BOTAN_LIBS)
+])
diff --git a/m4/acx_crypto_backend.m4 b/m4/acx_crypto_backend.m4
--- /dev/null
+++ b/m4/acx_crypto_backend.m4
@@ -0,0 +1,85 @@
+# $Id$
+
+AC_DEFUN([ACX_CRYPTO_BACKEND],[
+
+ # First check if we want to support GOST
+
+ AC_ARG_ENABLE(gost,
+ AC_HELP_STRING([--enable-gost],
+ [Enable support for GOST (default disabled)]
+ ),
+ [enable_gost="${enableval}"],
+ [enable_gost="no"]
+ )
+ AC_MSG_CHECKING(for GOST support)
+ if test "x${enable_gost}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(
+ [WITH_GOST],
+ [],
+ [Compile with GOST support]
+ )
+ else
+ AC_MSG_RESULT(no)
+ fi
+ AM_CONDITIONAL([WITH_GOST], [test "x${enable_gost}" = "xyes"])
+
+ # Then check what crypto library we want to use
+
+ AC_ARG_WITH(crypto-backend,
+ AC_HELP_STRING([--with-crypto-backend],
+ [Select crypto backend (openssl|botan)]
+ ),
+ [crypto_backend="${withval}"],
+ [crypto_backend="openssl"]
+ )
+
+ AC_MSG_CHECKING(for crypto backend)
+
+ if test "x${crypto_backend}" = "xopenssl"; then
+ AC_MSG_RESULT(OpenSSL)
+
+ if test "x${enable_gost}" = "xyes"; then
+ ACX_OPENSSL(1,0,0)
+ else
+ ACX_OPENSSL(0,9,8)
+ fi
+
+ CRYPTO_INCLUDES=$OPENSSL_INCLUDES
+ CRYPTO_LIBS=$OPENSSL_LIBS
+
+ AC_DEFINE_UNQUOTED(
+ [WITH_OPENSSL],
+ [],
+ [Compile with OpenSSL support]
+ )
+
+ elif test "x${crypto_backend}" = "xbotan"; then
+ AC_MSG_RESULT(Botan)
+
+ if test "x${enable_gost}" = "xyes"; then
+ ACX_BOTAN(1,10,0)
+ else
+ ACX_BOTAN(1,10,0)
+ fi
+
+ CRYPTO_INCLUDES=$BOTAN_INCLUDES
+ CRYPTO_LIBS=$BOTAN_LIBS
+
+ AC_DEFINE_UNQUOTED(
+ [WITH_BOTAN],
+ [],
+ [Compile with Botan support]
+ )
+
+ else
+ AC_MSG_RESULT(Unknown)
+ AC_MSG_ERROR([Crypto backend ${crypto_backend} not supported. Use openssl or botan.])
+ fi
+
+ AC_SUBST(CRYPTO_INCLUDES)
+ AC_SUBST(CRYPTO_LIBS)
+ AM_CONDITIONAL([WITH_OPENSSL], [test "x${crypto_backend}" = "xopenssl"])
+ AM_CONDITIONAL([WITH_BOTAN], [test "x${crypto_backend}" = "xbotan"])
+
+])
diff --git a/m4/acx_dlopen.m4 b/m4/acx_dlopen.m4
--- /dev/null
+++ b/m4/acx_dlopen.m4
@@ -0,0 +1,17 @@
+# $Id: acx_dlopen.m4 4829 2010-07-29 11:29:33Z rb $
+
+AC_DEFUN([ACX_DLOPEN],[
+ AC_CHECK_FUNC(dlopen, [AC_DEFINE(HAVE_DLOPEN,1,[Define if you have dlopen])],
+ [
+ AC_CHECK_LIB([dl],[dlopen],
+ [AC_DEFINE(HAVE_DLOPEN,1,[Define if you have dlopen])
+ LIBS="$LIBS -ldl"],
+ [AC_CHECK_FUNC(LoadLibrary,
+ [if test $ac_cv_func_LoadLibrary = yes; then
+ AC_DEFINE(HAVE_LOADLIBRARY, 1, [Whether LoadLibrary is available])
+ fi
+ ], [AC_MSG_ERROR(No dynamic library loading support)]
+ )]
+ )
+ ])
+])
diff --git a/m4/acx_non_paged_memory.m4 b/m4/acx_non_paged_memory.m4
--- /dev/null
@@ -0,0 +1,59 @@
+# $Id$
+
+AC_DEFUN([ACX_NON_PAGED_MEMORY],[
+
+ AC_ARG_ENABLE(non-paged-memory,
+ AC_HELP_STRING([--disable-non-paged-memory],
+ [Disable non-paged memory for secure storage (default enabled)]
+ ),
+ [enable_non_paged_memory="${enableval}"],
+ [enable_non_paged_memory="yes"]
+ )
+
+ AC_MSG_CHECKING(for non-paged memory for secure storage)
+
+ if test "x${enable_non_paged_memory}" = "xyes"; then
+ AC_MSG_RESULT(enabled)
+ AC_DEFINE_UNQUOTED(
+ [SENSITIVE_NON_PAGE],
+ [],
+ [Non-paged memory for secure storage]
+ )
+ AC_CHECK_HEADERS([sys/mman.h])
+
+ AC_MSG_CHECKING(the maximum size that may be locked into memory)
+ MLOCK_SIZE="`ulimit -l`"
+ AC_MSG_RESULT($MLOCK_SIZE)
+
+ if test "x${MLOCK_SIZE}" != "xunlimited"; then
+ AC_MSG_WARN([
+======================================================================
+SoftHSM has been configured to store sensitive data in non-page RAM
+(i.e. memory that is not swapped out to disk). This is the default and
+most secure configuration. Your system, however, is not configured to
+support this model in non-privileged accounts (i.e. user accounts).
+
+You can check the setting on your system by running the following
+command in a shell:
+
+ ulimit -l
+
+If this does not return "unlimited" and you plan to run SoftHSM from
+non-privileged accounts then you should edit the configuration file
+/etc/security/limits.conf (on most systems).
+
+You will need to add the following lines to this file:
+
+#<domain> <type> <item> <value>
+* - memlock unlimited
+
+Alternatively, you can elect to disable this feature of SoftHSM by
+re-running configure with the option "--disable-non-paged-memory".
+Please be advised that this may seriously degrade the security of
+SoftHSM.
+======================================================================])
+ fi
+ else
+ AC_MSG_RESULT(disabled)
+ fi
+])
diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4
--- /dev/null
+++ b/m4/acx_openssl.m4
@@ -0,0 +1,62 @@
+# $Id$
+
+AC_DEFUN([ACX_OPENSSL],[
+ AC_ARG_WITH(openssl,
+ AC_HELP_STRING([--with-openssl=PATH],[Specify prefix of path of OpenSSL]),
+ [
+ OPENSSL_PATH="$withval"
+ ],
+ [
+ OPENSSL_PATH="/usr/local"
+ ])
+
+ AC_MSG_CHECKING(what are the OpenSSL includes)
+ OPENSSL_INCLUDES="-I$OPENSSL_PATH/include"
+ AC_MSG_RESULT($OPENSSL_INCLUDES)
+
+ AC_MSG_CHECKING(what are the OpenSSL libs)
+ OPENSSL_LIBS="-L$OPENSSL_PATH/lib -lcrypto"
+ AC_MSG_RESULT($OPENSSL_LIBS)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $OPENSSL_INCLUDES"
+ LIBS="$LIBS $OPENSSL_LIBS"
+
+ AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([Can't find OpenSSL headers])])
+ AC_CHECK_LIB(crypto, BN_init,,[AC_MSG_ERROR([Can't find OpenSSL library])])
+
+ AC_MSG_CHECKING([for OpenSSL version])
+ CHECK_OPENSSL_VERSION=m4_format(0x%02x%02x%02x000L, $1, $2, $3)
+ AC_LANG_PUSH([C])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/ssl.h>
+ #include <openssl/opensslv.h>
+ int main()
+ {
+ #ifndef OPENSSL_VERSION_NUMBER
+ return -1;
+ #endif
+ #if OPENSSL_VERSION_NUMBER >= $CHECK_OPENSSL_VERSION
+ return 0;
+ #else
+ return 1;
+ #endif
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([>= $1.$2.$3])
+ ],[
+ AC_MSG_RESULT([< $1.$2.$3])
+ AC_MSG_ERROR([OpenSSL library too old ($1.$2.$3 or later required)])
+ ],[])
+ AC_LANG_POP([C])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+
+ AC_SUBST(OPENSSL_INCLUDES)
+ AC_SUBST(OPENSSL_LIBS)
+])
diff --git a/m4/acx_pedantic.m4 b/m4/acx_pedantic.m4
--- /dev/null
+++ b/m4/acx_pedantic.m4
@@ -0,0 +1,14 @@
+# $Id: acx_pedantic.m4 4747 2010-03-05 11:48:53Z rb $
+
+AC_DEFUN([ACX_PEDANTIC],[
+ AC_ARG_ENABLE(
+ [pedantic],
+ [AS_HELP_STRING([--enable-pedantic],[enable pedantic compile mode @<:@enabled@:>@])],
+ ,
+ [enable_pedantic="yes"]
+ )
+ if test "${enable_pedantic}" = "yes"; then
+ enable_strict="yes";
+ CFLAGS="${CFLAGS} -pedantic"
+ fi
+])
diff --git a/m4/acx_prefixhack.m4 b/m4/acx_prefixhack.m4
--- /dev/null
+++ b/m4/acx_prefixhack.m4
@@ -0,0 +1,25 @@
+# $Id: acx_prefixhack.m4 4747 2010-03-05 11:48:53Z rb $
+#
+# Special processing of paths depending on whether --prefix,
+# --sysconfdir or --localstatedir arguments were given.
+
+AC_DEFUN([ACX_PREFIXHACK],[
+ case "$prefix" in
+ NONE)
+ case "$sysconfdir" in
+ '${prefix}/etc')
+ sysconfdir=/etc
+ ac_configure_args="$ac_configure_args --sysconfdir=$sysconfdir"
+ AC_MSG_NOTICE([sysconfdir set to $sysconfdir])
+ ;;
+ esac
+ case "$localstatedir" in
+ '${prefix}/var')
+ localstatedir=/var
+ ac_configure_args="$ac_configure_args --localstatedir=$localstatedir"
+ AC_MSG_NOTICE([localstate set to $localstatedir])
+ ;;
+ esac
+ ;;
+ esac
+])
diff --git a/m4/acx_semaphore.m4 b/m4/acx_semaphore.m4
--- /dev/null
+++ b/m4/acx_semaphore.m4
@@ -0,0 +1,52 @@
+# $Id: acx_semaphore.m4 6718 2012-10-02 10:10:50Z rene $
+
+AC_DEFUN([ACX_SEMAPHORE],[
+ SEMAPHORE_LIB=
+
+ AC_CHECK_LIB(
+ rt,
+ sem_open,
+ [
+ AC_CHECK_LIB(rt, sem_close, [], AC_MSG_ERROR([Could not find sem_close]))
+ AC_CHECK_LIB(rt, sem_unlink, [], AC_MSG_ERROR([Could not find sem_unlink]))
+ AC_CHECK_LIB(rt, sem_post, [], AC_MSG_ERROR([Could not find sem_post]))
+ AC_CHECK_LIB(rt, sem_wait, [], AC_MSG_ERROR([Could not find sem_wait]))
+ AC_CHECK_LIB(rt, sem_trywait, [], AC_MSG_ERROR([Could not find sem_trywait]))
+ AC_CHECK_LIB(rt, sem_getvalue, [], AC_MSG_ERROR([Could not find sem_getvalue]))
+ SEMAPHORE_LIB=-lrt
+ ],
+ [
+ AC_CHECK_LIB(
+ posix4,
+ sem_open,
+ [
+ AC_CHECK_LIB(posix4, sem_close, [], AC_MSG_ERROR([Could not find sem_close]))
+ AC_CHECK_LIB(posix4, sem_unlink, [], AC_MSG_ERROR([Could not find sem_unlink]))
+ AC_CHECK_LIB(posix4, sem_post, [], AC_MSG_ERROR([Could not find sem_post]))
+ AC_CHECK_LIB(posix4, sem_wait, [], AC_MSG_ERROR([Could not find sem_wait]))
+ AC_CHECK_LIB(posix4, sem_trywait, [], AC_MSG_ERROR([Could not find sem_trywait]))
+ AC_CHECK_LIB(posix4, sem_getvalue, [], AC_MSG_ERROR([Could not find sem_getvalue]))
+ SEMAPHORE_LIB=-lposix4
+ ],
+ [
+ AC_CHECK_LIB(
+ pthread,
+ sem_open,
+ [
+ AC_CHECK_LIB(pthread, sem_close, [], AC_MSG_ERROR([Could not find sem_close]))
+ AC_CHECK_LIB(pthread, sem_unlink, [], AC_MSG_ERROR([Could not find sem_unlink]))
+ AC_CHECK_LIB(pthread, sem_post, [], AC_MSG_ERROR([Could not find sem_post]))
+ AC_CHECK_LIB(pthread, sem_wait, [], AC_MSG_ERROR([Could not find sem_wait]))
+ AC_CHECK_LIB(pthread, sem_trywait, [], AC_MSG_ERROR([Could not find sem_trywait]))
+ AC_CHECK_LIB(pthread, sem_getvalue, [], AC_MSG_ERROR([Could not find sem_getvalue]))
+ SEMAPHORE_LIB=-lpthread
+ ]
+ )
+ ]
+ )
+ ]
+ )
+ AC_SUBST([SEMAPHORE_LIB])
+
+ AC_CHECK_HEADERS([fcntl.h sys/stat.h])
+])
diff --git a/m4/acx_sqlite3.m4 b/m4/acx_sqlite3.m4
--- /dev/null
+++ b/m4/acx_sqlite3.m4
@@ -0,0 +1,42 @@
+# $Id: acx_sqlite3.m4 4838 2010-08-09 13:09:21Z rb $
+
+AC_DEFUN([ACX_SQLITE3],[
+ AC_ARG_WITH(sqlite3,
+ AC_HELP_STRING([--with-sqlite3=PATH],[Specify prefix of path of SQLite3]),
+ [
+ SQLITE3_PATH="$withval"
+ AC_PATH_PROGS(SQLITE3, sqlite3, sqlite3, $withval/bin)
+
+ ],[
+ SQLITE3_PATH="/usr/local"
+ AC_PATH_PROGS(SQLITE3, sqlite3, sqlite3, $PATH)
+ ])
+
+
+ if ! test -x "$SQLITE3"; then
+ AC_MSG_ERROR([sqlite3 command not found])
+ fi
+
+ AC_MSG_CHECKING(what are the SQLite3 includes)
+ SQLITE3_INCLUDES="-I$SQLITE3_PATH/include"
+ AC_MSG_RESULT($SQLITE3_INCLUDES)
+
+ AC_MSG_CHECKING(what are the SQLite3 libs)
+ SQLITE3_LIBS="-L$SQLITE3_PATH/lib -lsqlite3"
+ AC_MSG_RESULT($SQLITE3_LIBS)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $SQLITE3_INCLUDES"
+ LIBS="$LIBS $SQLITE3_LIBS"
+
+ AC_CHECK_HEADERS(sqlite3.h,,[AC_MSG_ERROR([Can't find SQLite3 headers])])
+ AC_CHECK_LIB(sqlite3, sqlite3_prepare_v2, [], [AC_MSG_ERROR([Missing SQLite3 library v3.4.2 or greater])])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+
+ AC_SUBST(SQLITE3_INCLUDES)
+ AC_SUBST(SQLITE3_LIBS)
+])
diff --git a/m4/acx_strict.m4 b/m4/acx_strict.m4
--- /dev/null
+++ b/m4/acx_strict.m4
@@ -0,0 +1,13 @@
+# $Id: acx_strict.m4 4747 2010-03-05 11:48:53Z rb $
+
+AC_DEFUN([ACX_STRICT],[
+ AC_ARG_ENABLE(
+ [strict],
+ [AS_HELP_STRING([--enable-strict],[enable strict compile mode @<:@enabled@:>@])],
+ ,
+ [enable_strict="yes"]
+ )
+ if test "${enable_strict}" = "yes"; then
+ CFLAGS="${CFLAGS} -Wall -Wextra"
+ fi
+])
diff --git a/m4/acx_yield.m4 b/m4/acx_yield.m4
--- /dev/null
+++ b/m4/acx_yield.m4
@@ -0,0 +1,12 @@
+# $Id: acx_yield.m4 4857 2010-08-23 08:42:09Z rb $
+
+AC_DEFUN([ACX_YIELD],[
+ YIELD_LIB=
+ # Solaris has sched_yield in librt, not in libpthread or libc.
+ # Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt.
+ AC_CHECK_LIB(rt, sched_yield, [YIELD_LIB=-lrt],
+ [AC_CHECK_LIB(posix4, sched_yield, [YIELD_LIB=-lposix4])])
+ AC_SUBST([YIELD_LIB])
+
+ AC_CHECK_HEADER([sched.h])
+])
diff --git a/src/Makefile.am b/src/Makefile.am
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,5 @@
+# $Id$
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+SUBDIRS = bin lib
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
--- /dev/null
+++ b/src/bin/Makefile.am
@@ -0,0 +1,9 @@
+# $Id: Makefile.am 4840 2010-08-10 12:05:40Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+SUBDIRS = common keyconv util
+
+if BUILD_MIGRATE
+SUBDIRS += migrate
+endif
diff --git a/src/bin/common/Makefile.am b/src/bin/common/Makefile.am
--- /dev/null
@@ -0,0 +1,5 @@
+# $Id: Makefile.am 4840 2010-08-10 12:05:40Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/bin/common/getpw.cpp b/src/bin/common/getpw.cpp
--- /dev/null
+++ b/src/bin/common/getpw.cpp
@@ -0,0 +1,128 @@
+/* $Id: getpw.cpp 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ getpw.cpp
+
+ Helper function to get a password from the user
+ *****************************************************************************/
+
+#include <config.h>
+#include "getpw.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Get a password from the user
+void getPW(char* pin, char* newPIN, CK_ULONG userType)
+{
+ // Keep a copy of the PIN because getpass/getpassphrase
+ // will overwrite the previous PIN.
+ char password[MAX_PIN_LEN+1];
+
+ int length = 0;
+
+ if (pin)
+ {
+ length = strlen(pin);
+ }
+
+ while (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
+ {
+ if (userType == CKU_SO)
+ {
+ printf("*** SO PIN (%i-%i characters) ***\n",
+ MIN_PIN_LEN, MAX_PIN_LEN);
+ }
+ else
+ {
+ printf("*** User PIN (%i-%i characters) ***\n",
+ MIN_PIN_LEN, MAX_PIN_LEN);
+ }
+
+#ifdef HAVE_GETPASSPHRASE
+ if (userType == CKU_SO)
+ {
+ pin = getpassphrase("Please enter SO PIN: ");
+ }
+ else
+ {
+ pin = getpassphrase("Please enter user PIN: ");
+ }
+#else
+ if (userType == CKU_SO)
+ {
+ pin = getpass("Please enter SO PIN: ");
+ }
+ else
+ {
+ pin = getpass("Please enter user PIN: ");
+ }
+#endif
+
+ length = strlen(pin);
+ if (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
+ {
+ fprintf(stderr, "ERROR: The length of the PIN is out of range.\n");
+ length = 0;
+ continue;
+ }
+ strcpy(password, pin);
+
+#ifdef HAVE_GETPASSPHRASE
+ if (userType == CKU_SO)
+ {
+ pin = getpassphrase("Please reenter SO PIN: ");
+ }
+ else
+ {
+ pin = getpassphrase("Please reenter user PIN: ");
+ }
+#else
+ if (userType == CKU_SO)
+ {
+ pin = getpass("Please reenter SO PIN: ");
+ }
+ else
+ {
+ pin = getpass("Please reenter user PIN: ");
+ }
+#endif
+
+ if (strcmp(password, pin))
+ {
+ fprintf(stderr, "ERROR: The entered PINs are not equal.\n");
+ length = 0;
+ continue;
+ }
+ }
+
+ strcpy(newPIN, pin);
+}
diff --git a/src/bin/common/getpw.h b/src/bin/common/getpw.h
--- /dev/null
+++ b/src/bin/common/getpw.h
@@ -0,0 +1,42 @@
+/* $Id: getpw.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ getpw.h
+
+ Helper function to get a password from the user
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_GETPW_H
+#define _SOFTHSM_V2_BIN_GETPW_H
+
+#include "pkcs11.h"
+
+void getPW(char* pin, char* newPIN, CK_ULONG userType);
+
+#endif // !_SOFTHSM_V2_BIN_GETPW_H
diff --git a/src/bin/common/library.cpp b/src/bin/common/library.cpp
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: library.cpp 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ library.cpp
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#include <config.h>
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_DLOPEN)
+#include <dlfcn.h>
+#endif
+
+// Load the PKCS#11 library
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle)
+{
+ CK_C_GetFunctionList pGetFunctionList = NULL;
+
+#if defined(HAVE_LOADLIBRARY)
+ HINSTANCE hDLL = NULL;
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ HINSTANCE hDLL = LoadLibrary(_T(module));
+ }
+ else
+ {
+ HINSTANCE hDLL = LoadLibrary(_T(DEFAULT_PKCS11_LIB));
+ }
+
+ if (hDLL == NULL)
+ {
+ // Failed to load the PKCS #11 library
+ return NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hDLL, _T("C_GetFunctionList"));
+
+#elif defined(HAVE_DLOPEN)
+ void* pDynLib = NULL;
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ pDynLib = dlopen(module, RTLD_NOW | RTLD_LOCAL);
+ }
+ else
+ {
+ pDynLib = dlopen(DEFAULT_PKCS11_LIB, RTLD_NOW | RTLD_LOCAL);
+ }
+
+ if (pDynLib == NULL)
+ {
+ // Failed to load the PKCS #11 library
+ return NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
+
+ // Store the handle so we can dlclose it later
+ *moduleHandle = pDynLib;
+
+#else
+ fprintf(stderr, "ERROR: Not compiled with library support.\n");
+
+ return NULL;
+#endif
+
+ return pGetFunctionList;
+}
+
+void unloadLibrary(void* moduleHandle)
+{
+ if (moduleHandle)
+ {
+#if defined(HAVE_LOADLIBRARY)
+ // no idea
+#elif defined(HAVE_DLOPEN)
+ dlclose(moduleHandle);
+#endif
+ }
+}
diff --git a/src/bin/common/library.h b/src/bin/common/library.h
--- /dev/null
+++ b/src/bin/common/library.h
@@ -0,0 +1,43 @@
+/* $Id: library.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ library.h
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_LIBRARY_H
+#define _SOFTHSM_V2_BIN_LIBRARY_H
+
+#include "pkcs11.h"
+
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle);
+void unloadLibrary(void* moduleHandle);
+
+#endif // !_SOFTHSM_V2_BIN_LIBRARY_H
diff --git a/src/bin/keyconv/Makefile.am b/src/bin/keyconv/Makefile.am
--- /dev/null
@@ -0,0 +1,26 @@
+# $Id: Makefile.am 4833 2010-08-03 13:21:05Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = @CRYPTO_INCLUDES@
+
+dist_man_MANS = softhsm-keyconv.1
+
+bin_PROGRAMS = softhsm-keyconv
+
+softhsm_keyconv_SOURCES = softhsm-keyconv.cpp \
+ base64.c
+softhsm_keyconv_LDADD = @CRYPTO_LIBS@
+
+# Compile with OpenSSL support
+if WITH_OPENSSL
+softhsm_keyconv_SOURCES += softhsm-keyconv-ossl.cpp
+endif
+
+# Compile with Botan support
+if WITH_BOTAN
+softhsm_keyconv_SOURCES += softhsm-keyconv-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/src/bin/keyconv/base64.c b/src/bin/keyconv/base64.c
--- /dev/null
+++ b/src/bin/keyconv/base64.c
@@ -0,0 +1,311 @@
+/* $Id: base64.c 4833 2010-08-03 13:21:05Z rb $ */
+
+/* $OpenBSD: base64.c,v 1.3 2002/06/09 08:13:07 todd Exp $ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$ISC: base64.c,v 8.6 1999/01/08 19:25:18 vixie Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(unsigned char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ unsigned char input[3];
+ unsigned char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(char const *src, unsigned char *target, size_t targsize) {
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/src/bin/keyconv/softhsm-keyconv-botan.cpp b/src/bin/keyconv/softhsm-keyconv-botan.cpp
--- /dev/null
@@ -0,0 +1,215 @@
+/* $Id: softhsm-keyconv-botan.cpp 5076 2011-05-10 14:46:06Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-keyconv-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/bigint.h>
+
+// Init Botan
+void crypto_init()
+{
+ Botan::LibraryInitializer::initialize();
+}
+
+// Final Botan
+void crypto_final()
+{
+ Botan::LibraryInitializer::deinitialize();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigE, bigP, bigQ, bigN, bigD;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigE = Botan::BigInt((Botan::byte*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size);
+ bigP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size);
+ bigQ = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size);
+ bigN = Botan::BigInt((Botan::byte*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size);
+ bigD = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+ priv_key = new Botan::RSA_PrivateKey(*rng, bigP, bigQ, bigE, bigD, bigN);
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (priv_file == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigDP, bigDQ, bigDG, bigDX;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigDP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size);
+ bigDQ = Botan::BigInt((Botan::byte*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size);
+ bigDG = Botan::BigInt((Botan::byte*)pkey[TAG_BASE].big, pkey[TAG_BASE].size);
+ bigDX = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+ priv_key = new Botan::DSA_PrivateKey(*rng, Botan::DL_Group(bigDP, bigDQ, bigDG), bigDX);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (priv_file == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
diff --git a/src/bin/keyconv/softhsm-keyconv-ossl.cpp b/src/bin/keyconv/softhsm-keyconv-ossl.cpp
--- /dev/null
@@ -0,0 +1,247 @@
+/* $Id: softhsm-keyconv-ossl.cpp 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-keyconv-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ OpenSSL_add_all_algorithms();
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ RSA* rsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0 ||
+ pkey[TAG_EXP1].size <= 0 ||
+ pkey[TAG_EXP2].size <= 0 ||
+ pkey[TAG_COEFF].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ rsa = RSA_new();
+ rsa->p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size, NULL);
+ rsa->q = BN_bin2bn((unsigned char*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size, NULL);
+ rsa->d = BN_bin2bn((unsigned char*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size, NULL);
+ rsa->n = BN_bin2bn((unsigned char*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size, NULL);
+ rsa->e = BN_bin2bn((unsigned char*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size, NULL);
+ rsa->dmp1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP1].big, pkey[TAG_EXP1].size, NULL);
+ rsa->dmq1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP2].big, pkey[TAG_EXP2].size, NULL);
+ rsa->iqmp = BN_bin2bn((unsigned char*)pkey[TAG_COEFF].big, pkey[TAG_COEFF].size, NULL);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert RSA to EVP_PKEY
+ if (!EVP_PKEY_set1_RSA(ossl_pkey, rsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert RSA key to EVP_PKEY.\n");
+ RSA_free(rsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ RSA_free(rsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ DSA* dsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0 ||
+ pkey[TAG_PUBVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ dsa = DSA_new();
+ dsa->p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size, NULL);
+ dsa->q = BN_bin2bn((unsigned char*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size, NULL);
+ dsa->g = BN_bin2bn((unsigned char*)pkey[TAG_BASE].big, pkey[TAG_BASE].size, NULL);
+ dsa->priv_key = BN_bin2bn((unsigned char*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size, NULL);
+ dsa->pub_key = BN_bin2bn((unsigned char*)pkey[TAG_PUBVAL].big, pkey[TAG_PUBVAL].size, NULL);
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert DSA to EVP_PKEY
+ if (!EVP_PKEY_set1_DSA(ossl_pkey, dsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert DSA key to EVP_PKEY.\n");
+ DSA_free(dsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ DSA_free(dsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
diff --git a/src/bin/keyconv/softhsm-keyconv.1 b/src/bin/keyconv/softhsm-keyconv.1
--- /dev/null
@@ -0,0 +1,64 @@
+.TH SOFTHSM-KEYCONV 1 "22 October 2012" "SoftHSM"
+.\" $Id: softhsm-keyconv.1 6757 2012-10-22 19:40:31Z rb $
+.SH NAME
+softhsm-keyconv \- converting from BIND to PKCS#8 key file format
+.SH SYNOPSIS
+.B softhsm-keyconv
+.B \-\-in
+.I path
+.B \-\-out
+.I path
+.RB [ \-\-pin
+.IR PIN ]
+.SH DESCRIPTION
+.B softhsm-keyconv
+can convert BIND .private-key files to the PKCS#8 file format.
+This is so that you can import the PKCS#8 file into
+libsofthsm using the command
+.BR softhsm\-util .
+If you have another file format, then
+.B openssl
+probably can help you to convert it into the PKCS#8 file format.
+.SH OPTIONS
+.B \-\-help\fR, \fB\-h\fR
+Shows the help screen.
+.TP
+.B \-\-in \fIpath\fR
+The
+.I path
+to the input file.
+.TP
+.B \-\-out \fIpath\fR
+The
+.I path
+to the output file.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+will be used to encrypt the PKCS#8 file.
+If not given then the PKCS#8 file will be unencrypted.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLES
+The following command can be used to convert a BIND .private-key file to a PKCS#8 file:
+.LP
+.RS
+.nf
+softhsm-keyconv \-\-in Kexample.com.+007+05474.private \\
+.ti +0.7i
+\-\-out rsa.pem
+.fi
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, René Post, and Roland van Rijswijk.
+.SH "SEE ALSO"
+.IR softhsm-migrate (1),
+.IR softhsm-util (1),
+.IR softhsm2.conf (5),
+.IR openssl (1),
+.IR named (1),
+.IR dnssec-keygen (1),
+.IR dnssec-signzone (1)
diff --git a/src/bin/keyconv/softhsm-keyconv.cpp b/src/bin/keyconv/softhsm-keyconv.cpp
--- /dev/null
@@ -0,0 +1,330 @@
+/* $Id: softhsm-keyconv.cpp 6762 2012-10-24 07:59:42Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/************************************************************
+*
+* softhsm-keyconv
+*
+* This program is for converting from BIND .private-key
+* format to PKCS#8 key file format. So that keys can be
+* imported from BIND to SoftHSM.
+*
+* Some of the design/code is from keyconv.c written by
+* Hakan Olsson and Jakob Schlyter in 2000 and 2001.
+*
+************************************************************/
+
+#include <config.h>
+#include "softhsm-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+#include <stdint.h>
+
+void usage()
+{
+ printf("Converting from BIND .private-key format to PKCS#8 key file format.\n");
+ printf("Usage: softhsm-keyconv [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --in <path> The path to the input file.\n");
+ printf(" --out <path> The path to the output file.\n");
+ printf(" --pin <PIN> To encrypt PKCS#8 file. Optional.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Give a number to each option
+enum {
+ OPT_HELP = 0x100,
+ OPT_IN,
+ OPT_OUT,
+ OPT_PIN,
+ OPT_VERSION
+};
+
+// Define the options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "in", 1, NULL, OPT_IN },
+ { "out", 1, NULL, OPT_OUT },
+ { "pin", 1, NULL, OPT_PIN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt, result;
+
+ char* in_path = NULL;
+ char* out_path = NULL;
+ char* file_pin = NULL;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_IN:
+ in_path = optarg;
+ break;
+ case OPT_OUT:
+ out_path = optarg;
+ break;
+ case OPT_PIN:
+ file_pin = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // We should convert to PKCS#8
+ result = to_pkcs8(in_path, out_path, file_pin);
+
+ return result;
+}
+
+// Convert from BIND to PKCS#8
+int to_pkcs8(char* in_path, char* out_path, char* file_pin)
+{
+ FILE* file_pointer = NULL;
+ char line[MAX_LINE], data[MAX_LINE];
+ char* value_pointer = NULL;
+ int lineno = 0, m, n, error = 0, found, algorithm = DNS_KEYALG_ERROR, data_length;
+ uint32_t bitfield = 0;
+ key_material_t pkey[TAG_MAX];
+
+ if (in_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the input file must be supplied. Use --in <path>\n");
+ return 1;
+ }
+
+ if (out_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the output file must be supplied. Use --out <path>\n");
+ return 1;
+ }
+
+ file_pointer = fopen(in_path, "r");
+ if (file_pointer == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open input file %.100s for reading.\n", in_path);
+ return 1;
+ }
+
+ // Loop over all of the lines
+ while (fgets(line, MAX_LINE, file_pointer) != NULL)
+ {
+ lineno++;
+
+ // Find the current text field in the BIND file.
+ for (m = 0, found = -1; found == -1 && file_tags[m]; m++)
+ {
+ if (strncasecmp(line, file_tags[m], strlen(file_tags[m])) == 0)
+ {
+ found = m;
+ }
+ }
+
+ // The text files is not recognized.
+ if (found == -1)
+ {
+ fprintf(stderr, "ERROR: Unrecognized input line %i\n", lineno);
+ fprintf(stderr, "ERROR: --> %s", line);
+ continue;
+ }
+
+ // Point to the data for this text field.
+ value_pointer = line + strlen(file_tags[found]) + 1;
+
+ // Continue if we are at the end of the string
+ if (*value_pointer == 0)
+ {
+ continue;
+ }
+
+ // Check that we do not get duplicates.
+ if (bitfield & (1 << found))
+ {
+ fprintf(stderr, "ERROR: Duplicate \"%s\" field, line %i - ignored\n",
+ file_tags[found], lineno);
+ continue;
+ }
+ bitfield |= (1 << found);
+
+ // Handle the data for this text field.
+ switch (found)
+ {
+ case TAG_VERSION:
+ if (sscanf(value_pointer, "v%i.%i", &m, &n) != 2)
+ {
+ fprintf(stderr, "ERROR: Invalid/unknown version string "
+ "(%.100s).\n", value_pointer);
+ error = 1;
+ break;
+ }
+ if (m > FILE_MAJOR_VERSION || (m == FILE_MAJOR_VERSION && n > FILE_MINOR_VERSION))
+ {
+ fprintf(stderr, "ERROR: Cannot parse this version of file format, "
+ "v%i.%i.\n", m, n);
+ error = 1;
+ }
+ break;
+ case TAG_ALGORITHM:
+ algorithm = strtol(value_pointer, NULL, 10);
+ break;
+ // RSA
+ case TAG_MODULUS:
+ case TAG_PUBEXP:
+ case TAG_PRIVEXP:
+ case TAG_PRIME1:
+ case TAG_PRIME2:
+ case TAG_EXP1:
+ case TAG_EXP2:
+ case TAG_COEFF:
+ // DSA
+ case TAG_PRIME:
+ case TAG_SUBPRIME:
+ case TAG_BASE:
+ case TAG_PRIVVAL:
+ case TAG_PUBVAL:
+ data_length = b64_pton(value_pointer, (unsigned char*)data, MAX_LINE);
+ if (data_length == -1)
+ {
+ error = 1;
+ fprintf(stderr, "ERROR: Could not parse the base64 string on line %i.\n", lineno);
+ }
+ else
+ {
+ pkey[found].big = malloc(data_length);
+ if (!pkey[found].big)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ error = 1;
+ break;
+ }
+ memcpy(pkey[found].big, data, data_length);
+ pkey[found].size = data_length;
+ }
+ break;
+ // Do not need these
+ case TAG_CREATED:
+ case TAG_PUBLISH:
+ case TAG_ACTIVATE:
+ default:
+ break;
+ }
+ }
+
+ fclose(file_pointer);
+
+ // Something went wrong. Clean up and quit.
+ if (error)
+ {
+ free_key_material(pkey);
+ return error;
+ }
+
+ crypto_init();
+
+ // Save the the key to the disk
+ switch (algorithm)
+ {
+ case DNS_KEYALG_ERROR:
+ fprintf(stderr, "ERROR: The algorithm was not given in the file.\n",
+ algorithm);
+ error = 1;
+ break;
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_RSASHA1_NSEC3_SHA1:
+ case DNS_KEYALG_RSASHA256:
+ case DNS_KEYALG_RSASHA512:
+ error = save_rsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_DSA_NSEC3_SHA1:
+ error = save_dsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_ECC:
+ case DNS_KEYALG_ECC_GOST:
+ default:
+ fprintf(stderr, "ERROR: The algorithm %i is not supported.\n",
+ algorithm);
+ error = 1;
+ break;
+ }
+
+ crypto_final();
+ free_key_material(pkey);
+
+ return error;
+}
+
+// Free allocated memory
+void free_key_material(key_material_t* pkey)
+{
+ int i;
+
+ if (!pkey)
+ {
+ return;
+ }
+
+ for (i = 0; i < TAG_MAX; i++)
+ {
+ if (pkey[i].big)
+ {
+ free(pkey[i].big);
+ }
+ }
+}
diff --git a/src/bin/keyconv/softhsm-keyconv.h b/src/bin/keyconv/softhsm-keyconv.h
--- /dev/null
@@ -0,0 +1,134 @@
+/* $Id: softhsm-keyconv.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SOFTHSM_V2_SOFTHSM_KEYCONV_H
+#define _SOFTHSM_V2_SOFTHSM_KEYCONV_H 1
+
+#include <stdlib.h>
+
+typedef struct key_material_t {
+ unsigned long size;
+ void* big;
+ key_material_t() {
+ size = 0;
+ big = NULL;
+ }
+} key_material_t;
+
+// Main functions
+
+void usage();
+int to_pkcs8(char* in_path, char* out_path, char* file_pin);
+
+// Support functions
+
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+void free_key_material(key_material_t* pkey);
+void crypto_init();
+void crypto_final();
+
+// base64.c prototypes
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int b64_pton(const char* , unsigned char*, size_t);
+int b64_ntop(const unsigned char*, size_t, char*, size_t);
+#ifdef __cplusplus
+}
+#endif
+
+// The BIND file version number.
+#define FILE_MAJOR_VERSION 1
+#define FILE_MINOR_VERSION 3
+
+// Key algorithm number
+#define DNS_KEYALG_ERROR -1
+#define DNS_KEYALG_RSAMD5 1
+#define DNS_KEYALG_DSA 3
+#define DNS_KEYALG_ECC 4
+#define DNS_KEYALG_RSASHA1 5
+#define DNS_KEYALG_DSA_NSEC3_SHA1 6
+#define DNS_KEYALG_RSASHA1_NSEC3_SHA1 7
+#define DNS_KEYALG_RSASHA256 8
+#define DNS_KEYALG_RSASHA512 10
+#define DNS_KEYALG_ECC_GOST 12
+
+// Maximum number of lines / line length
+#define MAX_LINE 4096
+
+// The text fields supported
+static const char* file_tags[] = {
+ "Private-key-format:",
+ "Algorithm:",
+ "Modulus:",
+ "PublicExponent:",
+ "PrivateExponent:",
+ "Prime1:",
+ "Prime2:",
+ "Exponent1:",
+ "Exponent2:",
+ "Coefficient:",
+ "Prime(p):",
+ "Private_value(x):",
+ "Public_value(y):",
+ "Subprime(q):",
+ "Base(g):",
+ "Created:",
+ "Publish:",
+ "Activate:",
+ NULL
+};
+
+// The number of each text field.
+// Must match the tags above.
+enum FILE_TAGS {
+ TAG_VERSION = 0,
+ TAG_ALGORITHM,
+ TAG_MODULUS,
+ TAG_PUBEXP,
+ TAG_PRIVEXP,
+ TAG_PRIME1,
+ TAG_PRIME2,
+ TAG_EXP1,
+ TAG_EXP2,
+ TAG_COEFF,
+ TAG_PRIME,
+ TAG_PRIVVAL,
+ TAG_PUBVAL,
+ TAG_SUBPRIME,
+ TAG_BASE,
+ TAG_CREATED,
+ TAG_PUBLISH,
+ TAG_ACTIVATE,
+ // So we know how long this list is
+ TAG_MAX
+};
+
+#endif /* _SOFTHSM_V2_SOFTHSM_KEYCONV_H */
diff --git a/src/bin/migrate/Makefile.am b/src/bin/migrate/Makefile.am
--- /dev/null
@@ -0,0 +1,19 @@
+# $Id: Makefile.am 4840 2010-08-10 12:05:40Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/cryptoki_compat \
+ -I$(srcdir)/../common \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm-migrate.1
+
+bin_PROGRAMS = softhsm-migrate
+
+softhsm_migrate_SOURCES = softhsm-migrate.cpp \
+ ../common/getpw.cpp \
+ ../common/library.cpp
+softhsm_migrate_LDADD = @SQLITE3_LIBS@ \
+ @YIELD_LIB@
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/bin/migrate/softhsm-migrate.1 b/src/bin/migrate/softhsm-migrate.1
--- /dev/null
@@ -0,0 +1,62 @@
+.TH SOFTHSM-MIGRATE 1 "22 October 2012" "SoftHSM"
+.\" $Id: softhsm-migrate.1 6757 2012-10-22 19:40:31Z rb $
+.SH NAME
+softhsm-migrate \- SoftHSM v1 migration tool
+.SH SYNOPSIS
+.PP
+.B softhsm-util \-\-db
+.I path
+.B \-\-slot
+.I number
+.RB [ \-\-pin
+.I PIN
+.B \-\-no\-public\-key]
+.SH DESCRIPTION
+.B softhsm-migration
+is a tool that can migrate SoftHSM v1 databases to PKCS#11.
+The default HSM is SoftHSM v2, but can be used with other
+PKCS#11 libraries by using the option
+.B \-\-module
+.LP
+.SH OPTIONS
+.TP
+.B \-\-db \fIpath\fR
+The SoftHSM v1 database that is going to be migrated.
+The location of the token database can be found in
+the configuration file for SoftHSM v1.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
+.TP
+.B \-\-module \fIpath\fR
+Use another PKCS#11 library than SoftHSM.
+.TP
+.B \-\-no\-public\-key
+Do not migrate the public key.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+for the normal user.
+.TP
+.B \-\-slot \fInumber\fR
+The database will be migrated to this slot.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLE
+.LP
+A token database can be migrated with the following command:
+.LP
+.RS
+.nf
+softhsm-migrate \-\-db /home/user/token.db \-\-slot 1
+.fi
+.RE
+.SH AUTHORS
+Written by Rickard Bellgrim, René Post, and Roland van Rijswijk.
+.LP
+.SH "SEE ALSO"
+.IR softhsm-keyconv (1),
+.IR softhsm-util (1),
+.IR softhsm2.conf (5)
diff --git a/src/bin/migrate/softhsm-migrate.cpp b/src/bin/migrate/softhsm-migrate.cpp
--- /dev/null
@@ -0,0 +1,776 @@
+/* $Id: softhsm-migrate.cpp 6762 2012-10-24 07:59:42Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-migrate.cpp
+
+ This program can be used for migrating SoftHSM v1 databases to any
+ PKCS#11 library. The default library is the libsofthsm.so
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm-migrate.h"
+#include "getpw.h"
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+#include <sched.h>
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM migration tool. From SoftHSM v1 database to PKCS#11.\n");
+ printf("Usage: softhsm-migrate [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --db <path> The SoftHSM v1 database that is going to be migrated.\n");
+ printf(" --module <path> Use another PKCS#11 library than SoftHSM.\n");
+ printf(" --no-public-key Do not migrate the public key.\n");
+ printf(" --pin <PIN> The PIN for the normal user.\n");
+ printf(" --slot <number> The slot where the token is located.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Enumeration of the long options
+enum {
+ OPT_HELP = 0x100,
+ OPT_DB,
+ OPT_MODULE,
+ OPT_NO_PUBLIC_KEY,
+ OPT_PIN,
+ OPT_SLOT,
+ OPT_VERSION
+};
+
+// Text representation of the long options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "db", 1, NULL, OPT_DB },
+ { "module", 1, NULL, OPT_MODULE },
+ { "no-public-key", 0, NULL, OPT_NO_PUBLIC_KEY },
+ { "pin", 1, NULL, OPT_PIN },
+ { "slot", 1, NULL, OPT_SLOT },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+CK_FUNCTION_LIST_PTR p11;
+
+// Prepared statements
+sqlite3_stmt* select_an_attribute_sql = NULL;
+sqlite3_stmt* select_object_ids_sql = NULL;
+sqlite3_stmt* count_object_id_sql = NULL;
+
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt;
+
+ char* dbPath = NULL;
+ char* userPIN = NULL;
+ char* module = NULL;
+ char* slot = NULL;
+ int noPublicKey = 0;
+
+ int result = 0;
+ CK_RV rv;
+
+ moduleHandle = NULL;
+ p11 = NULL;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_DB:
+ dbPath = optarg;
+ break;
+ case OPT_SLOT:
+ slot = optarg;
+ break;
+ case OPT_MODULE:
+ module = optarg;
+ break;
+ case OPT_NO_PUBLIC_KEY:
+ noPublicKey = 1;
+ break;
+ case OPT_PIN:
+ userPIN = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // Get a pointer to the function list for PKCS#11 library
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(module, &moduleHandle);
+ if (pGetFunctionList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not load the library.\n");
+ exit(1);
+ }
+
+ // Load the function list
+ (*pGetFunctionList)(&p11);
+
+ // Initialize the library
+ rv = p11->C_Initialize(NULL_PTR);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the library.\n");
+ exit(1);
+ }
+
+ // Migrate the database
+ result = migrate(dbPath, slot, userPIN, noPublicKey);
+
+ // Finalize the library
+ p11->C_Finalize(NULL_PTR);
+ unloadLibrary(moduleHandle);
+
+ return result;
+}
+
+// Migrate the database
+int migrate(char* dbPath, char* slot, char* userPIN, int noPublicKey)
+{
+ CK_SESSION_HANDLE hSession;
+ sqlite3* db = NULL;
+ int result;
+
+ if (dbPath == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the database must be supplied. "
+ "Use --db <path>\n");
+ return 1;
+ }
+
+ if (slot == NULL)
+ {
+ fprintf(stderr, "ERROR: A slot number must be supplied. "
+ "Use --slot <number>\n");
+ return 1;
+ }
+
+ // Open the database
+ db = openDB(dbPath);
+ if (db == NULL)
+ {
+ return 1;
+ }
+
+ // Connect to the PKCS#11 library
+ result = openP11(slot, userPIN, &hSession);
+ if (result)
+ {
+ sqlite3_close(db);
+ return result;
+ }
+
+ // Prepare the statements
+ if (prepStatements(db))
+ {
+ fprintf(stderr, "ERROR: Could not prepare the statements\n");
+ finalStatements();
+ sqlite3_close(db);
+ return 1;
+ }
+
+ // Start the migration
+ result = db2session(db, hSession, noPublicKey);
+
+ // Finalize the statements
+ finalStatements();
+
+ sqlite3_close(db);
+
+ if (result)
+ {
+ fprintf(stderr, "ERROR: Unable to migrate all of the objects.\n");
+ }
+ else
+ {
+ printf("The database has been migrated to the new HSM\n");
+ }
+
+ return result;
+}
+
+// Prepare the statements
+int prepStatements(sqlite3* db)
+{
+ select_an_attribute_sql = NULL;
+ select_object_ids_sql = NULL;
+ count_object_id_sql = NULL;
+
+ const char select_an_attribute_str[] = "SELECT value,length FROM Attributes WHERE objectID = ? AND type = ?;";
+ const char select_object_ids_str[] = "SELECT objectID FROM Objects;";
+ const char count_object_id_str[] = "SELECT COUNT(objectID) FROM Objects;";
+
+ if
+ (
+ sqlite3_prepare_v2(db, select_an_attribute_str, -1, &select_an_attribute_sql, NULL) ||
+ sqlite3_prepare_v2(db, select_object_ids_str, -1, &select_object_ids_sql, NULL) ||
+ sqlite3_prepare_v2(db, count_object_id_str, -1, &count_object_id_sql, NULL)
+ )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+// Finalize the statements
+void finalStatements()
+{
+ if (select_an_attribute_sql) sqlite3_finalize(select_an_attribute_sql);
+ if (select_object_ids_sql) sqlite3_finalize(select_object_ids_sql);
+ if (count_object_id_sql) sqlite3_finalize(count_object_id_sql);
+}
+
+// Open a connection to a valid SoftHSM v1 database
+sqlite3* openDB(char* dbPath)
+{
+ int result;
+ sqlite3* db = NULL;
+ sqlite3_stmt* pragStatem = NULL;
+ int dbVersion;
+
+ // Open the database
+ result = sqlite3_open(dbPath, &db);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: Could not open token database. "
+ "Probably wrong path or privileges: %s\n", dbPath);
+ return NULL;
+ }
+
+ // Check the schema version
+ if (sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &pragStatem, NULL))
+ {
+ fprintf(stderr, "ERROR: Could not prepare a SQL statement\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+ if (sqlite3_step(pragStatem) == SQLITE_ROW)
+ {
+ dbVersion = sqlite3_column_int(pragStatem, 0);
+ sqlite3_finalize(pragStatem);
+
+ if (dbVersion != 100)
+ {
+ fprintf(stderr, "ERROR: Wrong database schema version: %s\n", dbPath);
+ sqlite3_close(db);
+ return NULL;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: The token database has not been initialized by SoftHSM\n");
+ sqlite3_finalize(pragStatem);
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Token table exist
+ result = sqlite3_exec(db, "SELECT COUNT(variableID) FROM Token;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Token table is missing the in database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Objects table exist
+ result = sqlite3_exec(db, "SELECT COUNT(objectID) FROM Objects;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Objects table is missing the in database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Attributes table exist
+ result = sqlite3_exec(db, "SELECT COUNT(attributeID) FROM Attributes;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Attributes table is missing in the database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ return db;
+}
+
+// Connect and login to the token
+int openP11(char* slot, char* userPIN, CK_SESSION_HANDLE* hSession)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+ CK_RV rv;
+ CK_SLOT_ID slotID;
+
+ // Load the variable
+ slotID = atoi(slot);
+
+ rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ return 1;
+ }
+
+ // Get the password
+ getPW(userPIN, user_pin_copy, CKU_USER);
+
+ rv = p11->C_Login(*hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+// Migrate the database to the session
+int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey)
+{
+ CK_ULONG objectCount;
+ int i, result = 0, rv;
+ CK_OBJECT_HANDLE* objects = NULL;
+ CK_OBJECT_CLASS ckClass;
+
+ // Get all objects
+ objects = getObjects(db, &objectCount);
+ if (objects == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not find any objects in the database.\n");
+ return 1;
+ }
+
+ // Loop over all objects
+ for (i = 0; i < objectCount; i++)
+ {
+ ckClass = getObjectClass(objects[i]);
+
+ switch (ckClass)
+ {
+ case CKO_PUBLIC_KEY:
+ if (noPublicKey) continue;
+ if (getKeyType(objects[i]) != CKK_RSA)
+ {
+ fprintf(stderr, "ERROR: Cannot export object %lu. Only supporting RSA keys. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ }
+ rv = dbRSAPub2session(db, objects[i], hSession);
+ if (rv) result = 1;
+ break;
+ case CKO_PRIVATE_KEY:
+ if (getKeyType(objects[i]) != CKK_RSA)
+ {
+ fprintf(stderr, "ERROR: Cannot export object %lu. Only supporting RSA keys. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ }
+ rv = dbRSAPriv2session(db, objects[i], hSession);
+ if (rv) result = 1;
+ break;
+ case CKO_VENDOR_DEFINED:
+ fprintf(stderr, "ERROR: Could not get the class of object %lu. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Not supporting class %lu in object %lu. "
+ "Continuing.\n", ckClass, objects[i]);
+ result = 1;
+ break;
+ }
+ }
+
+ free(objects);
+
+ return result;
+}
+
+// Get the key type from key objects
+CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef)
+{
+ int retSQL = 0;
+ CK_KEY_TYPE retVal = CKK_VENDOR_DEFINED;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, CKA_KEY_TYPE);
+
+ // Get result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (pValue != NULL_PTR && length == sizeof(CK_KEY_TYPE))
+ {
+ retVal = *(CK_KEY_TYPE*)pValue;
+ }
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Get the class of the object
+CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef)
+{
+ int retSQL = 0;
+ CK_OBJECT_CLASS retVal = CKO_VENDOR_DEFINED;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, CKA_CLASS);
+
+ // Get the result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (pValue != NULL_PTR && length == sizeof(CK_OBJECT_CLASS))
+ {
+ retVal = *(CK_OBJECT_CLASS*)pValue;
+ }
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Get all object IDs
+CK_OBJECT_HANDLE* getObjects(sqlite3* db, CK_ULONG* objectCount)
+{
+ CK_ULONG objectsInDB;
+ CK_ULONG counter = 0;
+ CK_OBJECT_HANDLE* objectRefs = NULL;
+ int retSQL = 0;
+
+ *objectCount = 0;
+
+ // Find out how many objects we have.
+ while ((retSQL = sqlite3_step(count_object_id_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ if (retSQL != SQLITE_ROW)
+ {
+ fprintf(stderr, "ERROR: Could not count the number of objects in the database\n");
+ sqlite3_reset(count_object_id_sql);
+ return NULL;
+ }
+
+ // Get the number of objects
+ objectsInDB = sqlite3_column_int(count_object_id_sql, 0);
+ sqlite3_reset(count_object_id_sql);
+
+ if (!objectsInDB)
+ {
+ fprintf(stderr, "ERROR: There are not objects in the database\n");
+ return NULL;
+ }
+
+ // Create the object-reference buffer
+ objectRefs = (CK_OBJECT_HANDLE*)malloc(objectsInDB * sizeof(CK_OBJECT_HANDLE));
+ if (objectRefs == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory\n");
+ return NULL;
+ }
+
+ // Get all the object ids
+ while
+ (
+ ((retSQL = sqlite3_step(select_object_ids_sql)) == SQLITE_BUSY || retSQL == SQLITE_ROW) &&
+ counter < objectsInDB
+ )
+ {
+ if(retSQL == SQLITE_BUSY)
+ {
+ sched_yield();
+ continue;
+ }
+
+ objectRefs[counter++] = sqlite3_column_int(select_object_ids_sql, 0);
+ }
+
+ *objectCount = counter;
+
+ sqlite3_reset(select_object_ids_sql);
+
+ return objectRefs;
+}
+
+// Extract the information about the public RSA key and save it in the token
+int dbRSAPub2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession)
+{
+ int result = 0;
+ int i;
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv;
+
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_START_DATE, NULL, 0 },
+ { CKA_END_DATE, NULL, 0 },
+ { CKA_DERIVE, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_ENCRYPT, NULL, 0 },
+ { CKA_VERIFY, NULL, 0 },
+ { CKA_VERIFY_RECOVER, NULL, 0 },
+ { CKA_WRAP, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 }
+ };
+
+ for (i = 0; i < 17; i++)
+ {
+ result = getAttribute(objectID, &pubTemplate[i]);
+ if (result)
+ {
+ freeTemplate(pubTemplate, 17);
+ return 1;
+ }
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 17, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR %X: Could not save the public key in the token. "
+ "Skipping object %lu\n", (unsigned int)rv, objectID);
+ result = 1;
+ }
+ else
+ {
+ printf("Object %lu has been migrated\n", objectID);
+ }
+
+ freeTemplate(pubTemplate, 17);
+
+ return result;
+}
+
+// Extract the information about the private RSA key and save it in the token
+int dbRSAPriv2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession)
+{
+ int result = 0;
+ int i;
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv;
+
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_START_DATE, NULL, 0 },
+ { CKA_END_DATE, NULL, 0 },
+ { CKA_DERIVE, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_SENSITIVE, NULL, 0 },
+ { CKA_DECRYPT, NULL, 0 },
+ { CKA_SIGN, NULL, 0 },
+ { CKA_SIGN_RECOVER, NULL, 0 },
+ { CKA_UNWRAP, NULL, 0 },
+ { CKA_EXTRACTABLE, NULL, 0 },
+ { CKA_WRAP_WITH_TRUSTED, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL, 0 },
+ { CKA_PRIME_1, NULL, 0 },
+ { CKA_PRIME_2, NULL, 0 }
+// SoftHSM v1 did not store these values
+// { CKA_EXPONENT_1, NULL, 0 },
+// { CKA_EXPONENT_2, NULL, 0 },
+// { CKA_COEFFICIENT, NULL, 0 }
+ };
+
+ for (i = 0; i < 23; i++)
+ {
+ result = getAttribute(objectID, &privTemplate[i]);
+ if (result)
+ {
+ freeTemplate(privTemplate, 23);
+ return 1;
+ }
+ }
+
+ rv = p11->C_CreateObject(hSession, privTemplate, 23, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR %X: Could not save the private key in the token. "
+ "Skipping object %lu\n", (unsigned int)rv, objectID);
+ result = 1;
+ }
+ else
+ {
+ printf("Object %lu has been migrated\n", objectID);
+ }
+
+ freeTemplate(privTemplate, 23);
+
+ return result;
+}
+
+// Get the value of the given attribute
+int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate)
+{
+ int retSQL = 0;
+ int retVal = 0;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, attTemplate->type);
+
+ // Get result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get the attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (length)
+ {
+ attTemplate->pValue = malloc(length);
+ if (!attTemplate->pValue)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory. "
+ "Skipping object %lu\n", objectRef);
+ retVal = 1;
+ }
+ else
+ {
+ // Copy data
+ memcpy(attTemplate->pValue, pValue, length);
+ }
+ }
+
+ attTemplate->ulValueLen = length;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Do not have attribute %lu. "
+ "Skipping object %lu\n", attTemplate->type, objectRef);
+ retVal = 1;
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Free allocated memory in the template
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int size)
+{
+ int i;
+
+ if (!attTemplate) return;
+
+ for (i = 0; i < size; i++)
+ {
+ if(attTemplate[i].pValue)
+ {
+ free(attTemplate[i].pValue);
+ }
+ }
+}
diff --git a/src/bin/migrate/softhsm-migrate.h b/src/bin/migrate/softhsm-migrate.h
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: softhsm-migrate.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-migrate.h
+
+ This program can be used for migrating SoftHSM v1 databases to any
+ PKCS#11 library. The default library is the libsofthsm.so
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM_MIGRATE_H
+#define _SOFTHSM_V2_SOFTHSM_MIGRATE_H
+
+#include "pkcs11.h"
+#include <sqlite3.h>
+
+// Main functions
+
+void usage();
+int migrate(char* dbPath, char* slot, char* userPIN, int noPublicKey);
+
+// Support functions
+
+sqlite3* openDB(char* dbPath);
+int openP11(char* slot, char* userPIN, CK_SESSION_HANDLE* hSession);
+int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey);
+int dbRSAPub2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
+int dbRSAPriv2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int size);
+
+// Database functions
+
+CK_OBJECT_HANDLE* getObjects(sqlite3* db, CK_ULONG* objectCount);
+CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef);
+CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef);
+int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate);
+int prepStatements(sqlite3* db);
+void finalStatements();
+
+// Library
+
+static void* moduleHandle;
+extern CK_FUNCTION_LIST_PTR p11;
+
+#endif // !_SOFTHSM_V2_SOFTHSM_MIGRATE_H
diff --git a/src/bin/util/Makefile.am b/src/bin/util/Makefile.am
--- /dev/null
+++ b/src/bin/util/Makefile.am
@@ -0,0 +1,29 @@
+# $Id: Makefile.am 4840 2010-08-10 12:05:40Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/cryptoki_compat \
+ -I$(srcdir)/../common \
+ @CRYPTO_INCLUDES@
+
+dist_man_MANS = softhsm-util.1
+
+bin_PROGRAMS = softhsm-util
+
+softhsm_util_SOURCES = softhsm-util.cpp \
+ ../common/getpw.cpp \
+ ../common/library.cpp
+softhsm_util_LDADD = @CRYPTO_LIBS@
+
+# Compile with support of OpenSSL
+if WITH_OPENSSL
+softhsm_util_SOURCES += softhsm-util-ossl.cpp
+endif
+
+# Compile with support of Botan
+if WITH_BOTAN
+softhsm_util_SOURCES += softhsm-util-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/src/bin/util/softhsm-util-botan.cpp b/src/bin/util/softhsm-util-botan.cpp
--- /dev/null
@@ -0,0 +1,465 @@
+/* $Id: softhsm-util-botan.cpp 5045 2011-05-04 13:29:52Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-util-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm-util.h"
+#include "softhsm-util-botan.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/bigint.h>
+
+bool was_initialized = false;
+
+// Init Botan
+void crypto_init()
+{
+ // The PKCS#11 library might be using Botan
+ // Check if it has already initialized Botan
+ Botan::Library_State* state = Botan::Global_State_Management::swap_global_state(0);
+ // now put it back
+ Botan::Global_State_Management::swap_global_state(state);
+
+ if (state)
+ {
+ was_initialized = true;
+ }
+
+ if (was_initialized == false)
+ {
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+ }
+}
+
+// Final Botan
+void crypto_final()
+{
+ if (was_initialized == false)
+ {
+ Botan::LibraryInitializer::deinitialize();
+ }
+}
+
+// Import a key pair from given path
+int crypto_import_key_pair
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* filePIN,
+ char* label,
+ char* objID,
+ int objIDLen,
+ int noPublicKey
+)
+{
+ Botan::Private_Key* pkey = crypto_read_file(filePath, filePIN);
+ if (pkey == NULL)
+ {
+ return 1;
+ }
+
+ Botan::RSA_PrivateKey* rsa = NULL;
+ Botan::DSA_PrivateKey* dsa = NULL;
+
+ if (pkey->algo_name().compare("RSA") == 0)
+ {
+ rsa = dynamic_cast<Botan::RSA_PrivateKey*>(pkey);
+ }
+ else if (pkey->algo_name().compare("DSA") == 0)
+ {
+ dsa = dynamic_cast<Botan::DSA_PrivateKey*>(pkey);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: %s is not a supported algorithm.\n",
+ pkey->algo_name().c_str());
+ delete pkey;
+ return 1;
+ }
+
+ int result = 0;
+
+ if (rsa)
+ {
+ result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa);
+ }
+ else if (dsa)
+ {
+ result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not get the key material.\n");
+ result = 1;
+ }
+
+ delete pkey;
+ return result;
+}
+
+// Read the key from file
+Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN)
+{
+ if (filePath == NULL)
+ {
+ return NULL;
+ }
+
+ Botan::AutoSeeded_RNG* rng = new Botan::AutoSeeded_RNG();
+ Botan::Private_Key* pkey = NULL;
+
+ try
+ {
+ if (filePIN == NULL)
+ {
+ pkey = Botan::PKCS8::load_key(filePath, *rng);
+ }
+ else
+ {
+ pkey = Botan::PKCS8::load_key(filePath, *rng, filePIN);
+ }
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Perhaps wrong path to file, wrong file format, "
+ "or wrong PIN to file (--file-pin <PIN>).\n");
+ delete rng;
+ return NULL;
+ }
+ delete rng;
+
+ return pkey;
+}
+
+// Save the key data in PKCS#11
+int crypto_save_rsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ int objIDLen,
+ int noPublicKey,
+ Botan::RSA_PrivateKey* rsa
+)
+{
+ rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa);
+ if (!keyMat)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN },
+ { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD },
+ { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP },
+ { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 },
+ { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 },
+ { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_rsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_rsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* rsa)
+{
+ if (rsa == NULL)
+ {
+ return NULL;
+ }
+
+ rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeE = rsa->get_e().bytes();
+ keyMat->sizeN = rsa->get_n().bytes();
+ keyMat->sizeD = rsa->get_d().bytes();
+ keyMat->sizeP = rsa->get_p().bytes();
+ keyMat->sizeQ = rsa->get_q().bytes();
+ keyMat->sizeDMP1 = rsa->get_d1().bytes();
+ keyMat->sizeDMQ1 = rsa->get_d2().bytes();
+ keyMat->sizeIQMP = rsa->get_c().bytes();
+
+ keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE);
+ keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1);
+ keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1);
+ keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP);
+
+ if
+ (
+ !keyMat->bigE ||
+ !keyMat->bigN ||
+ !keyMat->bigD ||
+ !keyMat->bigP ||
+ !keyMat->bigQ ||
+ !keyMat->bigDMP1 ||
+ !keyMat->bigDMQ1 ||
+ !keyMat->bigIQMP
+ )
+ {
+ crypto_free_rsa(keyMat);
+ return NULL;
+ }
+
+ rsa->get_e().binary_encode((Botan::byte*)keyMat->bigE);
+ rsa->get_n().binary_encode((Botan::byte*)keyMat->bigN);
+ rsa->get_d().binary_encode((Botan::byte*)keyMat->bigD);
+ rsa->get_p().binary_encode((Botan::byte*)keyMat->bigP);
+ rsa->get_q().binary_encode((Botan::byte*)keyMat->bigQ);
+ rsa->get_d1().binary_encode((Botan::byte*)keyMat->bigDMP1);
+ rsa->get_d2().binary_encode((Botan::byte*)keyMat->bigDMQ1);
+ rsa->get_c().binary_encode((Botan::byte*)keyMat->bigIQMP);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_rsa(rsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigE) free(keyMat->bigE);
+ if (keyMat->bigN) free(keyMat->bigN);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigDMP1) free(keyMat->bigDMP1);
+ if (keyMat->bigDMQ1) free(keyMat->bigDMQ1);
+ if (keyMat->bigIQMP) free(keyMat->bigIQMP);
+ free(keyMat);
+}
+
+// Save the key data in PKCS#11
+int crypto_save_dsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ int objIDLen,
+ int noPublicKey,
+ Botan::DSA_PrivateKey* dsa
+)
+{
+ dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigY, keyMat->sizeY }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigX, keyMat->sizeX }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_dsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2);
+ crypto_free_dsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* dsa)
+{
+ if (dsa == NULL)
+ {
+ return NULL;
+ }
+
+ dsa_key_material_t *keyMat = (dsa_key_material_t *)malloc(sizeof(dsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeP = dsa->group_p().bytes();
+ keyMat->sizeQ = dsa->group_q().bytes();
+ keyMat->sizeG = dsa->group_g().bytes();
+ keyMat->sizeX = dsa->get_x().bytes();
+ keyMat->sizeY = dsa->get_y().bytes();
+
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG);
+ keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX);
+ keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY);
+
+ if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY)
+ {
+ crypto_free_dsa(keyMat);
+ return NULL;
+ }
+
+ dsa->group_p().binary_encode((Botan::byte*)keyMat->bigP);
+ dsa->group_q().binary_encode((Botan::byte*)keyMat->bigQ);
+ dsa->group_g().binary_encode((Botan::byte*)keyMat->bigG);
+ dsa->get_x().binary_encode((Botan::byte*)keyMat->bigX);
+ dsa->get_y().binary_encode((Botan::byte*)keyMat->bigY);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_dsa(dsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigG) free(keyMat->bigG);
+ if (keyMat->bigX) free(keyMat->bigX);
+ if (keyMat->bigY) free(keyMat->bigY);
+ free(keyMat);
+}
diff --git a/src/bin/util/softhsm-util-botan.h b/src/bin/util/softhsm-util-botan.h
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: softhsm-util-botan.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-util-botan.h
+
+ Header file for Botan implemented
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM_UTIL_BOTAN_H
+#define _SOFTHSM_V2_SOFTHSM_UTIL_BOTAN_H
+
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+
+typedef struct rsa_key_material_t {
+ CK_ULONG sizeE;
+ CK_ULONG sizeN;
+ CK_ULONG sizeD;
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeDMP1;
+ CK_ULONG sizeDMQ1;
+ CK_ULONG sizeIQMP;
+ CK_VOID_PTR bigE;
+ CK_VOID_PTR bigN;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigDMP1;
+ CK_VOID_PTR bigDMQ1;
+ CK_VOID_PTR bigIQMP;
+ rsa_key_material_t() {
+ sizeE = 0;
+ sizeN = 0;
+ sizeD = 0;
+ sizeP = 0;
+ sizeQ = 0;
+ sizeDMP1 = 0;
+ sizeDMQ1 = 0;
+ sizeIQMP = 0;
+ bigE = NULL_PTR;
+ bigN = NULL_PTR;
+ bigD = NULL_PTR;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigDMP1 = NULL_PTR;
+ bigDMQ1 = NULL_PTR;
+ bigIQMP = NULL_PTR;
+ }
+} rsa_key_material_t;
+
+typedef struct dsa_key_material_t {
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeG;
+ CK_ULONG sizeX;
+ CK_ULONG sizeY;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigG;
+ CK_VOID_PTR bigX;
+ CK_VOID_PTR bigY;
+ dsa_key_material_t() {
+ sizeP = 0;
+ sizeQ = 0;
+ sizeG = 0;
+ sizeX = 0;
+ sizeY = 0;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigG = NULL_PTR;
+ bigX = NULL_PTR;
+ bigY = NULL_PTR;
+ }
+} dsa_key_material_t;
+
+Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN);
+
+// RSA
+int crypto_save_rsa(CK_SESSION_HANDLE hSession, char* label, char* objID, int objIDLen, int noPublicKey, Botan::RSA_PrivateKey* rsa);
+rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* rsa);
+void crypto_free_rsa(rsa_key_material_t* keyMat);
+
+// DSA
+int crypto_save_dsa(CK_SESSION_HANDLE hSession, char* label, char* objID, int objIDLen, int noPublicKey, Botan::DSA_PrivateKey* dsa);
+dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* dsa);
+void crypto_free_dsa(dsa_key_material_t* keyMat);
+
+#endif // !_SOFTHSM_V2_SOFTHSM_UTIL_OSSL_H
diff --git a/src/bin/util/softhsm-util-ossl.cpp b/src/bin/util/softhsm-util-ossl.cpp
--- /dev/null
@@ -0,0 +1,483 @@
+/* $Id: softhsm-util-ossl.cpp 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-util-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm-util.h"
+#include "softhsm-util-ossl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ // We do not need to do this one
+ // OpenSSL_add_all_algorithms();
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ // EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+// Import a key pair from given path
+int crypto_import_key_pair
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* filePIN,
+ char* label,
+ char* objID,
+ int objIDLen,
+ int noPublicKey
+)
+{
+ EVP_PKEY* pkey = crypto_read_file(filePath, filePIN);
+ if (pkey == NULL)
+ {
+ return 1;
+ }
+
+ RSA* rsa = NULL;
+ DSA* dsa = NULL;
+
+ switch (EVP_PKEY_type(pkey->type))
+ {
+ case EVP_PKEY_RSA:
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ break;
+ case EVP_PKEY_DSA:
+ dsa = EVP_PKEY_get1_DSA(pkey);
+ break;
+ default:
+ fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
+ EVP_PKEY_free(pkey);
+ return 1;
+ break;
+ }
+ EVP_PKEY_free(pkey);
+
+ int result = 0;
+
+ if (rsa)
+ {
+ result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa);
+ RSA_free(rsa);
+ }
+ else if (dsa)
+ {
+ result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa);
+ DSA_free(dsa);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not get the key material.\n");
+ result = 1;
+ }
+
+ return result;
+}
+
+// Read the key from file
+EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
+{
+ BIO* in = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ EVP_PKEY* pkey = NULL;
+ X509_SIG* p8 = NULL;
+
+ if (!(in = BIO_new_file(filePath, "rb")))
+ {
+ fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath);
+ return NULL;
+ }
+
+ // The PKCS#8 file is encrypted
+ if (filePIN)
+ {
+ p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (!p8)
+ {
+ fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
+ "Maybe the file is not encrypted.\n");
+ return NULL;
+ }
+
+ p8inf = PKCS8_decrypt(p8, filePIN, strlen(filePIN));
+ X509_SIG_free(p8);
+
+ if (!p8inf)
+ {
+ fprintf(stderr, "ERROR: Could not decrypt the PKCS#8 file. "
+ "Maybe wrong PIN to file (--file-pin <PIN>)\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (!p8inf)
+ {
+ fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
+ "Maybe it is encypted (--file-pin <PIN>)\n");
+ return NULL;
+ }
+ }
+
+ if (p8inf->broken)
+ {
+ fprintf(stderr, "ERROR: Broken key encoding.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return NULL;
+ }
+
+ // Convert the PKCS#8 to OpenSSL
+ pkey = EVP_PKCS82PKEY(p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (!pkey)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key.\n");
+ return NULL;
+ }
+
+ return pkey;
+}
+
+// Save the key data in PKCS#11
+int crypto_save_rsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ int objIDLen,
+ int noPublicKey,
+ RSA* rsa
+)
+{
+ rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa);
+ if (!keyMat)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN },
+ { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD },
+ { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP },
+ { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 },
+ { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 },
+ { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_rsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_rsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+rsa_key_material_t* crypto_malloc_rsa(RSA* rsa)
+{
+ if (rsa == NULL)
+ {
+ return NULL;
+ }
+
+ rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeE = BN_num_bytes(rsa->e);
+ keyMat->sizeN = BN_num_bytes(rsa->n);
+ keyMat->sizeD = BN_num_bytes(rsa->d);
+ keyMat->sizeP = BN_num_bytes(rsa->p);
+ keyMat->sizeQ = BN_num_bytes(rsa->q);
+ keyMat->sizeDMP1 = BN_num_bytes(rsa->dmp1);
+ keyMat->sizeDMQ1 = BN_num_bytes(rsa->dmq1);
+ keyMat->sizeIQMP = BN_num_bytes(rsa->iqmp);
+
+ keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE);
+ keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1);
+ keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1);
+ keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP);
+
+ if
+ (
+ !keyMat->bigE ||
+ !keyMat->bigN ||
+ !keyMat->bigD ||
+ !keyMat->bigP ||
+ !keyMat->bigQ ||
+ !keyMat->bigDMP1 ||
+ !keyMat->bigDMQ1 ||
+ !keyMat->bigIQMP
+ )
+ {
+ crypto_free_rsa(keyMat);
+ return NULL;
+ }
+
+ BN_bn2bin(rsa->e, (unsigned char*)keyMat->bigE);
+ BN_bn2bin(rsa->n, (unsigned char*)keyMat->bigN);
+ BN_bn2bin(rsa->d, (unsigned char*)keyMat->bigD);
+ BN_bn2bin(rsa->p, (unsigned char*)keyMat->bigP);
+ BN_bn2bin(rsa->q, (unsigned char*)keyMat->bigQ);
+ BN_bn2bin(rsa->dmp1, (unsigned char*)keyMat->bigDMP1);
+ BN_bn2bin(rsa->dmq1, (unsigned char*)keyMat->bigDMQ1);
+ BN_bn2bin(rsa->iqmp, (unsigned char*)keyMat->bigIQMP);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_rsa(rsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigE) free(keyMat->bigE);
+ if (keyMat->bigN) free(keyMat->bigN);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigDMP1) free(keyMat->bigDMP1);
+ if (keyMat->bigDMQ1) free(keyMat->bigDMQ1);
+ if (keyMat->bigIQMP) free(keyMat->bigIQMP);
+ free(keyMat);
+}
+
+// Save the key data in PKCS#11
+int crypto_save_dsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ int objIDLen,
+ int noPublicKey,
+ DSA* dsa
+)
+{
+ dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigY, keyMat->sizeY }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigX, keyMat->sizeX }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_dsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2);
+ crypto_free_dsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+dsa_key_material_t* crypto_malloc_dsa(DSA* dsa)
+{
+ if (dsa == NULL)
+ {
+ return NULL;
+ }
+
+ dsa_key_material_t* keyMat = (dsa_key_material_t*)malloc(sizeof(dsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeP = BN_num_bytes(dsa->p);
+ keyMat->sizeQ = BN_num_bytes(dsa->q);
+ keyMat->sizeG = BN_num_bytes(dsa->g);
+ keyMat->sizeX = BN_num_bytes(dsa->priv_key);
+ keyMat->sizeY = BN_num_bytes(dsa->pub_key);
+
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG);
+ keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX);
+ keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY);
+
+ if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY)
+ {
+ crypto_free_dsa(keyMat);
+ return NULL;
+ }
+
+ BN_bn2bin(dsa->p, (unsigned char*)keyMat->bigP);
+ BN_bn2bin(dsa->q, (unsigned char*)keyMat->bigQ);
+ BN_bn2bin(dsa->g, (unsigned char*)keyMat->bigG);
+ BN_bn2bin(dsa->priv_key, (unsigned char*)keyMat->bigX);
+ BN_bn2bin(dsa->pub_key, (unsigned char*)keyMat->bigY);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_dsa(dsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigG) free(keyMat->bigG);
+ if (keyMat->bigX) free(keyMat->bigX);
+ if (keyMat->bigY) free(keyMat->bigY);
+ free(keyMat);
+}
diff --git a/src/bin/util/softhsm-util-ossl.h b/src/bin/util/softhsm-util-ossl.h
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: softhsm-util-ossl.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-util-ossl.h
+
+ Header file for OpenSSL implemented
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM_UTIL_OSSL_H
+#define _SOFTHSM_V2_SOFTHSM_UTIL_OSSL_H
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+
+typedef struct rsa_key_material_t {
+ CK_ULONG sizeE;
+ CK_ULONG sizeN;
+ CK_ULONG sizeD;
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeDMP1;
+ CK_ULONG sizeDMQ1;
+ CK_ULONG sizeIQMP;
+ CK_VOID_PTR bigE;
+ CK_VOID_PTR bigN;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigDMP1;
+ CK_VOID_PTR bigDMQ1;
+ CK_VOID_PTR bigIQMP;
+ rsa_key_material_t() {
+ sizeE = 0;
+ sizeN = 0;
+ sizeD = 0;
+ sizeP = 0;
+ sizeQ = 0;
+ sizeDMP1 = 0;
+ sizeDMQ1 = 0;
+ sizeIQMP = 0;
+ bigE = NULL_PTR;
+ bigN = NULL_PTR;
+ bigD = NULL_PTR;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigDMP1 = NULL_PTR;
+ bigDMQ1 = NULL_PTR;
+ bigIQMP = NULL_PTR;
+ }
+} rsa_key_material_t;
+
+typedef struct dsa_key_material_t {
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeG;
+ CK_ULONG sizeX;
+ CK_ULONG sizeY;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigG;
+ CK_VOID_PTR bigX;
+ CK_VOID_PTR bigY;
+ dsa_key_material_t() {
+ sizeP = 0;
+ sizeQ = 0;
+ sizeG = 0;
+ sizeX = 0;
+ sizeY = 0;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigG = NULL_PTR;
+ bigX = NULL_PTR;
+ bigY = NULL_PTR;
+ }
+} dsa_key_material_t;
+
+EVP_PKEY* crypto_read_file(char* filePath, char* filePIN);
+
+// RSA
+int crypto_save_rsa(CK_SESSION_HANDLE hSession, char* label, char* objID, int objIDLen, int noPublicKey, RSA* rsa);
+rsa_key_material_t* crypto_malloc_rsa(RSA* rsa);
+void crypto_free_rsa(rsa_key_material_t* keyMat);
+
+// DSA
+int crypto_save_dsa(CK_SESSION_HANDLE hSession, char* label, char* objID, int objIDLen, int noPublicKey, DSA* dsa);
+dsa_key_material_t* crypto_malloc_dsa(DSA* dsa);
+void crypto_free_dsa(dsa_key_material_t* keyMat);
+
+#endif // !_SOFTHSM_V2_SOFTHSM_UTIL_OSSL_H
diff --git a/src/bin/util/softhsm-util.1 b/src/bin/util/softhsm-util.1
--- /dev/null
@@ -0,0 +1,207 @@
+.TH SOFTHSM-UTIL 1 "22 October 2012" "SoftHSM"
+.\" $Id: softhsm-util.1 6757 2012-10-22 19:40:31Z rb $
+.SH NAME
+softhsm-util \- support tool for libsofthsm
+.SH SYNOPSIS
+.B softhsm-util \-\-show-slots
+.PP
+.B softhsm-util \-\-init-token
+.B \-\-slot
+.I number
+.B \-\-label
+.I text
+\\
+.ti +0.7i
+.RB [ \-\-so-pin
+.I PIN
+.B \-\-pin
+.IR PIN ]
+.PP
+.B softhsm-util \-\-import
+.I path
+.RB [ \-\-file-pin
+.IR PIN ]
+.B \-\-slot
+.I number
+\\
+.ti +0.7i
+.RB [ \-\-pin
+.I PIN
+.B \-\-no\-public\-key]
+.B \-\-label
+.I text
+.B \-\-id
+.I hex
+.SH DESCRIPTION
+.B softhsm-util
+is a support tool mainly for libsofthsm. It can also
+be used with other PKCS#11 libraries by using the option
+.B \-\-module
+.PP
+Read the sections below to get more information on
+the libsofthsm and PKCS#11.
+Most applications assumes that the token they want
+to use is already initialized.
+It is then up to the user
+to initialize the PKCS#11 token.
+This is done by using the PKCS#11 interface,
+but instead of writing your own
+tool you can use the
+.B softhsm-util
+tool.
+.PP
+Keys are usually created directly in the token,
+but the user may want to use an existing key pair.
+Keys can be imported to a token by using the PKCS#11 interface,
+but this tool can also be used if the
+user has the key pair in a PKCS#8 file.
+If you need to convert keys from
+BIND .private-key format over to PKCS#8,
+one can
+use
+.BR softhsm-keyconv .
+.LP
+The libary
+.BR libsofthsm ,
+known as SoftHSM, provides cryptographic functionality
+by using the PKCS#11 API.
+It was developed as a part of the OpenDNSSEC project,
+thus designed to meet the requirements
+of OpenDNSSEC,
+but can also work together with other
+software that want to use the functionality
+of the PKCS#11 API.
+.PP
+SoftHSM is a software implementation of a generic cryptographic device with a PKCS#11 interface.
+These devices are often called tokens.
+Read in the manual softhsm.conf(5) on how to create these
+tokens and how they are added to a slot in SoftHSM.
+.LP
+The
+.B PKCS#11
+API
+can be used to handle and store cryptographic keys.
+This interface
+specifies how to communicate with cryptographic devices such as HSMs
+(Hardware Security Modules) and smart cards.
+The purpose of these devices
+is, among others,
+to generate cryptographic keys and sign information without
+revealing private-key material to the outside world.
+They are often designed
+to perform well on these specific tasks
+compared to ordinary processes in a normal computer.
+.LP
+.SH ACTIONS
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
+.TP
+.B \-\-import \fIpath\fR
+Import a key pair from the given
+.IR path .
+The file must be in PKCS#8-format.
+.br
+Use with
+.BR \-\-file-pin ,
+.BR \-\-slot ,
+.BR \-\-pin ,
+.BR \-\-no\-public\-key ,
+.BR \-\-label ,
+and
+.BR \-\-id .
+.TP
+.B \-\-init-token
+Initialize the token at a given slot.
+If the token is already initialized then this command
+will reinitialize it, thus erasing all the objects in the token.
+The matching Security Officer (SO) PIN must also
+be provided when doing reinitialization.
+.br
+Use with
+.BR \-\-slot ,
+.BR \-\-label .
+.BR \-\-so-pin ,
+and
+.BR \-\-pin .
+.LP
+.TP
+.B \-\-show-slots
+Display all the available slots and their current status.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH OPTIONS
+.TP
+.B \-\-file-pin \fIPIN\fR
+The
+.I PIN
+will be used to decrypt the PKCS#8 file.
+If not given then the PKCS#8 file is assumed to be unencrypted.
+.TP
+.B \-\-force
+Use this option to override the warnings and force the given action.
+.TP
+.B \-\-id \fIhex\fR
+Choose an ID of the key pair.
+The ID is in hexadecimal with a variable length.
+Use with
+.B \-\-force
+when importing a key pair if the ID already exists.
+.TP
+.B \-\-label \fItext\fR
+Defines the
+.I label
+of the object or the token.
+.TP
+.B \-\-module \fIpath\fR
+Use another PKCS#11 library than SoftHSM.
+.TP
+.B \-\-no\-public\-key
+Do not import the public key.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+for the normal user.
+.TP
+.B \-\-slot \fInumber\fR
+The slot where the token is located.
+.TP
+.B \-\-so-pin \fIPIN\fR
+The
+.I PIN
+for the Security Officer (SO).
+.SH EXAMPLES
+.LP
+The token can be initialized using this command:
+.LP
+.RS
+.nf
+softhsm-util \-\-init-token \-\-slot 1 \-\-label "A token"
+.fi
+.RE
+.LP
+A key pair can be imported using the softhsm tool where you specify the path
+to the key file, slot number, label and ID of the new objects, and the
+user PIN.
+The file must be in PKCS#8 format.
+.LP
+.RS
+.nf
+softhsm-util \-\-import key1.pem \-\-slot 1 \-\-label "My key" \\
+.ti +0.7i
+\-\-id A1B2 \-\-pin 123456
+.fi
+(Add, \-\-file-pin
+.IR PIN ,
+if the key file is encrypted.)
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, René Post, and Roland van Rijswijk.
+.LP
+.SH "SEE ALSO"
+.IR softhsm-keyconv (1),
+.IR softhsm-migrate (1),
+.IR softhsm2.conf (5)
diff --git a/src/bin/util/softhsm-util.cpp b/src/bin/util/softhsm-util.cpp
--- /dev/null
@@ -0,0 +1,680 @@
+/* $Id: softhsm-util.cpp 5880 2011-11-18 15:19:13Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-util.cpp
+
+ This program can be used for interacting with HSMs using PKCS#11.
+ The default library is the libsofthsm.so
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm-util.h"
+#include "getpw.h"
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+
+// Display the usage
+void usage()
+{
+ printf("Support tool for PKCS#11\n");
+ printf("Usage: softhsm-util [ACTION] [OPTIONS]\n");
+ printf("Action:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --import <path> Import a key pair from the given path.\n");
+ printf(" The file must be in PKCS#8-format.\n");
+ printf(" Use with --file-pin, --slot, --label, --id,\n");
+ printf(" --no-public-key, and --pin.\n");
+ printf(" --init-token Initialize the token at a given slot.\n");
+ printf(" Use with --slot, --label, --so-pin, and --pin.\n");
+ printf(" WARNING: Any content in token token will be erased.\n");
+ printf(" --show-slots Display all the available slots.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+ printf("Options:\n");
+ printf(" --file-pin <PIN> Supply a PIN if the file is encrypted.\n");
+ printf(" --force Used to override a warning.\n");
+ printf(" --id <hex> Defines the ID of the object. Hexadecimal characters.\n");
+ printf(" Use with --force if multiple key pairs may share\n");
+ printf(" the same ID.\n");
+ printf(" --label <text> Defines the label of the object or the token.\n");
+ printf(" --module <path> Use another PKCS#11 library than SoftHSM.\n");
+ printf(" --no-public-key Do not import the public key.\n");
+ printf(" --pin <PIN> The PIN for the normal user.\n");
+ printf(" --slot <number> The slot where the token is located.\n");
+ printf(" --so-pin <PIN> The PIN for the Security Officer (SO).\n");
+}
+
+// Enumeration of the long options
+enum {
+ OPT_FILE_PIN = 0x100,
+ OPT_FORCE,
+ OPT_HELP,
+ OPT_ID,
+ OPT_IMPORT,
+ OPT_INIT_TOKEN,
+ OPT_LABEL,
+ OPT_MODULE,
+ OPT_NO_PUBLIC_KEY,
+ OPT_PIN,
+ OPT_SHOW_SLOTS,
+ OPT_SLOT,
+ OPT_SO_PIN,
+ OPT_VERSION
+};
+
+// Text representation of the long options
+static const struct option long_options[] = {
+ { "file-pin", 1, NULL, OPT_FILE_PIN },
+ { "force", 0, NULL, OPT_FORCE },
+ { "help", 0, NULL, OPT_HELP },
+ { "id", 1, NULL, OPT_ID },
+ { "import", 1, NULL, OPT_IMPORT },
+ { "init-token", 0, NULL, OPT_INIT_TOKEN },
+ { "label", 1, NULL, OPT_LABEL },
+ { "module", 1, NULL, OPT_MODULE },
+ { "no-public-key", 0, NULL, OPT_NO_PUBLIC_KEY },
+ { "pin", 1, NULL, OPT_PIN },
+ { "show-slots", 0, NULL, OPT_SHOW_SLOTS },
+ { "slot", 1, NULL, OPT_SLOT },
+ { "so-pin", 1, NULL, OPT_SO_PIN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+CK_FUNCTION_LIST_PTR p11;
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt;
+
+ char* inPath = NULL;
+ char* outPath = NULL;
+ char* soPIN = NULL;
+ char* userPIN = NULL;
+ char* filePIN = NULL;
+ char* label = NULL;
+ char* module = NULL;
+ char* objectID = NULL;
+ char* slot = NULL;
+ int forceExec = 0;
+ int noPublicKey = 0;
+
+ int doInitToken = 0;
+ int doShowSlots = 0;
+ int doImport = 0;
+ int doExport = 0;
+ int action = 0;
+ int rv = 0;
+
+ moduleHandle = NULL;
+ p11 = NULL;
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_SHOW_SLOTS:
+ doShowSlots = 1;
+ action++;
+ break;
+ case OPT_INIT_TOKEN:
+ doInitToken = 1;
+ action++;
+ break;
+ case OPT_IMPORT:
+ doImport = 1;
+ action++;
+ inPath = optarg;
+ break;
+ case OPT_SLOT:
+ slot = optarg;
+ break;
+ case OPT_LABEL:
+ label = optarg;
+ break;
+ case OPT_MODULE:
+ module = optarg;
+ break;
+ case OPT_NO_PUBLIC_KEY:
+ noPublicKey = 1;
+ break;
+ case OPT_ID:
+ objectID = optarg;
+ break;
+ case OPT_SO_PIN:
+ soPIN = optarg;
+ break;
+ case OPT_PIN:
+ userPIN = optarg;
+ break;
+ case OPT_FILE_PIN:
+ filePIN = optarg;
+ break;
+ case OPT_FORCE:
+ forceExec = 1;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // No action given, display the usage.
+ if (!action)
+ {
+ usage();
+ }
+ else
+ {
+ // Get a pointer to the function list for PKCS#11 library
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(module, &moduleHandle);
+ if (!pGetFunctionList)
+ {
+ fprintf(stderr, "ERROR: Could not load the library.\n");
+ exit(1);
+ }
+
+ // Load the function list
+ (*pGetFunctionList)(&p11);
+
+ // Initialize the library
+ CK_RV rv = p11->C_Initialize(NULL_PTR);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the library.\n");
+ exit(1);
+ }
+ }
+
+ // We should create the token.
+ if (doInitToken)
+ {
+ rv = initToken(slot, label, soPIN, userPIN);
+ }
+
+ // Show all available slots
+ if (doShowSlots)
+ {
+ rv = showSlots();
+ }
+
+ // Import a key pair from the given path
+ if (doImport)
+ {
+ rv = importKeyPair(inPath, filePIN, slot, userPIN, label, objectID,
+ forceExec, noPublicKey);
+ }
+
+ // Finalize the library
+ if (action)
+ {
+ p11->C_Finalize(NULL_PTR);
+ unloadLibrary(moduleHandle);
+ }
+
+ return rv;
+}
+
+// Initialize the token
+int initToken(char* slot, char* label, char* soPIN, char* userPIN)
+{
+ char so_pin_copy[MAX_PIN_LEN+1];
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (slot == NULL)
+ {
+ fprintf(stderr, "ERROR: A slot number must be supplied. "
+ "Use --slot <number>\n");
+ return 1;
+ }
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the token must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (strlen(label) > 32)
+ {
+ fprintf(stderr, "ERROR: The token label must not have a length "
+ "greater than 32 chars.\n");
+ return 1;
+ }
+
+ // Get the passwords
+ getPW(soPIN, so_pin_copy, CKU_SO);
+ getPW(userPIN, user_pin_copy, CKU_USER);
+
+ // Load the variables
+ CK_SLOT_ID slotID = atoi(slot);
+ CK_UTF8CHAR paddedLabel[32];
+ memset(paddedLabel, ' ', sizeof(paddedLabel));
+ memcpy(paddedLabel, label, strlen(label));
+
+ CK_RV rv = p11->C_InitToken(slotID, (CK_UTF8CHAR_PTR)so_pin_copy, strlen(so_pin_copy), paddedLabel);
+
+ switch (rv)
+ {
+ case CKR_OK:
+ break;
+ case CKR_SLOT_ID_INVALID:
+ fprintf(stderr, "CKR_SLOT_ID_INVALID: Slot %lu does not exist.\n", slotID);
+ return 1;
+ break;
+ case CKR_PIN_INCORRECT:
+ fprintf(stderr, "CKR_PIN_INCORRECT: The given SO PIN does not match the "
+ "one in the token. Needed when reinitializing the token.\n");
+ return 1;
+ break;
+ case CKR_TOKEN_NOT_PRESENT:
+ fprintf(stderr, "CKR_TOKEN_NOT_PRESENT: The token is not present. "
+ "Please read the HSM manual for further assistance.\n");
+ return 1;
+ break;
+ default:
+ fprintf(stderr, "ERROR %X: Could not initialize the token.\n", (unsigned int)rv);
+ return 1;
+ break;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not open a session with the library.\n");
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_SO, (CK_UTF8CHAR_PTR)so_pin_copy, strlen(so_pin_copy));
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ return 1;
+ }
+
+ rv = p11->C_InitPIN(hSession, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the user PIN.\n");
+ return 1;
+ }
+
+ printf("The token has been initialized.\n");
+
+ return 0;
+}
+
+// Show what slots are available
+int showSlots()
+{
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (!pSlotList)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ printf("Available slots:\n");
+
+ for (unsigned int i = 0; i < ulSlotCount; i++)
+ {
+ CK_SLOT_INFO slotInfo;
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetSlotInfo(pSlotList[i], &slotInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about slot %lu.\n", pSlotList[i]);
+ continue;
+ }
+
+ printf("Slot %lu\n", pSlotList[i]);
+ printf(" Slot info:\n");
+ printf(" Description: %.*s\n", 64, slotInfo.slotDescription);
+ printf(" Manufacturer ID: %.*s\n", 32, slotInfo.manufacturerID);
+ printf(" Hardware version: %i.%i\n", slotInfo.hardwareVersion.major,
+ slotInfo.hardwareVersion.minor);
+ printf(" Firmware version: %i.%i\n", slotInfo.firmwareVersion.major,
+ slotInfo.firmwareVersion.minor);
+ printf(" Token present: ");
+ if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0)
+ {
+ printf("no\n");
+ continue;
+ }
+
+ printf("yes\n");
+ printf(" Token info:\n");
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ continue;
+ }
+
+ printf(" Manufacturer ID: %.*s\n", 32, tokenInfo.manufacturerID);
+ printf(" Model: %.*s\n", 16, tokenInfo.model);
+ printf(" Hardware version: %i.%i\n", tokenInfo.hardwareVersion.major,
+ tokenInfo.hardwareVersion.minor);
+ printf(" Firmware version: %i.%i\n", tokenInfo.firmwareVersion.major,
+ tokenInfo.firmwareVersion.minor);
+ printf(" Serial number: %.*s\n", 16, tokenInfo.serialNumber);
+ printf(" Initialized: ");
+ if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0)
+ {
+ printf("no\n");
+ }
+ else
+ {
+ printf("yes\n");
+ }
+
+ printf(" User PIN init.: ");
+ if ((tokenInfo.flags & CKF_USER_PIN_INITIALIZED) == 0)
+ {
+ printf("no\n");
+ }
+ else
+ {
+ printf("yes\n");
+ }
+
+ printf(" Label: %.*s\n", 32, tokenInfo.label);
+
+ }
+
+ free(pSlotList);
+
+ return 0;
+}
+
+// Import a key pair from given path
+int importKeyPair
+(
+ char* filePath,
+ char* filePIN,
+ char* slot,
+ char* userPIN,
+ char* label,
+ char* objectID,
+ int forceExec,
+ int noPublicKey
+)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (slot == NULL)
+ {
+ fprintf(stderr, "ERROR: A slot number must be supplied. "
+ "Use --slot <number>\n");
+ return 1;
+ }
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the object must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (objectID == NULL)
+ {
+ fprintf(stderr, "ERROR: An ID for the object must be supplied. "
+ "Use --id <hex>\n");
+ return 1;
+ }
+
+ int objIDLen = 0;
+ char* objID = hexStrToBin(objectID, strlen(objectID), &objIDLen);
+ if (objID == NULL)
+ {
+ fprintf(stderr, "Please edit --id <hex> to correct error.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID slotID = atoi(slot);
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ free(objID);
+ return 1;
+ }
+
+ // Get the password
+ getPW(userPIN, user_pin_copy, CKU_USER);
+
+ rv = p11->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ free(objID);
+ return 1;
+ }
+
+ CK_OBJECT_HANDLE oHandle = searchObject(hSession, objID, objIDLen);
+ if (oHandle != CK_INVALID_HANDLE && forceExec == 0)
+ {
+ free(objID);
+ fprintf(stderr, "ERROR: The ID is already assigned to another object. "
+ "Use --force to override this message.\n");
+ return 1;
+ }
+
+ crypto_init();
+ int result = crypto_import_key_pair(hSession, filePath, filePIN, label, objID, objIDLen, noPublicKey);
+ crypto_final();
+
+ free(objID);
+
+ return result;
+}
+
+// Convert a char array of hexadecimal characters into a binary representation
+char* hexStrToBin(char* objectID, int idLength, int* newLen)
+{
+ char* bytes = NULL;
+
+ if (idLength % 2 != 0)
+ {
+ fprintf(stderr, "ERROR: Invalid length on hex string.\n");
+ return NULL;
+ }
+
+ for (int i = 0; i < idLength; i++)
+ {
+ if (hexdigit_to_int(objectID[i]) == -1)
+ {
+ fprintf(stderr, "ERROR: Invalid character in hex string.\n");
+ return NULL;
+ }
+ }
+
+ *newLen = idLength / 2;
+ bytes = (char*) malloc(*newLen);
+ if (bytes == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return NULL;
+ }
+
+ for (int i = 0; i < *newLen; i++)
+ {
+ bytes[i] = hexdigit_to_int(objectID[2*i]) * 16 +
+ hexdigit_to_int(objectID[2*i+1]);
+ }
+
+ return bytes;
+}
+
+// Return the integer value of a hexadecimal character
+int hexdigit_to_int(char ch)
+{
+ switch (ch)
+ {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ default:
+ return -1;
+ }
+}
+
+// Search for an object
+CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, int objIDLen)
+{
+ if (objID == NULL)
+ {
+ return CK_INVALID_HANDLE;
+ }
+
+ CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_ULONG objectCount = 0;
+
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &oClass, sizeof(oClass) },
+ { CKA_ID, objID, objIDLen }
+ };
+
+ CK_RV rv = p11->C_FindObjectsInit(hSession, objTemplate, 2);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not prepare the object search.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ rv = p11->C_FindObjects(hSession, &hObject, 1, &objectCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the search results.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ rv = p11->C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not finalize the search.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ if (objectCount == 0)
+ {
+ return CK_INVALID_HANDLE;
+ }
+
+ return hObject;
+}
diff --git a/src/bin/util/softhsm-util.h b/src/bin/util/softhsm-util.h
--- /dev/null
@@ -0,0 +1,65 @@
+/* $Id: softhsm-util.h 4951 2011-03-29 08:54:51Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm-util.h
+
+ This program can be used for interacting with HSMs using PKCS#11.
+ The default library is the libsofthsm.so
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM_UTIL_H
+#define _SOFTHSM_V2_SOFTHSM_UTIL_H
+
+#include "pkcs11.h"
+
+// Main functions
+
+void usage();
+int initToken(char* slot, char* label, char* soPIN, char* userPIN);
+int showSlots();
+int importKeyPair(char* filePath, char* filePIN, char* slot, char* userPIN, char* objectLabel, char* objectID, int forceExec, int noPublicKey);
+int crypto_import_key_pair(CK_SESSION_HANDLE hSession, char* filePath, char* filePIN, char* label, char* objID, int objIDLen, int noPublicKey);
+
+// Support functions
+
+void crypto_init();
+void crypto_final();
+
+/// Hex
+char* hexStrToBin(char* objectID, int idLength, int* newLen);
+int hexdigit_to_int(char ch);
+
+/// Library
+static void* moduleHandle;
+extern CK_FUNCTION_LIST_PTR p11;
+
+/// PKCS#11 support
+CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, int objIDLen);
+
+#endif // !_SOFTHSM_V2_SOFTHSM_UTIL_H
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
--- /dev/null
+++ b/src/lib/Makefile.am
@@ -0,0 +1,50 @@
+# $Id: Makefile.am 6717 2012-10-02 00:04:31Z rene $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/cryptoki_compat \
+ -I$(srcdir)/common \
+ -I$(srcdir)/object_store \
+ -I$(srcdir)/slot_mgr \
+ -I$(srcdir)/session_mgr \
+ -I$(srcdir)/data_mgr \
+ -I$(srcdir)/handle_mgr \
+ -I$(srcdir)/crypto
+
+lib_LTLIBRARIES = libsofthsm.la
+
+libsofthsm_la_SOURCES = access.cpp \
+ main.cpp \
+ P11Attributes.cpp \
+ P11Objects.cpp \
+ SoftHSM.cpp
+libsofthsm_la_LIBADD = common/libsofthsm_common.la \
+ crypto/libsofthsm_crypto.la \
+ data_mgr/libsofthsm_datamgr.la \
+ handle_mgr/libsofthsm_handlemgr.la \
+ object_store/libsofthsm_objectstore.la \
+ session_mgr/libsofthsm_sessionmgr.la \
+ slot_mgr/libsofthsm_slotmgr.la
+libsofthsm_la_LDFLAGS = -version-info @VERSION_INFO@ \
+ -avoid-version -module
+
+# Create a convenience library from all the other convenience library; this is
+# necessary to resolve circular dependencies when statically linking the test
+# executables
+noinst_LTLIBRARIES = libsofthsm_convarch.la
+
+libsofthsm_convarch_la_SOURCES =
+
+libsofthsm_convarch_la_LIBADD = $(libsofthsm_la_LIBADD)
+
+SUBDIRS = common \
+ crypto \
+ data_mgr \
+ object_store \
+ session_mgr \
+ slot_mgr \
+ handle_mgr \
+ test
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/cryptoki_compat/*.h
diff --git a/src/lib/Makefile.old b/src/lib/Makefile.old
--- /dev/null
+++ b/src/lib/Makefile.old
@@ -0,0 +1,42 @@
+# Temporary Makefile that is used until this project has been auto'd by Rickard ;-)
+#
+# $Id: Makefile.old 4748 2010-03-05 12:51:02Z rb $
+
+CC=gcc
+CFLAGS=-g -Wall -DWITH_OPENSSL
+
+CPP=g++
+CPPFLAGS=-g -Wall -DWITH_OPENSSL
+
+LDFLAGS=
+
+-include Makefile.crypto
+-include Makefile.lib
+
+SOURCES=$(CRYPTOSOURCES) $(LIBSOURCES)
+HEADERS=$(CRYPTOHEADERS) $(LIBHEADERS)
+OBJECTS=$(CRYPTOOBJECTS) $(LIBOBJECTS)
+
+LIBRARY=libsofthsm
+
+# Include dependencies
+-include $(OBJECTS:.o=.d)
+
+# Include test dependencies
+-include $(CRYPTOTESTOBJECTS:.o=.d)
+
+all: $(SOURCES) $(HEADERS) $(LIBRARY)
+
+clean:
+ rm -f *.d *.o $(LIBRARY)
+
+libsofthsm: $(SOURCES) $(HEADERS) $(OBJECTS)
+ echo "No build rule for libsofthsm yet"
+
+.cpp.o:
+ $(CPP) $(CPPFLAGS) $< -c -o $@
+ @$(CPP) -MM $(CPPFLAGS) $< > $*.d
+
+.c.o:
+ $(CC) $(CFLAGS) $< -c -o $@
+ @$(CC) -MM $(CFLAGS) $< > $*.d
diff --git a/src/lib/P11Attributes.cpp b/src/lib/P11Attributes.cpp
--- /dev/null
@@ -0,0 +1,1755 @@
+/* $Id: P11Attributes.cpp 6784 2012-10-26 10:08:06Z rb $ */
+
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Attributes.h
+
+ This file contains classes for controlling attributes
+ *****************************************************************************/
+
+#include "config.h"
+#include "P11Attributes.h"
+#include "ByteString.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+// Constructor
+P11Attribute::P11Attribute(OSObject* osobject)
+{
+ this->osobject = osobject;
+ type = CKA_VENDOR_DEFINED;
+ size = (CK_ULONG)-1;
+ checks = 0;
+}
+
+// Destructor
+P11Attribute::~P11Attribute()
+{
+}
+
+CK_RV P11Attribute::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ ByteString value;
+ if (isPrivate)
+ {
+ if (!token->encrypt(ByteString((unsigned char*)pValue, ulValueLen),value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = ByteString((unsigned char*)pValue, ulValueLen);
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+ osobject->setAttribute(type, value);
+ return CKR_OK;
+}
+
+bool P11Attribute::isModifiable()
+{
+ // Get the CKA_MODIFIABLE attribute, when the attribute is
+ // not present return the default value which is CK_TRUE.
+ OSAttribute* attr = osobject->getAttribute(CKA_MODIFIABLE);
+ return attr == NULL || attr->getBooleanValue();
+}
+
+bool P11Attribute::isSensitive()
+{
+ // Get the CKA_SENSITIVE attribute, when the attribute is not present
+ // assume the object is not sensitive.
+ OSAttribute* attr = osobject->getAttribute(CKA_SENSITIVE);
+ return attr != NULL && attr->getBooleanValue();
+}
+
+bool P11Attribute::isExtractable()
+{
+ // Get the CKA_EXTRACTABLE attribute, when the attribute is
+ // not present assume the object allows extraction.
+ OSAttribute* attr = osobject->getAttribute(CKA_EXTRACTABLE);
+ return attr == NULL || attr->getBooleanValue();
+}
+
+bool P11Attribute::isTrusted()
+{
+ // Get the CKA_TRUSTED attribute, when the attribute is
+ // not present assume the object is not trusted.
+ OSAttribute* attr = osobject->getAttribute(CKA_TRUSTED);
+ return attr != NULL && attr->getBooleanValue();
+}
+
+// Initialize the attribute
+bool P11Attribute::init()
+{
+ if (osobject == NULL) return false;
+
+ // Create a default value if the attribute does not exist
+ if (osobject->attributeExists(type) == false)
+ {
+ return setDefault();
+ }
+
+ return true;
+}
+
+// Return the attribute type
+CK_ATTRIBUTE_TYPE P11Attribute::getType()
+{
+ return type;
+}
+
+// Retrieve the value if allowed
+CK_RV P11Attribute::retrieve(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG_PTR pulValueLen)
+{
+
+ if (osobject == NULL) {
+ ERROR_MSG("Internal error: osobject field contains NULL_PTR");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (pulValueLen == NULL) {
+ ERROR_MSG("Internal error: pulValueLen contains NULL_PTR");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // [PKCS#11 v2.3 pg.131 C_GetAttributeValue]
+ // 1. If the specified attribute (i.e. the attribute specified by the
+ // type field) for the object cannot be revealed because the object
+ // is sensitive or unextractable, then the ulValueLen field in that
+ // tripple is modified to hold the value -1 (i.e., when it is cast
+ // to a CK_LONG, it holds -1).
+ //
+ // [PKCS#11 v2.3 pg. 62 table 15]
+ // 7 Cannot be revealed if object has its CKA_SENSITIVE attribute
+ // set to CK_TRUE or its CKA_EXTRACTABLE attribute set to CK_FALSE.
+ if ((checks & ck7) == ck7 && (isSensitive() || !isExtractable())) {
+ *pulValueLen = (CK_ULONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+
+ // Get the actual attribute size.
+ OSAttribute* attr = NULL_PTR;
+ CK_ULONG attrSize = size;
+ if (size == (CK_ULONG)-1) {
+ // We don't have a fixed size attribute so we need to consult
+ // the lower level attribute for the exact size.
+
+ // Retrieve the lower level attribute.
+ attr = osobject->getAttribute(type);
+ if (attr == NULL_PTR) {
+ // Should be impossible.
+ ERROR_MSG("Internal error: attribute not present");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Lower level attribute has to be variable sized.
+ if (!attr->isByteStringAttribute()) {
+ // Should be impossible.
+ ERROR_MSG("Internal error: attribute has fixed size");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (isPrivate && attr->getByteStringValue().size() != 0)
+ {
+ ByteString value;
+ if (!token->decrypt(attr->getByteStringValue(),value))
+ {
+ ERROR_MSG("Internal error: failed to decrypt private attribute value");
+ return CKR_GENERAL_ERROR;
+ }
+ attrSize = value.size();
+ }
+ else
+ attrSize = attr->getByteStringValue().size();
+ }
+
+ // [PKCS#11 v2.3 pg.131 C_GetAttributeValue]
+ // 3. Otherwise, if the pValue field has the value NULL_PTR, then the
+ // ulValueLen field is modified to hold the exact length of the
+ // specified attribute for the object.
+ if (pValue == NULL_PTR) {
+ // Return the size of the attribute.
+ *pulValueLen = attrSize;
+ return CKR_OK;
+ }
+
+ // [PKCS#11 v2.3 pg.131 C_GetAttributeValue]
+ // 4. Otherwise, if the length specified in ulValueLen is large enough
+ // to hold the value of the specified attribute for the object, then
+ // that attribute is copied into the buffer located at pValue, and
+ // the ulValueLen field is modified to hold the exact length of the
+ // attribute.
+ if (*pulValueLen >= attrSize) {
+ // Only copy when there is actually something to copy
+ if (attrSize > 0) {
+ // Retrieve the attribute when this was not already done.
+ if (attr == NULL_PTR) {
+ // attr was not retrieved, happens only for a fixed size attribute.
+ attr = osobject->getAttribute(type);
+ if (attr == NULL_PTR) {
+ // Should be impossible.
+ ERROR_MSG("Internal error: attribute not present");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Get the unsigned long or boolean value.
+ if (attr->isUnsignedLongAttribute()) {
+ *(CK_ULONG_PTR)pValue = attr->getUnsignedLongValue();
+ } else {
+ if (attr->isBooleanAttribute()) {
+ *(CK_BBOOL*)pValue = attr->getBooleanValue() ? CK_TRUE : CK_FALSE;
+ } else {
+ // Should be impossible.
+ ERROR_MSG("Internal error: attribute has variable size");
+ return CKR_GENERAL_ERROR;
+ }
+ }
+
+ } else {
+ // attr is alread retrieved and verified to be a ByteString.
+ if (isPrivate)
+ {
+ ByteString value;
+ if (!token->decrypt(attr->getByteStringValue(),value))
+ {
+ ERROR_MSG("Internal error: failed to decrypt private attribute value");
+ return CKR_GENERAL_ERROR;
+ }
+ const unsigned char* attrPtr = value.const_byte_str();
+ memcpy(pValue,attrPtr,attrSize);
+ }
+ else
+ {
+ const unsigned char* attrPtr = attr->getByteStringValue().const_byte_str();
+ memcpy(pValue,attrPtr,attrSize);
+ }
+ }
+ }
+ *pulValueLen = attrSize;
+ return CKR_OK;
+ }
+
+ // [PKCS#11 v2.3 pg.131]
+ // 5. Otherwise, the ulValueLen field is modified to hold the value -1.
+ *pulValueLen = (CK_ULONG)-1;
+ return CKR_BUFFER_TOO_SMALL;
+}
+
+// Update the value if allowed
+CK_RV P11Attribute::update(Token* token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ if (osobject == NULL) {
+ ERROR_MSG("Internal error: osobject field contains NULL_PTR");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // [PKCS#11 v2.3 pg. 60]
+ // 2. If the supplied template specifies an invalid value for a valid attribute, then the
+ // attempt should fail with the error code CKR_ATTRIBUTE_VALUE_INVALID.
+ // The valid values for Cryptoki attributes are described in the Cryptoki specification.
+
+ // Check for null pointers in values.
+ if (pValue == NULL_PTR && ulValueLen != 0) {
+ ERROR_MSG("The attribute is a NULL_PTR but has a non-zero length")
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // For fixed sized attributes check that the size matches.
+ if (size != ((CK_ULONG)-1) && size != ulValueLen) {
+ ERROR_MSG("The attribute size is different from the expected size")
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // [PKCS#11 v2.3 pg. 60] OBJECT_OP_CREATE | OBJECT_OP_SET | OBJECT_OP_COPY
+ // 3. If the supplied template specifies a value for a read-only attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_READ_ONLY.
+ // Whether or not a given Cryptoki attribute is read-only is explicitly stated in the Cryptoki
+ // specification; however, a particular library and token may be even more restrictive than
+ // Cryptoki specifies. In other words, an attribute which Cryptoki says is not read-only may
+ // nonetheless be read-only under certain circumstances (i.e., in conjunction with some
+ // combinations of other attributes) for a particular library and token. Whether or not a
+ // given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki.
+
+
+ // Attributes cannot be changed if CKA_MODIFIABLE is set to false
+ if (!isModifiable()) {
+ ERROR_MSG("An object is with CKA_MODIFIABLE set to false is not modifiable");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ // Attributes cannot be modified if CKA_TRUSTED is true on a certificate object.
+ if (isTrusted()) {
+ OSAttribute* attrClass = osobject->getAttribute(CKA_CLASS);
+ if (attrClass != NULL && attrClass->getUnsignedLongValue() == CKO_CERTIFICATE)
+ {
+ ERROR_MSG("A trusted certificate cannot be modified");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck2 Must not be specified when object is created with C_CreateObject.
+ if ((checks & ck2) == ck2)
+ {
+ if (OBJECT_OP_CREATE==op)
+ {
+ ERROR_MSG("Prohibited attribute was passed to object creation function");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck4 Must not be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ if ((checks & ck4) == ck4)
+ {
+ if (OBJECT_OP_GENERATE==op)
+ {
+ ERROR_MSG("Prohibited attribute was passed to key generation function");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck6 Must not be specified when object is unwrapped with C_UnwrapKey.
+ if ((checks & ck6) == ck6)
+ {
+ if (OBJECT_OP_UNWRAP==op)
+ {
+ ERROR_MSG("Prohibited attribute was passed to key unwrapping function");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck8 May be modified after object is created with a C_SetAttributeValue call
+ // or in the process of copying an object with a C_CopyObject call.
+ // However, it is possible that a particular token may not permit modification of
+ // the attribute during the course of a C_CopyObject call.
+ if ((checks & ck8) == ck8)
+ {
+ if (OBJECT_OP_SET==op || OBJECT_OP_COPY==op)
+ {
+ return updateAttr(token, isPrivate, pValue, ulValueLen, op);
+ }
+ }
+
+ // ck17 Can be changed in the process of copying the object using C_CopyObject.
+ if ((checks & ck17) == ck17)
+ {
+ if (OBJECT_OP_COPY==op)
+ {
+ return updateAttr(token, isPrivate, pValue, ulValueLen, op);
+ }
+ }
+
+ // For attributes that have not been explicitly excluded from modification
+ // during create/derive/generate/unwrap, we allow them to be modified.
+ if (OBJECT_OP_CREATE==op || OBJECT_OP_DERIVE==op || OBJECT_OP_GENERATE==op || OBJECT_OP_UNWRAP==op)
+ {
+ return updateAttr(token, isPrivate, pValue, ulValueLen, op);
+ }
+
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_CLASS
+ *****************************************/
+
+// Set default value
+bool P11AttrClass::setDefault()
+{
+ OSAttribute attrClass((unsigned long)CKO_VENDOR_DEFINED);
+ return osobject->setAttribute(type, attrClass);
+}
+
+// Update the value if allowed
+CK_RV P11AttrClass::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute* attr = NULL;
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ attr = osobject->getAttribute(type);
+ if (attr == NULL) {
+ ERROR_MSG("Internal error: attribute not present");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (attr->getUnsignedLongValue() != *(CK_ULONG*)pValue)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_KEY_TYPE
+ *****************************************/
+
+// Set default value
+bool P11AttrKeyType::setDefault()
+{
+ OSAttribute attr((unsigned long)CKK_VENDOR_DEFINED);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrKeyType::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute* attr = NULL;
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ attr = osobject->getAttribute(type);
+ if (attr == NULL) {
+ ERROR_MSG("Internal error: attribute not present");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (attr->getUnsignedLongValue() != *(CK_ULONG*)pValue)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_CERTIFICATE_TYPE
+ * footnote 1
+ * 1 Must be specified when object is created with C_CreateObject.
+ *****************************************/
+
+// Set default value
+bool P11AttrCertificateType::setDefault()
+{
+ OSAttribute attr((unsigned long)CKC_VENDOR_DEFINED);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCertificateType::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute* attr = NULL;
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ attr = osobject->getAttribute(type);
+ if (attr == NULL) {
+ ERROR_MSG("Internal error: attribute not present");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (attr->getUnsignedLongValue() != *(CK_ULONG*)pValue)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_TOKEN
+ *****************************************/
+
+// Set default value
+bool P11AttrToken::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrToken::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE && op != OBJECT_OP_COPY)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_PRIVATE
+ *****************************************/
+
+// Set default value
+bool P11AttrPrivate::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrPrivate::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE && op != OBJECT_OP_COPY)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_MODIFIABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrModifiable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrModifiable::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE && op != OBJECT_OP_COPY)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_LABEL
+ *****************************************/
+
+// Set default value
+bool P11AttrLabel::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_COPYABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrCopyable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCopyable::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE && op != OBJECT_OP_COPY)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ if (osobject->getAttribute(type)->getBooleanValue() == false)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_APPLICATION
+ *****************************************/
+
+// Set default value
+bool P11AttrApplication::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_OBJECT_ID
+ *****************************************/
+
+// Set default value
+bool P11AttrObjectID::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_CHECK_VALUE
+ *****************************************/
+
+// Set default value
+bool P11AttrCheckValue::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_ID
+ *****************************************/
+
+// Set default value
+bool P11AttrID::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_VALUE
+ *****************************************/
+
+// Set default value
+bool P11AttrValue::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_SUBJECT
+ *****************************************/
+
+// Set default value
+bool P11AttrSubject::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_ISSUER
+ *****************************************/
+
+// Set default value
+bool P11AttrIssuer::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_TRUSTED
+ *****************************************/
+
+// Set default value
+bool P11AttrTrusted::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrTrusted::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ if (!token->isSOLoggedIn())
+ {
+ ERROR_MSG("CKA_TRUSTED can only be set to true by the SO");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_CERTIFICATE_CATEGORY
+ *****************************************/
+
+// Set default value
+bool P11AttrCertificateCategory::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCertificateCategory::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_SET)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_START_DATE
+ *****************************************/
+
+// Set default value
+bool P11AttrStartDate::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrStartDate::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_DATE) && ulValueLen !=0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, ByteString((unsigned char*)pValue, ulValueLen));
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_END_DATE
+ *****************************************/
+
+// Set default value
+bool P11AttrEndDate::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrEndDate::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_DATE) && ulValueLen !=0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, ByteString((unsigned char*)pValue, ulValueLen));
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SERIAL_NUMBER
+ *****************************************/
+
+// Set default value
+bool P11AttrSerialNumber::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_URL
+ *****************************************/
+
+// Set default value
+bool P11AttrURL::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_HASH_OF_SUBJECT_PUBLIC_KEY
+ *****************************************/
+
+// Set default value
+bool P11AttrHashOfSubjectPublicKey::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_HASH_OF_ISSUER_PUBLIC_KEY
+ *****************************************/
+
+// Set default value
+bool P11AttrHashOfIssuerPublicKey::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_JAVA_MIDP_SECURITY_DOMAIN
+ *****************************************/
+
+// Set default value
+bool P11AttrJavaMidpSecurityDomain::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrJavaMidpSecurityDomain::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_SET)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_NAME_HASH_ALGORITHM
+ *****************************************/
+
+// Set default value
+bool P11AttrNameHashAlgorithm::setDefault()
+{
+ OSAttribute attr((unsigned long)CKM_SHA_1);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrNameHashAlgorithm::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_SET)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_DERIVE
+ *****************************************/
+
+// Set default value
+bool P11AttrDerive::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrDerive::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_ENCRYPT
+ *****************************************/
+
+// Set default value
+bool P11AttrEncrypt::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrEncrypt::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_VERIFY
+ *****************************************/
+
+// Set default value
+bool P11AttrVerify::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrVerify::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_VERIFY_RECOVER
+ *****************************************/
+
+// Set default value
+bool P11AttrVerifyRecover::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrVerifyRecover::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_WRAP
+ *****************************************/
+
+// Set default value
+bool P11AttrWrap::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrWrap::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_DECRYPT
+ *****************************************/
+
+// Set default value
+bool P11AttrDecrypt::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrDecrypt::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SIGN
+ *****************************************/
+
+// Set default value
+bool P11AttrSign::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrSign::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SIGN_RECOVER
+ *****************************************/
+
+// Set default value
+bool P11AttrSignRecover::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrSignRecover::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_UNWRAP
+ *****************************************/
+
+// Set default value
+bool P11AttrUnwrap::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrUnwrap::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_LOCAL
+ *****************************************/
+
+// Set default value
+bool P11AttrLocal::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrLocal::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_KEY_GEN_MECHANISM
+ *****************************************/
+
+// Set default value
+bool P11AttrKeyGenMechanism::setDefault()
+{
+ OSAttribute attr((unsigned long)CK_UNAVAILABLE_INFORMATION);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrKeyGenMechanism::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_ALWAYS_SENSITIVE
+ *****************************************/
+
+// Set default value
+bool P11AttrAlwaysSensitive::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrAlwaysSensitive::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_NEVER_EXTRACTABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrNeverExtractable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrNeverExtractable::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_SENSITIVE
+ *****************************************/
+
+// Set default value
+bool P11AttrSensitive::setDefault()
+{
+ // We default to false because we want to handle the secret keys in a correct way
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrSensitive::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
+ {
+ if (osobject->getAttribute(type)->getBooleanValue())
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ osobject->setAttribute(CKA_ALWAYS_SENSITIVE, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+
+ // This is so that generated keys get the correct value
+ if (op == OBJECT_OP_GENERATE)
+ {
+ osobject->setAttribute(CKA_ALWAYS_SENSITIVE, attrTrue);
+ }
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_EXTRACTABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrExtractable::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrExtractable::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
+ {
+ if (osobject->getAttribute(type)->getBooleanValue() == false)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ osobject->setAttribute(CKA_NEVER_EXTRACTABLE, attrFalse);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_WRAP_WITH_TRUSTED
+ *****************************************/
+
+// Set default value
+bool P11AttrWrapWithTrusted::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrWrapWithTrusted::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
+ {
+ if (osobject->getAttribute(type)->getBooleanValue())
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_ALWAYS_AUTHENTICATE
+ *****************************************/
+
+// Set default value
+bool P11AttrAlwaysAuthenticate::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrAlwaysAuthenticate::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ if (!isPrivate)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_MODULUS
+ *****************************************/
+
+// Set default value
+bool P11AttrModulus::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrModulus::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ ByteString plaintext((unsigned char*)pValue, ulValueLen);
+ ByteString value;
+
+ // Encrypt
+
+ if (isPrivate)
+ {
+ if (!token->encrypt(plaintext, value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = plaintext;
+
+ // Attribute specific checks
+
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+
+ // Store data
+
+ osobject->setAttribute(type, value);
+
+ OSAttribute* attrClass = osobject->getAttribute(CKA_CLASS);
+ if (op == OBJECT_OP_CREATE && attrClass != NULL && attrClass->getUnsignedLongValue() == CKO_PUBLIC_KEY)
+ {
+ OSAttribute bits((unsigned long)plaintext.bits());
+ osobject->setAttribute(CKA_MODULUS_BITS, bits);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_PUBLIC_EXPONENT
+ *****************************************/
+
+// Set default value
+bool P11AttrPublicExponent::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIVATE_EXPONENT
+ *****************************************/
+
+// Set default value
+bool P11AttrPrivateExponent::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIME_1
+ *****************************************/
+
+// Set default value
+bool P11AttrPrime1::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIME_2
+ *****************************************/
+
+// Set default value
+bool P11AttrPrime2::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_EXPONENT_1
+ *****************************************/
+
+// Set default value
+bool P11AttrExponent1::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_EXPONENT_2
+ *****************************************/
+
+// Set default value
+bool P11AttrExponent2::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_COEFFICIENT
+ *****************************************/
+
+// Set default value
+bool P11AttrCoefficient::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_MODULUS_BITS
+ *****************************************/
+
+// Set default value
+bool P11AttrModulusBits::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrModulusBits::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
diff --git a/src/lib/P11Attributes.h b/src/lib/P11Attributes.h
--- /dev/null
+++ b/src/lib/P11Attributes.h
@@ -0,0 +1,1008 @@
+/* $Id: P11Attributes.h 6769 2012-10-24 11:35:12Z rb $ */
+
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Attributes.h
+
+ This file contains classes for controlling attributes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_P11ATTRIBUTES_H
+#define _SOFTHSM_V2_P11ATTRIBUTES_H
+
+#include "cryptoki.h"
+#include "OSObject.h"
+#include "Token.h"
+
+// The operation types
+#define OBJECT_OP_NONE 0x0
+#define OBJECT_OP_COPY 0x1
+#define OBJECT_OP_CREATE 0x2
+#define OBJECT_OP_DERIVE 0x3
+#define OBJECT_OP_GENERATE 0x4
+#define OBJECT_OP_SET 0x5
+#define OBJECT_OP_UNWRAP 0x6
+
+class P11Attribute
+{
+public:
+ // Destructor
+ ~P11Attribute();
+
+ // Initialize the attribute
+ bool init();
+
+ // Return the attribute type
+ CK_ATTRIBUTE_TYPE getType();
+
+ // Retrieve the value if allowed
+ CK_RV retrieve(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG_PTR pulValueLen);
+
+ // Update the value if allowed
+ CK_RV update(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+
+ // Checks are determined by footnotes from table 15 on page 62 in the PKCS#11 v2.3 spec.
+ // Table 15 contains common footnotes for object attribute tables that determine the checks to perform on attributes.
+ // There are also checks not in table 15 that have been added here to allow enforcing additional contraints.
+ enum {
+ ck1=1, // 1 Must be specified when object is created with C_CreateObject.
+ ck2=2, // 2 Must not be specified when object is created with C_CreateObject.
+ ck3=4, // 3 Must be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ ck4=8, // 4 Must not be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ ck5=0x10, // 5 Must be specified when object is unwrapped with C_UnwrapKey.
+ ck6=0x20, // 6 Must not be specified when object is unwrapped with C_UnwrapKey.
+ ck7=0x40, // 7 Cannot be revealed if object has its CKA_SENSITIVE attribute set to CK_TRUE or
+ // its CKA_EXTRACTABLE attribute set to CK_FALSE.
+ ck8=0x80, // 8 May be modified after object is created with a C_SetAttributeValue call
+ // or in the process of copying an object with a C_CopyObject call.
+ // However, it is possible that a particular token may not permit modification of
+ // the attribute during the course of a C_CopyObject call.
+ ck9=0x100, // 9 Default value is token-specific, and may depend on the values of other attributes.
+ ck10=0x200, // 10 Can only be set to CK_TRUE by the SO user.
+ ck11=0x400, // 11 Attribute cannot be changed once set to CK_TRUE. It becomes a read only attribute.
+ ck12=0x800, // 12 Attribute cannot be changed once set to CK_FALSE. It becomes a read only attribute.
+ ck13=0x1000, // Intentionally not defined
+ ck14=0x2000, // 14 Must be non-empty if CKA_URL is empty (CKA_VALUE)
+ ck15=0x4000, // 15 Must be non-empty if CKA_VALUE is empty (CKA_URL)
+ ck16=0x8000, // 16 Can only be empty if CKA_URL is empty
+ ck17=0x10000, // 17 Can be changed in the process of copying the object using C_CopyObject.
+ ck18=0x20000,
+ ck19=0x40000,
+ ck20=0x80000,
+ ck21=0x100000,
+ ck22=0x200000,
+ ck23=0x400000,
+ ck24=0x800000
+ };
+protected:
+ // Constructor
+ P11Attribute(OSObject* osobject);
+
+ // The object
+ OSObject* osobject;
+
+ // The attribute type
+ CK_ATTRIBUTE_TYPE type;
+
+ // The checks to perform when the attribute is accessed.
+ CK_ULONG checks;
+
+ // The attribute fixed size contains (CK_ULONG)-1 when size is variable.
+ CK_ULONG size;
+
+ // Set the default value of the attribute
+ virtual bool setDefault() = 0;
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+
+ // Helper functions
+ bool isModifiable();
+ bool isSensitive();
+ bool isExtractable();
+ bool isTrusted();
+};
+
+/*****************************************
+ * CKA_CLASS
+ *****************************************/
+
+class P11AttrClass : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrClass(OSObject* osobject) : P11Attribute(osobject) { type = CKA_CLASS; size = sizeof(CK_OBJECT_CLASS); checks = ck1; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_KEY_TYPE
+ *****************************************/
+
+class P11AttrKeyType : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrKeyType(OSObject* osobject) : P11Attribute(osobject) { type = CKA_KEY_TYPE; size = sizeof(CK_KEY_TYPE); checks = ck1|ck5; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_CERTIFICATE_TYPE
+ *****************************************/
+
+class P11AttrCertificateType : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCertificateType(OSObject* osobject) : P11Attribute(osobject) { type = CKA_CERTIFICATE_TYPE; size = sizeof(CK_CERTIFICATE_TYPE); checks = ck1; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_TOKEN
+ *****************************************/
+
+class P11AttrToken : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrToken(OSObject* osobject) : P11Attribute(osobject) { type = CKA_TOKEN; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_PRIVATE
+ *****************************************/
+
+class P11AttrPrivate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrivate(OSObject* osobject) : P11Attribute(osobject) { type = CKA_PRIVATE; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_MODIFIABLE
+ *****************************************/
+
+class P11AttrModifiable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrModifiable(OSObject* osobject) : P11Attribute(osobject) { type = CKA_MODIFIABLE; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_LABEL
+ *****************************************/
+
+class P11AttrLabel : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrLabel(OSObject* osobject) : P11Attribute(osobject) { type = CKA_LABEL; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_COPYABLE
+ *****************************************/
+
+class P11AttrCopyable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCopyable(OSObject* osobject) : P11Attribute(osobject) { type = CKA_COPYABLE; size = sizeof(CK_BBOOL); checks = ck12; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_APPLICATION
+ *****************************************/
+
+class P11AttrApplication : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrApplication(OSObject* osobject) : P11Attribute(osobject) { type = CKA_APPLICATION; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_OBJECT_ID
+ *****************************************/
+
+class P11AttrObjectID : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrObjectID(OSObject* osobject) : P11Attribute(osobject) { type = CKA_OBJECT_ID; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_CHECK_VALUE
+ *****************************************/
+
+class P11AttrCheckValue : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCheckValue(OSObject* osobject) : P11Attribute(osobject) { type = CKA_CHECK_VALUE; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_ID
+ *****************************************/
+
+class P11AttrID : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrID(OSObject* osobject) : P11Attribute(osobject) { type = CKA_ID; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_VALUE
+ *****************************************/
+
+class P11AttrValue : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrValue(OSObject* osobject, CK_ULONG inchecks) : P11Attribute(osobject) { type = CKA_VALUE; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_SUBJECT
+ *****************************************/
+
+class P11AttrSubject : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSubject(OSObject* osobject, CK_ULONG inchecks) : P11Attribute(osobject) { type = CKA_SUBJECT; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_ISSUER
+ *****************************************/
+
+class P11AttrIssuer : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrIssuer(OSObject* osobject) : P11Attribute(osobject) { type = CKA_ISSUER; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_TRUSTED
+ *****************************************/
+
+class P11AttrTrusted : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrTrusted(OSObject* osobject) : P11Attribute(osobject) { type = CKA_TRUSTED; size = sizeof(CK_BBOOL); checks = ck10; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_CERTIFICATE_CATEGORY
+ *****************************************/
+
+class P11AttrCertificateCategory : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCertificateCategory(OSObject* osobject) : P11Attribute(osobject) { type = CKA_CERTIFICATE_CATEGORY; size = sizeof(CK_ULONG); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_START_DATE
+ * Because this attribute is used in a
+ * certificate object where the CKA_VALUE
+ * containing the certificate data is not
+ * modifiable, we assume that this attribute
+ * is also not modifiable.
+ * There is also no explicit mention of
+ * this CKA_START_DATE attribute being
+ * modifiable,
+ *****************************************/
+
+class P11AttrStartDate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrStartDate(OSObject* osobject) : P11Attribute(osobject) { type = CKA_START_DATE; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_END_DATE
+ * Because this attribute is used in a
+ * certificate object where the CKA_VALUE
+ * containing the certificate data is not
+ * modifiable, we assume that this attribute
+ * is also not modifiable.
+ * There is also no explicit mention of
+ * this CKA_END_DATE attribute being
+ * modifiable,
+ *****************************************/
+
+class P11AttrEndDate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrEndDate(OSObject* osobject) : P11Attribute(osobject) { type = CKA_END_DATE; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SERIAL_NUMBER
+ *****************************************/
+
+class P11AttrSerialNumber : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSerialNumber(OSObject* osobject) : P11Attribute(osobject) { type = CKA_SERIAL_NUMBER; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_URL
+ *****************************************/
+
+class P11AttrURL : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrURL(OSObject* osobject) : P11Attribute(osobject) { type = CKA_URL; checks = ck15; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_HASH_OF_SUBJECT_PUBLIC_KEY
+ *****************************************/
+
+class P11AttrHashOfSubjectPublicKey : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrHashOfSubjectPublicKey(OSObject* osobject) : P11Attribute(osobject) { type = CKA_HASH_OF_SUBJECT_PUBLIC_KEY; checks = ck16; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_HASH_OF_ISSUER_PUBLIC_KEY
+ *****************************************/
+
+class P11AttrHashOfIssuerPublicKey : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrHashOfIssuerPublicKey(OSObject* osobject) : P11Attribute(osobject) { type = CKA_HASH_OF_ISSUER_PUBLIC_KEY; checks = ck16; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_JAVA_MIDP_SECURITY_DOMAIN
+ *****************************************/
+
+class P11AttrJavaMidpSecurityDomain : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrJavaMidpSecurityDomain(OSObject* osobject) : P11Attribute(osobject) { type = CKA_JAVA_MIDP_SECURITY_DOMAIN; size = sizeof(CK_ULONG); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_NAME_HASH_ALGORITHM
+ *****************************************/
+
+class P11AttrNameHashAlgorithm : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrNameHashAlgorithm(OSObject* osobject) : P11Attribute(osobject) { type = CKA_NAME_HASH_ALGORITHM; size = sizeof(CK_MECHANISM_TYPE); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_DERIVE
+ *****************************************/
+
+class P11AttrDerive : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrDerive(OSObject* osobject) : P11Attribute(osobject) { type = CKA_DERIVE; size = sizeof(CK_BBOOL); checks = ck8;}
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ENCRYPT
+ *****************************************/
+
+class P11AttrEncrypt : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrEncrypt(OSObject* osobject) : P11Attribute(osobject) { type = CKA_ENCRYPT; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_VERIFY
+ *****************************************/
+
+class P11AttrVerify : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrVerify(OSObject* osobject) : P11Attribute(osobject) { type = CKA_VERIFY; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_VERIFY_RECOVER
+ *****************************************/
+
+class P11AttrVerifyRecover : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrVerifyRecover(OSObject* osobject) : P11Attribute(osobject) { type = CKA_VERIFY_RECOVER; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_WRAP
+ *****************************************/
+
+class P11AttrWrap : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrWrap(OSObject* osobject) : P11Attribute(osobject) { type = CKA_WRAP; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_DECRYPT
+ *****************************************/
+
+class P11AttrDecrypt : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrDecrypt(OSObject* osobject) : P11Attribute(osobject) { type = CKA_DECRYPT; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SIGN
+ *****************************************/
+
+class P11AttrSign : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSign(OSObject* osobject) : P11Attribute(osobject) { type = CKA_SIGN; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SIGN_RECOVER
+ *****************************************/
+
+class P11AttrSignRecover : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSignRecover(OSObject* osobject) : P11Attribute(osobject) { type = CKA_SIGN_RECOVER; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_UNWRAP
+ *****************************************/
+
+class P11AttrUnwrap : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrUnwrap(OSObject* osobject) : P11Attribute(osobject) { type = CKA_UNWRAP; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_LOCAL
+ *****************************************/
+
+class P11AttrLocal : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrLocal(OSObject* osobject) : P11Attribute(osobject) { type = CKA_LOCAL; size = sizeof(CK_BBOOL); checks = ck2|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_KEY_GEN_MECHANISM
+ *****************************************/
+
+class P11AttrKeyGenMechanism : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrKeyGenMechanism(OSObject* osobject) : P11Attribute(osobject) { type = CKA_KEY_GEN_MECHANISM; size = sizeof(CK_MECHANISM_TYPE); checks = ck2|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ALWAYS_SENSITIVE
+ *****************************************/
+
+class P11AttrAlwaysSensitive : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrAlwaysSensitive(OSObject* osobject) : P11Attribute(osobject) { type = CKA_ALWAYS_SENSITIVE; size = sizeof(CK_BBOOL); checks = ck2|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_NEVER_EXTRACTABLE
+ *****************************************/
+
+class P11AttrNeverExtractable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrNeverExtractable(OSObject* osobject) : P11Attribute(osobject) { type = CKA_NEVER_EXTRACTABLE; size = sizeof(CK_BBOOL); checks = ck2|ck4; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SENSITIVE
+ *****************************************/
+
+class P11AttrSensitive : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSensitive(OSObject* osobject) : P11Attribute(osobject) { type = CKA_SENSITIVE; size = sizeof(CK_BBOOL); checks = ck8|ck9|ck11; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_EXTRACTABLE
+ *****************************************/
+
+class P11AttrExtractable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrExtractable(OSObject* osobject) : P11Attribute(osobject) { type = CKA_EXTRACTABLE; size = sizeof(CK_BBOOL); checks = ck8|ck9|ck12; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_WRAP_WITH_TRUSTED
+ *****************************************/
+
+class P11AttrWrapWithTrusted : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrWrapWithTrusted(OSObject* osobject) : P11Attribute(osobject) { type = CKA_WRAP_WITH_TRUSTED; size = sizeof(CK_BBOOL); checks = ck11; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ALWAYS_AUTHENTICATE
+ *****************************************/
+
+class P11AttrAlwaysAuthenticate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrAlwaysAuthenticate(OSObject* osobject) : P11Attribute(osobject) { type = CKA_ALWAYS_AUTHENTICATE; size = sizeof(CK_BBOOL); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_MODULUS
+ *****************************************/
+
+class P11AttrModulus : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrModulus(OSObject* osobject) : P11Attribute(osobject) { type = CKA_MODULUS; checks = ck1|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_PUBLIC_EXPONENT
+ *****************************************/
+
+class P11AttrPublicExponent : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPublicExponent(OSObject* osobject, CK_ULONG inchecks) : P11Attribute(osobject) { type = CKA_PUBLIC_EXPONENT; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIVATE_EXPONENT
+ *****************************************/
+
+class P11AttrPrivateExponent : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrivateExponent(OSObject* osobject) : P11Attribute(osobject) { type = CKA_PRIVATE_EXPONENT; checks = ck1|ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIME_1
+ *****************************************/
+
+class P11AttrPrime1 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrime1(OSObject* osobject) : P11Attribute(osobject) { type = CKA_PRIME_1; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIME_2
+ *****************************************/
+
+class P11AttrPrime2 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrime2(OSObject* osobject) : P11Attribute(osobject) { type = CKA_PRIME_2; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_EXPONENT_1
+ *****************************************/
+
+class P11AttrExponent1 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrExponent1(OSObject* osobject) : P11Attribute(osobject) { type = CKA_EXPONENT_1; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_EXPONENT_2
+ *****************************************/
+
+class P11AttrExponent2 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrExponent2(OSObject* osobject) : P11Attribute(osobject) { type = CKA_EXPONENT_2; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_COEFFICIENT
+ *****************************************/
+
+class P11AttrCoefficient : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCoefficient(OSObject* osobject) : P11Attribute(osobject) { type = CKA_COEFFICIENT; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_MODULUS_BITS
+ *****************************************/
+
+class P11AttrModulusBits : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrModulusBits(OSObject* osobject) : P11Attribute(osobject) { type = CKA_MODULUS_BITS; size = sizeof(CK_ULONG); checks = ck2|ck3;}
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+#endif // !_SOFTHSM_V2_P11ATTRIBUTES_H
diff --git a/src/lib/P11Objects.cpp b/src/lib/P11Objects.cpp
--- /dev/null
+++ b/src/lib/P11Objects.cpp
@@ -0,0 +1,827 @@
+/* $Id: P11Objects.cpp 6775 2012-10-25 06:47:07Z rb $ */
+
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Objects.cpp
+
+ This class respresent a PKCS#11 object
+ *****************************************************************************/
+
+#include "config.h"
+#include "P11Objects.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+// Constructor
+P11Object::P11Object()
+{
+ initialized = false;
+}
+
+// Destructor
+P11Object::~P11Object()
+{
+ std::map<CK_ATTRIBUTE_TYPE, P11Attribute*> cleanUp = attributes;
+ attributes.clear();
+
+ for (std::map<CK_ATTRIBUTE_TYPE, P11Attribute*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ delete i->second;
+ i->second = NULL;
+ }
+}
+
+// Add attributes
+bool P11Object::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ this->osobject = osobject;
+
+ // Create attributes
+ P11Attribute* attrClass = new P11AttrClass(osobject);
+ P11Attribute* attrToken = new P11AttrToken(osobject);
+ P11Attribute* attrPrivate = new P11AttrPrivate(osobject);
+ P11Attribute* attrModifiable = new P11AttrModifiable(osobject);
+ P11Attribute* attrLabel = new P11AttrLabel(osobject);
+ P11Attribute* attrCopyable = new P11AttrCopyable(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrClass->init() ||
+ !attrToken->init() ||
+ !attrPrivate->init() ||
+ !attrModifiable->init() ||
+ !attrLabel->init() ||
+ !attrCopyable->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrClass->getType()] = attrClass;
+ attributes[attrToken->getType()] = attrToken;
+ attributes[attrPrivate->getType()] = attrPrivate;
+ attributes[attrModifiable->getType()] = attrModifiable;
+ attributes[attrLabel->getType()] = attrLabel;
+ attributes[attrCopyable->getType()] = attrCopyable;
+
+ initialized = true;
+ return true;
+}
+
+CK_RV P11Object::loadTemplate(Token *token, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
+{
+ bool isPrivate = this->isPrivate();
+
+ // [PKCS#11 v2.3 pg.131]
+ // 1. If the specified attribute (i.e. the attribute specified by the
+ // type field) for the object cannot be revealed because the object
+ // is sensitive or unextractable, then the ulValueLen field in that
+ // tripple is modified to hold the value -1 (i.e., when it is cast
+ // to a CK_LONG, it holds -1).
+ //
+ // 2. Otherwise, if the specified attribute for the object is invalid
+ // (the object does not possess such and attribute), then the
+ // ulValueLen field in that triple is modified to hold the value -1.
+ //
+ // 3. Otherwise, if the pValue field has the value NULL_PTR, then the
+ // ulValueLen field is modified to hold the exact length of the
+ // specified attribute for the object.
+ //
+ // 4. Otherwise, if the length specified in ulValueLen is large enough
+ // to hold the value of the specified attribute for the object, then
+ // that attribute is copied into the buffer located at pValue, and
+ // the ulValueLen field is modified to hold the exact length of the
+ // attribute.
+ //
+ // 5. Otherwise, the ulValueLen field is modified to hold the value -1.
+
+ // If case 3 or 4 applies to all the requested attributes, then the call will return CKR_OK.
+ CK_RV rv = CKR_OK;
+ for (CK_ULONG i = 0; i < ulAttributeCount; ++i)
+ {
+ P11Attribute* attr = attributes[pTemplate[i].type];
+
+ // case 2 of the attribute checks
+ if (attr == NULL) {
+ pTemplate[i].ulValueLen = (CK_ULONG)-1;
+ // If case 2 applies to any of the requested attributes, then the call should
+ // return the value CKR_ATTRIBUTE_TYPE_INVALID.
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ // case 1,3,4 and 5 of the attribute checks are done while retrieving the attribute itself.
+ CK_RV retrieve_rv = attr->retrieve(token, isPrivate, pTemplate[i].pValue, &pTemplate[i].ulValueLen);
+ if (retrieve_rv != CKR_OK) {
+ // If case 1 applies to any of the requested attributes, then the call should
+ // return the value CKR_ATTRIBUTE_SENSITIVE.
+ // If case 5 applies to any of the requested attributes, then the call should
+ // return the value CKR_BUFFER_TOO_SMALL.
+ return retrieve_rv;
+ }
+
+ }
+
+ // As usual if more than one of these error codes is applicable, Cryptoki may
+ // return any of them. Only if none of them applies to any of the requested
+ // attributes will CKR_OK be returned.
+ return CKR_OK;
+}
+
+// Save template
+CK_RV P11Object::saveTemplate(Token *token, bool isPrivate, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, int op)
+{
+ if (osobject == NULL)
+ return CKR_GENERAL_ERROR;
+ if (osobject->startTransaction() == false)
+ return CKR_GENERAL_ERROR;
+
+ // [PKCS#11 v2.3 pg. 62] OBJECT_OP_COPY
+ // If the CKA_COPYABLE attribute of the object to be copied is set to CK_FALSE, C_CopyObject
+ // returns CKR_COPY_PROHIBITED.
+ if (op == OBJECT_OP_COPY)
+ {
+ if (!isCopyable())
+ {
+ osobject->abortTransaction();
+ return CKR_COPY_PROHIBITED;
+ }
+ }
+
+ for (CK_ULONG i = 0; i < ulAttributeCount; i++)
+ {
+ // [PKCS#11 v2.3 pg. 61] OBJECT_OP_CREATE | OBJECT_OP_SET | OBJECT_OP_COPY
+ // 1. If the supplied template specifies a value for an invalid attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_TYPE_INVALID. An attribute
+ // is valid if it is either one of the attributes described in the Cryptoki specification or an
+ // additional vendor-specific attribute supported by the library and token.
+ P11Attribute* attr = attributes[pTemplate[i].type];
+ if (attr == NULL)
+ {
+ osobject->abortTransaction();
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ // Additonal checks are done while updating the attributes themselves.
+ CK_RV rv = attr->update(token,isPrivate, pTemplate[i].pValue, pTemplate[i].ulValueLen, op);
+ if (rv != CKR_OK)
+ {
+ osobject->abortTransaction();
+ return rv;
+ }
+ }
+
+ // [PKCS#11 v2.3 pg. 60]
+ // 4. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are insufficient to fully specify the object to create, then the attempt
+ // should fail with the error code CKR_TEMPLATE_INCOMPLETE.
+
+ // All attributes that have to be specified are marked as such in the specification.
+ // The following checks are relevant here:
+ // ck1 Must be specified when object is created with C_CreateObject.
+ // ck3 Must be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ // ck5 Must be specified when object is unwrapped with C_UnwrapKey.
+
+ // TODO:
+ // Go through the attributes and see whether any attribute that MUST be specified
+ // during creation etc. have been specified in pTemplate.
+
+ // [PKCS#11 v2.3 pg. 60]
+ // 5. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are inconsistent, then the attempt should fail with the error code
+ // CKR_TEMPLATE_INCONSISTENT. A set of attribute values is inconsistent if not
+ // all of its members can be satisfied simultaneously by the token, although each value
+ // individually is valid in Cryptoki. One example of an inconsistent template would be
+ // using a template which specifies two different values for the same attribute. Another
+ // example would be trying to create a secret key object with an attribute which is
+ // appropriate for various types of public keys or private keys, but not for secret keys.
+ // A final example would be a template with an attribute that violates some token
+ // specific requirement. Note that this final example of an inconsistent template is
+ // token-dependent—on a different token, such a template might not be inconsistent.
+
+ if (osobject->commitTransaction() == false)
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+bool P11Object::isPrivate()
+{
+ // Get the CKA_PRIVATE attribute, when the attribute is
+ // not present return the default value which we have
+ // chosen to be CK_FALSE.
+ OSAttribute* attr = osobject->getAttribute(CKA_PRIVATE);
+ return attr != NULL && attr->getBooleanValue();
+}
+
+bool P11Object::isCopyable()
+{
+ // Get the CKA_COPYABLE attribute, when the attribute is not
+ // present return the default value which is CK_TRUE.
+ OSAttribute* attr = osobject->getAttribute(CKA_COPYABLE);
+ return attr == NULL || attr->getBooleanValue();
+}
+
+bool P11Object::isModifiable()
+{
+ // Get the CKA_MODIFIABLE attribute, when the attribute is
+ // not present return the default value which is CK_TRUE.
+ OSAttribute* attr = osobject->getAttribute(CKA_MODIFIABLE);
+ return attr == NULL || attr->getBooleanValue();
+}
+
+// Constructor
+P11DataObj::P11DataObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DataObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ OSAttribute attrClass((unsigned long)CKO_DATA);
+ osobject->setAttribute(CKA_CLASS, attrClass);
+
+ // Create parent
+ if (!P11Object::init(osobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrApplication = new P11AttrApplication(osobject);
+ P11Attribute* attrObjectID = new P11AttrObjectID(osobject);
+ // NOTE: There is no mention in the PKCS#11 v2.3 spec that for a Data
+ // Object the CKA_VALUE attribute may be modified after creation !
+ // Therefore we assume it is not allowed to change the CKA_VALUE
+ // attribute of a Data Object.
+ P11Attribute* attrValue = new P11AttrValue(osobject,0);
+
+ // Initialize the attributes
+ if
+ (
+ !attrApplication->init() ||
+ !attrObjectID->init() ||
+ !attrValue->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrApplication->getType()] = attrApplication;
+ attributes[attrObjectID->getType()] = attrObjectID;
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11CertificateObj::P11CertificateObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11CertificateObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ OSAttribute attrClass((unsigned long)CKO_CERTIFICATE);
+ osobject->setAttribute(CKA_CLASS, attrClass);
+
+ // Create parent
+ if (!P11Object::init(osobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrCertificateType = new P11AttrCertificateType(osobject);
+ P11Attribute* attrTrusted = new P11AttrTrusted(osobject);
+ P11Attribute* attrCertificateCategory = new P11AttrCertificateCategory(osobject);
+ P11Attribute* attrCheckValue = new P11AttrCheckValue(osobject);
+ P11Attribute* attrStartDate = new P11AttrStartDate(osobject);
+ P11Attribute* attrEndDate = new P11AttrEndDate(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrCertificateType->init() ||
+ !attrTrusted->init() ||
+ !attrCertificateCategory->init() ||
+ !attrCheckValue->init() ||
+ !attrStartDate->init() ||
+ !attrEndDate->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrCertificateType->getType()] = attrCertificateType;
+ attributes[attrTrusted->getType()] = attrTrusted;
+ attributes[attrCertificateCategory->getType()] = attrCertificateCategory;
+ attributes[attrCheckValue->getType()] = attrCheckValue;
+ attributes[attrStartDate->getType()] = attrStartDate;
+ attributes[attrEndDate->getType()] = attrEndDate;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11X509CertificateObj::P11X509CertificateObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11X509CertificateObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ OSAttribute attrCertType((unsigned long)CKC_X_509);
+ osobject->setAttribute(CKA_CERTIFICATE_TYPE, attrCertType);
+
+ // Create parent
+ if (!P11CertificateObj::init(osobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck1);
+ P11Attribute* attrID = new P11AttrID(osobject);
+ P11Attribute* attrIssuer = new P11AttrIssuer(osobject);
+ P11Attribute* attrSerialNumber = new P11AttrSerialNumber(osobject);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck14);
+ P11Attribute* attrURL = new P11AttrURL(osobject);
+ P11Attribute* attrHashOfSubjectPublicKey = new P11AttrHashOfSubjectPublicKey(osobject);
+ P11Attribute* attrHashOfIssuerPublicKey = new P11AttrHashOfIssuerPublicKey(osobject);
+ P11Attribute* attrJavaMidpSecurityDomain = new P11AttrJavaMidpSecurityDomain(osobject);
+ P11Attribute* attrNameHashAlgorithm = new P11AttrNameHashAlgorithm(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrID->init() ||
+ !attrIssuer->init() ||
+ !attrSerialNumber->init() ||
+ !attrValue->init() ||
+ !attrURL->init() ||
+ !attrHashOfSubjectPublicKey->init() ||
+ !attrHashOfIssuerPublicKey->init() ||
+ !attrJavaMidpSecurityDomain->init() ||
+ !attrNameHashAlgorithm->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrID->getType()] = attrID;
+ attributes[attrIssuer->getType()] = attrIssuer;
+ attributes[attrSerialNumber->getType()] = attrSerialNumber;
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrURL->getType()] = attrURL;
+ attributes[attrHashOfSubjectPublicKey->getType()] = attrHashOfSubjectPublicKey;
+ attributes[attrHashOfIssuerPublicKey->getType()] = attrHashOfIssuerPublicKey;
+ attributes[attrJavaMidpSecurityDomain->getType()] = attrJavaMidpSecurityDomain;
+ attributes[attrNameHashAlgorithm->getType()] = attrNameHashAlgorithm;
+
+ return true;
+}
+
+// Constructor
+P11KeyObj::P11KeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11KeyObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ // Create parent
+ if (!P11Object::init(osobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrKeyType = new P11AttrKeyType(osobject);
+ P11Attribute* attrID = new P11AttrID(osobject);
+ P11Attribute* attrStartDate = new P11AttrStartDate(osobject);
+ P11Attribute* attrEndDate = new P11AttrEndDate(osobject);
+ P11Attribute* attrDerive = new P11AttrDerive(osobject);
+ P11Attribute* attrLocal = new P11AttrLocal(osobject);
+ P11Attribute* attrKeyGenMechanism = new P11AttrKeyGenMechanism(osobject);
+ // CKA_ALLOWED_MECHANISMS is not supported
+
+ // Initialize the attributes
+ if
+ (
+ !attrKeyType->init() ||
+ !attrID->init() ||
+ !attrStartDate->init() ||
+ !attrEndDate->init() ||
+ !attrDerive->init() ||
+ !attrLocal->init() ||
+ !attrKeyGenMechanism->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrKeyType->getType()] = attrKeyType;
+ attributes[attrID->getType()] = attrID;
+ attributes[attrStartDate->getType()] = attrStartDate;
+ attributes[attrEndDate->getType()] = attrEndDate;
+ attributes[attrDerive->getType()] = attrDerive;
+ attributes[attrLocal->getType()] = attrLocal;
+ attributes[attrKeyGenMechanism->getType()] = attrKeyGenMechanism;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11PublicKeyObj::P11PublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11PublicKeyObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ OSAttribute attrClass((unsigned long)CKO_PUBLIC_KEY);
+ osobject->setAttribute(CKA_CLASS, attrClass);
+
+ // Create parent
+ if (!P11KeyObj::init(osobject)) return false;
+
+ if (initialized) return true;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck8);
+ P11Attribute* attrEncrypt = new P11AttrEncrypt(osobject);
+ P11Attribute* attrVerify = new P11AttrVerify(osobject);
+ P11Attribute* attrVerifyRecover = new P11AttrVerifyRecover(osobject);
+ P11Attribute* attrWrap = new P11AttrWrap(osobject);
+ P11Attribute* attrTrusted = new P11AttrTrusted(osobject);
+ // CKA_WRAP_TEMPLATE is not supported
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrEncrypt->init() ||
+ !attrVerify->init() ||
+ !attrVerifyRecover->init() ||
+ !attrWrap->init() ||
+ !attrTrusted->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrEncrypt->getType()] = attrEncrypt;
+ attributes[attrVerify->getType()] = attrVerify;
+ attributes[attrVerifyRecover->getType()] = attrVerifyRecover;
+ attributes[attrWrap->getType()] = attrWrap;
+ attributes[attrTrusted->getType()] = attrTrusted;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11RSAPublicKeyObj::P11RSAPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11RSAPublicKeyObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+ if (osobject == NULL) return false;
+
+ OSAttribute attrKeyType((unsigned long)CKK_RSA);
+ osobject->setAttribute(CKA_KEY_TYPE, attrKeyType);
+
+ // Create parent
+ if (!P11PublicKeyObj::init(osobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrModulus = new P11AttrModulus(osobject);
+ P11Attribute* attrModulusBits = new P11AttrModulusBits(osobject);
+ P11Attribute* attrPublicExponent = new P11AttrPublicExponent(osobject,P11Attribute::ck1);
+
+ // Initialize the attributes
+ if
+ (
+ !attrModulus->init() ||
+ !attrModulusBits->init() ||
+ !attrPublicExponent->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrModulus->getType()] = attrModulus;
+ attributes[attrModulusBits->getType()] = attrModulusBits;
+ attributes[attrPublicExponent->getType()] = attrPublicExponent;
+
+ initialized = true;
+ return true;
+}
+
+//constructor
+P11PrivateKeyObj::P11PrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11PrivateKeyObj::init(OSObject *osobject)
+{
+ if (initialized) return true;
+
+ OSAttribute attrClass((unsigned long)CKO_PRIVATE_KEY);
+ osobject->setAttribute(CKA_CLASS, attrClass);
+
+ // Create parent
+ if (!P11KeyObj::init(osobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck8);
+ P11Attribute* attrSensitive = new P11AttrSensitive(osobject);
+ P11Attribute* attrDecrypt = new P11AttrDecrypt(osobject);
+ P11Attribute* attrSign = new P11AttrSign(osobject);
+ P11Attribute* attrSignRecover = new P11AttrSignRecover(osobject);
+ P11Attribute* attrUnwrap = new P11AttrUnwrap(osobject);
+ P11Attribute* attrExtractable = new P11AttrExtractable(osobject);
+ P11Attribute* attrAlwaysSensitive = new P11AttrAlwaysSensitive(osobject);
+ P11Attribute* attrNeverExtractable = new P11AttrNeverExtractable(osobject);
+ P11Attribute* attrWrapWithTrusted = new P11AttrWrapWithTrusted(osobject);
+ // CKA_UNWRAP_TEMPLATE is not supported
+ P11Attribute* attrAlwaysAuthenticate = new P11AttrAlwaysAuthenticate(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrSensitive->init() ||
+ !attrDecrypt->init() ||
+ !attrSign->init() ||
+ !attrSignRecover->init() ||
+ !attrUnwrap->init() ||
+ !attrExtractable->init() ||
+ !attrAlwaysSensitive->init() ||
+ !attrNeverExtractable->init() ||
+ !attrWrapWithTrusted->init() ||
+ !attrAlwaysAuthenticate->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrSensitive->getType()] = attrSensitive;
+ attributes[attrDecrypt->getType()] = attrDecrypt;
+ attributes[attrSign->getType()] = attrSign;
+ attributes[attrSignRecover->getType()] = attrSignRecover;
+ attributes[attrUnwrap->getType()] = attrUnwrap;
+ attributes[attrExtractable->getType()] = attrExtractable;
+ attributes[attrAlwaysSensitive->getType()] = attrAlwaysSensitive;
+ attributes[attrNeverExtractable->getType()] = attrNeverExtractable;
+ attributes[attrWrapWithTrusted->getType()] = attrWrapWithTrusted;
+ attributes[attrAlwaysAuthenticate->getType()] = attrAlwaysAuthenticate;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11RSAPrivateKeyObj::P11RSAPrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11RSAPrivateKeyObj::init(OSObject *osobject)
+{
+ // Create parent
+ if (!P11PrivateKeyObj::init(osobject)) return false;
+
+ OSAttribute attrKeyType((unsigned long)CKK_RSA);
+ osobject->setAttribute(CKA_KEY_TYPE, attrKeyType);
+
+ if (initialized) return true;
+
+ // Create attributes
+ P11Attribute* attrModulus = new P11AttrModulus(osobject);
+ P11Attribute* attrPublicExponent = new P11AttrPublicExponent(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrPrivateExponent = new P11AttrPrivateExponent(osobject);
+ P11Attribute* attrPrime1 = new P11AttrPrime1(osobject);
+ P11Attribute* attrPrime2 = new P11AttrPrime2(osobject);
+ P11Attribute* attrExponent1 = new P11AttrExponent1(osobject);
+ P11Attribute* attrExponent2 = new P11AttrExponent2(osobject);
+ P11Attribute* attrCoefficient = new P11AttrCoefficient(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrModulus->init() ||
+ !attrPublicExponent->init() ||
+ !attrPrivateExponent->init() ||
+ !attrPrime1->init() ||
+ !attrPrime2->init() ||
+ !attrExponent1->init() ||
+ !attrExponent2->init() ||
+ !attrCoefficient->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrModulus->getType()] = attrModulus;
+ attributes[attrPublicExponent->getType()] = attrPublicExponent;
+ attributes[attrPrivateExponent->getType()] = attrPrivateExponent;
+ attributes[attrPrime1->getType()] = attrPrime1;
+ attributes[attrPrime2->getType()] = attrPrime2;
+ attributes[attrExponent1->getType()] = attrExponent1;
+ attributes[attrExponent2->getType()] = attrExponent2;
+ attributes[attrCoefficient->getType()] = attrCoefficient;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11SecretKeyObj::P11SecretKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11SecretKeyObj::init(OSObject *osobject)
+{
+ // Create parent
+ if (!P11KeyObj::init(osobject)) return false;
+
+ if (initialized) return true;
+
+ // Create attributes
+ P11Attribute* attrSensitive = new P11AttrSensitive(osobject);
+ P11Attribute* attrEncrypt = new P11AttrEncrypt(osobject);
+ P11Attribute* attrDecrypt = new P11AttrDecrypt(osobject);
+ P11Attribute* attrSign = new P11AttrSign(osobject);
+ P11Attribute* attrVerify = new P11AttrVerify(osobject);
+ P11Attribute* attrWrap = new P11AttrWrap(osobject);
+ P11Attribute* attrUnwrap = new P11AttrUnwrap(osobject);
+ P11Attribute* attrExtractable = new P11AttrExtractable(osobject);
+ P11Attribute* attrAlwaysSensitive = new P11AttrAlwaysSensitive(osobject);
+ P11Attribute* attrNeverExtractable = new P11AttrNeverExtractable(osobject);
+ P11Attribute* attrCheckValue = new P11AttrCheckValue(osobject);
+ P11Attribute* attrWrapWithTrusted = new P11AttrWrapWithTrusted(osobject);
+ P11Attribute* attrTrusted = new P11AttrTrusted(osobject);
+ // CKA_WRAP_TEMPLATE is not supported
+ // CKA_UNWRAP_TEMPLATE is not supported
+
+ // Initialize the attributes
+ if
+ (
+ !attrSensitive->init() ||
+ !attrEncrypt->init() ||
+ !attrDecrypt->init() ||
+ !attrSign->init() ||
+ !attrVerify->init() ||
+ !attrWrap->init() ||
+ !attrUnwrap->init() ||
+ !attrExtractable->init() ||
+ !attrAlwaysSensitive->init() ||
+ !attrNeverExtractable->init() ||
+ !attrCheckValue->init() ||
+ !attrWrapWithTrusted->init() ||
+ !attrTrusted->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSensitive->getType()] = attrSensitive;
+ attributes[attrEncrypt->getType()] = attrEncrypt;
+ attributes[attrDecrypt->getType()] = attrDecrypt;
+ attributes[attrSign->getType()] = attrSign;
+ attributes[attrVerify->getType()] = attrVerify;
+ attributes[attrWrap->getType()] = attrWrap;
+ attributes[attrUnwrap->getType()] = attrUnwrap;
+ attributes[attrExtractable->getType()] = attrExtractable;
+ attributes[attrAlwaysSensitive->getType()] = attrAlwaysSensitive;
+ attributes[attrNeverExtractable->getType()] = attrNeverExtractable;
+ attributes[attrCheckValue->getType()] = attrCheckValue;
+ attributes[attrWrapWithTrusted->getType()] = attrWrapWithTrusted;
+ attributes[attrTrusted->getType()] = attrTrusted;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DomainObj::P11DomainObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DomainObj::init(OSObject *osobject)
+{
+ // Create parent
+ if (!P11Object::init(osobject)) return false;
+
+ if (initialized) return true;
+
+ // Create attributes
+ P11Attribute* attrKeyType = new P11AttrApplication(osobject);
+ P11Attribute* attrLocal = new P11AttrObjectID(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrKeyType->init() ||
+ !attrLocal->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrKeyType->getType()] = attrKeyType;
+ attributes[attrLocal->getType()] = attrLocal;
+
+ initialized = true;
+ return true;
+}
diff --git a/src/lib/P11Objects.h b/src/lib/P11Objects.h
--- /dev/null
+++ b/src/lib/P11Objects.h
@@ -0,0 +1,198 @@
+/* $Id: P11Objects.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Objects.h
+
+ This class respresent a PKCS#11 object
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_P11OBJECTS_H
+#define _SOFTHSM_V2_P11OBJECTS_H
+
+#include "OSObject.h"
+#include "P11Attributes.h"
+#include "RSAPublicKey.h"
+#include "Token.h"
+#include "cryptoki.h"
+#include <map>
+
+class P11Object
+{
+public:
+ // Destructor
+ virtual ~P11Object();
+
+protected:
+ // Constructor
+ P11Object();
+
+ // The object
+ OSObject* osobject;
+
+ // The attributes
+ std::map<CK_ATTRIBUTE_TYPE, P11Attribute*> attributes;
+
+public:
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+
+protected:
+ bool initialized;
+
+public:
+ CK_RV loadTemplate(Token *token, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount);
+
+ // Save template
+ CK_RV saveTemplate(Token *token, bool isPrivate, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, int op);
+
+protected:
+ bool isPrivate();
+ bool isCopyable();
+ bool isModifiable();
+};
+
+class P11DataObj : public P11Object
+{
+public:
+ // Constructor
+ P11DataObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+
+protected:
+ bool initialized;
+};
+
+class P11CertificateObj : public P11Object
+{
+protected:
+ // Constructor
+ P11CertificateObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+ bool initialized;
+};
+
+class P11X509CertificateObj : public P11CertificateObj
+{
+public:
+ // Constructor
+ P11X509CertificateObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+
+protected:
+ bool initialized;
+};
+
+class P11KeyObj : public P11Object
+{
+protected:
+ // Constructor
+ P11KeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+ bool initialized;
+};
+
+class P11PublicKeyObj : public P11KeyObj
+{
+protected:
+ // Constructor
+ P11PublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+ bool initialized;
+};
+
+class P11RSAPublicKeyObj : public P11PublicKeyObj
+{
+public:
+ // Constructor
+ P11RSAPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+
+protected:
+ bool initialized;
+};
+
+class P11PrivateKeyObj : public P11KeyObj
+{
+protected:
+ // Constructor
+ P11PrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+ bool initialized;
+};
+
+class P11RSAPrivateKeyObj : public P11PrivateKeyObj
+{
+public:
+ // Constructor
+ P11RSAPrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+
+protected:
+ bool initialized;
+};
+
+class P11SecretKeyObj : public P11KeyObj
+{
+protected:
+ // Constructor
+ P11SecretKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+ bool initialized;
+};
+
+class P11DomainObj : public P11Object
+{
+protected:
+ // Constructor
+ P11DomainObj();
+
+ // Add attributes
+ virtual bool init(OSObject *osobject);
+ bool initialized;
+};
+
+#endif // !_SOFTHSM_V2_P11OBJECTS_H
diff --git a/src/lib/SoftHSM.cpp b/src/lib/SoftHSM.cpp
--- /dev/null
+++ b/src/lib/SoftHSM.cpp
@@ -0,0 +1,3261 @@
+/* $Id: SoftHSM.cpp 6910 2012-12-21 10:39:20Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SoftHSM.cpp
+
+ The implementation of the SoftHSM's main class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "access.h"
+#include "Configuration.h"
+#include "SimpleConfigLoader.h"
+#include "MutexFactory.h"
+#include "CryptoFactory.h"
+#include "AsymmetricAlgorithm.h"
+#include "RNG.h"
+#include "RSAParameters.h"
+#include "RSAPublicKey.h"
+#include "RSAPrivateKey.h"
+#include "DSAParameters.h"
+#include "DSAPublicKey.h"
+#include "DSAPrivateKey.h"
+#include "cryptoki.h"
+#include "SoftHSM.h"
+#include "osmutex.h"
+#include "SessionManager.h"
+#include "SessionObjectStore.h"
+#include "HandleManager.h"
+#include "P11Objects.h"
+
+#include <stdlib.h>
+
+static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, std::auto_ptr< P11Object > &p11object)
+{
+ switch(objClass) {
+ case CKO_DATA:
+ p11object.reset( new P11DataObj);
+ break;
+ case CKO_CERTIFICATE:
+ p11object.reset( new P11X509CertificateObj );
+ break;
+ case CKO_PUBLIC_KEY:
+ if (keyType == CKK_RSA)
+ p11object.reset( new P11RSAPublicKeyObj );
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ case CKO_PRIVATE_KEY:
+ // we need to know the type too
+ if (keyType == CKK_RSA)
+ p11object.reset( new P11RSAPrivateKeyObj );
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ case CKO_SECRET_KEY:
+#if 0
+ p11object.reset( new P11SecretKeyObj );
+ break;
+#endif
+ default:
+ return CKR_ATTRIBUTE_VALUE_INVALID; // invalid value for a valid argument
+ }
+ return CKR_OK;
+}
+
+static CK_RV extractObjectInformation(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_CLASS &objClass,
+ CK_KEY_TYPE &keyType,
+ CK_CERTIFICATE_TYPE &certType,
+ CK_BBOOL &isToken,
+ CK_BBOOL &isPrivate)
+{
+ bool bHasClass = false;
+ bool bHasKeyType = false;
+ bool bHasCertType = false;
+
+ // Extract object information
+ for (CK_ULONG i = 0; i < ulCount; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ if (pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS))
+ {
+ objClass = *(CK_OBJECT_CLASS_PTR)pTemplate[i].pValue;
+ bHasClass = true;
+ }
+ case CKA_KEY_TYPE:
+ if (pTemplate[i].ulValueLen == sizeof(CK_KEY_TYPE))
+ {
+ keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
+ bHasKeyType = true;
+ }
+ break;
+ case CKA_CERTIFICATE_TYPE:
+ if (pTemplate[i].ulValueLen == sizeof(CK_CERTIFICATE_TYPE))
+ {
+ certType = *(CK_CERTIFICATE_TYPE*)pTemplate[i].pValue;
+ bHasCertType = true;
+ }
+ break;
+ case CKA_TOKEN:
+ if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
+ {
+ isToken = *(CK_BBOOL*)pTemplate[i].pValue;
+ }
+ break;
+ case CKA_PRIVATE:
+ if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
+ {
+ isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!bHasClass)
+ {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ bool bKeyTypeRequired = (objClass == CKO_PUBLIC_KEY || objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY);
+ if (bKeyTypeRequired && !bHasKeyType)
+ {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ bool bCertTypeRequired = (objClass == CKO_CERTIFICATE);
+ if (bCertTypeRequired && !bHasCertType)
+ {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV newP11Object(OSObject *object, std::auto_ptr< P11Object > &p11object)
+{
+ CK_OBJECT_CLASS objClass = object->getAttribute(CKA_CLASS)->getUnsignedLongValue();
+ CK_KEY_TYPE keyType = CKK_RSA;
+ if (object->attributeExists(CKA_KEY_TYPE))
+ keyType = object->getAttribute(CKA_KEY_TYPE)->getUnsignedLongValue();
+ CK_RV rv = newP11Object(objClass,keyType,p11object);
+ if (rv != CKR_OK)
+ return rv;
+ if (!p11object->init(object))
+ return CKR_GENERAL_ERROR; // something went wrong that shouldn't have.
+ return CKR_OK;
+}
+
+static CK_ATTRIBUTE bsAttribute(CK_ATTRIBUTE_TYPE type, const ByteString &value)
+{
+ CK_ATTRIBUTE attr = {type, (CK_VOID_PTR)value.const_byte_str(), value.size() };
+ return attr;
+}
+
+static void libcleanup()
+{
+ SoftHSM::i()->C_Finalize(NULL);
+}
+
+/*****************************************************************************
+ Implementation of SoftHSM class specific functions
+ *****************************************************************************/
+
+// Initialise the one-and-only instance
+std::auto_ptr<SoftHSM> SoftHSM::instance(NULL);
+
+// Return the one-and-only instance
+SoftHSM* SoftHSM::i()
+{
+ if (!instance.get())
+ {
+ instance = std::auto_ptr<SoftHSM>(new SoftHSM());
+ }
+
+ return instance.get();
+}
+
+void SoftHSM::reset()
+{
+ if (instance.get())
+ instance.reset();
+}
+
+// Constructor
+SoftHSM::SoftHSM()
+{
+ isInitialised = false;
+ sessionObjectStore = NULL;
+ objectStore = NULL;
+ slotManager = NULL;
+ sessionManager = NULL;
+ handleManager = NULL;
+}
+
+// Destructor
+SoftHSM::~SoftHSM()
+{
+ if (handleManager != NULL) delete handleManager;
+ if (sessionManager != NULL) delete sessionManager;
+ if (slotManager != NULL) delete slotManager;
+ if (objectStore != NULL) delete objectStore;
+ if (sessionObjectStore != NULL) delete sessionObjectStore;
+}
+
+/*****************************************************************************
+ Implementation of PKCS #11 functions
+ *****************************************************************************/
+
+// PKCS #11 initialisation function
+CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
+{
+ CK_C_INITIALIZE_ARGS_PTR args;
+
+ // Check if PKCS #11 is already initialised
+ if (isInitialised)
+ {
+ return CKR_CRYPTOKI_ALREADY_INITIALIZED;
+ }
+
+ // Do we have any arguments?
+ if (pInitArgs != NULL_PTR)
+ {
+ args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+
+ // Must be set to NULL_PTR in this version of PKCS#11
+ if (args->pReserved != NULL_PTR)
+ {
+ DEBUG_MSG("pReserved must be set to NULL_PTR");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // Can we spawn our own threads?
+ // if (args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)
+ // {
+ // DEBUG_MSG("Cannot create threads if CKF_LIBRARY_CANT_CREATE_OS_THREADS is set");
+ // return CKR_NEED_TO_CREATE_THREADS;
+ // }
+
+ // Are we not supplied with mutex functions?
+ if
+ (
+ args->CreateMutex == NULL_PTR &&
+ args->DestroyMutex == NULL_PTR &&
+ args->LockMutex == NULL_PTR &&
+ args->UnlockMutex == NULL_PTR
+ )
+ {
+ // Can we use our own mutex functions?
+ if (args->flags & CKF_OS_LOCKING_OK)
+ {
+ // Use our own mutex functions.
+ MutexFactory::i()->setCreateMutex(OSCreateMutex);
+ MutexFactory::i()->setDestroyMutex(OSDestroyMutex);
+ MutexFactory::i()->setLockMutex(OSLockMutex);
+ MutexFactory::i()->setUnlockMutex(OSUnlockMutex);
+ MutexFactory::i()->enable();
+ }
+ else
+ {
+ // The external application is not using threading
+ MutexFactory::i()->disable();
+ }
+ }
+ else
+ {
+ // We must have all mutex functions
+ if
+ (
+ args->CreateMutex == NULL_PTR ||
+ args->DestroyMutex == NULL_PTR ||
+ args->LockMutex == NULL_PTR ||
+ args->UnlockMutex == NULL_PTR
+ )
+ {
+ DEBUG_MSG("Not all mutex functions are supplied");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // We could use our own mutex functions if the flag is set,
+ // but we use the external functions in both cases.
+
+ // Load the external mutex functions
+ MutexFactory::i()->setCreateMutex(args->CreateMutex);
+ MutexFactory::i()->setDestroyMutex(args->DestroyMutex);
+ MutexFactory::i()->setLockMutex(args->LockMutex);
+ MutexFactory::i()->setUnlockMutex(args->UnlockMutex);
+ MutexFactory::i()->enable();
+ }
+ }
+ else
+ {
+ // No concurrent access by multiple threads
+ MutexFactory::i()->disable();
+ }
+
+ // (Re)load the configuration
+ if (!Configuration::i()->reload(SimpleConfigLoader::i()))
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ sessionObjectStore = new SessionObjectStore();
+
+
+ // Load the object store
+ objectStore = new ObjectStore(Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR));
+ if (!objectStore->isValid())
+ {
+ ERROR_MSG("Could not load the object store");
+ delete objectStore;
+ objectStore = NULL;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Load the slot manager
+ slotManager = new SlotManager(objectStore);
+
+ // Load the session manager
+ sessionManager = new SessionManager();
+
+ // Load the handle manager
+ handleManager = new HandleManager();
+
+ // Set the state to initialised
+ isInitialised = true;
+
+ // Hook cleanup on dlclose() or exit()
+ atexit(libcleanup);
+
+ return CKR_OK;
+}
+
+// PKCS #11 finalisation function
+CK_RV SoftHSM::C_Finalize(CK_VOID_PTR pReserved)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Must be set to NULL_PTR in this version of PKCS#11
+ if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ if (handleManager != NULL) delete handleManager;
+ handleManager = NULL;
+ if (sessionManager != NULL) delete sessionManager;
+ sessionManager = NULL;
+ if (slotManager != NULL) delete slotManager;
+ slotManager = NULL;
+ if (objectStore != NULL) delete objectStore;
+ objectStore = NULL;
+
+ // TODO: What should we finalize?
+
+ isInitialised = false;
+
+ SoftHSM::reset();
+ return CKR_OK;
+}
+
+// Return information about the PKCS #11 module
+CK_RV SoftHSM::C_GetInfo(CK_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
+ pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
+ memset(pInfo->manufacturerID, ' ', 32);
+ memcpy(pInfo->manufacturerID, "SoftHSM", 7);
+ pInfo->flags = 0;
+ memset(pInfo->libraryDescription, ' ', 32);
+ memcpy(pInfo->libraryDescription, "Implementation of PKCS11", 24);
+ pInfo->libraryVersion.major = VERSION_MAJOR;
+ pInfo->libraryVersion.minor = VERSION_MINOR;
+
+ return CKR_OK;
+}
+
+// Return a list of available slots
+CK_RV SoftHSM::C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return slotManager->getSlotList(tokenPresent, pSlotList, pulCount);
+}
+
+// Return information about a slot
+CK_RV SoftHSM::C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ return slot->getSlotInfo(pInfo);
+}
+
+// Return information about a token in a slot
+CK_RV SoftHSM::C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ Token* token = slot->getToken();
+ if (token == NULL)
+ {
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+
+ return token->getTokenInfo(pInfo);
+}
+
+// Return the list of supported mechanisms for a given slot
+CK_RV SoftHSM::C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
+{
+ // A list with the supported mechanisms
+ CK_ULONG nrSupportedMechanisms = 24;
+ CK_MECHANISM_TYPE supportedMechanisms[] =
+ {
+ CKM_MD5,
+ CKM_SHA_1,
+ CKM_SHA224,
+ CKM_SHA256,
+ CKM_SHA384,
+ CKM_SHA512,
+ CKM_RSA_PKCS_KEY_PAIR_GEN,
+ CKM_RSA_PKCS,
+ CKM_RSA_X_509,
+ CKM_MD5_RSA_PKCS,
+ CKM_SHA1_RSA_PKCS,
+ CKM_RSA_PKCS_OAEP,
+ CKM_SHA256_RSA_PKCS,
+ CKM_SHA384_RSA_PKCS,
+ CKM_SHA512_RSA_PKCS,
+ CKM_DES_KEY_GEN,
+ CKM_DES2_KEY_GEN,
+ CKM_DES3_KEY_GEN,
+ CKM_DES_ECB,
+ CKM_DES_CBC,
+ CKM_DES3_ECB,
+ CKM_DES3_CBC,
+ CKM_AES_KEY_GEN,
+ CKM_AES_ECB,
+ CKM_AES_CBC,
+ CKM_DSA_PARAMETER_GEN,
+ CKM_DSA_KEY_PAIR_GEN,
+ CKM_DSA_SHA1
+ };
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (pulCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ if (pMechanismList == NULL_PTR)
+ {
+ *pulCount = nrSupportedMechanisms;
+
+ return CKR_OK;
+ }
+
+ if (*pulCount < nrSupportedMechanisms)
+ {
+ *pulCount = nrSupportedMechanisms;
+
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ *pulCount = nrSupportedMechanisms;
+
+ for (int i = 0; i < nrSupportedMechanisms; i ++)
+ {
+ pMechanismList[i] = supportedMechanisms[i];
+ }
+
+ return CKR_OK;
+}
+
+// Return more information about a mechanism for a given slot
+CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
+{
+ unsigned long rsaMinSize, rsaMaxSize;
+ unsigned long dsaMinSize, dsaMaxSize;
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm("RSA");
+ if (rsa != NULL)
+ {
+ rsaMinSize = rsa->getMinKeySize();
+ rsaMaxSize = rsa->getMaxKeySize();
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+
+ AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm("DSA");
+ if (dsa != NULL)
+ {
+ dsaMinSize = dsa->getMinKeySize();
+ // Limitation in PKCS#11
+ if (dsaMinSize < 512)
+ {
+ dsaMinSize = 512;
+ }
+
+ dsaMaxSize = dsa->getMaxKeySize();
+ // Limitation in PKCS#11
+ if (dsaMaxSize > 1024)
+ {
+ dsaMaxSize = 1024;
+ }
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+
+ switch (type)
+ {
+ case CKM_MD5:
+ case CKM_SHA_1:
+ case CKM_SHA224:
+ case CKM_SHA256:
+ case CKM_SHA384:
+ case CKM_SHA512:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_DIGEST;
+ break;
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ case CKM_RSA_PKCS:
+ case CKM_RSA_X_509:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ case CKM_MD5_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_SHA512_RSA_PKCS:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ case CKM_DES_KEY_GEN:
+ case CKM_DES2_KEY_GEN:
+ case CKM_DES3_KEY_GEN:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_GENERATE;
+ break;
+ case CKM_DES_ECB:
+ case CKM_DES_CBC:
+ case CKM_DES3_ECB:
+ case CKM_DES3_CBC:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ case CKM_AES_KEY_GEN:
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 32;
+ pInfo->flags = CKF_GENERATE;
+ break;
+ case CKM_AES_ECB:
+ case CKM_AES_CBC:
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 32;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ case CKM_DSA_PARAMETER_GEN:
+ pInfo->ulMinKeySize = dsaMinSize;
+ pInfo->ulMaxKeySize = dsaMaxSize;
+ pInfo->flags = CKF_GENERATE;
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = dsaMinSize;
+ pInfo->ulMaxKeySize = dsaMaxSize;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ case CKM_DSA_SHA1:
+ pInfo->ulMinKeySize = dsaMinSize;
+ pInfo->ulMaxKeySize = dsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ default:
+ DEBUG_MSG("The selected mechanism is not supported");
+ return CKR_MECHANISM_INVALID;
+ break;
+ }
+
+ return CKR_OK;
+}
+
+// Initialise the token in the specified slot
+CK_RV SoftHSM::C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ // Check if any session is open with this token.
+ if (sessionManager->haveSession(slotID))
+ {
+ return CKR_SESSION_EXISTS;
+ }
+
+ // Check the PIN
+ if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_INCORRECT;
+
+ ByteString soPIN(pPin, ulPinLen);
+
+ return slot->initToken(soPIN, pLabel);
+}
+
+// Initialise the user PIN
+CK_RV SoftHSM::C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // The SO must be logged in
+ if (session->getState() != CKS_RW_SO_FUNCTIONS) return CKR_USER_NOT_LOGGED_IN;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the PIN
+ if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
+
+ ByteString userPIN(pPin, ulPinLen);
+
+ return token->initUserPIN(userPIN);
+}
+
+// Change the PIN
+CK_RV SoftHSM::C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+ CK_RV rv = CKR_OK;
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check the new PINs
+ if (pOldPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pNewPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (ulNewLen < MIN_PIN_LEN || ulNewLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
+
+ ByteString oldPIN(pOldPin, ulOldLen);
+ ByteString newPIN(pNewPin, ulNewLen);
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ switch (session->getState())
+ {
+ case CKS_RW_PUBLIC_SESSION:
+ case CKS_RW_USER_FUNCTIONS:
+ rv = token->setUserPIN(oldPIN, newPIN);
+ break;
+ case CKS_RW_SO_FUNCTIONS:
+ rv = token->setSOPIN(oldPIN, newPIN);
+ break;
+ default:
+ return CKR_SESSION_READ_ONLY;
+ }
+
+ return rv;
+}
+
+// Open a new session to the specified slot
+CK_RV SoftHSM::C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+
+ CK_RV rv = sessionManager->openSession(slot, flags, pApplication, notify, phSession);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Get a pointer to the session object and store it in the handle manager.
+ Session* session = sessionManager->getSession(*phSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+ *phSession = handleManager->addSession(slotID,session);
+
+ return CKR_OK;
+}
+
+// Close the given session
+CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Tell the handle manager the session has been closed.
+ handleManager->sessionClosed(hSession);
+
+
+ // Tell the session object store that the session has closed.
+ sessionObjectStore->sessionClosed(hSession);
+
+ // Tell the session manager the session has been closed.
+ return sessionManager->closeSession(session->getHandle());
+}
+
+// Close all open sessions
+CK_RV SoftHSM::C_CloseAllSessions(CK_SLOT_ID slotID)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the slot
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+
+ // Tell the handle manager all sessions were closed for the given slotID.
+ // The handle manager should then remove all session and object handles for this slot.
+ handleManager->allSessionsClosed(slotID);
+
+ // Tell the session object store that all sessions were closed for the given slotID.
+ // The session object store should then remove all session objects for this slot.
+ sessionObjectStore->allSessionsClosed(slotID);
+
+ // Finally tell the session manager tho close all sessions for the given slot.
+ // This will also trigger a logout on the associated token to occur.
+ return sessionManager->closeAllSessions(slot);
+}
+
+// Retrieve information about the specified session
+CK_RV SoftHSM::C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return session->getInfo(pInfo);
+}
+
+// Determine the state of a running operation in a session
+CK_RV SoftHSM::C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Set the operation sate in a session
+CK_RV SoftHSM::C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Login on the token in the specified session
+CK_RV SoftHSM::C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ CK_RV rv = CKR_OK;
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the PIN
+ if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ ByteString pin(pPin, ulPinLen);
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ switch (userType)
+ {
+ case CKU_SO:
+ // There cannot exist a R/O session on this slot
+ if (sessionManager->haveROSession(session->getSlot()->getSlotID())) return CKR_SESSION_READ_ONLY_EXISTS;
+
+ // Login
+ rv = token->loginSO(pin);
+ break;
+ case CKU_USER:
+ // Login
+ rv = token->loginUser(pin);
+ break;
+ case CKU_CONTEXT_SPECIFIC:
+ // TODO: When do we want to use this user type?
+ return CKR_OPERATION_NOT_INITIALIZED;
+ break;
+ default:
+ return CKR_USER_TYPE_INVALID;
+ }
+
+ return rv;
+}
+
+// Log out of the token in the specified session
+CK_RV SoftHSM::C_Logout(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Logout
+ token->logout();
+
+ // [PKCS#11 v2.3 p124] When logout is successful...
+ // a. Any of the application's handles to private objects become invalid.
+ // b. Even if a user is later logged back into the token those handles remain invalid.
+ // c. All private session objects from sessions belonging to the application area destroyed.
+
+ // Have the handle manager remove all handles pointing to private objects for this slot.
+ CK_SLOT_ID slotID = session->getSlot()->getSlotID();
+ handleManager->tokenLoggedOut(slotID);
+ sessionObjectStore->tokenLoggedOut(slotID);
+
+ return CKR_OK;
+}
+
+// Create a new object on the token in the specified session using the given attribute template
+CK_RV SoftHSM::C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+ return this->CreateObject(hSession,pTemplate,ulCount,phObject,OBJECT_OP_CREATE);
+}
+
+// Create a copy of the object with the specified handle
+CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Destroy the specified object
+CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isToken = object->getAttribute(CKA_TOKEN)->getBooleanValue();
+ CK_BBOOL isPrivate = object->getAttribute(CKA_PRIVATE)->getBooleanValue();
+
+ // Check user credentials
+ CK_RV rv = haveWrite(session->getState(), isToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Tell the handleManager to forget about the object.
+ handleManager->destroyObject(hObject);
+
+ // Destroy the object
+ if (!object->destroyObject())
+ return CKR_FUNCTION_FAILED;
+
+ return CKR_OK;
+}
+
+// Determine the size of the specified object
+CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Retrieve the specified attributes for the given object
+CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ // Wrap a P11Object around the OSObject so we can access the attributes in the
+ // context of the object in which it is defined.
+ std::auto_ptr< P11Object > p11object;
+ CK_RV rv = newP11Object(object,p11object);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Ask the P11Object to fill the template with attribute values.
+ return p11object->loadTemplate(token, pTemplate,ulCount);
+}
+
+// Change or set the value of the specified attributes on the specified object
+CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isToken = object->getAttribute(CKA_TOKEN)->getBooleanValue();
+ CK_BBOOL isPrivate = object->getAttribute(CKA_PRIVATE)->getBooleanValue();
+
+ // Check user credentials
+ CK_RV rv = haveWrite(session->getState(), isToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Wrap a P11Object around the OSObject so we can access the attributes in the
+ // context of the object in which it is defined.
+ std::auto_ptr< P11Object > p11object;
+ rv = newP11Object(object,p11object);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Ask the P11Object to save the template with attribute values.
+ return p11object->saveTemplate(token, isPrivate, pTemplate,ulCount,OBJECT_OP_SET);
+}
+
+// Initialise object search in the specified session using the specified attribute template as search parameters
+CK_RV SoftHSM::C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the slot
+ Slot* slot = session->getSlot();
+ if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Determine whether we have a public session or not.
+ bool isPublicSession;
+ switch (session->getState()) {
+ case CKS_RO_USER_FUNCTIONS:
+ case CKS_RW_USER_FUNCTIONS:
+ case CKS_RW_SO_FUNCTIONS:
+ isPublicSession = false;
+ break;
+ default:
+ isPublicSession = true;
+ }
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ session->setOpType(SESSION_OP_FIND);
+ FindOperation *findOp = FindOperation::create();
+
+ // Check if we are out of memory
+ if (findOp == NULL_PTR) return CKR_HOST_MEMORY;
+
+ std::set<OSObject*> allObjects;
+ token->getObjects(allObjects);
+ sessionObjectStore->getObjects(slot->getSlotID(),allObjects);
+
+ std::set<CK_OBJECT_HANDLE> handles;
+ std::set<OSObject*>::iterator it;
+ for (it=allObjects.begin(); it != allObjects.end(); ++it)
+ {
+
+ // Determine if the object has CKA_PRIVATE set to CK_TRUE
+ bool isPrivateObject;
+ OSAttribute *attr = (*it)->getAttribute(CKA_PRIVATE);
+ if (attr == NULL_PTR || !attr->isBooleanAttribute())
+ {
+ // This attribute does not exist or is of an incompatible type
+ return CKR_GENERAL_ERROR;
+ }
+ isPrivateObject = attr->getBooleanValue();
+
+ // If the object is private, and we are in a public session then skip it !
+ if (isPublicSession && isPrivateObject)
+ continue; // skip object
+
+ // Perform the actual attribute matching.
+ bool bAttrMatch = true; // We let an empty template match everything.
+ for (CK_ULONG i=0; i<ulCount; ++i)
+ {
+ bAttrMatch = false;
+
+ OSAttribute *attr = (*it)->getAttribute(pTemplate[i].type);
+ if (attr == NULL_PTR)
+ break;
+
+ if (attr->isBooleanAttribute())
+ {
+ if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen)
+ break;
+ bool bTemplateValue = (*(CK_BBOOL*)pTemplate[i].pValue == CK_TRUE);
+ if (attr->getBooleanValue() != bTemplateValue)
+ break;
+ }
+ else
+ {
+ if (attr->isUnsignedLongAttribute())
+ {
+ if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
+ break;
+ CK_ULONG ulTemplateValue = *(CK_ULONG_PTR)pTemplate[i].pValue;
+ if (attr->getUnsignedLongValue() != ulTemplateValue)
+ break;
+ }
+ else
+ {
+ if (attr->isByteStringAttribute())
+ {
+ ByteString bsAttrValue;
+ if (isPrivateObject && attr->getByteStringValue().size() != 0)
+ {
+ if (!token->decrypt(attr->getByteStringValue(), bsAttrValue))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ bsAttrValue = attr->getByteStringValue();
+
+ if (bsAttrValue.size() != pTemplate[i].ulValueLen)
+ break;
+ if (pTemplate[i].ulValueLen != 0)
+ {
+ ByteString bsTemplateValue((const unsigned char*)pTemplate[i].pValue, pTemplate[i].ulValueLen);
+ if (bsAttrValue != bsTemplateValue)
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+ // The attribute matched !
+ bAttrMatch = true;
+ }
+
+ if (bAttrMatch)
+ {
+ CK_SLOT_ID slotID = slot->getSlotID();
+ CK_BBOOL isToken = (*it)->getAttribute(CKA_TOKEN)->getBooleanValue();
+ CK_BBOOL isPrivate = (*it)->getAttribute(CKA_PRIVATE)->getBooleanValue();
+ // Create an object handle for every returned object.
+ CK_OBJECT_HANDLE hObject;
+ if (isToken)
+ hObject = handleManager->addTokenObject(slotID,isPrivate,*it);
+ else
+ hObject = handleManager->addSessionObject(slotID,hSession,isPrivate,*it);
+ if (hObject == CK_INVALID_HANDLE)
+ return CKR_GENERAL_ERROR;
+ handles.insert(hObject);
+ }
+ }
+
+ // Storing the object handles for the find will protect the library
+ // whenever a stale object handle is used to access the library.
+ findOp->setHandles(handles);
+
+ session->setFindOp(findOp);
+
+ return CKR_OK;
+}
+
+// Continue the search for objects in the specified session
+CK_RV SoftHSM::C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulObjectCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // return the object handles that have been added to the find operation.
+ FindOperation *findOp = session->getFindOp();
+ if (findOp == NULL) return CKR_GENERAL_ERROR;
+
+ // Ask the find operation to retrieve the object handles
+ *pulObjectCount = findOp->retrieveHandles(phObject,ulMaxObjectCount);
+
+ // Erase the object handles from the find operation.
+ findOp->eraseHandles(0,*pulObjectCount);
+
+ return CKR_OK;
+}
+
+// Finish searching for objects
+CK_RV SoftHSM::C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Initialise encryption using the specified object and mechanism
+CK_RV SoftHSM::C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ // Check if key can be used for encryption
+ if (!key->attributeExists(CKA_ENCRYPT) || key->getAttribute(CKA_ENCRYPT)->getBooleanValue() == false)
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Get the asymmetric algorithm matching the mechanism
+ const char *mechanism;
+ bool isRSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = "rsa-pkcs";
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = "rsa-raw";
+ isRSA = true;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
+ {
+ DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
+ {
+ DEBUG_MSG("hashAlg must be CKM_SHA_1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
+ {
+ DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ mechanism = "rsa-pkcs-oaep";
+ isRSA = true;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PublicKey* publicKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm("rsa");
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_ENCRYPT);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setIsMultiPartOp(false);
+ session->setPublicKey(publicKey);
+
+ return CKR_OK;
+}
+
+// Perform a single operation encryption operation in the specified session
+CK_RV SoftHSM::C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_ENCRYPT)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ const char *mechanism = session->getMechanism();
+ PublicKey* publicKey = session->getPublicKey();
+ if (asymCrypto == NULL || mechanism == NULL || session->getIsMultiPartOp() || publicKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the encrypted data
+ CK_ULONG size = publicKey->getOutputLength();
+
+ if (pEncryptedData == NULL_PTR)
+ {
+ *pulEncryptedDataLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulEncryptedDataLen < size)
+ {
+ *pulEncryptedDataLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data;
+ ByteString encryptedData;
+
+ // PKCS #11 Mechanisms v2.30: Cryptoki Draft 7 page 32
+ // We must allow input length <= k and therfore need to prepend the data with zeroes.
+ if (strcmp(mechanism,"rsa-raw") == 0) {
+ data.wipe(size-ulDataLen);
+ }
+
+ data += ByteString(pData, ulDataLen);
+
+ // Encrypt the data
+ if (!asymCrypto->encrypt(publicKey,data,encryptedData,mechanism))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (encryptedData.size() != size)
+ {
+ ERROR_MSG("The size of the encrypted data differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pEncryptedData, encryptedData.byte_str(), size);
+ *pulEncryptedDataLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Feed data to the running encryption operation in a session
+CK_RV SoftHSM::C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Finalise the encryption operation
+CK_RV SoftHSM::C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Initialise decryption using the specified object
+CK_RV SoftHSM::C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ // Check if key can be used for decryption
+ if (!key->attributeExists(CKA_DECRYPT) || key->getAttribute(CKA_DECRYPT)->getBooleanValue() == false)
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Get the asymmetric algorithm matching the mechanism
+ const char *mechanism;
+ bool isRSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = "rsa-pkcs";
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = "rsa-raw";
+ isRSA = true;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
+ {
+ DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
+ {
+ DEBUG_MSG("hashAlg must be CKM_SHA_1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
+ {
+ DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ mechanism = "rsa-pkcs-oaep";
+ isRSA = true;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PrivateKey* privateKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm("rsa");
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_DECRYPT);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setIsMultiPartOp(false);
+ session->setPrivateKey(privateKey);
+
+ return CKR_OK;
+}
+
+// Perform a single operation decryption in the given session
+CK_RV SoftHSM::C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DECRYPT)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ const char *mechanism = session->getMechanism();
+ PrivateKey* privateKey = session->getPrivateKey();
+ if (asymCrypto == NULL || mechanism == NULL || session->getIsMultiPartOp() || privateKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the data
+ CK_ULONG size = privateKey->getOutputLength();
+ if (pData == NULL_PTR)
+ {
+ *pulDataLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDataLen < size)
+ {
+ *pulDataLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
+ ByteString data;
+
+ // Decrypt the data
+ if (!asymCrypto->decrypt(privateKey,encryptedData,data,mechanism))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (data.size() > size)
+ {
+ ERROR_MSG("The size of the decrypted data exceeds the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pData, data.byte_str(), data.size());
+ *pulDataLen = data.size();
+
+ session->resetOp();
+ return CKR_OK;
+
+}
+
+// Feed data to the running decryption operation in a session
+CK_RV SoftHSM::C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Finalise the decryption operation
+CK_RV SoftHSM::C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Initialise digesting using the specified mechanism in the specified session
+CK_RV SoftHSM::C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the mechanism
+ HashAlgorithm* hash = NULL;
+ switch(pMechanism->mechanism) {
+ case CKM_MD5:
+ hash = CryptoFactory::i()->getHashAlgorithm("md5");
+ break;
+ case CKM_SHA_1:
+ hash = CryptoFactory::i()->getHashAlgorithm("sha1");
+ break;
+ case CKM_SHA224:
+ hash = CryptoFactory::i()->getHashAlgorithm("sha224");
+ break;
+ case CKM_SHA256:
+ hash = CryptoFactory::i()->getHashAlgorithm("sha256");
+ break;
+ case CKM_SHA384:
+ hash = CryptoFactory::i()->getHashAlgorithm("sha384");
+ break;
+ case CKM_SHA512:
+ hash = CryptoFactory::i()->getHashAlgorithm("sha512");
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ if (hash == NULL) return CKR_MECHANISM_INVALID;
+
+ // Initialize hashing
+ if (hash->hashInit() == false)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ return CKR_GENERAL_ERROR;
+ }
+
+ session->setOpType(SESSION_OP_DIGEST);
+ session->setDigestOp(hash);
+
+ return CKR_OK;
+}
+
+// Digest the specified data in a one-pass operation and return the resulting digest
+CK_RV SoftHSM::C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Return size
+ CK_ULONG size = session->getDigestOp()->getHashSize();
+ if (pDigest == NULL_PTR)
+ {
+ *pulDigestLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDigestLen < size)
+ {
+ *pulDigestLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data(pData, ulDataLen);
+
+ // Digest the data
+ if (session->getDigestOp()->hashUpdate(data) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Get the digest
+ ByteString digest;
+ if (session->getDigestOp()->hashFinal(digest) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (digest.size() != size)
+ {
+ ERROR_MSG("The size of the digest differ from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pDigest, digest.byte_str(), size);
+ *pulDigestLen = size;
+
+ session->resetOp();
+
+ return CKR_OK;
+}
+
+// Update a running digest operation
+CK_RV SoftHSM::C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Get the data
+ ByteString data(pPart, ulPartLen);
+
+ // Digest the data
+ if (session->getDigestOp()->hashUpdate(data) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+// Update a running digest operation by digesting a secret key with the specified handle
+CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Finalise the digest operation in the specified session and return the digest
+CK_RV SoftHSM::C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Return size
+ CK_ULONG size = session->getDigestOp()->getHashSize();
+ if (pDigest == NULL_PTR)
+ {
+ *pulDigestLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDigestLen < size)
+ {
+ *pulDigestLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the digest
+ ByteString digest;
+ if (session->getDigestOp()->hashFinal(digest) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (digest.size() != size)
+ {
+ ERROR_MSG("The size of the digest differ from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pDigest, digest.byte_str(), size);
+ *pulDigestLen = size;
+
+ session->resetOp();
+
+ return CKR_OK;
+}
+
+// Initialise a signing operation using the specified key and mechanism
+CK_RV SoftHSM::C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ // Check if key can be used for signing
+ if (!key->attributeExists(CKA_SIGN) || key->getAttribute(CKA_SIGN)->getBooleanValue() == false)
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Get the asymmetric algorithm matching the mechanism
+ const char *mechanism;
+ bool bIsMultiPartOp;
+ bool isRSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = "rsa-pkcs";
+ bIsMultiPartOp = false;
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = "rsa-raw";
+ bIsMultiPartOp = false;
+ isRSA = true;
+ break;
+ case CKM_MD5_RSA_PKCS:
+ mechanism = "rsa-md5-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA1_RSA_PKCS:
+ mechanism = "rsa-sha1-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ mechanism = "rsa-sha256-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA384_RSA_PKCS:
+ mechanism = "rsa-sha384-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA512_RSA_PKCS:
+ mechanism = "rsa-sha512-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PrivateKey* privateKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm("rsa");
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Initialize signing
+ if (bIsMultiPartOp && !asymCrypto->signInit(privateKey,mechanism))
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_SIGN);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setIsMultiPartOp(bIsMultiPartOp);
+ session->setPrivateKey(privateKey);
+
+ return CKR_OK;
+}
+
+// Sign the data in a single pass operation
+CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_SIGN)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ const char *mechanism = session->getMechanism();
+ PrivateKey* privateKey = session->getPrivateKey();
+ if (asymCrypto == NULL || mechanism == NULL || session->getIsMultiPartOp() || privateKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = privateKey->getOutputLength();
+ if (pSignature == NULL_PTR)
+ {
+ *pulSignatureLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulSignatureLen < size)
+ {
+ *pulSignatureLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data;
+
+ // PKCS #11 Mechanisms v2.30: Cryptoki Draft 7 page 32
+ // We must allow input length <= k and therfore need to prepend the data with zeroes.
+ if (strcmp(mechanism,"rsa-raw") == 0) {
+ data.wipe(size-ulDataLen);
+ }
+
+ data += ByteString(pData, ulDataLen);
+ ByteString signature;
+
+ // Sign the data
+ if (!asymCrypto->sign(privateKey,data,signature,mechanism))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (signature.size() != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pSignature, signature.byte_str(), size);
+ *pulSignatureLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Update a running signing operation with additional data
+CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_SIGN || !session->getIsMultiPartOp())
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ if (asymCrypto == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Get the part
+ ByteString part(pPart, ulPartLen);
+
+ // Sign the data
+ if (!asymCrypto->signUpdate(part))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+// Finalise a running signing operation and return the signature
+CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_SIGN || !session->getIsMultiPartOp())
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ PrivateKey* privateKey = session->getPrivateKey();
+ if (asymCrypto == NULL || privateKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = privateKey->getOutputLength();
+ if (pSignature == NULL_PTR)
+ {
+ *pulSignatureLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulSignatureLen < size)
+ {
+ *pulSignatureLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString signature;
+
+ // Generate the signature
+ if (!asymCrypto->signFinal(signature))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (signature.size() != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pSignature, signature.byte_str(), size);
+ *pulSignatureLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Initialise a signing operation that allows recovery of the signed data
+CK_RV SoftHSM::C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Perform a single part signing operation that allows recovery of the signed data
+CK_RV SoftHSM::C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Initialise a verification operation using the specified key and mechanism
+CK_RV SoftHSM::C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR) return CKR_OBJECT_HANDLE_INVALID;
+
+ // Check if key can be used for verifying
+ if (!key->attributeExists(CKA_VERIFY) || key->getAttribute(CKA_VERIFY)->getBooleanValue() == false)
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Get the asymmetric algorithm matching the mechanism
+ const char *mechanism;
+ bool bIsMultiPartOp;
+ bool isRSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = "rsa-pkcs";
+ bIsMultiPartOp = false;
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = "rsa-raw";
+ bIsMultiPartOp = false;
+ isRSA = true;
+ break;
+ case CKM_MD5_RSA_PKCS:
+ mechanism = "rsa-md5-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA1_RSA_PKCS:
+ mechanism = "rsa-sha1-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ mechanism = "rsa-sha256-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA384_RSA_PKCS:
+ mechanism = "rsa-sha384-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA512_RSA_PKCS:
+ mechanism = "rsa-sha512-pkcs";
+ bIsMultiPartOp = true;
+ isRSA = true;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PublicKey* publicKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm("rsa");
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Initialize verifying
+ if (bIsMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism))
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_VERIFY);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setIsMultiPartOp(bIsMultiPartOp);
+ session->setPublicKey(publicKey);
+
+ return CKR_OK;
+}
+
+// Perform a single pass verification operation
+CK_RV SoftHSM::C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_VERIFY)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ const char *mechanism = session->getMechanism();
+ PublicKey* publicKey = session->getPublicKey();
+ if (asymCrypto == NULL || mechanism == NULL || session->getIsMultiPartOp() || publicKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = publicKey->getOutputLength();
+
+ // Check buffer size
+ if (ulSignatureLen != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ return CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ // Get the data
+ ByteString data;
+
+ // PKCS #11 Mechanisms v2.30: Cryptoki Draft 7 page 32
+ // We must allow input length <= k and therfore need to prepend the data with zeroes.
+ if (strcmp(mechanism,"rsa-raw") == 0) {
+ data.wipe(size-ulDataLen);
+ }
+
+ data += ByteString(pData, ulDataLen);
+ ByteString signature(pSignature, ulSignatureLen);
+
+ // Verify the data
+ if (!asymCrypto->verify(publicKey,data,signature,mechanism))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Update a running verification operation with additional data
+CK_RV SoftHSM::C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_VERIFY || !session->getIsMultiPartOp())
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ if (asymCrypto == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Get the part
+ ByteString part(pPart, ulPartLen);
+
+ // Verify the data
+ if (!asymCrypto->verifyUpdate(part))
+ {
+ // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+// Finalise the verification operation and check the signature
+CK_RV SoftHSM::C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_VERIFY || !session->getIsMultiPartOp())
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ PublicKey* publicKey = session->getPublicKey();
+ if (asymCrypto == NULL || publicKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = publicKey->getOutputLength();
+
+ // Check buffer size
+ if (ulSignatureLen != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ return CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ // Get the data
+ ByteString signature(pSignature, ulSignatureLen);
+
+ // Verify the data
+ if (!asymCrypto->verifyFinal(signature))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Initialise a verification operation the allows recovery of the signed data from the signature
+CK_RV SoftHSM::C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Perform a single part verification operation and recover the signed data
+CK_RV SoftHSM::C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part encryption and digesting operation
+CK_RV SoftHSM::C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part decryption and digesting operation
+CK_RV SoftHSM::C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pDecryptedPart, CK_ULONG_PTR pulDecryptedPartLen)
+{ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part signing and encryption operation
+CK_RV SoftHSM::C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part decryption and verification operation
+CK_RV SoftHSM::C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Generate a secret key using the specified mechanism
+CK_RV SoftHSM::C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Generate a key-pair using the specified mechanism
+CK_RV SoftHSM::C_GenerateKeyPair
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pPublicKeyTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pPrivateKeyTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phPublicKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check the mechanism, only accept RSA and DSA key pair generation.
+ CK_KEY_TYPE keyType;
+ switch (pMechanism->mechanism)
+ {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ keyType = CKK_RSA;
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ keyType = CKK_DSA;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ CK_CERTIFICATE_TYPE dummy;
+
+ // Extract information from the public key template that is needed to create the object.
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_BBOOL ispublicKeyToken = CK_FALSE;
+ CK_BBOOL ispublicKeyPrivate = CK_TRUE;
+ extractObjectInformation(pPublicKeyTemplate, ulPublicKeyAttributeCount, publicKeyClass, keyType, dummy, ispublicKeyToken, ispublicKeyPrivate);
+
+ // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
+ if (publicKeyClass != CKO_PUBLIC_KEY)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ // Extract information from the private key template that is needed to create the object.
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_BBOOL isprivateKeyToken = CK_FALSE;
+ CK_BBOOL isprivateKeyPrivate = CK_TRUE;
+ extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate);
+
+ // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
+ if (privateKeyClass != CKO_PRIVATE_KEY)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ // Check user credentials
+ CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Generate RSA keys
+ if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
+ {
+ return this->generateRSA(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ // Generate DSA keys
+ if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN)
+ {
+ return this->generateDSA(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ return CKR_GENERAL_ERROR;
+}
+
+// Wrap the specified key using the specified wrapping key and mechanism
+CK_RV SoftHSM::C_WrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey,
+ CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Unwrap the specified key using the specified unwrapping key
+CK_RV SoftHSM::C_UnwrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR hKey
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Derive a key from the specified base key
+CK_RV SoftHSM::C_DeriveKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Seed the random number generator with new data
+CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the RNG
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL) return CKR_GENERAL_ERROR;
+
+ // Seed the RNG
+ ByteString seed(pSeed, ulSeedLen);
+ rng->seed(seed);
+
+ return CKR_OK;
+}
+
+// Generate the specified amount of random data
+CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the RNG
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL) return CKR_GENERAL_ERROR;
+
+ // Generate random data
+ ByteString randomData;
+ if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
+
+ // Return random data
+ memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
+
+ return CKR_OK;
+}
+
+// Legacy function
+CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+// Legacy function
+CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+// Wait or poll for a slot even on the specified slot
+CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Generate an RSA key pair
+CK_RV SoftHSM::generateRSA
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+)
+{
+ *phPublicKey = CK_INVALID_HANDLE;
+ *phPrivateKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired key information: bitlen and public exponent
+ size_t bitLen = 0;
+ ByteString exponent("010001");
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_MODULUS_BITS:
+ if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
+ break;
+ case CKA_PUBLIC_EXPONENT:
+ exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
+ if (bitLen == 0) {
+ INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Set the parameters
+ RSAParameters p;
+ p.setE(exponent);
+ p.setBitLength(bitLen);
+
+ // Generate key pair
+ AsymmetricKeyPair* kp = NULL;
+ AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm("RSA");
+ if (rsa == NULL)
+ return CKR_GENERAL_ERROR;
+ if (!rsa->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+ return CKR_GENERAL_ERROR;
+ }
+
+ RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+
+ CK_RV rv = CKR_OK;
+
+ // Create a public key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE publicKeyType = CKK_RSA;
+ CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
+ { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
+ { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
+ { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
+ };
+ CK_ULONG publicKeyAttribsCount = 4;
+
+ // Put the generated key material in the attributes
+ publicKeyAttribs[publicKeyAttribsCount++] = bsAttribute(CKA_PUBLIC_EXPONENT, pub->getE());
+
+ // Add the additional
+ if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
+ return CKR_TEMPLATE_INCONSISTENT;
+ for (int i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
+ if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // RSA Public Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ if (isPublicKeyPrivate)
+ {
+ token->encrypt(pub->getN(), modulus);
+ token->encrypt(pub->getE(), publicExponent);
+ }
+ else
+ {
+ modulus = pub->getN();
+ publicExponent = pub->getE();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
+ bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv == CKR_FUNCTION_FAILED;
+ }
+ }
+ }
+
+ // Create a private key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE privateKeyType = CKK_RSA;
+ CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
+ { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
+ { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
+ { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
+ };
+ CK_ULONG privateKeyAttribsCount = 4;
+ if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
+ return CKR_TEMPLATE_INCONSISTENT;
+ for (int i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
+ if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Private Key Attributes
+ bool bAlwaysSensitive = osobject->getAttribute(CKA_SENSITIVE)->getBooleanValue();
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getAttribute(CKA_EXTRACTABLE)->getBooleanValue() == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // RSA Private Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ ByteString privateExponent;
+ ByteString prime1;
+ ByteString prime2;
+ ByteString exponent1;
+ ByteString exponent2;
+ ByteString coefficient;
+ if (isPrivateKeyPrivate)
+ {
+ token->encrypt(priv->getN(), modulus);
+ token->encrypt(priv->getE(), publicExponent);
+ token->encrypt(priv->getD(), privateExponent);
+ token->encrypt(priv->getP(), prime1);
+ token->encrypt(priv->getQ(), prime2);
+ token->encrypt(priv->getDP1(), exponent1);
+ token->encrypt(priv->getDQ1(), exponent2);
+ token->encrypt(priv->getPQ(), coefficient);
+ }
+ else
+ {
+ modulus = priv->getN();
+ publicExponent = priv->getE();
+ privateExponent = priv->getD();
+ prime1 = priv->getP();
+ prime2 = priv->getQ();
+ exponent1 = priv->getDP1();
+ exponent2 = priv->getDQ1();
+ coefficient = priv->getPQ();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
+ bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
+ bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
+ bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
+ bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
+ bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
+ bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
+ bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+ }
+
+ // Clean up
+ rsa->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+
+ // Remove keys that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phPrivateKey != CK_INVALID_HANDLE)
+ {
+ OSObject* priv = (OSObject*)handleManager->getObject(*phPrivateKey);
+ handleManager->destroyObject(*phPrivateKey);
+ if (priv) priv->destroyObject();
+ *phPrivateKey = CK_INVALID_HANDLE;
+ }
+
+ if (*phPublicKey != CK_INVALID_HANDLE)
+ {
+ OSObject* pub = (OSObject*)handleManager->getObject(*phPublicKey);
+ handleManager->destroyObject(*phPublicKey);
+ if (pub) pub->destroyObject();
+ *phPublicKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate an DSA key pair
+CK_RV SoftHSM::generateDSA
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate)
+{
+ AsymmetricKeyPair* kp = NULL;
+ DSAParameters p;
+ ByteString prime;
+ ByteString subprime;
+ ByteString generator;
+
+ // Extract desired key information
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_PRIME:
+ prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_SUBPRIME:
+ subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_BASE:
+ generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The parameters must be specified to be able to generate a key pair.
+ if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
+ INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Set the parameters
+ p.setP(prime);
+ p.setQ(subprime);
+ p.setG(generator);
+
+ // Generate key pair
+ AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm("DSA");
+ if (dsa == NULL) return CKR_GENERAL_ERROR;
+ if (!dsa->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ return CKR_GENERAL_ERROR;
+ }
+
+ DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
+ DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
+
+ // TODO: Save keys
+
+ // Clean up
+ dsa->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the slot
+ Slot* slot = session->getSlot();
+ if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Extract information from the template that is needed to create the object.
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_CERTIFICATE_TYPE certType = CKC_X_509;
+ CK_BBOOL isToken = CK_FALSE;
+ CK_BBOOL isPrivate = CK_TRUE;
+ CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ ERROR_MSG("Mandatory attribute not present in template");
+ return rv;
+ }
+
+ // Check user credentials
+ rv = haveWrite(session->getState(), isToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ std::auto_ptr< P11Object > p11object;
+ rv = newP11Object(objClass,keyType,p11object);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Create the object in session or on the token
+ OSObject *object = NULL_PTR;
+ if (isToken)
+ {
+ object = (OSObject*) token->createObject();
+ }
+ else
+ {
+ object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate);
+ }
+ if (object == NULL) return CKR_GENERAL_ERROR;
+
+ p11object->init(object);
+
+ rv = p11object->saveTemplate(token, isPrivate, pTemplate,ulCount,op);
+ if (rv != CKR_OK)
+ return rv;
+
+ if (isToken) {
+ *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate, object);
+ } else {
+ *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate, object);
+ }
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
+{
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ OSAttribute* attr = key->getAttribute(CKA_PRIVATE);
+ bool isKeyPrivate = (attr != NULL && attr->getBooleanValue());
+
+ // RSA Private Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ ByteString privateExponent;
+ ByteString prime1;
+ ByteString prime2;
+ ByteString exponent1;
+ ByteString exponent2;
+ ByteString coefficient;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_MODULUS)->getByteStringValue(), modulus);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_PUBLIC_EXPONENT)->getByteStringValue(), publicExponent);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_PRIVATE_EXPONENT)->getByteStringValue(), privateExponent);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_PRIME_1)->getByteStringValue(), prime1);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_PRIME_2)->getByteStringValue(), prime2);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_EXPONENT_1)->getByteStringValue(), exponent1);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_EXPONENT_2)->getByteStringValue(), exponent2);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_COEFFICIENT)->getByteStringValue(), coefficient);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ modulus = key->getAttribute(CKA_MODULUS)->getByteStringValue();
+ publicExponent = key->getAttribute(CKA_PUBLIC_EXPONENT)->getByteStringValue();
+ privateExponent = key->getAttribute(CKA_PRIVATE_EXPONENT)->getByteStringValue();
+ prime1 = key->getAttribute(CKA_PRIME_1)->getByteStringValue();
+ prime2 = key->getAttribute(CKA_PRIME_2)->getByteStringValue();
+ exponent1 = key->getAttribute(CKA_EXPONENT_1)->getByteStringValue();
+ exponent2 = key->getAttribute(CKA_EXPONENT_2)->getByteStringValue();
+ coefficient = key->getAttribute(CKA_COEFFICIENT)->getByteStringValue();
+ }
+
+ privateKey->setN(modulus);
+ privateKey->setE(publicExponent);
+ privateKey->setD(privateExponent);
+ privateKey->setP(prime1);
+ privateKey->setQ(prime2);
+ privateKey->setDP1(exponent1);
+ privateKey->setDQ1(exponent2);
+ privateKey->setPQ(coefficient);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ OSAttribute* attr = key->getAttribute(CKA_PRIVATE);
+ bool isKeyPrivate = (attr != NULL && attr->getBooleanValue());
+
+ // RSA Public Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_MODULUS)->getByteStringValue(), modulus);
+ bOK = bOK && token->decrypt(key->getAttribute(CKA_PUBLIC_EXPONENT)->getByteStringValue(), publicExponent);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ modulus = key->getAttribute(CKA_MODULUS)->getByteStringValue();
+ publicExponent = key->getAttribute(CKA_PUBLIC_EXPONENT)->getByteStringValue();
+ }
+
+ publicKey->setN(modulus);
+ publicKey->setE(publicExponent);
+
+ return CKR_OK;
+}
diff --git a/src/lib/SoftHSM.h b/src/lib/SoftHSM.h
--- /dev/null
+++ b/src/lib/SoftHSM.h
@@ -0,0 +1,223 @@
+/* $Id: SoftHSM.h 6735 2012-10-15 11:08:58Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SoftHSM.h
+
+ This is the main class of the SoftHSM; it has the PKCS #11 interface and
+ dispatches all calls to the relevant components of the SoftHSM. The SoftHSM
+ class is a singleton implementation.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "cryptoki.h"
+#include "SessionObjectStore.h"
+#include "ObjectStore.h"
+#include "SessionManager.h"
+#include "SlotManager.h"
+#include "HandleManager.h"
+#include "RSAPublicKey.h"
+#include "RSAPrivateKey.h"
+
+#include <memory>
+
+class SoftHSM
+{
+public:
+ // Return the one-and-only instance
+ static SoftHSM* i();
+
+ // This will destroy the one-and-only instance.
+ static void reset();
+
+ // Destructor
+ virtual ~SoftHSM();
+
+ // PKCS #11 functions
+ CK_RV C_Initialize(CK_VOID_PTR pInitArgs);
+ CK_RV C_Finalize(CK_VOID_PTR pReserved);
+ CK_RV C_GetInfo(CK_INFO_PTR pInfo);
+ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo);
+ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo);
+ CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount);
+ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo);
+ CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel);
+ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen);
+ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen);
+ CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession);
+ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession);
+ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID);
+ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo);
+ CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen);
+ CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey);
+ CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen);
+ CK_RV C_Logout(CK_SESSION_HANDLE hSession);
+ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject);
+ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
+ CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize);
+ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount);
+ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession);
+ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen);
+ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen);
+ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism);
+ CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen);
+ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+ CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
+ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen);
+ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+ CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+ CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pDecryptedPart, CK_ULONG_PTR pulDecryptedPartLen);
+ CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen);
+ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV C_GenerateKeyPair
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey
+ );
+ CK_RV C_WrapKey
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey,
+ CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen
+ );
+ CK_RV C_UnwrapKey
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR hKey
+ );
+ CK_RV C_DeriveKey
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+ );
+ CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen);
+ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen);
+ CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession);
+ CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession);
+ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved);
+
+private:
+ // Constructor
+ SoftHSM();
+
+ // The one-and-only instance
+ static std::auto_ptr<SoftHSM> instance;
+
+ // Is the SoftHSM PKCS #11 library initialised?
+ bool isInitialised;
+
+ SessionObjectStore* sessionObjectStore;
+ ObjectStore* objectStore;
+ SlotManager* slotManager;
+ SessionManager* sessionManager;
+ HandleManager* handleManager;
+
+ // Key generation
+ CK_RV generateRSA
+ (CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV generateDSA
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV CreateObject
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phObject,
+ int op
+ );
+
+ CK_RV getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key);
+ CK_RV getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key);
+};
+
diff --git a/src/lib/access.cpp b/src/lib/access.cpp
--- /dev/null
+++ b/src/lib/access.cpp
@@ -0,0 +1,103 @@
+/* $Id: access.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ access.cpp
+
+ Implements the access rules.
+ *****************************************************************************/
+
+#include "access.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+// Checks if a read operation is allowed on a given object type.
+//
+// Type of session
+// Type of object R/O Public | R/W Public | R/O User | R/W User | R/W SO
+// ------------------------------------------------------------------------------
+// Public session object OK | OK | OK | OK | OK
+// Private session object UNLI | UNLI | OK | OK | UNLI
+// Public token object OK | OK | OK | OK | OK
+// Private token object UNLI | UNLI | OK | OK | UNLI
+//
+// OK = CKR_OK
+// SRO = CKR_SESSION_READ_ONLY
+// UNLI = CKR_USER_NOT_LOGGED_IN
+
+// Can we do read operations?
+CK_RV haveRead(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject)
+{
+ switch (sessionState)
+ {
+ case CKS_RO_PUBLIC_SESSION:
+ case CKS_RW_PUBLIC_SESSION:
+ case CKS_RW_SO_FUNCTIONS:
+ return isPrivateObject ? CKR_USER_NOT_LOGGED_IN : CKR_OK;
+ case CKS_RO_USER_FUNCTIONS:
+ case CKS_RW_USER_FUNCTIONS:
+ return CKR_OK;
+ }
+ return CKR_GENERAL_ERROR; // internal error, switch should have covered every state
+}
+
+// Checks if a write operation is allowed on a given object type.
+//
+// Type of session
+// Type of object R/O Public | R/W Public | R/O User | R/W User | R/W SO
+// ------------------------------------------------------------------------------
+// Public session object OK | OK | OK | OK | OK
+// Private session object UNLI | UNLI | OK | OK | UNLI
+// Public token object SRO | OK | SRO | OK | OK
+// Private token object SRO/UNLI | UNLI | SRO | OK | UNLI
+//
+// OK = CKR_OK
+// SRO = CKR_SESSION_READ_ONLY
+// UNLI = CKR_USER_NOT_LOGGED_IN
+// In the situation where both SRO and UNLI may be returned we favor SRO.
+
+// Can we do write operations?
+CK_RV haveWrite(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject)
+{
+ switch (sessionState)
+ {
+ case CKS_RO_PUBLIC_SESSION:
+ if (isTokenObject)
+ return CKR_SESSION_READ_ONLY;
+ else
+ return isPrivateObject ? CKR_USER_NOT_LOGGED_IN : CKR_OK;
+ case CKS_RW_PUBLIC_SESSION:
+ case CKS_RW_SO_FUNCTIONS:
+ return isPrivateObject ? CKR_USER_NOT_LOGGED_IN : CKR_OK;
+ case CKS_RO_USER_FUNCTIONS:
+ return isTokenObject ? CKR_SESSION_READ_ONLY : CKR_OK;
+ case CKS_RW_USER_FUNCTIONS:
+ return CKR_OK;
+ }
+ return CKR_GENERAL_ERROR; // internal error, switch should have covered every state
+}
diff --git a/src/lib/access.h b/src/lib/access.h
--- /dev/null
+++ b/src/lib/access.h
@@ -0,0 +1,44 @@
+/* $Id: access.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ access.h
+
+ Implements the access rules.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ACCESS_H
+#define _SOFTHSM_V2_ACCESS_H
+
+#include "cryptoki.h"
+
+CK_RV haveRead(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject);
+CK_RV haveWrite(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject);
+
+#endif /* !_SOFTHSM_V2_ACCESS_H */
+
diff --git a/src/lib/common/Configuration.cpp b/src/lib/common/Configuration.cpp
--- /dev/null
@@ -0,0 +1,168 @@
+/* $Id: Configuration.cpp 4893 2010-09-13 11:52:38Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Configuration.cpp
+
+ Loads the configuration and supports retrieval of configuration information
+ *****************************************************************************/
+
+#include <string>
+#include <map>
+#include "Configuration.h"
+#include "log.h"
+
+// Initialise the one-and-only instance
+std::auto_ptr<Configuration> Configuration::instance(NULL);
+
+// Add all valid configurations
+const struct config Configuration::valid_config[] = {
+ { "directories.tokendir", CONFIG_TYPE_STRING },
+ { "", CONFIG_TYPE_UNSUPPORTED }
+};
+
+// Return the one-and-only instance
+Configuration* Configuration::i()
+{
+ if (instance.get() == NULL)
+ {
+ instance = std::auto_ptr<Configuration>(new Configuration());
+ }
+
+ return instance.get();
+}
+
+// Constructor
+Configuration::Configuration()
+{
+ configLoader = NULL;
+}
+
+// Get the type of the configuration value
+int Configuration::getType(std::string key)
+{
+ for (int i = 0; valid_config[i].key.compare("") != 0; i++)
+ {
+ if (valid_config[i].key.compare(key) == 0)
+ {
+ return valid_config[i].type;
+ }
+ }
+
+ return CONFIG_TYPE_UNSUPPORTED;
+}
+
+// Retrieve a string based configuration value
+std::string Configuration::getString(std::string key, std::string ifEmpty /* = "" */)
+{
+ if (stringConfiguration.find(key) != stringConfiguration.end())
+ {
+ return stringConfiguration[key];
+ }
+ else
+ {
+ return ifEmpty;
+ }
+}
+
+// Retrieve an integer configuration value
+int Configuration::getInt(std::string key, int ifEmpty /* = 0 */)
+{
+ if (integerConfiguration.find(key) != integerConfiguration.end())
+ {
+ return integerConfiguration[key];
+ }
+ else
+ {
+ return ifEmpty;
+ }
+}
+
+// Retrieve a boolean configuration value
+bool Configuration::getBool(std::string key, bool ifEmpty /* = false */)
+{
+ if (booleanConfiguration.find(key) != booleanConfiguration.end())
+ {
+ return booleanConfiguration[key];
+ }
+ else
+ {
+ return ifEmpty;
+ }
+}
+
+// Set a string based configuration value
+void Configuration::setString(std::string key, std::string value)
+{
+ stringConfiguration[key] = value;
+}
+
+// Set an integer based configuration value
+void Configuration::setInt(std::string key, int value)
+{
+ integerConfiguration[key] = value;
+}
+
+// Set a boolean configuration value
+void Configuration::setBool(std::string key, bool value)
+{
+ booleanConfiguration[key] = value;
+}
+
+// Reload the configuration
+bool Configuration::reload()
+{
+ if (configLoader == NULL)
+ {
+ return false;
+ }
+
+ // Discard the current configuration
+ stringConfiguration.clear();
+ integerConfiguration.clear();
+ booleanConfiguration.clear();
+
+ // Reload the configuration
+ if (!configLoader->loadConfiguration())
+ {
+ ERROR_MSG("Failed to load the SoftHSM configuration");
+
+ return false;
+ }
+
+ return true;
+}
+
+// Reload the configuration using the specified configuration loader
+bool Configuration::reload(ConfigLoader* configLoader)
+{
+ this->configLoader = configLoader;
+
+ return reload();
+}
+
diff --git a/src/lib/common/Configuration.h b/src/lib/common/Configuration.h
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: Configuration.h 4893 2010-09-13 11:52:38Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Configuration.h
+
+ Loads the configuration and supports retrieval of configuration information
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_CONFIGURATION_H
+#define _SOFTHSM_V2_CONFIGURATION_H
+
+#include "config.h"
+#include <string>
+#include <map>
+#include <memory>
+
+enum
+{
+ CONFIG_TYPE_UNSUPPORTED,
+ CONFIG_TYPE_STRING,
+ CONFIG_TYPE_INT,
+ CONFIG_TYPE_BOOL
+};
+
+struct config
+{
+ std::string key;
+ int type;
+};
+
+class ConfigLoader
+{
+public:
+ virtual ~ConfigLoader() { }
+
+ // Trigger loading of the configuration
+ virtual bool loadConfiguration() = 0;
+};
+
+class Configuration
+{
+public:
+ static Configuration* i();
+
+ virtual ~Configuration() { }
+
+ // Get the type of the configuration value
+ int getType(std::string key);
+
+ // Retrieve a string based configuration value
+ std::string getString(std::string key, std::string ifEmpty = std::string(""));
+
+ // Retrieve an integer configuration value
+ int getInt(std::string key, int ifEmpty = 0);
+
+ // Retrieve a boolean configuration value
+ bool getBool(std::string key, bool ifEmpty = false);
+
+ // Set a string based configuration value
+ void setString(std::string key, std::string value);
+
+ // Set an integer based configuration value
+ void setInt(std::string key, int value);
+
+ // Set a boolean configuration value
+ void setBool(std::string key, bool value);
+
+ // Reload the configuration
+ bool reload();
+
+ // Reload the configuration using the specified configuration loader
+ bool reload(ConfigLoader* configLoader);
+
+private:
+ Configuration();
+
+ static std::auto_ptr<Configuration> instance;
+
+ std::map<std::string, std::string> stringConfiguration;
+ std::map<std::string, int> integerConfiguration;
+ std::map<std::string, bool> booleanConfiguration;
+
+ ConfigLoader* configLoader;
+
+ static const struct config valid_config[];
+};
+
+#endif // !_SOFTHSM_V2_CONFIGURATION_H
+
diff --git a/src/lib/common/HandleFactory.h b/src/lib/common/HandleFactory.h
--- /dev/null
@@ -0,0 +1,123 @@
+/* $Id: HandleFactory.h 4854 2010-08-18 12:43:03Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleFactory.h
+
+ This is a template class for handling handles ;-)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEFACTORY_H
+#define _SOFTHSM_V2_HANDLEFACTORY_H
+
+#include "config.h"
+#include "log.h"
+#include "MutexFactory.h"
+#include <map>
+#include <queue>
+
+template <class hType, class oType> class HandleFactory
+{
+public:
+ // Constructor
+ HandleFactory()
+ {
+ nextFree = (hType) 1;
+ handleMutex = MutexFactory::i()->getMutex();
+ }
+
+ // Destructor
+ virtual ~HandleFactory()
+ {
+ MutexFactory::i()->recycleMutex(handleMutex);
+ }
+
+ // Get a new handle for the specified object
+ hType getHandle(oType object)
+ {
+ MutexLocker lock(handleMutex);
+
+ hType handle;
+
+ if (!recycledHandles.empty())
+ {
+ handle = recycledHandles.front();
+ recycledHandles.pop();
+ }
+ else
+ {
+ handle = nextFree++;
+ }
+
+ handleMap[handle] = object;
+
+ return handle;
+ }
+
+ // Check whether the specified handle is valid
+ bool isValid(hType handle)
+ {
+ MutexLocker lock(handleMutex);
+
+ return (handleMap.find(handle) != handleMap.end());
+ }
+
+ // Return the object for the specified handle
+ oType getObjectByHandle(hType handle)
+ {
+ MutexLocker lock(handleMutex);
+
+ return handleMap[handle];
+ }
+
+ // Discard the specified handle
+ void deleteHandle(hType handle)
+ {
+ MutexLocker lock(handleMutex);
+
+ handleMap.erase(handle);
+
+ recycledHandles.push(handle);
+ }
+
+private:
+ // The handle map
+ std::map<hType, oType> handleMap;
+
+ // The set of recycled handles
+ std::queue<hType> recycledHandles;
+
+ // The next free handle
+ hType nextFree;
+
+ // Cross-thread synchronisation
+ Mutex* handleMutex;
+};
+
+#endif // !_SOFTHSM_V2_HANDLEFACTORY_H
+
diff --git a/src/lib/common/IPCSignal.cpp b/src/lib/common/IPCSignal.cpp
--- /dev/null
@@ -0,0 +1,109 @@
+/* $Id: IPCSignal.cpp 4828 2010-07-27 14:23:02Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ IPCSignal.cpp
+
+ This class implements rudimentary IPC signalling based on POSIX semaphores.
+
+ N.B.: Because of the way this code works, SoftHSM v2 is not suitable for use
+ in environments where it is both long lived as well as has a high
+ object change ratio (either separately is not a problem). This is
+ caused by the fact that the counter on a POSIX semaphore has a limit
+ of INT_MAX.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "IPCSignal.h"
+
+// Factory
+IPCSignal* IPCSignal::create(const std::string name)
+{
+ Semaphore* semaphore = Semaphore::create(0, name);
+
+ if (semaphore == NULL)
+ {
+ ERROR_MSG("Failed to create a named semaphore (%s)", name.c_str());
+
+ return NULL;
+ }
+
+ return new IPCSignal(semaphore);
+}
+
+// Destructor
+IPCSignal::~IPCSignal()
+{
+ delete semaphore;
+}
+
+// Update the signal
+void IPCSignal::trigger()
+{
+ if (!semaphore->inc())
+ {
+ if (semaphore->getValue() > 0)
+ {
+ // Decrement by 10; this is to prevent listeners from missing
+ // the changed in case of a saturated semaphore. This is not
+ // ideal, however
+ for (int i = 0; i < 10; i++) semaphore->dec();
+
+ currentValue -= 10;
+ }
+ else
+ {
+ // Make sure this instance isn't triggered by its own action
+ currentValue++;
+ }
+ }
+}
+
+// Has the signal been triggered?
+bool IPCSignal::wasTriggered()
+{
+ int value = semaphore->getValue();
+
+ if (value != currentValue)
+ {
+ currentValue = value;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Constructor
+IPCSignal::IPCSignal(Semaphore* semaphore)
+{
+ this->semaphore = semaphore;
+ currentValue = semaphore->getValue();
+}
+
diff --git a/src/lib/common/IPCSignal.h b/src/lib/common/IPCSignal.h
--- /dev/null
@@ -0,0 +1,75 @@
+/* $Id: IPCSignal.h 4827 2010-07-26 15:02:28Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ IPCSignal.h
+
+ This class implements rudimentary IPC signalling based on POSIX semaphores.
+
+ N.B.: Because of the way this code works, SoftHSM v2 is not suitable for use
+ in environments where it is both long lived as well as has a high
+ object change ratio (either separately is not a problem). This is
+ caused by the fact that the counter on a POSIX semaphore has a limit
+ of INT_MAX.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_IPCSIGNAL_H
+#define _SOFTHSM_V2_IPCSIGNAL_H
+
+#include "config.h"
+#include "Semaphore.h"
+#include <string>
+
+class IPCSignal
+{
+public:
+ // Factory
+ static IPCSignal* create(const std::string name);
+
+ // Destructor
+ virtual ~IPCSignal();
+
+ // Update the signal
+ void trigger();
+
+ // Has the signal been triggered?
+ bool wasTriggered();
+
+private:
+ // Constructor
+ IPCSignal(Semaphore* semaphore);
+
+ // The semaphore
+ Semaphore* semaphore;
+
+ // The current semaphore value
+ int currentValue;
+};
+
+#endif // !_SOFTHSM_V2_IPCSIGNAL_H
+
diff --git a/src/lib/common/Makefile.am b/src/lib/common/Makefile.am
--- /dev/null
@@ -0,0 +1,33 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/..
+
+noinst_LTLIBRARIES = libsofthsm_common.la
+libsofthsm_common_la_SOURCES = Configuration.cpp \
+ fatal.cpp \
+ log.cpp \
+ osmutex.cpp \
+ SimpleConfigLoader.cpp \
+ MutexFactory.cpp \
+ Semaphore.cpp \
+ IPCSignal.cpp
+libsofthsm_common_la_LIBADD = @SEMAPHORE_LIB@
+
+man_MANS = softhsm2.conf.5
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/softhsm2.conf.5.in
+
+install-data-hook:
+ test -d ${DESTDIR}${sysconfdir} || \
+ ${INSTALL} -d ${DESTDIR}${sysconfdir}
+ test -f ${DESTDIR}${sysconfdir}/softhsm2.conf || \
+ ${INSTALL_DATA} ${top_builddir}/src/lib/common/softhsm2.conf ${DESTDIR}${sysconfdir}
+ ${INSTALL_DATA} ${top_builddir}/src/lib/common/softhsm2.conf ${DESTDIR}${sysconfdir}/softhsm2.conf.sample
+ test -d ${DESTDIR}${softhsmtokendir} || \
+ ${INSTALL} -d -m 700 ${DESTDIR}${softhsmtokendir}
diff --git a/src/lib/common/MutexFactory.cpp b/src/lib/common/MutexFactory.cpp
--- /dev/null
@@ -0,0 +1,197 @@
+/* $Id: MutexFactory.cpp 4860 2010-08-23 13:04:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MutexFactory.cpp
+
+ This factory produces OS specific mutex objects
+ *****************************************************************************/
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "osmutex.h"
+#include <memory>
+
+
+/*****************************************************************************
+ Mutex implementation
+ *****************************************************************************/
+
+// Constructor
+Mutex::Mutex()
+{
+ isValid = (MutexFactory::i()->createMutex(&handle) == CKR_OK);
+}
+
+// Destructor
+Mutex::~Mutex()
+{
+ if (isValid)
+ {
+ MutexFactory::i()->destroyMutex(handle);
+ }
+}
+
+// Lock the mutex
+bool Mutex::lock()
+{
+ return (isValid && (MutexFactory::i()->lockMutex(handle) == CKR_OK));
+}
+
+// Unlock the mutex
+void Mutex::unlock()
+{
+ if (isValid)
+ {
+ MutexFactory::i()->unlockMutex(handle);
+ }
+}
+
+/*****************************************************************************
+ MutexLocker implementation
+ *****************************************************************************/
+
+// Constructor
+MutexLocker::MutexLocker(Mutex* mutex)
+{
+ this->mutex = mutex;
+
+ if (this->mutex != NULL) this->mutex->lock();
+}
+
+// Destructor
+MutexLocker::~MutexLocker()
+{
+ if (this->mutex != NULL) this->mutex->unlock();
+}
+
+/*****************************************************************************
+ MutexFactory implementation
+ *****************************************************************************/
+
+// Initialise the one-and-only instance
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+
+// Constructor
+MutexFactory::MutexFactory()
+{
+ createMutex = OSCreateMutex;
+ destroyMutex = OSDestroyMutex;
+ lockMutex = OSLockMutex;
+ unlockMutex = OSUnlockMutex;
+
+ enabled = true;
+}
+
+// Destructor
+MutexFactory::~MutexFactory()
+{
+}
+
+// Return the one-and-only instance
+MutexFactory* MutexFactory::i()
+{
+ if (!instance.get())
+ {
+ instance = std::auto_ptr<MutexFactory>(new MutexFactory());
+ }
+
+ return instance.get();
+}
+
+// Get a mutex instance
+Mutex* MutexFactory::getMutex()
+{
+ return new Mutex();
+}
+
+// Recycle a mutex instance
+void MutexFactory::recycleMutex(Mutex* mutex)
+{
+ if (mutex != NULL) delete mutex;
+}
+
+// Set the function pointers
+void MutexFactory::setCreateMutex(CK_CREATEMUTEX createMutex)
+{
+ this->createMutex = createMutex;
+}
+
+void MutexFactory::setDestroyMutex(CK_DESTROYMUTEX destroyMutex)
+{
+ this->destroyMutex = destroyMutex;
+}
+
+void MutexFactory::setLockMutex(CK_LOCKMUTEX lockMutex)
+{
+ this->lockMutex = lockMutex;
+}
+
+void MutexFactory::setUnlockMutex(CK_UNLOCKMUTEX unlockMutex)
+{
+ this->unlockMutex = unlockMutex;
+}
+
+void MutexFactory::enable()
+{
+ enabled = true;
+}
+
+void MutexFactory::disable()
+{
+ enabled = false;
+}
+
+CK_RV MutexFactory::CreateMutex(CK_VOID_PTR_PTR newMutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->createMutex)(newMutex);
+}
+
+CK_RV MutexFactory::DestroyMutex(CK_VOID_PTR mutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->destroyMutex)(mutex);
+}
+
+CK_RV MutexFactory::LockMutex(CK_VOID_PTR mutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->lockMutex)(mutex);
+}
+
+CK_RV MutexFactory::UnlockMutex(CK_VOID_PTR mutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->unlockMutex)(mutex);
+}
+
diff --git a/src/lib/common/MutexFactory.h b/src/lib/common/MutexFactory.h
--- /dev/null
@@ -0,0 +1,131 @@
+/* $Id: MutexFactory.h 4860 2010-08-23 13:04:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MutexFactory.h
+
+ This factory produces OS specific mutex objects
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_MUTEXFACTORY_H
+#define _SOFTHSM_V2_MUTEXFACTORY_H
+
+#include "config.h"
+#include "osmutex.h"
+#include "cryptoki.h"
+#include <memory>
+
+class Mutex
+{
+public:
+ // Constructor
+ Mutex();
+
+ // Destructor
+ virtual ~Mutex();
+
+ // Lock the mutex
+ bool lock();
+
+ // Unlock the mutex
+ void unlock();
+
+private:
+ // The mutex handle
+ CK_VOID_PTR handle;
+
+ // Is the mutex valid?
+ bool isValid;
+};
+
+class MutexLocker
+{
+public:
+ // Constructor
+ MutexLocker(Mutex* mutex);
+
+ // Destructor
+ virtual ~MutexLocker();
+
+private:
+ // The mutex to lock
+ Mutex* mutex;
+};
+
+class MutexFactory
+{
+public:
+ // Return the one-and-only instance
+ static MutexFactory* i();
+
+ // Destructor
+ virtual ~MutexFactory();
+
+ // Get a mutex instance
+ Mutex* getMutex();
+
+ // Recycle a mutex instance
+ void recycleMutex(Mutex* mutex);
+
+ // Set the function pointers
+ void setCreateMutex(CK_CREATEMUTEX createMutex);
+ void setDestroyMutex(CK_DESTROYMUTEX destroyMutex);
+ void setLockMutex(CK_LOCKMUTEX lockMutex);
+ void setUnlockMutex(CK_UNLOCKMUTEX unlockMutex);
+
+ // Enable/disable mutex handling
+ void enable();
+ void disable();
+
+private:
+ // Constructor
+ MutexFactory();
+
+ // Mutex operations
+ friend class Mutex;
+
+ CK_RV CreateMutex(CK_VOID_PTR_PTR newMutex);
+ CK_RV DestroyMutex(CK_VOID_PTR mutex);
+ CK_RV LockMutex(CK_VOID_PTR mutex);
+ CK_RV UnlockMutex(CK_VOID_PTR mutex);
+
+ // The one-and-only instance
+ static std::auto_ptr<MutexFactory> instance;
+
+ // The function pointers
+ CK_CREATEMUTEX createMutex;
+ CK_DESTROYMUTEX destroyMutex;
+ CK_LOCKMUTEX lockMutex;
+ CK_UNLOCKMUTEX unlockMutex;
+
+ // Can we do mutex handling?
+ bool enabled;
+};
+
+#endif // !_SOFTHSM_V2_MUTEXFACTORY_H
+
diff --git a/src/lib/common/Semaphore.cpp b/src/lib/common/Semaphore.cpp
--- /dev/null
@@ -0,0 +1,122 @@
+/* $Id: Semaphore.cpp 4827 2010-07-26 15:02:28Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Semaphore.cpp
+
+ This class implements an object version of POSIX semaphores
+ *****************************************************************************/
+
+#include "config.h"
+#include "Semaphore.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <algorithm>
+
+// Search/replace for "/" to "_"
+char replaceSlashByUnderscore(const char in)
+{
+ return ((in == '/') ? '_' : in);
+}
+
+// Factory
+Semaphore* Semaphore::create(int initialValue, const std::string name /* = "" */)
+{
+ std::string semName;
+
+ if (!name.empty())
+ {
+ // Replace all occurences of "/" by "_" in the name
+ semName.resize(name.size());
+ std::transform(name.begin(), name.end(), semName.begin(), replaceSlashByUnderscore);
+
+ semName = "/" + semName;
+ }
+
+ sem_t* semaphore = sem_open(semName.empty() ? NULL : semName.c_str(), O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO, initialValue);
+
+ if (semaphore == NULL)
+ {
+ return NULL;
+ }
+
+ return new Semaphore(semaphore, semName);
+}
+
+// Constructor
+Semaphore::Semaphore(sem_t* semaphore, std::string name)
+{
+ this->semaphore = semaphore;
+ this->name = name;
+}
+
+// Destructor
+Semaphore::~Semaphore()
+{
+ // Close the semaphore
+ sem_close(semaphore);
+
+ // Destroy it (if necessary)
+ if (!name.empty())
+ {
+ sem_unlink(name.c_str());
+ }
+}
+
+// Increment (unlock) the semaphore
+bool Semaphore::inc()
+{
+ return (sem_post(semaphore) != -1);
+}
+
+// Decrement (lock) the semaphore
+bool Semaphore::dec(bool wait /* = false */)
+{
+ if (wait)
+ {
+ return (sem_wait(semaphore) != -1);
+ }
+ else
+ {
+ return (sem_trywait(semaphore) != -1);
+ }
+}
+
+// Retrieve the value of the semaphore
+int Semaphore::getValue()
+{
+ int value = -1;
+
+ if (sem_getvalue(semaphore, &value) == -1)
+ {
+ return -1;
+ }
+
+ return value;
+}
+
diff --git a/src/lib/common/Semaphore.h b/src/lib/common/Semaphore.h
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: Semaphore.h 4827 2010-07-26 15:02:28Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Semaphore.h
+
+ This class implements an object version of POSIX semaphores
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SEMAPHORE_H
+#define _SOFTHSM_V2_SEMAPHORE_H
+
+#include "config.h"
+#include <semaphore.h>
+#include <string>
+
+class Semaphore
+{
+public:
+ // Factory
+ static Semaphore* create(int initialValue, const std::string name = "");
+
+ // Destructor
+ virtual ~Semaphore();
+
+ // Increment (unlock) the semaphore
+ bool inc();
+
+ // Decrement (lock) the semaphore
+ bool dec(bool wait = false);
+
+ // Retrieve the value of the semaphore
+ int getValue();
+
+private:
+ // Constructor
+ Semaphore(sem_t* semaphore, std::string name);
+
+ // The actual POSIX semaphore
+ sem_t* semaphore;
+
+ // The name of the semaphore (needed to destroy it)
+ std::string name;
+};
+
+#endif // !_SOFTHSM_V2_SEMAPHORE_H
+
diff --git a/src/lib/common/Serialisable.h b/src/lib/common/Serialisable.h
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Id: Serialisable.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Serialisable.h
+
+ Interface description for serialisable classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SERIALISABLE_H
+#define _SOFTHSM_V2_SERIALISABLE_H
+
+#include "config.h"
+#include "ByteString.h"
+
+class ByteString;
+
+class Serialisable
+{
+public:
+ // Serialise the data content of a class
+ virtual ByteString serialise() const = 0;
+
+ // Default destructor
+ virtual ~Serialisable() { }
+};
+
+#endif // !_SOFTHSM_V2_SERIALISABLE_H
+
diff --git a/src/lib/common/SimpleConfigLoader.cpp b/src/lib/common/SimpleConfigLoader.cpp
--- /dev/null
@@ -0,0 +1,225 @@
+/* $Id: SimpleConfigLoader.cpp 4950 2011-03-29 08:07:48Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE, The Internet Infrastructure Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SimpleConfigLoader.cpp
+
+ Loads the configuration from the configuration file.
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <algorithm>
+#include "config.h"
+#include "SimpleConfigLoader.h"
+#include "log.h"
+#include "Configuration.h"
+
+// Initialise the one-and-only instance
+std::auto_ptr<SimpleConfigLoader> SimpleConfigLoader::instance(NULL);
+
+// Return the one-and-only instance
+SimpleConfigLoader* SimpleConfigLoader::i()
+{
+ if (instance.get() == NULL)
+ {
+ instance = std::auto_ptr<SimpleConfigLoader>(new SimpleConfigLoader());
+ }
+
+ return instance.get();
+}
+
+// Constructor
+SimpleConfigLoader::SimpleConfigLoader()
+{
+}
+
+// Load the configuration
+bool SimpleConfigLoader::loadConfiguration()
+{
+ const char* configPath = getConfigPath();
+
+ FILE* fp = fopen(configPath,"r");
+
+ if (fp == NULL)
+ {
+ ERROR_MSG("Could not open the config file: %s", configPath);
+ return false;
+ }
+
+ char fileBuf[1024];
+
+ // Format in config file
+ //
+ // <name> = <value>
+ // # Line is ignored
+
+ while (fgets(fileBuf, sizeof(fileBuf), fp) != NULL)
+ {
+ // End the string at the first comment or newline
+ fileBuf[strcspn(fileBuf, "#\n\r")] = '\0';
+
+ // Get the first part of the line
+ char* name = strtok(fileBuf, "=");
+ if (name == NULL)
+ {
+ continue;
+ }
+
+ // Trim the name
+ char* trimmedName = trimString(name);
+ if (trimmedName == NULL)
+ {
+ continue;
+ }
+
+ // Get the second part of the line
+ char* value = strtok(NULL, "=");
+ if(value == NULL) {
+ free(trimmedName);
+ continue;
+ }
+
+ // Trim the value
+ char* trimmedValue = trimString(value);
+ if (trimmedValue == NULL)
+ {
+ free(trimmedName);
+ continue;
+ }
+
+ // Save name,value
+ std::string stringName(trimmedName);
+ std::string stringValue(trimmedValue);
+ free(trimmedName);
+ free(trimmedValue);
+
+ switch (Configuration::i()->getType(stringName))
+ {
+ case CONFIG_TYPE_STRING:
+ Configuration::i()->setString(stringName, stringValue);
+ break;
+ case CONFIG_TYPE_INT:
+ Configuration::i()->setInt(stringName, atoi(stringValue.c_str()));
+ break;
+ case CONFIG_TYPE_BOOL:
+ bool boolValue;
+ if (string2bool(stringValue, &boolValue))
+ {
+ Configuration::i()->setBool(stringName, boolValue);
+ }
+ else
+ {
+ WARNING_MSG("The value %s is not a boolean", stringValue.c_str());
+ }
+ break;
+ case CONFIG_TYPE_UNSUPPORTED:
+ default:
+ WARNING_MSG("The following configuration is not supported: %s = %s",
+ stringName.c_str(), stringValue.c_str());
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ return true;
+}
+
+// Get the boolean value from a string
+bool SimpleConfigLoader::string2bool(std::string stringValue, bool* boolValue)
+{
+ // Convert to lowercase
+ std::transform(stringValue.begin(), stringValue.end(), stringValue.begin(), tolower);
+
+ if (stringValue.compare("true") == 0)
+ {
+ *boolValue = true;
+ return true;
+ }
+
+ if (stringValue.compare("false") == 0)
+ {
+ *boolValue = false;
+ return true;
+ }
+
+ return false;
+}
+
+const char* SimpleConfigLoader::getConfigPath()
+{
+ const char* configPath = getenv("SOFTHSM2_CONF");
+
+ if (configPath == NULL) {
+ configPath = DEFAULT_SOFTHSM2_CONF;
+ }
+
+ return configPath;
+}
+
+char* SimpleConfigLoader::trimString(char* text)
+{
+ if (text == NULL)
+ {
+ return NULL;
+ }
+
+ int startPos = 0;
+ int endPos = strlen(text) - 1;
+
+ // Find the first position without a space
+ while (startPos <= endPos && isspace((int)*(text + startPos)))
+ {
+ startPos++;
+ }
+ // Find the last position without a space
+ while (startPos <= endPos && isspace((int)*(text + endPos)))
+ {
+ endPos--;
+ }
+
+ // We must have a valid string
+ int length = endPos - startPos + 1;
+ if (length <= 0)
+ {
+ return NULL;
+ }
+
+ // Create the trimmed text
+ char* trimmedText = (char*)malloc(length + 1);
+ if (trimmedText == NULL)
+ {
+ return NULL;
+ }
+ trimmedText[length] = '\0';
+ memcpy(trimmedText, text + startPos, length);
+
+ return trimmedText;
+}
diff --git a/src/lib/common/SimpleConfigLoader.h b/src/lib/common/SimpleConfigLoader.h
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id: SimpleConfigLoader.h 4950 2011-03-29 08:07:48Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE, The Internet Infrastructure Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SimpleConfigLoader.h
+
+ Loads the configuration from the configuration file.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SIMPLECONFIGLOADER_H
+#define _SOFTHSM_V2_SIMPLECONFIGLOADER_H
+
+#include <memory>
+#include "config.h"
+#include "Configuration.h"
+
+class SimpleConfigLoader : public ConfigLoader
+{
+public:
+ static SimpleConfigLoader* i();
+
+ virtual ~SimpleConfigLoader() { }
+
+ virtual bool loadConfiguration();
+
+private:
+ SimpleConfigLoader();
+ const char* getConfigPath();
+ char* trimString(char* text);
+ bool string2bool(std::string stringValue, bool* boolValue);
+
+ static std::auto_ptr<SimpleConfigLoader> instance;
+};
+
+#endif // !_SOFTHSM_V2_SIMPLECONFIGLOADER_H
+
diff --git a/src/lib/common/fatal.cpp b/src/lib/common/fatal.cpp
--- /dev/null
+++ b/src/lib/common/fatal.cpp
@@ -0,0 +1,66 @@
+/* $Id: fatal.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ fatal.cpp
+
+ Implementens calls for handling fatal exceptions. When a fatal exception
+ occurs, this code ensures that as much of the securely allocated memory as
+ possible is wiped clean.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "fatal.h"
+#include "SecureMemoryRegistry.h"
+#include "pkcs11.h"
+
+void FatalException(void)
+{
+ try
+ {
+ DEBUG_MSG("Fatal exception handler called");
+ }
+ catch (...)
+ {
+ }
+
+ // Wipe as much of the securely allocated memory as possible
+ SecureMemoryRegistry::i()->wipe();
+
+ try
+ {
+ ERROR_MSG("A fatal exception occurred; exiting...");
+ }
+ catch (...)
+ {
+ }
+
+ exit(CKR_GENERAL_ERROR);
+}
+
diff --git a/src/lib/common/fatal.h b/src/lib/common/fatal.h
--- /dev/null
+++ b/src/lib/common/fatal.h
@@ -0,0 +1,54 @@
+/* $Id: fatal.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ fatal.h
+
+ Implementens calls for handling fatal exceptions. When a fatal exception
+ occurs, this code ensures that as much of the securely allocated memory as
+ possible is wiped clean.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FATAL_H
+#define _SOFTHSM_V2_FATAL_H
+
+#include "config.h"
+#include "log.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif // __cplusplus
+
+void FatalException(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // !_SOFTHSM_V2_FATAL_H
+
diff --git a/src/lib/common/log.cpp b/src/lib/common/log.cpp
--- /dev/null
+++ b/src/lib/common/log.cpp
@@ -0,0 +1,79 @@
+/* $Id: log.cpp 31 2010-03-05 12:51:02Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ log.cpp
+
+ Implements logging functions. This file is based on the concepts from
+ SoftHSM v1 but extends the logging functions with support for a variable
+ argument list as defined in stdarg (3).
+ *****************************************************************************/
+
+#include <stdarg.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <sstream>
+#include <vector>
+#include "config.h"
+#include "log.h"
+
+void softHSMLog(const int loglevel, const char* functionName, const char* fileName, const int lineNo, const char* format, ...)
+{
+ std::stringstream prepend;
+
+#ifdef SOFTHSM_LOG_FILE_AND_LINE
+ prepend << fileName << "(" << lineNo << ")";
+#ifndef SOFTHSM_LOG_FUNCTION_NAME
+ prepend << ":";
+#endif // !SOFTHSM_LOG_FUNCTION_NAME
+ prepend << " ";
+#endif // SOFTHSM_LOG_FILE_AND_LINE
+
+#ifdef SOFTHSM_LOG_FUNCTION_NAME
+ prepend << functionName << ": ";
+#endif // SOFTHSM_LOG_FUNCTION_NAME
+
+ // Print the format to a log message
+ std::vector<char> logMessage;
+ va_list args;
+
+ logMessage.resize(4096);
+
+ va_start(args, format);
+ vsnprintf(&logMessage[0], 4096, format, args);
+ va_end(args);
+
+ // And log it
+ syslog(loglevel, "%s%s", prepend.str().c_str(), &logMessage[0]);
+
+#ifdef DEBUG_LOG_STDERR
+ fprintf(stderr, "%s%s\n", prepend.str().c_str(), &logMessage[0]);
+ fflush(stderr);
+#endif // DEBUG_LOG_STDERR
+}
+
diff --git a/src/lib/common/log.h b/src/lib/common/log.h
--- /dev/null
+++ b/src/lib/common/log.h
@@ -0,0 +1,95 @@
+/* $Id: log.h 31 2010-03-05 12:51:02Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ log.h
+
+ Implements logging functions. This file is based on the concepts from
+ SoftHSM v1 but extends the logging functions with support for a variable
+ argument list as defined in stdarg (3).
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_LOG_H
+#define _SOFTHSM_V2_LOG_H
+
+#include <syslog.h>
+#include "config.h"
+
+/* The log levels */
+#define SOFTERROR 1
+#define SOFTWARNING 2
+#define SOFTINFO 3
+#define SOFTDEBUG 4
+
+/* Set the default loglevel if none is set */
+#ifndef SOFTLOGLEVEL
+#define SOFTLOGLEVEL SOFTDEBUG
+#endif /* !SOFTLOGLEVEL */
+
+/* Unset this define if you don't want to log the source file name and line number */
+#define SOFTHSM_LOG_FILE_AND_LINE
+
+/* Set this define to log the function name */
+/* #define SOFTHSM_LOG_FUNCTION_NAME */
+
+/* Define this symbol (either here or in the build setup) to log to stderr */
+/* #define DEBUG_LOG_STDERR */
+
+/* Logging errors */
+#if SOFTLOGLEVEL >= SOFTERROR
+#define ERROR_MSG(...) softHSMLog(LOG_ERR, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define ERROR_MSG(...)
+#endif
+
+/* Logging warnings */
+#if SOFTLOGLEVEL >= SOFTWARNING
+#define WARNING_MSG(...) softHSMLog(LOG_WARNING, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define WARNING_MSG(...)
+#endif
+
+/* Logging information */
+#if SOFTLOGLEVEL >= SOFTINFO
+#define INFO_MSG(...) softHSMLog(LOG_INFO, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define INFO_MSG(...)
+#endif
+
+/* Logging debug information */
+#if SOFTLOGLEVEL >= SOFTDEBUG
+#define DEBUG_MSG(...) softHSMLog(LOG_DEBUG, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define DEBUG_MSG(...)
+#endif
+
+/* Function definitions */
+void softHSMLog(const int loglevel, const char* functionName, const char* fileName, const int lineNo, const char* format, ...);
+
+#endif /* !_SOFTHSM_V2_LOG_H */
+
diff --git a/src/lib/common/osmutex.cpp b/src/lib/common/osmutex.cpp
--- /dev/null
@@ -0,0 +1,146 @@
+/* $Id: osmutex.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2008-2010 .SE (The Internet Infrastructure Foundation).
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ osmutex.cpp
+
+ Contains OS-specific implementations of intraprocess mutex functions. This
+ implementation is based on SoftHSM v1
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "osmutex.h"
+
+#ifdef HAVE_PTHREAD_H
+
+#include <stdlib.h>
+#include <pthread.h>
+
+CK_RV OSCreateMutex(CK_VOID_PTR_PTR newMutex)
+{
+ int rv;
+
+ /* Allocate memory */
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Failed to allocate memory for a new mutex");
+
+ return CKR_HOST_MEMORY;
+ }
+
+ /* Initialise the mutex */
+ if ((rv = pthread_mutex_init(pthreadMutex, NULL)) != 0)
+ {
+ free(pthreadMutex);
+
+ ERROR_MSG("Failed to initialise POSIX mutex (0x%08X)", rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ *newMutex = pthreadMutex;
+
+ return CKR_OK;
+}
+
+CK_RV OSDestroyMutex(CK_VOID_PTR mutex)
+{
+ int rv;
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) mutex;
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Cannot destroy NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if ((rv = pthread_mutex_destroy(pthreadMutex)) != 0)
+ {
+ ERROR_MSG("Failed to destroy POSIX mutex (0x%08X)", rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ free(pthreadMutex);
+
+ return CKR_OK;
+}
+
+CK_RV OSLockMutex(CK_VOID_PTR mutex)
+{
+ int rv;
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) mutex;
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Cannot lock NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if ((rv = pthread_mutex_lock(pthreadMutex)) != 0)
+ {
+ ERROR_MSG("Failed to lock POSIX mutex 0x%08X (0x%08X)", pthreadMutex, rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV OSUnlockMutex(CK_VOID_PTR mutex)
+{
+ int rv;
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) mutex;
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Cannot unlock NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if ((rv = pthread_mutex_unlock(pthreadMutex)) != 0)
+ {
+ ERROR_MSG("Failed to unlock POSIX mutex 0x%08X (0x%08X)", pthreadMutex, rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+#else
+#error "There are no mutex implementations for your operating system yet"
+#endif
+
diff --git a/src/lib/common/osmutex.h b/src/lib/common/osmutex.h
--- /dev/null
+++ b/src/lib/common/osmutex.h
@@ -0,0 +1,49 @@
+/* $Id: osmutex.h 4826 2010-07-26 10:41:38Z rijswijk $ */
+
+/*
+ * Copyright (c) 2008-2010 .SE (The Internet Infrastructure Foundation).
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ osmutex.h
+
+ Contains OS-specific implementations of intraprocess mutex functions. This
+ implementation is based on SoftHSM v1
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSMUTEX_H
+#define _SOFTHSM_V2_OSMUTEX_H
+
+#include "config.h"
+#include "cryptoki.h"
+
+CK_RV OSCreateMutex(CK_VOID_PTR_PTR newMutex);
+CK_RV OSDestroyMutex(CK_VOID_PTR mutex);
+CK_RV OSLockMutex(CK_VOID_PTR mutex);
+CK_RV OSUnlockMutex(CK_VOID_PTR mutex);
+
+#endif /* !_SOFTHSM_V2_OSMUTEX_H */
+
diff --git a/src/lib/common/softhsm2.conf.5.in b/src/lib/common/softhsm2.conf.5.in
--- /dev/null
@@ -0,0 +1,56 @@
+.TH softhsm2.conf 5 "22 October 2012" "SoftHSM"
+.\" $Id: softhsm2.conf.5.in 6757 2012-10-22 19:40:31Z rb $
+.SH NAME
+softhsm2.conf \- SoftHSM configuration file
+.SH SYNOPSIS
+.B softhsm2.conf
+.SH DESCRIPTION
+This is the configuration file for SoftHSM. It can be found on a
+default location, but can also be relocated by using the
+environment variable. Any configuration must be done according
+to the file format found in this document.
+.SH FILE FORMAT
+Each configuration option is a pair of name and value separated by
+a equality sign. The configuration option must be located on a single line.
+.LP
+.RS
+.nf
+<name> = <value>
+.fi
+.RE
+.LP
+It is also possible to add comments in the file by using the hash sign.
+Anything after the hash sign will be ignored.
+.LP
+.RS
+.nf
+# A comment
+.RE
+.LP
+Any empty lines or lines that does not have the correct format will be ignored.
+.SH DIRECTORIES.TOKENDIR
+The location where SoftHSM can store the tokens.
+.LP
+.RS
+.nf
+directories.tokendir = @softhsmtokendir@
+.fi
+.RE
+.LP
+.SH ENVIRONMENT
+.TP
+SOFTHSM2_CONF
+When defined, the value will be used as path to the configuration file.
+.SH FILES
+.TP
+.I @default_softhsm2_conf@
+default location of the SoftHSM configuration file
+.TP
+.I @default_softhsm2_conf@.sample
+an example of a SoftHSM configuration file
+.SH AUTHOR
+Written by Rickard Bellgrim, René Post, and Roland van Rijswijk.
+.SH "SEE ALSO"
+.IR softhsm-keyconv (1),
+.IR softhsm-migrate (1),
+.IR softhsm-util (1)
diff --git a/src/lib/common/softhsm2.conf.in b/src/lib/common/softhsm2.conf.in
--- /dev/null
@@ -0,0 +1,3 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @softhsmtokendir@
diff --git a/src/lib/crypto/AESKey.h b/src/lib/crypto/AESKey.h
--- /dev/null
+++ b/src/lib/crypto/AESKey.h
@@ -0,0 +1,50 @@
+/* $Id: AESKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESKey.h
+
+ AES key symmetric key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_AESKEY_H
+#define _SOFTHSM_V2_AESKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "SymmetricKey.h"
+
+class AESKey : public SymmetricKey
+{
+public:
+ // Base constructor
+ AESKey(size_t bitLen = 0) : SymmetricKey(bitLen) { }
+};
+
+#endif // !SOFTHSM_V2_AESKEY_H
+
diff --git a/src/lib/crypto/AsymmetricAlgorithm.cpp b/src/lib/crypto/AsymmetricAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,172 @@
+/* $Id: AsymmetricAlgorithm.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricAlgorithm.cpp
+
+ Base class for asymmetric algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "AsymmetricAlgorithm.h"
+
+// Base constructor
+AsymmetricAlgorithm::AsymmetricAlgorithm()
+{
+ currentOperation = NONE;
+ currentPublicKey = NULL;
+ currentPrivateKey = NULL;
+}
+
+// Signing functions
+bool AsymmetricAlgorithm::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism)
+{
+ // Compose from multi-part operations
+ return (signInit(privateKey, mechanism) && signUpdate(dataToSign) && signFinal(signature));
+}
+
+bool AsymmetricAlgorithm::signInit(PrivateKey* privateKey, const std::string mechanism)
+{
+ if ((currentOperation != NONE) || (privateKey == NULL))
+ {
+ return false;
+ }
+
+ currentPrivateKey = privateKey;
+ currentMechanism = mechanism;
+ currentOperation = SIGN;
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::signUpdate(const ByteString& dataToSign)
+{
+ if (currentOperation != SIGN)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::signFinal(ByteString& signature)
+{
+ if (currentOperation != SIGN)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+ currentPrivateKey = NULL;
+ currentMechanism = "";
+
+ return true;
+}
+
+// Verification functions
+bool AsymmetricAlgorithm::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism)
+{
+ // Compose from multi-part operations
+ return (verifyInit(publicKey, mechanism) && verifyUpdate(originalData) && verifyFinal(signature));
+}
+
+bool AsymmetricAlgorithm::verifyInit(PublicKey* publicKey, const std::string mechanism)
+{
+ if ((currentOperation != NONE) || (publicKey == NULL))
+ {
+ return false;
+ }
+
+ currentOperation = VERIFY;
+ currentPublicKey = publicKey;
+ currentMechanism = mechanism;
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::verifyUpdate(const ByteString& originalData)
+{
+ if (currentOperation != VERIFY)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::verifyFinal(const ByteString& signature)
+{
+ if (currentOperation != VERIFY)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+ currentPublicKey = NULL;
+ currentMechanism = "";
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* rng /* = NULL*/)
+{
+ return false;
+}
+
+bool AsymmetricAlgorithm::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ return false;
+}
+
+AsymmetricParameters* AsymmetricAlgorithm::newParameters()
+{
+ return NULL;
+}
+
+// Key recycling -- override these functions in a derived class if you need to perform specific cleanup
+void AsymmetricAlgorithm::recycleKeyPair(AsymmetricKeyPair* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recycleParameters(AsymmetricParameters* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recyclePublicKey(PublicKey* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recyclePrivateKey(PrivateKey* toRecycle)
+{
+ delete toRecycle;
+}
+
diff --git a/src/lib/crypto/AsymmetricAlgorithm.h b/src/lib/crypto/AsymmetricAlgorithm.h
--- /dev/null
@@ -0,0 +1,110 @@
+/* $Id: AsymmetricAlgorithm.h 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricAlgorithm.h
+
+ Base class for asymmetric algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_ASYMMETRICALGORITHM_H
+
+#include "config.h"
+#include <string>
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricParameters.h"
+#include "PublicKey.h"
+#include "PrivateKey.h"
+#include "RNG.h"
+
+class AsymmetricAlgorithm
+{
+public:
+ // Base constructors
+ AsymmetricAlgorithm();
+
+ // Destructor
+ virtual ~AsymmetricAlgorithm() { }
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism);
+ virtual bool signInit(PrivateKey* privateKey, const std::string mechanism);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism);
+ virtual bool verifyInit(PublicKey* publicKey, const std::string mechanism);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding) = 0;
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding) = 0;
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL) = 0;
+ virtual unsigned long getMinKeySize() = 0;
+ virtual unsigned long getMaxKeySize() = 0;
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData) = 0;
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) = 0;
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) = 0;
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey() = 0;
+ virtual PrivateKey* newPrivateKey() = 0;
+ virtual AsymmetricParameters* newParameters();
+
+ // Key recycling -- override these functions in a derived class if you need to perform specific cleanup
+ virtual void recycleKeyPair(AsymmetricKeyPair* toRecycle);
+ virtual void recycleParameters(AsymmetricParameters* toRecycle);
+ virtual void recyclePublicKey(PublicKey* toRecycle);
+ virtual void recyclePrivateKey(PrivateKey* toRecycle);
+
+protected:
+ PublicKey* currentPublicKey;
+ PrivateKey* currentPrivateKey;
+
+ std::string currentMechanism;
+ std::string currentPadding;
+
+private:
+ enum
+ {
+ NONE,
+ SIGN,
+ VERIFY
+ }
+ currentOperation;
+};
+
+#endif // !_SOFTHSM_V2_ASYMMETRICALGORITHM_H
+
diff --git a/src/lib/crypto/AsymmetricKeyPair.cpp b/src/lib/crypto/AsymmetricKeyPair.cpp
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id: AsymmetricKeyPair.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricKeyPair.cpp
+
+ Asymmetric key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "AsymmetricKeyPair.h"
+
+ByteString AsymmetricKeyPair::serialise() const
+{
+ return getConstPublicKey()->serialise().serialise() + getConstPrivateKey()->serialise().serialise();
+}
+
diff --git a/src/lib/crypto/AsymmetricKeyPair.h b/src/lib/crypto/AsymmetricKeyPair.h
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id: AsymmetricKeyPair.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricKeyPair.h
+
+ Base class for asymmetric key-pair classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMMETRICKEYPAIR_H
+#define _SOFTHSM_V2_ASYMMETRICKEYPAIR_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "PublicKey.h"
+#include "PrivateKey.h"
+#include "Serialisable.h"
+
+class AsymmetricKeyPair : public Serialisable
+{
+public:
+ // Base constructors
+ AsymmetricKeyPair() { }
+
+ AsymmetricKeyPair(const AsymmetricKeyPair& in) { }
+
+ // Destructor
+ virtual ~AsymmetricKeyPair() { }
+
+ // Return the public key
+ virtual PublicKey* getPublicKey() = 0;
+ virtual const PublicKey* getConstPublicKey() const = 0;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey() = 0;
+ virtual const PrivateKey* getConstPrivateKey() const = 0;
+
+ // Serialise the contents
+ virtual ByteString serialise() const;
+};
+
+#endif // !_SOFTHSM_V2_ASYMMETRICKEYPAIR_H
+
diff --git a/src/lib/crypto/AsymmetricParameters.h b/src/lib/crypto/AsymmetricParameters.h
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id: AsymmetricParameters.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricParameters.h
+
+ Base class for asymmetric parameter classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMMETRICPARAMETERS_H
+#define _SOFTHSM_V2_ASYMMETRICPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+
+class AsymmetricParameters : public Serialisable
+{
+public:
+ // Base constructors
+ AsymmetricParameters() { }
+
+ AsymmetricParameters(const AsymmetricParameters& in) { }
+
+ // Destructor
+ virtual ~AsymmetricParameters() { }
+
+ // Check if it is of the given type
+ virtual bool areOfType(const char* type) = 0;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+};
+
+#endif // !_SOFTHSM_V2_ASYMMETRICPARAMETERS_H
+
diff --git a/src/lib/crypto/BotanAES.cpp b/src/lib/crypto/BotanAES.cpp
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id: BotanAES.cpp 4791 2010-05-23 21:32:48Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanAES.cpp
+
+ Botan AES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanAES.h"
+#include <algorithm>
+
+std::string BotanAES::getCipher() const
+{
+ // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys
+ if ((currentKey->getBitLen() != 128) &&
+ (currentKey->getBitLen() != 192) &&
+ (currentKey->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return "";
+ }
+
+ // Determine the cipher mode
+ if (!currentCipherMode.compare("cbc"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return "AES-128/CBC/PKCS7";
+ case 192:
+ return "AES-192/CBC/PKCS7";
+ case 256:
+ return "AES-256/CBC/PKCS7";
+ };
+ }
+ else if (!currentCipherMode.compare("ecb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return "AES-128/ECB/PKCS7";
+ case 192:
+ return "AES-192/ECB/PKCS7";
+ case 256:
+ return "AES-256/ECB/PKCS7";
+ };
+ }
+
+ ERROR_MSG("Invalid AES cipher mode %s", currentCipherMode.c_str());
+
+ return "";
+}
+
+size_t BotanAES::getBlockSize() const
+{
+ // The block size is 128 bits
+ return 128 >> 3;
+}
+
diff --git a/src/lib/crypto/BotanAES.h b/src/lib/crypto/BotanAES.h
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id: BotanAES.h 4791 2010-05-23 21:32:48Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanAES.h
+
+ Botan AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANAES_H
+#define _SOFTHSM_V2_BOTANAES_H
+
+#include <string>
+#include "config.h"
+#include "BotanSymmetricAlgorithm.h"
+
+class BotanAES : public BotanSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~BotanAES() { }
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual std::string getCipher() const;
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANAES_H
+
diff --git a/src/lib/crypto/BotanCryptoFactory.cpp b/src/lib/crypto/BotanCryptoFactory.cpp
--- /dev/null
@@ -0,0 +1,232 @@
+/* $Id: BotanCryptoFactory.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanCryptoFactory.cpp
+
+ This is a Botan based cryptographic algorithm factory
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanCryptoFactory.h"
+#include "BotanAES.h"
+#include "BotanDES.h"
+#include "BotanDSA.h"
+#include "BotanMD5.h"
+#include "BotanRNG.h"
+#include "BotanRSA.h"
+#include "BotanSHA1.h"
+#include "BotanSHA224.h"
+#include "BotanSHA256.h"
+#include "BotanSHA384.h"
+#include "BotanSHA512.h"
+
+#include <botan/init.h>
+
+// Initialise the one-and-only instance
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+
+// Constructor
+BotanCryptoFactory::BotanCryptoFactory()
+{
+ // Init the Botan crypto library
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+
+ // Create mutex
+ rngsMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+BotanCryptoFactory::~BotanCryptoFactory()
+{
+ // Delete the RNGs
+#ifdef HAVE_PTHREAD_H
+ std::map<pthread_t,RNG*>::iterator it;
+ for (it=rngs.begin(); it != rngs.end(); it++)
+ {
+ delete (BotanRNG*)it->second;
+ }
+#endif
+
+ // TODO: We cannot do this because the MutexFactory is destroyed before the CryptoFactory
+ // MutexFactory::i()->recycleMutex(rngsMutex);
+
+ // Deinitialize the Botan crypto lib
+ Botan::LibraryInitializer::deinitialize();
+}
+
+// Return the one-and-only instance
+BotanCryptoFactory* BotanCryptoFactory::i()
+{
+ if (!instance.get())
+ {
+ instance = std::auto_ptr<BotanCryptoFactory>(new BotanCryptoFactory());
+ }
+
+ return instance.get();
+}
+
+// Create a concrete instance of a symmetric algorithm
+SymmetricAlgorithm* BotanCryptoFactory::getSymmetricAlgorithm(std::string algorithm)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(algorithm.size());
+ std::transform(algorithm.begin(), algorithm.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("aes"))
+ {
+ return new BotanAES();
+ }
+ else if (!lcAlgo.compare("des") || !lcAlgo.compare("3des"))
+ {
+ return new BotanDES();
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", lcAlgo.c_str());
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of an asymmetric algorithm
+AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(std::string algorithm)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(algorithm.size());
+ std::transform(algorithm.begin(), algorithm.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("rsa"))
+ {
+ return new BotanRSA();
+ }
+ else if (!lcAlgo.compare("dsa"))
+ {
+ return new BotanDSA();
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", algorithm.c_str());
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of a hash algorithm
+HashAlgorithm* BotanCryptoFactory::getHashAlgorithm(std::string algorithm)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(algorithm.size());
+ std::transform(algorithm.begin(), algorithm.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("md5"))
+ {
+ return new BotanMD5();
+ }
+ else if (!lcAlgo.compare("sha1"))
+ {
+ return new BotanSHA1();
+ }
+ else if (!lcAlgo.compare("sha224"))
+ {
+ return new BotanSHA224();
+ }
+ else if (!lcAlgo.compare("sha256"))
+ {
+ return new BotanSHA256();
+ }
+ else if (!lcAlgo.compare("sha384"))
+ {
+ return new BotanSHA384();
+ }
+ else if (!lcAlgo.compare("sha512"))
+ {
+ return new BotanSHA512();
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", algorithm.c_str());
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Get the global RNG (may be an unique RNG per thread)
+RNG* BotanCryptoFactory::getRNG(std::string name /* = "default" */)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(name.size());
+ std::transform(name.begin(), name.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("default"))
+ {
+ RNG *threadRNG = NULL;
+
+ // Lock access to the map
+ MutexLocker lock(rngsMutex);
+
+#ifdef HAVE_PTHREAD_H
+ // Get thread ID
+ pthread_t threadID = pthread_self();
+
+ // Find the RNG
+ std::map<pthread_t,RNG*>::iterator findIt;
+ findIt=rngs.find(threadID);
+ if (findIt != rngs.end())
+ {
+ return findIt->second;
+ }
+
+ threadRNG = new BotanRNG();
+ rngs[threadID] = threadRNG;
+#else
+#error "There are no thread-specific data implementations for your operating system yet"
+#endif
+ return threadRNG;
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", name.c_str());
+
+ return NULL;
+ }
+}
diff --git a/src/lib/crypto/BotanCryptoFactory.h b/src/lib/crypto/BotanCryptoFactory.h
--- /dev/null
@@ -0,0 +1,89 @@
+/* $Id: BotanCryptoFactory.h 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanCryptoFactory.h
+
+ This is a Botan based cryptographic algorithm factory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANCRYPTOFACTORY_H
+#define _SOFTHSM_V2_BOTANCRYPTOFACTORY_H
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#include "config.h"
+#include "CryptoFactory.h"
+#include "SymmetricAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "RNG.h"
+#include "MutexFactory.h"
+#include <memory>
+#include <map>
+
+class BotanCryptoFactory : public CryptoFactory
+{
+public:
+ // Return the one-and-only instance
+ static BotanCryptoFactory* i();
+
+ // Create a concrete instance of a symmetric algorithm
+ SymmetricAlgorithm* getSymmetricAlgorithm(std::string algorithm);
+
+ // Create a concrete instance of an asymmetric algorithm
+ AsymmetricAlgorithm* getAsymmetricAlgorithm(std::string algorithm);
+
+ // Create a concrete instance of a hash algorithm
+ HashAlgorithm* getHashAlgorithm(std::string algorithm);
+
+ // Get the global RNG (may be an unique RNG per thread)
+ RNG* getRNG(std::string name = "default");
+
+ // Destructor
+ ~BotanCryptoFactory();
+
+private:
+ // Constructor
+ BotanCryptoFactory();
+
+ // The one-and-only instance
+ static std::auto_ptr<BotanCryptoFactory> instance;
+
+ // Thread specific RNG
+#ifdef HAVE_PTHREAD_H
+ std::map<pthread_t, RNG*> rngs;
+#endif
+ Mutex* rngsMutex;
+};
+
+#endif // !_SOFTHSM_V2_BOTANCRYPTOFACTORY_H
+
diff --git a/src/lib/crypto/BotanDES.cpp b/src/lib/crypto/BotanDES.cpp
--- /dev/null
@@ -0,0 +1,117 @@
+/* $Id: BotanDES.cpp 4793 2010-05-24 13:00:13Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDES.cpp
+
+ Botan (3)DES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanDES.h"
+#include <algorithm>
+
+std::string BotanDES::getCipher() const
+{
+ // Check currentKey bit length; 3DES only supports 56-bit, 112-bit or 168-bit keys
+ if ((currentKey->getBitLen() != 56) &&
+ (currentKey->getBitLen() != 112) &&
+ (currentKey->getBitLen() != 168))
+ {
+ ERROR_MSG("Invalid DES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return "";
+ }
+
+ // People shouldn't really be using 56-bit DES keys, generate a warning
+ if (currentKey->getBitLen() == 56)
+ {
+ DEBUG_MSG("CAUTION: use of 56-bit DES keys is not recommended!");
+ }
+
+ // Determine the cipher mode
+ if (!currentCipherMode.compare("cbc"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return "DES/CBC/PKCS7";
+ case 112:
+ return "TripleDES/CBC/PKCS7";
+ case 168:
+ return "TripleDES/CBC/PKCS7";
+ };
+ }
+ else if (!currentCipherMode.compare("ecb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return "DES/ECB/PKCS7";
+ case 112:
+ return "TripleDES/ECB/PKCS7";
+ case 168:
+ return "TripleDES/ECB/PKCS7";
+ };
+ }
+ else if (!currentCipherMode.compare("ofb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return "DES/OFB/NoPadding";
+ case 112:
+ return "TripleDES/OFB/NoPadding";
+ case 168:
+ return "TripleDES/OFB/NoPadding";
+ };
+ }
+ else if (!currentCipherMode.compare("cfb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return "DES/CFB/NoPadding";
+ case 112:
+ return "TripleDES/CFB/NoPadding";
+ case 168:
+ return "TripleDES/CFB/NoPadding";
+ };
+ }
+
+ ERROR_MSG("Invalid DES cipher mode %s", currentCipherMode.c_str());
+
+ return "";
+}
+
+size_t BotanDES::getBlockSize() const
+{
+ // The block size is 64 bits
+ return 64 >> 3;
+}
+
diff --git a/src/lib/crypto/BotanDES.h b/src/lib/crypto/BotanDES.h
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id: BotanDES.h 4793 2010-05-24 13:00:13Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDES.h
+
+ Botan (3)DES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDES_H
+#define _SOFTHSM_V2_BOTANDES_H
+
+#include <string>
+#include "config.h"
+#include "BotanSymmetricAlgorithm.h"
+
+class BotanDES : public BotanSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~BotanDES() { }
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual std::string getCipher() const;
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDES_H
+
diff --git a/src/lib/crypto/BotanDSA.cpp b/src/lib/crypto/BotanDSA.cpp
--- /dev/null
@@ -0,0 +1,559 @@
+/* $Id: BotanDSA.cpp 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSA.cpp
+
+ Botan DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSA.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "DSAParameters.h"
+#include "BotanDSAKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/dl_group.h>
+#include <botan/dsa.h>
+#include <iostream>
+
+// Constructor
+BotanDSA::BotanDSA()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanDSA::~BotanDSA()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanDSA::signInit(PrivateKey* privateKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+ std::string emsa;
+
+ if (!lowerMechanism.compare("dsa-sha1"))
+ {
+ emsa = "EMSA1(SHA-160)";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str());
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) currentPrivateKey;
+ Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ try
+ {
+ signer->update(dataToSign.const_byte_str(), dataToSign.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::signFinal(ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+ Botan::SecureVector<Botan::byte> signResult;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->signature(*rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool BotanDSA::verifyInit(PublicKey* publicKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(BotanDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+ std::string emsa;
+
+ if (!lowerMechanism.compare("dsa-sha1"))
+ {
+ emsa = "EMSA1(SHA-160)";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str());
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ BotanDSAPublicKey* pk = (BotanDSAPublicKey*) currentPublicKey;
+ Botan::DSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ try
+ {
+ verifier->update(originalData.const_byte_str(), originalData.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::verifyFinal(const ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->check_signature(signature.const_byte_str(), signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Encryption functions
+bool BotanDSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding)
+{
+ ERROR_MSG("DSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanDSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding)
+{
+ ERROR_MSG("DSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng /* = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(DSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for DSA key generation");
+
+ return false;
+ }
+
+ DSAParameters* params = (DSAParameters*) parameters;
+
+ // Generate the key-pair
+ Botan::DSA_PrivateKey* dsa = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ dsa = new Botan::DSA_PrivateKey(*rng->getRNG(),
+ Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()),
+ BotanUtil::byteString2bigInt(params->getQ()),
+ BotanUtil::byteString2bigInt(params->getG())));
+ }
+ catch (...)
+ {
+ ERROR_MSG("DSA key generation failed");
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanDSAKeyPair* kp = new BotanDSAKeyPair();
+
+ ((BotanDSAPublicKey*) kp->getPublicKey())->setFromBotan(dsa);
+ ((BotanDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(dsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete dsa;
+
+ return true;
+}
+
+unsigned long BotanDSA::getMinKeySize()
+{
+ return 512;
+}
+
+unsigned long BotanDSA::getMaxKeySize()
+{
+ return 1024;
+}
+
+bool BotanDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* rng /* = NULL*/)
+{
+ if ((ppParams == NULL) || (parameters == NULL))
+ {
+ return false;
+ }
+
+ size_t bitLen = (size_t) parameters;
+
+ if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
+ {
+ ERROR_MSG("This DSA key size is not supported");
+
+ return false;
+ }
+
+ Botan::DL_Group* group = NULL;
+ try
+ {
+ BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Prime_Subgroup, bitLen, 160);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to generate %d bit DSA parameters", bitLen);
+
+ return false;
+ }
+
+ // Store the DSA parameters
+ DSAParameters* params = new DSAParameters();
+
+ ByteString p = BotanUtil::bigInt2ByteString(group->get_p());
+ params->setP(p);
+ ByteString q = BotanUtil::bigInt2ByteString(group->get_q());
+ params->setQ(q);
+ ByteString g = BotanUtil::bigInt2ByteString(group->get_g());
+ params->setG(g);
+
+ *ppParams = params;
+
+ delete group;
+
+ return true;
+}
+
+bool BotanDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanDSAKeyPair* kp = new BotanDSAKeyPair();
+
+ bool rv = true;
+
+ if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanDSAPublicKey* pub = new BotanDSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanDSAPrivateKey* priv = new BotanDSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanDSA::newPublicKey()
+{
+ return (PublicKey*) new BotanDSAPublicKey();
+}
+
+PrivateKey* BotanDSA::newPrivateKey()
+{
+ return (PrivateKey*) new BotanDSAPrivateKey();
+}
+
+AsymmetricParameters* BotanDSA::newParameters()
+{
+ return (AsymmetricParameters*) new DSAParameters();
+}
+
+bool BotanDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ DSAParameters* params = new DSAParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
diff --git a/src/lib/crypto/BotanDSA.h b/src/lib/crypto/BotanDSA.h
--- /dev/null
@@ -0,0 +1,86 @@
+/* $Id: BotanDSA.h 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSA.h
+
+ Botan DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSA_H
+#define _SOFTHSM_V2_BOTANDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanDSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanDSA();
+
+ // Destructor
+ virtual ~BotanDSA();
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const std::string mechanism);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const std::string mechanism);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSA_H
+
diff --git a/src/lib/crypto/BotanDSAKeyPair.cpp b/src/lib/crypto/BotanDSAKeyPair.cpp
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: BotanDSAKeyPair.cpp 4805 2010-05-28 14:53:29Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAKeyPair.cpp
+
+ Botan DSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSAKeyPair.h"
+
+// Set the public key
+void BotanDSAKeyPair::setPublicKey(BotanDSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanDSAKeyPair::setPrivateKey(BotanDSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanDSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanDSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanDSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanDSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/src/lib/crypto/BotanDSAKeyPair.h b/src/lib/crypto/BotanDSAKeyPair.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: BotanDSAKeyPair.h 4805 2010-05-28 14:53:29Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAKeyPair.h
+
+ Botan DSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSAKEYPAIR_H
+#define _SOFTHSM_V2_BOTANDSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanDSAPublicKey.h"
+#include "BotanDSAPrivateKey.h"
+
+class BotanDSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanDSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanDSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanDSAPublicKey pubKey;
+
+ // The private key
+ BotanDSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSAKEYPAIR_H
+
diff --git a/src/lib/crypto/BotanDSAPrivateKey.cpp b/src/lib/crypto/BotanDSAPrivateKey.cpp
--- /dev/null
@@ -0,0 +1,185 @@
+/* $Id: BotanDSAPrivateKey.cpp 6787 2012-10-26 13:35:25Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPrivateKey.cpp
+
+ Botan DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSAPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanDSAPrivateKey::BotanDSAPrivateKey()
+{
+ dsa = NULL;
+}
+
+BotanDSAPrivateKey::BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA)
+{
+ BotanDSAPrivateKey();
+
+ setFromBotan(inDSA);
+}
+
+// Destructor
+BotanDSAPrivateKey::~BotanDSAPrivateKey()
+{
+ delete dsa;
+}
+
+// The type
+/*static*/ const char* BotanDSAPrivateKey::type = "Botan DSA Private Key";
+
+// Set from Botan representation
+void BotanDSAPrivateKey::setFromBotan(const Botan::DSA_PrivateKey* dsa)
+{
+ ByteString p = BotanUtil::bigInt2ByteString(dsa->group_p());
+ setP(p);
+ ByteString q = BotanUtil::bigInt2ByteString(dsa->group_q());
+ setQ(q);
+ ByteString g = BotanUtil::bigInt2ByteString(dsa->group_g());
+ setG(g);
+ ByteString x = BotanUtil::bigInt2ByteString(dsa->get_x());
+ setX(x);
+ ByteString y = BotanUtil::bigInt2ByteString(dsa->get_y());
+ setY(y);
+}
+
+// Check if the key is of the given type
+bool BotanDSAPrivateKey::isOfType(const char* type)
+{
+ return !strcmp(BotanDSAPrivateKey::type, type);
+}
+
+// Setters for the DSA private key components
+void BotanDSAPrivateKey::setX(const ByteString& x)
+{
+ DSAPrivateKey::setX(x);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+
+// Setters for the DSA public key components
+void BotanDSAPrivateKey::setP(const ByteString& p)
+{
+ DSAPrivateKey::setP(p);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPrivateKey::setQ(const ByteString& q)
+{
+ DSAPrivateKey::setQ(q);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPrivateKey::setG(const ByteString& g)
+{
+ DSAPrivateKey::setG(g);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPrivateKey::setY(const ByteString& y)
+{
+ DSAPrivateKey::setY(y);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::DSA_PrivateKey* BotanDSAPrivateKey::getBotanKey()
+{
+ if (!dsa)
+ {
+ createBotanKey();
+ }
+
+ return dsa;
+}
+
+// Create the Botan representation of the key
+void BotanDSAPrivateKey::createBotanKey()
+{
+ // y is not needed
+ // Todo: Either q or x is needed. Both is not needed
+ if (this->p.size() != 0 &&
+ this->q.size() != 0 &&
+ this->g.size() != 0 &&
+ this->x.size() != 0)
+ {
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ dsa = new Botan::DSA_PrivateKey(*rng->getRNG(),
+ Botan::DL_Group(BotanUtil::byteString2bigInt(this->p),
+ BotanUtil::byteString2bigInt(this->q),
+ BotanUtil::byteString2bigInt(this->g)),
+ BotanUtil::byteString2bigInt(this->x));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/src/lib/crypto/BotanDSAPrivateKey.h b/src/lib/crypto/BotanDSAPrivateKey.h
--- /dev/null
@@ -0,0 +1,83 @@
+/* $Id: BotanDSAPrivateKey.h 4805 2010-05-28 14:53:29Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPrivateKey.h
+
+ Botan DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSAPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANDSAPRIVATEKEY_H
+
+#include "config.h"
+#include "DSAPrivateKey.h"
+#include <botan/dsa.h>
+
+class BotanDSAPrivateKey : public DSAPrivateKey
+{
+public:
+ // Constructors
+ BotanDSAPrivateKey();
+
+ BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA);
+
+ // Destructor
+ virtual ~BotanDSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the DSA private key components
+ virtual void setX(const ByteString& x);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setG(const ByteString& g);
+ virtual void setY(const ByteString& y);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::DSA_PrivateKey* dsa);
+
+ // Retrieve the Botan representation of the key
+ Botan::DSA_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::DSA_PrivateKey* dsa;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSAPRIVATEKEY_H
+
diff --git a/src/lib/crypto/BotanDSAPublicKey.cpp b/src/lib/crypto/BotanDSAPublicKey.cpp
--- /dev/null
@@ -0,0 +1,164 @@
+/* $Id: BotanDSAPublicKey.cpp 6787 2012-10-26 13:35:25Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPublicKey.cpp
+
+ Botan DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSAPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanDSAPublicKey::BotanDSAPublicKey()
+{
+ dsa = NULL;
+}
+
+BotanDSAPublicKey::BotanDSAPublicKey(const Botan::DSA_PublicKey* inDSA)
+{
+ BotanDSAPublicKey();
+
+ setFromBotan(inDSA);
+}
+
+// Destructor
+BotanDSAPublicKey::~BotanDSAPublicKey()
+{
+ delete dsa;
+}
+
+// The type
+/*static*/ const char* BotanDSAPublicKey::type = "Botan DSA Public Key";
+
+// Set from Botan representation
+void BotanDSAPublicKey::setFromBotan(const Botan::DSA_PublicKey* dsa)
+{
+ ByteString p = BotanUtil::bigInt2ByteString(dsa->group_p());
+ setP(p);
+ ByteString q = BotanUtil::bigInt2ByteString(dsa->group_q());
+ setQ(q);
+ ByteString g = BotanUtil::bigInt2ByteString(dsa->group_g());
+ setG(g);
+ ByteString y = BotanUtil::bigInt2ByteString(dsa->get_y());
+ setY(y);
+}
+
+// Check if the key is of the given type
+bool BotanDSAPublicKey::isOfType(const char* type)
+{
+ return !strcmp(BotanDSAPublicKey::type, type);
+}
+
+// Setters for the DSA public key components
+void BotanDSAPublicKey::setP(const ByteString& p)
+{
+ DSAPublicKey::setP(p);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPublicKey::setQ(const ByteString& q)
+{
+ DSAPublicKey::setQ(q);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPublicKey::setG(const ByteString& g)
+{
+ DSAPublicKey::setG(g);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPublicKey::setY(const ByteString& y)
+{
+ DSAPublicKey::setY(y);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::DSA_PublicKey* BotanDSAPublicKey::getBotanKey()
+{
+ if (!dsa)
+ {
+ createBotanKey();
+ }
+
+ return dsa;
+}
+
+// Create the Botan representation of the key
+void BotanDSAPublicKey::createBotanKey()
+{
+ // We actually do not need to check q, since it can be set zero
+ if (this->p.size() != 0 &&
+ this->g.size() != 0 &&
+ this->y.size() != 0)
+ {
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+
+ try
+ {
+ dsa = new Botan::DSA_PublicKey(Botan::DL_Group(BotanUtil::byteString2bigInt(this->p),
+ BotanUtil::byteString2bigInt(this->q),
+ BotanUtil::byteString2bigInt(this->g)),
+ BotanUtil::byteString2bigInt(this->y));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/src/lib/crypto/BotanDSAPublicKey.h b/src/lib/crypto/BotanDSAPublicKey.h
--- /dev/null
@@ -0,0 +1,80 @@
+/* $Id: BotanDSAPublicKey.h 4805 2010-05-28 14:53:29Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPublicKey.h
+
+ Botan DSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSAPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANDSAPUBLICKEY_H
+
+#include "config.h"
+#include "DSAPublicKey.h"
+#include <botan/dsa.h>
+
+class BotanDSAPublicKey : public DSAPublicKey
+{
+public:
+ // Constructors
+ BotanDSAPublicKey();
+
+ BotanDSAPublicKey(const Botan::DSA_PublicKey* inDSA);
+
+ // Destructor
+ virtual ~BotanDSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setG(const ByteString& g);
+ virtual void setY(const ByteString& y);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::DSA_PublicKey* dsa);
+
+ // Retrieve the Botan representation of the key
+ Botan::DSA_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::DSA_PublicKey* dsa;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSAPUBLICKEY_H
+
diff --git a/src/lib/crypto/BotanHashAlgorithm.cpp b/src/lib/crypto/BotanHashAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,132 @@
+/* $Id: BotanHashAlgorithm.cpp 5045 2011-05-04 13:29:52Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanHashAlgorithm.cpp
+
+ Base class for Botan hash algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/filters.h>
+
+// Base constructor
+BotanHashAlgorithm::BotanHashAlgorithm()
+{
+ hash = NULL;
+}
+
+// Destructor
+BotanHashAlgorithm::~BotanHashAlgorithm()
+{
+ delete hash;
+}
+
+// Hashing functions
+bool BotanHashAlgorithm::hashInit()
+{
+ if (!HashAlgorithm::hashInit())
+ {
+ return false;
+ }
+
+ // Initialize digesting
+ try
+ {
+ if (hash == NULL)
+ {
+ hash = getHash();
+ }
+ else
+ {
+ hash->clear();
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to initialize the digesting token");
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanHashAlgorithm::hashUpdate(const ByteString& data)
+{
+ if (!HashAlgorithm::hashUpdate(data))
+ {
+ return false;
+ }
+
+ // Continue digesting
+ try
+ {
+ hash->update(data.const_byte_str(), data.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to buffer data");
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanHashAlgorithm::hashFinal(ByteString& hashedData)
+{
+ if (!HashAlgorithm::hashFinal(hashedData))
+ {
+ return false;
+ }
+
+ // Resize
+ hashedData.resize(hash->output_length());
+
+ // Read the digest
+ try
+ {
+ hash->final(&hashedData[0]);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to digest the data");
+
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/lib/crypto/BotanHashAlgorithm.h b/src/lib/crypto/BotanHashAlgorithm.h
--- /dev/null
@@ -0,0 +1,66 @@
+/* $Id: BotanHashAlgorithm.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanHashAlgorithm.h
+
+ Base class for Botan hash algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANHASHALGORITHM_H
+#define _SOFTHSM_V2_BOTANHASHALGORITHM_H
+
+#include "config.h"
+#include "HashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanHashAlgorithm : public HashAlgorithm
+{
+public:
+ // Base constructor
+ BotanHashAlgorithm();
+
+ // Destructor
+ virtual ~BotanHashAlgorithm();
+
+ // Hashing functions
+ virtual bool hashInit();
+ virtual bool hashUpdate(const ByteString& data);
+ virtual bool hashFinal(ByteString& hashedData);
+
+ virtual int getHashSize() = 0;
+protected:
+ virtual Botan::HashFunction* getHash() const = 0;
+
+private:
+ // Current hashing context
+ Botan::HashFunction *hash;
+};
+
+#endif // !_SOFTHSM_V2_BOTANHASHALGORITHM_H
+
diff --git a/src/lib/crypto/BotanMD5.cpp b/src/lib/crypto/BotanMD5.cpp
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: BotanMD5.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMD5.cpp
+
+ Botan MD5 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanMD5.h"
+#include <botan/md5.h>
+
+int BotanMD5::getHashSize()
+{
+ return 16;
+}
+
+Botan::HashFunction* BotanMD5::getHash() const
+{
+ return new Botan::MD5();
+}
diff --git a/src/lib/crypto/BotanMD5.h b/src/lib/crypto/BotanMD5.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: BotanMD5.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMD5.h
+
+ Botan MD5 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANMD5_H
+#define _SOFTHSM_V2_BOTANMD5_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanMD5 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANMD5_H
+
diff --git a/src/lib/crypto/BotanRNG.cpp b/src/lib/crypto/BotanRNG.cpp
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: BotanRNG.cpp 4800 2010-05-27 12:58:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BOTANRNG.cpp
+
+ Botan random number generator class
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanRNG.h"
+
+#include <botan/libstate.h>
+
+// Base constructor
+BotanRNG::BotanRNG()
+{
+ rng = &Botan::global_state().global_rng();
+}
+
+// Destructor
+BotanRNG::~BotanRNG()
+{
+}
+
+// Generate random data
+bool BotanRNG::generateRandom(ByteString& data, const size_t len)
+{
+ data.wipe(len);
+
+ rng->randomize(&data[0], len);
+
+ return true;
+}
+
+// Seed the random pool
+void BotanRNG::seed(ByteString& seedData)
+{
+ rng->add_entropy(seedData.byte_str(), seedData.size());
+ rng->reseed(seedData.size());
+}
+
+// Get the RNG
+Botan::RandomNumberGenerator* BotanRNG::getRNG()
+{
+ return rng;
+}
diff --git a/src/lib/crypto/BotanRNG.h b/src/lib/crypto/BotanRNG.h
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id: BotanRNG.h 4800 2010-05-27 12:58:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRNG.h
+
+ Botan random number generator class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRNG_H
+#define _SOFTHSM_V2_BOTANRNG_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "RNG.h"
+
+#include "botan/rng.h"
+
+class BotanRNG : public RNG
+{
+public:
+ // Base constructor
+ BotanRNG();
+
+ // Destructor
+ virtual ~BotanRNG();
+
+ // Generate random data
+ virtual bool generateRandom(ByteString& data, const size_t len);
+
+ // Seed the random pool
+ virtual void seed(ByteString& seedData);
+
+ // Get RNG
+ Botan::RandomNumberGenerator* getRNG();
+
+private:
+ // The RNG
+ Botan::RandomNumberGenerator* rng;
+};
+
+#endif // !_SOFTHSM_V2_BOTANRNG_H
+
diff --git a/src/lib/crypto/BotanRSA.cpp b/src/lib/crypto/BotanRSA.cpp
--- /dev/null
@@ -0,0 +1,860 @@
+/* $Id: BotanRSA.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSA.cpp
+
+ Botan RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSA.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "RSAParameters.h"
+#include "BotanRSAKeyPair.h"
+#include <algorithm>
+#include <botan/rsa.h>
+
+// Constructor
+BotanRSA::BotanRSA()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanRSA::~BotanRSA()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const
+std::string mechanism)
+{
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+ std::string emsa = "";
+
+ if (!lowerMechanism.compare("rsa-pkcs"))
+ {
+ emsa = "EMSA3(Raw)";
+ }
+ else if (!lowerMechanism.compare("rsa-raw"))
+ {
+ emsa = "Raw";
+ }
+ else
+ {
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism);
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey;
+ Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ try
+ {
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ Botan::SecureVector<Botan::byte> signResult;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+bool BotanRSA::signInit(PrivateKey* privateKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+ std::string emsa;
+
+ if (!lowerMechanism.compare("rsa-md5-pkcs"))
+ {
+ emsa = "EMSA3(MD5)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha1-pkcs"))
+ {
+ emsa = "EMSA3(SHA-160)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha256-pkcs"))
+ {
+ emsa = "EMSA3(SHA-256)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha384-pkcs"))
+ {
+ emsa = "EMSA3(SHA-384)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha512-pkcs"))
+ {
+ emsa = "EMSA3(SHA-512)";
+ }
+ else if (!lowerMechanism.compare("rsa-ssl"))
+ {
+ emsa = "EMSA3(Parallel(MD5,SHA-160))";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str());
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) currentPrivateKey;
+ Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ try
+ {
+ signer->update(dataToSign.const_byte_str(), dataToSign.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::signFinal(ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+ Botan::SecureVector<Botan::byte> signResult;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->signature(*rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool BotanRSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism)
+{
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+ std::string emsa = "";
+
+ if (!lowerMechanism.compare("rsa-pkcs"))
+ {
+ emsa = "EMSA3(Raw)";
+ }
+ else if (!lowerMechanism.compare("rsa-raw"))
+ {
+ emsa = "Raw";
+ }
+ else
+ {
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism);
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey;
+ Botan::RSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->verify_message(originalData.const_byte_str(),
+ originalData.size(),
+ signature.const_byte_str(),
+ signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+bool BotanRSA::verifyInit(PublicKey* publicKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+ std::string emsa;
+
+ if (!lowerMechanism.compare("rsa-md5-pkcs"))
+ {
+ emsa = "EMSA3(MD5)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha1-pkcs"))
+ {
+ emsa = "EMSA3(SHA-160)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha256-pkcs"))
+ {
+ emsa = "EMSA3(SHA-256)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha384-pkcs"))
+ {
+ emsa = "EMSA3(SHA-384)";
+ }
+ else if (!lowerMechanism.compare("rsa-sha512-pkcs"))
+ {
+ emsa = "EMSA3(SHA-512)";
+ }
+ else if (!lowerMechanism.compare("rsa-ssl"))
+ {
+ emsa = "EMSA3(Parallel(MD5,SHA-160))";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str());
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ BotanRSAPublicKey* pk = (BotanRSAPublicKey*) currentPublicKey;
+ Botan::RSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ try
+ {
+ verifier->update(originalData.const_byte_str(), originalData.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::verifyFinal(const ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->check_signature(signature.const_byte_str(), signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Encryption functions
+bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding)
+{
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ std::string lowerPadding;
+ lowerPadding.resize(padding.size());
+ std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower);
+ std::string eme;
+
+ if (!lowerPadding.compare("rsa-pkcs"))
+ {
+ eme = "PKCS1v15";
+ }
+ else if (!lowerPadding.compare("rsa-pkcs-oaep"))
+ {
+ eme = "EME1(SHA-160)";
+ }
+ else if (!lowerPadding.compare("rsa-raw"))
+ {
+ eme = "Raw";
+ }
+ else
+ {
+ ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str());
+
+ return false;
+ }
+
+ BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey;
+ Botan::RSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ Botan::PK_Encryptor_EME* encryptor = NULL;
+ try
+ {
+ encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the encryptor token");
+
+ return false;
+ }
+
+ // Perform the encryption operation
+ Botan::SecureVector<Botan::byte> encResult;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not encrypt the data");
+
+ delete encryptor;
+
+ return false;
+ }
+
+ // Return the result
+ encryptedData.resize(encResult.size());
+ memcpy(&encryptedData[0], encResult.begin(), encResult.size());
+
+ delete encryptor;
+
+ return true;
+}
+
+// Decryption functions
+bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding)
+{
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ std::string lowerPadding;
+ lowerPadding.resize(padding.size());
+ std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower);
+ std::string eme;
+
+ if (!lowerPadding.compare("rsa-pkcs"))
+ {
+ eme = "PKCS1v15";
+ }
+ else if (!lowerPadding.compare("rsa-pkcs-oaep"))
+ {
+ eme = "EME1(SHA-160)";
+ }
+ else if (!lowerPadding.compare("rsa-raw"))
+ {
+ eme = "Raw";
+ }
+ else
+ {
+ ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str());
+
+ return false;
+ }
+
+ BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey;
+ Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ Botan::PK_Decryptor_EME* decryptor = NULL;
+ try
+ {
+ decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the decryptor token");
+
+ return false;
+ }
+
+ // Perform the decryption operation
+ Botan::SecureVector<Botan::byte> decResult;
+ try
+ {
+ decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not decrypt the data");
+
+ delete decryptor;
+
+ return false;
+ }
+
+ // Return the result
+ if (!eme.compare("Raw"))
+ {
+ // We compensate that Botan removes leading zeros
+ int modSize = pk->getN().size();
+ int decSize = decResult.size();
+ data.resize(modSize);
+ memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize);
+ }
+ else
+ {
+ data.resize(decResult.size());
+ memcpy(&data[0], decResult.begin(), decResult.size());
+ }
+
+ delete decryptor;
+
+ return true;
+}
+
+// Key factory
+bool BotanRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng /* = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(RSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for RSA key generation");
+
+ return false;
+ }
+
+ RSAParameters* params = (RSAParameters*) parameters;
+
+ if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize())
+ {
+ ERROR_MSG("This RSA key size is not supported");
+
+ return false;
+ }
+
+ if (params->getBitLength() < 1024)
+ {
+ WARNING_MSG("Using an RSA key size < 1024 bits is not recommended");
+ }
+
+ // Retrieve the desired public exponent
+ unsigned long e = params->getE().long_val();
+
+ // Check the public exponent
+ if ((e == 0) || (e % 2 != 1))
+ {
+ ERROR_MSG("Invalid RSA public exponent %d", e);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanRSAKeyPair* kp = new BotanRSAKeyPair();
+
+ // Generate the key-pair
+ Botan::RSA_PrivateKey* rsa = NULL;
+ try {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ rsa = new Botan::RSA_PrivateKey(*rng->getRNG(), params->getBitLength(), e);
+ }
+ catch(...) {
+ ERROR_MSG("RSA key generation failed");
+
+ delete kp;
+
+ return false;
+ }
+
+ ((BotanRSAPublicKey*) kp->getPublicKey())->setFromBotan(rsa);
+ ((BotanRSAPrivateKey*) kp->getPrivateKey())->setFromBotan(rsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete rsa;
+
+ return true;
+}
+
+unsigned long BotanRSA::getMinKeySize()
+{
+ return 512;
+}
+
+unsigned long BotanRSA::getMaxKeySize()
+{
+ return 4096;
+}
+
+bool BotanRSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanRSAKeyPair* kp = new BotanRSAKeyPair();
+
+ bool rv = true;
+
+ if (!((RSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((RSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanRSAPublicKey* pub = new BotanRSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanRSAPrivateKey* priv = new BotanRSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanRSA::newPublicKey()
+{
+ return (PublicKey*) new BotanRSAPublicKey();
+}
+
+PrivateKey* BotanRSA::newPrivateKey()
+{
+ return (PrivateKey*) new BotanRSAPrivateKey();
+}
+
+AsymmetricParameters* BotanRSA::newParameters()
+{
+ return (AsymmetricParameters*) new RSAParameters();
+}
+
diff --git a/src/lib/crypto/BotanRSA.h b/src/lib/crypto/BotanRSA.h
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id: BotanRSA.h 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSA.h
+
+ Botan RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSA_H
+#define _SOFTHSM_V2_BOTANRSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanRSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanRSA();
+
+ // Destructor
+ virtual ~BotanRSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism);
+ virtual bool signInit(PrivateKey* privateKey, const std::string mechanism);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism);
+ virtual bool verifyInit(PublicKey* publicKey, const std::string mechanism);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+};
+
+#endif // !_SOFTHSM_V2_BOTANRSA_H
+
diff --git a/src/lib/crypto/BotanRSAKeyPair.cpp b/src/lib/crypto/BotanRSAKeyPair.cpp
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: BotanRSAKeyPair.cpp 4800 2010-05-27 12:58:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAKeyPair.cpp
+
+ Botan RSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSAKeyPair.h"
+
+// Set the public key
+void BotanRSAKeyPair::setPublicKey(BotanRSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanRSAKeyPair::setPrivateKey(BotanRSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanRSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanRSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanRSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanRSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/src/lib/crypto/BotanRSAKeyPair.h b/src/lib/crypto/BotanRSAKeyPair.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: BotanRSAKeyPair.h 4800 2010-05-27 12:58:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAKeyPair.h
+
+ Botan RSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSAKEYPAIR_H
+#define _SOFTHSM_V2_BOTANRSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanRSAPublicKey.h"
+#include "BotanRSAPrivateKey.h"
+
+class BotanRSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanRSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanRSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanRSAPublicKey pubKey;
+
+ // The private key
+ BotanRSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANRSAKEYPAIR_H
+
diff --git a/src/lib/crypto/BotanRSAPrivateKey.cpp b/src/lib/crypto/BotanRSAPrivateKey.cpp
--- /dev/null
@@ -0,0 +1,223 @@
+/* $Id: BotanRSAPrivateKey.cpp 6787 2012-10-26 13:35:25Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPrivateKey.cpp
+
+ Botan RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSAPrivateKey.h"
+#include "BotanUtil.h"
+#include "BotanRNG.h"
+#include "BotanCryptoFactory.h"
+#include <string.h>
+
+// Constructors
+BotanRSAPrivateKey::BotanRSAPrivateKey()
+{
+ rsa = NULL;
+}
+
+BotanRSAPrivateKey::BotanRSAPrivateKey(const Botan::RSA_PrivateKey* inRSA)
+{
+ BotanRSAPrivateKey();
+
+ setFromBotan(inRSA);
+}
+
+// Destructor
+BotanRSAPrivateKey::~BotanRSAPrivateKey()
+{
+ delete rsa;
+}
+
+// The type
+/*static*/ const char* BotanRSAPrivateKey::type = "Botan RSA Private Key";
+
+// Set from Botan representation
+void BotanRSAPrivateKey::setFromBotan(const Botan::RSA_PrivateKey* rsa)
+{
+ ByteString p = BotanUtil::bigInt2ByteString(rsa->get_p());
+ setP(p);
+ ByteString q = BotanUtil::bigInt2ByteString(rsa->get_q());
+ setQ(q);
+ ByteString dp1 = BotanUtil::bigInt2ByteString(rsa->get_d1());
+ setDP1(dp1);
+ ByteString dq1 = BotanUtil::bigInt2ByteString(rsa->get_d2());
+ setDQ1(dq1);
+ ByteString pq = BotanUtil::bigInt2ByteString(rsa->get_c());
+ setPQ(pq);
+ ByteString d = BotanUtil::bigInt2ByteString(rsa->get_d());
+ setD(d);
+ ByteString n = BotanUtil::bigInt2ByteString(rsa->get_n());
+ setN(n);
+ ByteString e = BotanUtil::bigInt2ByteString(rsa->get_e());
+ setE(e);
+}
+
+// Check if the key is of the given type
+bool BotanRSAPrivateKey::isOfType(const char* type)
+{
+ return !strcmp(BotanRSAPrivateKey::type, type);
+}
+
+// Setters for the RSA private key components
+void BotanRSAPrivateKey::setP(const ByteString& p)
+{
+ RSAPrivateKey::setP(p);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setQ(const ByteString& q)
+{
+ RSAPrivateKey::setQ(q);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setPQ(const ByteString& pq)
+{
+ RSAPrivateKey::setPQ(pq);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setDP1(const ByteString& dp1)
+{
+ RSAPrivateKey::setDP1(dp1);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setDQ1(const ByteString& dq1)
+{
+ RSAPrivateKey::setDQ1(dq1);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setD(const ByteString& d)
+{
+ RSAPrivateKey::setD(d);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+
+// Setters for the RSA public key components
+void BotanRSAPrivateKey::setN(const ByteString& n)
+{
+ RSAPrivateKey::setN(n);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setE(const ByteString& e)
+{
+ RSAPrivateKey::setE(e);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::RSA_PrivateKey* BotanRSAPrivateKey::getBotanKey()
+{
+ if (!rsa)
+ {
+ createBotanKey();
+ }
+
+ return rsa;
+}
+
+// Create the Botan representation of the key
+void BotanRSAPrivateKey::createBotanKey()
+{
+ // d and n is not needed, they can be calculated
+ if (this->p.size() != 0 &&
+ this->q.size() != 0 &&
+ this->e.size() != 0)
+ {
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ rsa = new Botan::RSA_PrivateKey(*rng->getRNG(),
+ BotanUtil::byteString2bigInt(this->p),
+ BotanUtil::byteString2bigInt(this->q),
+ BotanUtil::byteString2bigInt(this->e),
+ BotanUtil::byteString2bigInt(this->d),
+ BotanUtil::byteString2bigInt(this->n));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan private key");
+ }
+ }
+}
diff --git a/src/lib/crypto/BotanRSAPrivateKey.h b/src/lib/crypto/BotanRSAPrivateKey.h
--- /dev/null
@@ -0,0 +1,84 @@
+/* $Id: BotanRSAPrivateKey.h 4800 2010-05-27 12:58:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPrivateKey.h
+
+ Botan RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSAPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANRSAPRIVATEKEY_H
+
+#include "config.h"
+#include "RSAPrivateKey.h"
+#include <botan/rsa.h>
+
+class BotanRSAPrivateKey : public RSAPrivateKey
+{
+public:
+ // Constructors
+ BotanRSAPrivateKey();
+
+ BotanRSAPrivateKey(const Botan::RSA_PrivateKey* inRSA);
+
+ // Destructor
+ virtual ~BotanRSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the RSA private key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setPQ(const ByteString& pq);
+ virtual void setDP1(const ByteString& dp1);
+ virtual void setDQ1(const ByteString& dq1);
+ virtual void setD(const ByteString& d);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& n);
+ virtual void setE(const ByteString& e);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::RSA_PrivateKey* rsa);
+
+ // Retrieve the Botan representation of the key
+ Botan::RSA_PrivateKey* getBotanKey();
+private:
+ // The internal Botan representation
+ Botan::RSA_PrivateKey* rsa;
+
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+
diff --git a/src/lib/crypto/BotanRSAPublicKey.cpp b/src/lib/crypto/BotanRSAPublicKey.cpp
--- /dev/null
@@ -0,0 +1,133 @@
+/* $Id: BotanRSAPublicKey.cpp 6787 2012-10-26 13:35:25Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPublicKey.cpp
+
+ Botan RSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSAPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanRSAPublicKey::BotanRSAPublicKey()
+{
+ rsa = NULL;
+}
+
+BotanRSAPublicKey::BotanRSAPublicKey(const Botan::RSA_PublicKey* inRSA)
+{
+ BotanRSAPublicKey();
+
+ setFromBotan(inRSA);
+}
+
+// Destructor
+BotanRSAPublicKey::~BotanRSAPublicKey()
+{
+ delete rsa;
+}
+
+// The type
+/*static*/ const char* BotanRSAPublicKey::type = "Botan RSA Public Key";
+
+// Check if the key is of the given type
+bool BotanRSAPublicKey::isOfType(const char* type)
+{
+ return !strcmp(BotanRSAPublicKey::type, type);
+}
+
+// Set from OpenSSL representation
+void BotanRSAPublicKey::setFromBotan(const Botan::RSA_PublicKey* rsa)
+{
+ ByteString n = BotanUtil::bigInt2ByteString(rsa->get_n());
+ setN(n);
+ ByteString e = BotanUtil::bigInt2ByteString(rsa->get_e());
+ setE(e);
+}
+
+// Setters for the RSA public key components
+void BotanRSAPublicKey::setN(const ByteString& n)
+{
+ RSAPublicKey::setN(n);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPublicKey::setE(const ByteString& e)
+{
+ RSAPublicKey::setE(e);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::RSA_PublicKey* BotanRSAPublicKey::getBotanKey()
+{
+ if (!rsa)
+ {
+ createBotanKey();
+ }
+
+ return rsa;
+}
+
+// Create the Botan representation of the key
+void BotanRSAPublicKey::createBotanKey()
+{
+ if (this->n.size() != 0 && this->e.size() != 0)
+ {
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+
+ try
+ {
+ rsa = new Botan::RSA_PublicKey(BotanUtil::byteString2bigInt(this->n),
+ BotanUtil::byteString2bigInt(this->e));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/src/lib/crypto/BotanRSAPublicKey.h b/src/lib/crypto/BotanRSAPublicKey.h
--- /dev/null
@@ -0,0 +1,77 @@
+/* $Id: BotanRSAPublicKey.h 4800 2010-05-27 12:58:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPublicKey.h
+
+ Botan RSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSAPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANRSAPUBLICKEY_H
+
+#include "config.h"
+#include "RSAPublicKey.h"
+#include <botan/rsa.h>
+
+class BotanRSAPublicKey : public RSAPublicKey
+{
+public:
+ // Constructors
+ BotanRSAPublicKey();
+
+ BotanRSAPublicKey(const Botan::RSA_PublicKey* inRSA);
+
+ // Destructor
+ virtual ~BotanRSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& n);
+ virtual void setE(const ByteString& e);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::RSA_PublicKey* rsa);
+
+ // Retrieve the Botan representation of the key
+ Botan::RSA_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::RSA_PublicKey* rsa;
+
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANRSAPUBLICKEY_H
+
diff --git a/src/lib/crypto/BotanSHA1.cpp b/src/lib/crypto/BotanSHA1.cpp
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: BotanSHA1.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA1.cpp
+
+ Botan SHA1 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA1.h"
+#include <botan/sha160.h>
+
+int BotanSHA1::getHashSize()
+{
+ return 20;
+}
+
+Botan::HashFunction* BotanSHA1::getHash() const
+{
+ return new Botan::SHA_160();
+}
diff --git a/src/lib/crypto/BotanSHA1.h b/src/lib/crypto/BotanSHA1.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: BotanSHA1.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA1.h
+
+ Botan SHA1 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA1_H
+#define _SOFTHSM_V2_BOTANSHA1_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA1 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA1_H
+
diff --git a/src/lib/crypto/BotanSHA224.cpp b/src/lib/crypto/BotanSHA224.cpp
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: BotanSHA224.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA224.cpp
+
+ Botan SHA224 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA224.h"
+#include <botan/sha2_32.h>
+
+int BotanSHA224::getHashSize()
+{
+ return 28;
+}
+
+Botan::HashFunction* BotanSHA224::getHash() const
+{
+ return new Botan::SHA_224();
+}
diff --git a/src/lib/crypto/BotanSHA224.h b/src/lib/crypto/BotanSHA224.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: BotanSHA224.h 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA224.h
+
+ Botan SHA224 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA224_H
+#define _SOFTHSM_V2_BOTANSHA224_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA224 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA224_H
+
diff --git a/src/lib/crypto/BotanSHA256.cpp b/src/lib/crypto/BotanSHA256.cpp
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: BotanSHA256.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA256.cpp
+
+ Botan SHA256 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA256.h"
+#include <botan/sha2_32.h>
+
+int BotanSHA256::getHashSize()
+{
+ return 32;
+}
+
+Botan::HashFunction* BotanSHA256::getHash() const
+{
+ return new Botan::SHA_256();
+}
diff --git a/src/lib/crypto/BotanSHA256.h b/src/lib/crypto/BotanSHA256.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: BotanSHA256.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA256.h
+
+ Botan SHA256 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA256_H
+#define _SOFTHSM_V2_BOTANSHA256_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA256 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA256_H
+
diff --git a/src/lib/crypto/BotanSHA384.cpp b/src/lib/crypto/BotanSHA384.cpp
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: BotanSHA384.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA384.cpp
+
+ Botan SHA384 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA384.h"
+#include <botan/sha2_64.h>
+
+int BotanSHA384::getHashSize()
+{
+ return 48;
+}
+
+Botan::HashFunction* BotanSHA384::getHash() const
+{
+ return new Botan::SHA_384();
+}
diff --git a/src/lib/crypto/BotanSHA384.h b/src/lib/crypto/BotanSHA384.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: BotanSHA384.h 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA384.h
+
+ Botan SHA384 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA384_H
+#define _SOFTHSM_V2_BOTANSHA384_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA384 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA384_H
+
diff --git a/src/lib/crypto/BotanSHA512.cpp b/src/lib/crypto/BotanSHA512.cpp
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: BotanSHA512.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA512.cpp
+
+ Botan SHA512 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA512.h"
+#include <botan/sha2_64.h>
+
+int BotanSHA512::getHashSize()
+{
+ return 64;
+}
+
+Botan::HashFunction* BotanSHA512::getHash() const
+{
+ return new Botan::SHA_512();
+}
diff --git a/src/lib/crypto/BotanSHA512.h b/src/lib/crypto/BotanSHA512.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: BotanSHA512.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA512.h
+
+ Botan SHA512 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA512_H
+#define _SOFTHSM_V2_BOTANSHA512_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA512 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA512_H
+
diff --git a/src/lib/crypto/BotanSymmetricAlgorithm.cpp b/src/lib/crypto/BotanSymmetricAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,395 @@
+/* $Id: BotanSymmetricAlgorithm.cpp 5075 2011-05-10 14:36:32Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store context in securely allocated memory
+
+/*****************************************************************************
+ BotanSymmetricAlgorithm.cpp
+
+ Botan symmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSymmetricAlgorithm.h"
+#include "salloc.h"
+#include <iostream>
+
+#include <botan/symkey.h>
+#include <botan/botan.h>
+
+// Constructor
+BotanSymmetricAlgorithm::BotanSymmetricAlgorithm()
+{
+ cryption = NULL;
+}
+
+// Destructor
+BotanSymmetricAlgorithm::~BotanSymmetricAlgorithm()
+{
+ delete cryption;
+ cryption = NULL;
+}
+
+// Encryption functions
+bool BotanSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const std::string mode /* = "cbc" */, const ByteString& IV /* = ByteString()*/)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::encryptInit(key, mode, IV))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if ((IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Determine the cipher
+ std::string cipherName = getCipher();
+
+ if (cipherName == "")
+ {
+ ERROR_MSG("Invalid encryption cipher");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the context
+ try
+ {
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+ Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
+ if (mode == "ecb")
+ {
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::ENCRYPTION));
+ }
+ else
+ {
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::ENCRYPTION));
+ }
+ cryption->start_msg();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to create the encryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Write data
+ try
+ {
+ cryption->write(data.const_byte_str(), data.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to write to the encryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ int outLen = cryption->remaining();
+ encryptedData.resize(outLen);
+ bytesRead = cryption->read(&encryptedData[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to encrypt the data");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ encryptedData.resize(bytesRead);
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::encryptFinal(ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptFinal(encryptedData))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ cryption->end_msg();
+ int outLen = cryption->remaining();
+ encryptedData.resize(outLen);
+ bytesRead = cryption->read(&encryptedData[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to encrypt the data");
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Clean up
+ delete cryption;
+ cryption = NULL;
+
+ // Resize the output block
+ encryptedData.resize(bytesRead);
+
+ return true;
+}
+
+// Decryption functions
+bool BotanSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const std::string mode /* = "cbc" */, const ByteString& IV /* = ByteString() */)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::decryptInit(key, mode, IV))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if ((IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Determine the cipher class
+ std::string cipherName = getCipher();
+
+ if (cipherName == "")
+ {
+ ERROR_MSG("Invalid decryption cipher");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the context
+ try
+ {
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+ Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
+ if (mode == "ecb")
+ {
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::DECRYPTION));
+ }
+ else
+ {
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::DECRYPTION));
+ }
+ cryption->start_msg();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to create the decryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data)
+{
+ if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Write data
+ try
+ {
+ cryption->write(encryptedData.const_byte_str(), encryptedData.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to write to the decryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ int outLen = cryption->remaining();
+ data.resize(outLen);
+ bytesRead = cryption->read(&data[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to decrypt the data");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ data.resize(bytesRead);
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::decryptFinal(ByteString& data)
+{
+ if (!SymmetricAlgorithm::decryptFinal(data))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ cryption->end_msg();
+ int outLen = cryption->remaining();
+ data.resize(outLen);
+ bytesRead = cryption->read(&data[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to decrypt the data");
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Clean up
+ delete cryption;
+ cryption = NULL;
+
+ // Resize the output block
+ data.resize(bytesRead);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/BotanSymmetricAlgorithm.h b/src/lib/crypto/BotanSymmetricAlgorithm.h
--- /dev/null
@@ -0,0 +1,77 @@
+/* $Id: BotanSymmetricAlgorithm.h 4791 2010-05-23 21:32:48Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSymmetricAlgorithm.h
+
+ Botan symmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "SymmetricAlgorithm.h"
+
+#include <botan/pipe.h>
+
+class BotanSymmetricAlgorithm : public SymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanSymmetricAlgorithm();
+
+ // Destructor
+ virtual ~BotanSymmetricAlgorithm();
+
+ // Encryption functions
+ virtual bool encryptInit(const SymmetricKey* key, const std::string mode = "cbc", const ByteString& IV = ByteString());
+ virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData);
+ virtual bool encryptFinal(ByteString& encryptedData);
+
+ // Decryption functions
+ virtual bool decryptInit(const SymmetricKey* key, const std::string mode = "cbc", const ByteString& IV = ByteString());
+ virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data);
+ virtual bool decryptFinal(ByteString& data);
+
+protected:
+ // Return the right cipher for the operation
+ virtual std::string getCipher() const = 0;
+
+ // Return the block size
+ virtual size_t getBlockSize() const = 0;
+
+private:
+ // The current context
+ Botan::Pipe* cryption;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H
+
diff --git a/src/lib/crypto/BotanUtil.cpp b/src/lib/crypto/BotanUtil.cpp
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Id: BotanUtil.cpp 4799 2010-05-25 08:49:45Z rb $ */
+
+/*
+ * Copyright (c) .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanUtil.h
+
+ Botan convenience functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanUtil.h"
+
+// Convert a Botan BigInt to a ByteString
+ByteString BotanUtil::bigInt2ByteString(const Botan::BigInt& bigInt)
+{
+ ByteString rv;
+
+ rv.resize(bigInt.bytes());
+ bigInt.binary_encode(&rv[0]);
+
+ return rv;
+}
+
+// Convert a ByteString to an Botan BigInt
+Botan::BigInt BotanUtil::byteString2bigInt(const ByteString& byteString)
+{
+ return Botan::BigInt(byteString.const_byte_str(), byteString.size());
+}
+
diff --git a/src/lib/crypto/BotanUtil.h b/src/lib/crypto/BotanUtil.h
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: BotanUtil.h 4799 2010-05-25 08:49:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanUtil.h
+
+ Botan convenience functions
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANUTIL_H
+#define _SOFTHSM_V2_BOTANUTIL_H
+
+#include "config.h"
+#include "ByteString.h"
+#include <botan/bigint.h>
+
+namespace BotanUtil
+{
+ // Convert a Botan BigInt to a ByteString
+ ByteString bigInt2ByteString(const Botan::BigInt& bigInt);
+
+ // Convert a ByteString to a Botan BigInt
+ Botan::BigInt byteString2bigInt(const ByteString& byteString);
+}
+
+#endif // !_SOFTHSM_V2_BOTANUTIL_H
+
diff --git a/src/lib/crypto/CryptoFactory.cpp b/src/lib/crypto/CryptoFactory.cpp
--- /dev/null
@@ -0,0 +1,85 @@
+/* $Id: CryptoFactory.cpp 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ CryptoFactory.cpp
+
+ This class is a factory for all cryptographic algorithm implementations. It
+ is an abstract base class for a factory that produces cryptographic library
+ specific implementations of cryptographic algorithms.
+ *****************************************************************************/
+
+#include "config.h"
+#include "CryptoFactory.h"
+
+#if defined(WITH_OPENSSL)
+
+#include "OSSLCryptoFactory.h"
+
+// Return the one-and-only instance
+CryptoFactory* CryptoFactory::i()
+{
+ return OSSLCryptoFactory::i();
+}
+
+#elif defined(WITH_BOTAN)
+
+#include "BotanCryptoFactory.h"
+
+// Return the one-and-only instance
+CryptoFactory* CryptoFactory::i()
+{
+ return BotanCryptoFactory::i();
+}
+
+#else
+
+#error "You must configure a cryptographic library to use"
+
+#endif
+
+// Recycle a symmetric algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleSymmetricAlgorithm(SymmetricAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
+
+// Recycle an asymmetric algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleAsymmetricAlgorithm(AsymmetricAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
+
+// Recycle a hash algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleHashAlgorithm(HashAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
diff --git a/src/lib/crypto/CryptoFactory.h b/src/lib/crypto/CryptoFactory.h
--- /dev/null
@@ -0,0 +1,83 @@
+/* $Id: CryptoFactory.h 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ CryptoFactory.h
+
+ This class is a factory for all cryptographic algorithm implementations. It
+ is an abstract base class for a factory that produces cryptographic library
+ specific implementations of cryptographic algorithms.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_CRYPTOFACTORY_H
+#define _SOFTHSM_V2_CRYPTOFACTORY_H
+
+#include "config.h"
+#include "SymmetricAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "RNG.h"
+
+class CryptoFactory
+{
+public:
+ // Return the one-and-only instance
+ static CryptoFactory* i();
+
+ // Create a concrete instance of a symmetric algorithm
+ virtual SymmetricAlgorithm* getSymmetricAlgorithm(std::string algorithm) = 0;
+
+ // Recycle a symmetric algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleSymmetricAlgorithm(SymmetricAlgorithm* toRecycle);
+
+ // Create a concrete instance of an asymmetric algorithm
+ virtual AsymmetricAlgorithm* getAsymmetricAlgorithm(std::string algorithm) = 0;
+
+ // Recycle an asymmetric algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleAsymmetricAlgorithm(AsymmetricAlgorithm* toRecycle);
+
+ // Create a concrete instance of a hash algorithm
+ virtual HashAlgorithm* getHashAlgorithm(std::string algorithm) = 0;
+
+ // Recycle a hash algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleHashAlgorithm(HashAlgorithm* toRecycle);
+
+ // Get the global RNG (may be an unique RNG per thread)
+ virtual RNG* getRNG(std::string name = "default") = 0;
+
+ // Destructor
+ virtual ~CryptoFactory() { }
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_CRYPTOFACTORY_H
+
diff --git a/src/lib/crypto/DESKey.cpp b/src/lib/crypto/DESKey.cpp
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: DESKey.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESKey.cpp
+
+ DES key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "DESKey.h"
+
+// Set the key
+bool DESKey::setKeyBits(const ByteString& keybits)
+{
+ if (bitLen > 0)
+ {
+ // Check if the correct input data is supplied
+ size_t expectedLen = 0;
+
+ switch(bitLen)
+ {
+ case 56:
+ expectedLen = 8;
+ break;
+ case 112:
+ expectedLen = 16;
+ break;
+ case 168:
+ expectedLen = 24;
+ break;
+ };
+
+ // Check the length
+ if (keybits.size() != expectedLen)
+ {
+ return false;
+ }
+ }
+
+ keyData = keybits;
+
+ return true;
+}
+
diff --git a/src/lib/crypto/DESKey.h b/src/lib/crypto/DESKey.h
--- /dev/null
+++ b/src/lib/crypto/DESKey.h
@@ -0,0 +1,54 @@
+/* $Id: DESKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESKey.h
+
+ Base class for symmetric key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DESKEY_H
+#define _SOFTHSM_V2_DESKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "SymmetricKey.h"
+
+class DESKey : public SymmetricKey
+{
+public:
+ // Base constructor
+ DESKey(size_t bitLen = 0) : SymmetricKey(bitLen) { }
+
+ // Set the key
+ virtual bool setKeyBits(const ByteString& keybits);
+};
+
+#endif // !_SOFTHSM_V2_DESKEY_H
+
diff --git a/src/lib/crypto/DSAParameters.cpp b/src/lib/crypto/DSAParameters.cpp
--- /dev/null
@@ -0,0 +1,110 @@
+/* $Id: DSAParameters.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAParameters.cpp
+
+ DSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DSAParameters.h"
+#include <string.h>
+
+// The type
+/*static*/ const char* DSAParameters::type = "Generic DSA parameters";
+
+// Set the public prime p
+void DSAParameters::setP(const ByteString& p)
+{
+ this->p = p;
+}
+
+// Set the public subprime q
+void DSAParameters::setQ(const ByteString& q)
+{
+ this->q = q;
+}
+
+// Set the generator g
+void DSAParameters::setG(const ByteString& g)
+{
+ this->g = g;
+}
+
+// Get the public prime p
+const ByteString& DSAParameters::getP() const
+{
+ return p;
+}
+
+// Get the public subprime q
+const ByteString& DSAParameters::getQ() const
+{
+ return q;
+}
+
+// Get the generator g
+const ByteString& DSAParameters::getG() const
+{
+ return g;
+}
+
+// Are the parameters of the given type?
+bool DSAParameters::areOfType(const char* type)
+{
+ return (strcmp(type, DSAParameters::type) == 0);
+}
+
+// Serialisation
+ByteString DSAParameters::serialise() const
+{
+ return p.serialise() + q.serialise() + g.serialise();
+}
+
+bool DSAParameters::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dQ.size() == 0) ||
+ (dG.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setG(dG);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/DSAParameters.h b/src/lib/crypto/DSAParameters.h
--- /dev/null
@@ -0,0 +1,80 @@
+/* $Id: DSAParameters.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAParameters.h
+
+ DSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSAPARAMETERS_H
+#define _SOFTHSM_V2_DSAPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "AsymmetricParameters.h"
+
+class DSAParameters : public AsymmetricParameters
+{
+public:
+ // The type
+ static const char* type;
+
+ // Set the public prime p
+ void setP(const ByteString& p);
+
+ // Set the public subprime q
+ void setQ(const ByteString& q);
+
+ // Set the generator g
+ void setG(const ByteString& g);
+
+ // Get the public prime p
+ const ByteString& getP() const;
+
+ // Get the public subprime q
+ const ByteString& getQ() const;
+
+ // Get the generator g
+ const ByteString& getG() const;
+
+ // Are the parameters of the given type?
+ virtual bool areOfType(const char* type);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+private:
+ ByteString p;
+ ByteString q;
+ ByteString g;
+};
+
+#endif // !_SOFTHSM_V2_DSAPARAMETERS_H
+
diff --git a/src/lib/crypto/DSAPrivateKey.cpp b/src/lib/crypto/DSAPrivateKey.cpp
--- /dev/null
@@ -0,0 +1,150 @@
+/* $Id: DSAPrivateKey.cpp 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPrivateKey.cpp
+
+ DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DSAPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* DSAPrivateKey::type = "Abstract DSA private key";
+
+// Check if the key is of the given type
+bool DSAPrivateKey::isOfType(const char* type)
+{
+ return !strcmp(this->type, type);
+}
+
+// Get the bit length
+unsigned long DSAPrivateKey::getBitLength() const
+{
+ return getP().bits();
+}
+
+// Get the output length
+unsigned long DSAPrivateKey::getOutputLength() const
+{
+ return getQ().size() * 2;
+}
+
+// Setters for the DSA private key components
+void DSAPrivateKey::setX(const ByteString& x)
+{
+ this->x = x;
+}
+
+// Setters for the DSA public key components
+void DSAPrivateKey::setP(const ByteString& p)
+{
+ this->p = p;
+}
+
+void DSAPrivateKey::setQ(const ByteString& q)
+{
+ this->q = q;
+}
+
+void DSAPrivateKey::setG(const ByteString& g)
+{
+ this->g = g;
+}
+
+void DSAPrivateKey::setY(const ByteString& y)
+{
+ this->y = y;
+}
+
+// Getters for the DSA private key components
+const ByteString& DSAPrivateKey::getX() const
+{
+ return x;
+}
+
+// Getters for the DSA public key components
+const ByteString& DSAPrivateKey::getP() const
+{
+ return p;
+}
+
+const ByteString& DSAPrivateKey::getQ() const
+{
+ return q;
+}
+
+const ByteString& DSAPrivateKey::getG() const
+{
+ return g;
+}
+
+const ByteString& DSAPrivateKey::getY() const
+{
+ return y;
+}
+
+// Serialisation
+ByteString DSAPrivateKey::serialise() const
+{
+ return p.serialise() +
+ q.serialise() +
+ g.serialise() +
+ x.serialise() +
+ y.serialise();
+}
+
+bool DSAPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dX = ByteString::chainDeserialise(serialised);
+ ByteString dY = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dQ.size() == 0) ||
+ (dG.size() == 0) ||
+ (dX.size() == 0) ||
+ (dY.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setG(dG);
+ setX(dX);
+ setY(dY);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/DSAPrivateKey.h b/src/lib/crypto/DSAPrivateKey.h
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id: DSAPrivateKey.h 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPrivateKey.h
+
+ DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSAPRIVATEKEY_H
+#define _SOFTHSM_V2_DSAPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class DSAPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the DSA private key components
+ virtual void setX(const ByteString& x);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setG(const ByteString& g);
+ virtual void setY(const ByteString& y);
+
+ // Getters for the DSA private key components
+ virtual const ByteString& getX() const;
+
+ // Getters for the DSA public key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getG() const;
+ virtual const ByteString& getY() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString x;
+
+ // Public components
+ ByteString p,q,g,y;
+};
+
+#endif // !_SOFTHSM_V2_DSAPRIVATEKEY_H
+
diff --git a/src/lib/crypto/DSAPublicKey.cpp b/src/lib/crypto/DSAPublicKey.cpp
--- /dev/null
@@ -0,0 +1,134 @@
+/* $Id: DSAPublicKey.cpp 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPublicKey.cpp
+
+ DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DSAPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* DSAPublicKey::type = "Abstract DSA public key";
+
+// Check if the key is of the given type
+bool DSAPublicKey::isOfType(const char* type)
+{
+ return !strcmp(this->type, type);
+}
+
+// Get the bit length
+unsigned long DSAPublicKey::getBitLength() const
+{
+ return getP().bits();
+}
+
+// Get the output length
+unsigned long DSAPublicKey::getOutputLength() const
+{
+ return getQ().size() * 2;
+}
+
+// Setters for the DSA public key components
+void DSAPublicKey::setP(const ByteString& p)
+{
+ this->p = p;
+}
+
+void DSAPublicKey::setQ(const ByteString& q)
+{
+ this->q = q;
+}
+
+void DSAPublicKey::setG(const ByteString& g)
+{
+ this->g = g;
+}
+
+void DSAPublicKey::setY(const ByteString& y)
+{
+ this->y = y;
+}
+
+// Getters for the DSA public key components
+const ByteString& DSAPublicKey::getP() const
+{
+ return p;
+}
+
+const ByteString& DSAPublicKey::getQ() const
+{
+ return q;
+}
+
+const ByteString& DSAPublicKey::getG() const
+{
+ return g;
+}
+
+const ByteString& DSAPublicKey::getY() const
+{
+ return y;
+}
+
+// Serialisation
+ByteString DSAPublicKey::serialise() const
+{
+ return p.serialise() +
+ q.serialise() +
+ g.serialise() +
+ y.serialise();
+}
+
+bool DSAPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dY = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dQ.size() == 0) ||
+ (dG.size() == 0) ||
+ (dY.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setG(dG);
+ setY(dY);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/DSAPublicKey.h b/src/lib/crypto/DSAPublicKey.h
--- /dev/null
@@ -0,0 +1,78 @@
+/* $Id: DSAPublicKey.h 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPublicKey.h
+
+ DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSAPUBLICKEY_H
+#define _SOFTHSM_V2_DSAPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class DSAPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setG(const ByteString& g);
+ virtual void setY(const ByteString& y);
+
+ // Getters for the DSA public key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getG() const;
+ virtual const ByteString& getY() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString p,q,g,y;
+};
+
+#endif // !_SOFTHSM_V2_DSAPUBLICKEY_H
+
diff --git a/src/lib/crypto/HashAlgorithm.cpp b/src/lib/crypto/HashAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,78 @@
+/* $Id: HashAlgorithm.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashAlgorithm.cpp
+
+ Base class for hash algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "HashAlgorithm.h"
+
+// Base constructor
+HashAlgorithm::HashAlgorithm()
+{
+ currentOperation = NONE;
+}
+
+// Hashing functions
+bool HashAlgorithm::hashInit()
+{
+ if (currentOperation != NONE)
+ {
+ return false;
+ }
+
+ currentOperation = HASHING;
+
+ return true;
+}
+
+bool HashAlgorithm::hashUpdate(const ByteString& data)
+{
+ if (currentOperation != HASHING)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool HashAlgorithm::hashFinal(ByteString& hashedData)
+{
+ if (currentOperation != HASHING)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+
+ return true;
+}
+
diff --git a/src/lib/crypto/HashAlgorithm.h b/src/lib/crypto/HashAlgorithm.h
--- /dev/null
@@ -0,0 +1,67 @@
+/* $Id: HashAlgorithm.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashAlgorithm.h
+
+ Base class for hash algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HASHALGORITHM_H
+#define _SOFTHSM_V2_HASHALGORITHM_H
+
+#include "config.h"
+#include "ByteString.h"
+
+class HashAlgorithm
+{
+public:
+ // Base constructors
+ HashAlgorithm();
+
+ // Destructor
+ virtual ~HashAlgorithm() { }
+
+ // Hashing functions
+ virtual bool hashInit();
+ virtual bool hashUpdate(const ByteString& data);
+ virtual bool hashFinal(ByteString& hashedData);
+
+ virtual int getHashSize() = 0;
+protected:
+ // The current operation
+ enum
+ {
+ NONE,
+ HASHING
+ }
+ currentOperation;
+};
+
+#endif // !_SOFTHSM_V2_HASHALGORITHM_H
+
diff --git a/src/lib/crypto/Makefile.am b/src/lib/crypto/Makefile.am
--- /dev/null
@@ -0,0 +1,79 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../common \
+ -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/.. \
+ @CRYPTO_INCLUDES@
+
+noinst_LTLIBRARIES = libsofthsm_crypto.la
+libsofthsm_crypto_la_SOURCES = AsymmetricAlgorithm.cpp \
+ AsymmetricKeyPair.cpp \
+ CryptoFactory.cpp \
+ DESKey.cpp \
+ DSAParameters.cpp \
+ DSAPublicKey.cpp \
+ DSAPrivateKey.cpp \
+ HashAlgorithm.cpp \
+ RSAParameters.cpp \
+ RSAPrivateKey.cpp \
+ RSAPublicKey.cpp \
+ SymmetricAlgorithm.cpp \
+ SymmetricKey.cpp
+libsofthsm_crypto_la_LIBADD = @CRYPTO_LIBS@
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h $(srcdir)/*.cpp
+
+# Compile with support of OpenSSL
+if WITH_OPENSSL
+libsofthsm_crypto_la_SOURCES += OSSLAES.cpp \
+ OSSLCryptoFactory.cpp \
+ OSSLDES.cpp \
+ OSSLDSA.cpp \
+ OSSLDSAKeyPair.cpp \
+ OSSLDSAPrivateKey.cpp \
+ OSSLDSAPublicKey.cpp \
+ OSSLEVPHashAlgorithm.cpp \
+ OSSLEVPSymmetricAlgorithm.cpp \
+ OSSLMD5.cpp \
+ OSSLRNG.cpp \
+ OSSLRSA.cpp \
+ OSSLRSAKeyPair.cpp \
+ OSSLRSAPrivateKey.cpp \
+ OSSLRSAPublicKey.cpp \
+ OSSLSHA1.cpp \
+ OSSLSHA224.cpp \
+ OSSLSHA256.cpp \
+ OSSLSHA384.cpp \
+ OSSLSHA512.cpp \
+ OSSLUtil.cpp
+endif
+
+# Compile with support of Botan
+if WITH_BOTAN
+libsofthsm_crypto_la_SOURCES += BotanAES.cpp \
+ BotanCryptoFactory.cpp \
+ BotanDES.cpp \
+ BotanDSA.cpp \
+ BotanDSAKeyPair.cpp \
+ BotanDSAPrivateKey.cpp \
+ BotanDSAPublicKey.cpp \
+ BotanHashAlgorithm.cpp \
+ BotanMD5.cpp \
+ BotanRNG.cpp \
+ BotanRSA.cpp \
+ BotanRSAKeyPair.cpp \
+ BotanRSAPrivateKey.cpp \
+ BotanRSAPublicKey.cpp \
+ BotanSHA1.cpp \
+ BotanSHA224.cpp \
+ BotanSHA256.cpp \
+ BotanSHA384.cpp \
+ BotanSHA512.cpp \
+ BotanSymmetricAlgorithm.cpp \
+ BotanUtil.cpp
+endif
diff --git a/src/lib/crypto/OSSLAES.cpp b/src/lib/crypto/OSSLAES.cpp
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id: OSSLAES.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLAES.cpp
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLAES.h"
+#include <algorithm>
+
+const EVP_CIPHER* OSSLAES::getCipher() const
+{
+ // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys
+ if ((currentKey->getBitLen() != 128) &&
+ (currentKey->getBitLen() != 192) &&
+ (currentKey->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return NULL;
+ }
+
+ // Determine the cipher mode
+ if (!currentCipherMode.compare("cbc"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_cbc();
+ case 192:
+ return EVP_aes_192_cbc();
+ case 256:
+ return EVP_aes_256_cbc();
+ };
+ }
+ else if (!currentCipherMode.compare("ecb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_ecb();
+ case 192:
+ return EVP_aes_192_ecb();
+ case 256:
+ return EVP_aes_256_ecb();
+ };
+ }
+
+ ERROR_MSG("Invalid AES cipher mode %s", currentCipherMode.c_str());
+
+ return NULL;
+}
+
+size_t OSSLAES::getBlockSize() const
+{
+ // The block size is 128 bits
+ return 128 >> 3;
+}
+
diff --git a/src/lib/crypto/OSSLAES.h b/src/lib/crypto/OSSLAES.h
--- /dev/null
+++ b/src/lib/crypto/OSSLAES.h
@@ -0,0 +1,58 @@
+/* $Id: OSSLAES.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLAES.h
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLAES_H
+#define _SOFTHSM_V2_OSSLAES_H
+
+#include <openssl/evp.h>
+#include <string>
+#include "config.h"
+#include "OSSLEVPSymmetricAlgorithm.h"
+
+class OSSLAES : public OSSLEVPSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLAES() { }
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual const EVP_CIPHER* getCipher() const;
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLAES_H
+
diff --git a/src/lib/crypto/OSSLCryptoFactory.cpp b/src/lib/crypto/OSSLCryptoFactory.cpp
--- /dev/null
@@ -0,0 +1,200 @@
+/* $Id: OSSLCryptoFactory.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLCryptoFactory.cpp
+
+ This is an OpenSSL based cryptographic algorithm factory
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLCryptoFactory.h"
+#include "OSSLRNG.h"
+#include "OSSLAES.h"
+#include "OSSLDES.h"
+#include "OSSLMD5.h"
+#include "OSSLSHA1.h"
+#include "OSSLSHA224.h"
+#include "OSSLSHA256.h"
+#include "OSSLSHA384.h"
+#include "OSSLSHA512.h"
+#include "OSSLRSA.h"
+#include "OSSLDSA.h"
+
+#include <algorithm>
+#include <string.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+// Initialise the one-and-only instance
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+
+// Constructor
+OSSLCryptoFactory::OSSLCryptoFactory()
+{
+ // Initialise OpenSSL
+ OpenSSL_add_all_algorithms();
+
+ // Initialise the one-and-only RNG
+ rng = new OSSLRNG();
+}
+
+// Destructor
+OSSLCryptoFactory::~OSSLCryptoFactory()
+{
+ // Destroy the one-and-only RNG
+ delete rng;
+
+ // Clean up OpenSSL
+ ERR_remove_state(0);
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+// Return the one-and-only instance
+OSSLCryptoFactory* OSSLCryptoFactory::i()
+{
+ if (!instance.get())
+ {
+ instance = std::auto_ptr<OSSLCryptoFactory>(new OSSLCryptoFactory());
+ }
+
+ return instance.get();
+}
+
+// Create a concrete instance of a symmetric algorithm
+SymmetricAlgorithm* OSSLCryptoFactory::getSymmetricAlgorithm(std::string algorithm)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(algorithm.size());
+ std::transform(algorithm.begin(), algorithm.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("aes"))
+ {
+ return new OSSLAES();
+ }
+ else if (!lcAlgo.compare("des") || !lcAlgo.compare("3des"))
+ {
+ return new OSSLDES();
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", lcAlgo.c_str());
+
+ return NULL;
+ }
+}
+
+// Create a concrete instance of an asymmetric algorithm
+AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(std::string algorithm)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(algorithm.size());
+ std::transform(algorithm.begin(), algorithm.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("rsa"))
+ {
+ return new OSSLRSA();
+ }
+ else if (!lcAlgo.compare("dsa"))
+ {
+ return new OSSLDSA();
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", algorithm.c_str());
+
+ return NULL;
+ }
+}
+
+// Create a concrete instance of a hash algorithm
+HashAlgorithm* OSSLCryptoFactory::getHashAlgorithm(std::string algorithm)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(algorithm.size());
+ std::transform(algorithm.begin(), algorithm.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("md5"))
+ {
+ return new OSSLMD5();
+ }
+ else if (!lcAlgo.compare("sha1"))
+ {
+ return new OSSLSHA1();
+ }
+ else if (!lcAlgo.compare("sha224"))
+ {
+ return new OSSLSHA224();
+ }
+ else if (!lcAlgo.compare("sha256"))
+ {
+ return new OSSLSHA256();
+ }
+ else if (!lcAlgo.compare("sha384"))
+ {
+ return new OSSLSHA384();
+ }
+ else if (!lcAlgo.compare("sha512"))
+ {
+ return new OSSLSHA512();
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", algorithm.c_str());
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Get the global RNG (may be an unique RNG per thread)
+RNG* OSSLCryptoFactory::getRNG(std::string name /* = "default" */)
+{
+ std::string lcAlgo;
+ lcAlgo.resize(name.size());
+ std::transform(name.begin(), name.end(), lcAlgo.begin(), tolower);
+
+ if (!lcAlgo.compare("default"))
+ {
+ return rng;
+ }
+ else
+ {
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%s'", name.c_str());
+
+ return NULL;
+ }
+}
+
diff --git a/src/lib/crypto/OSSLCryptoFactory.h b/src/lib/crypto/OSSLCryptoFactory.h
--- /dev/null
@@ -0,0 +1,79 @@
+/* $Id: OSSLCryptoFactory.h 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLCryptoFactory.h
+
+ This is an OpenSSL based cryptographic algorithm factory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLCRYPTOFACTORY_H
+#define _SOFTHSM_V2_OSSLCRYPTOFACTORY_H
+
+#include "config.h"
+#include "CryptoFactory.h"
+#include "SymmetricAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "RNG.h"
+#include <memory>
+
+class OSSLCryptoFactory : public CryptoFactory
+{
+public:
+ // Return the one-and-only instance
+ static OSSLCryptoFactory* i();
+
+ // Create a concrete instance of a symmetric algorithm
+ virtual SymmetricAlgorithm* getSymmetricAlgorithm(std::string algorithm);
+
+ // Create a concrete instance of an asymmetric algorithm
+ virtual AsymmetricAlgorithm* getAsymmetricAlgorithm(std::string algorithm);
+
+ // Create a concrete instance of a hash algorithm
+ virtual HashAlgorithm* getHashAlgorithm(std::string algorithm);
+
+ // Get the global RNG (may be an unique RNG per thread)
+ virtual RNG* getRNG(std::string name = "default");
+
+ // Destructor
+ virtual ~OSSLCryptoFactory();
+
+private:
+ // Constructor
+ OSSLCryptoFactory();
+
+ // The one-and-only instance
+ static std::auto_ptr<OSSLCryptoFactory> instance;
+
+ // The one-and-only RNG instance
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_OSSLCRYPTOFACTORY_H
+
diff --git a/src/lib/crypto/OSSLDES.cpp b/src/lib/crypto/OSSLDES.cpp
--- /dev/null
@@ -0,0 +1,117 @@
+/* $Id: OSSLDES.cpp 4779 2010-05-13 13:34:10Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDES.cpp
+
+ OpenSSL (3)DES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLDES.h"
+#include <algorithm>
+
+const EVP_CIPHER* OSSLDES::getCipher() const
+{
+ // Check currentKey bit length; 3DES only supports 56-bit, 112-bit or 168-bit keys
+ if ((currentKey->getBitLen() != 56) &&
+ (currentKey->getBitLen() != 112) &&
+ (currentKey->getBitLen() != 168))
+ {
+ ERROR_MSG("Invalid DES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return NULL;
+ }
+
+ // People shouldn't really be using 56-bit DES keys, generate a warning
+ if (currentKey->getBitLen() == 56)
+ {
+ DEBUG_MSG("CAUTION: use of 56-bit DES keys is not recommended!");
+ }
+
+ // Determine the cipher mode
+ if (!currentCipherMode.compare("cbc"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_cbc();
+ case 112:
+ return EVP_des_ede_cbc();
+ case 168:
+ return EVP_des_ede3_cbc();
+ };
+ }
+ else if (!currentCipherMode.compare("ecb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_ecb();
+ case 112:
+ return EVP_des_ede_ecb();
+ case 168:
+ return EVP_des_ede3_ecb();
+ };
+ }
+ else if (!currentCipherMode.compare("ofb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_ofb();
+ case 112:
+ return EVP_des_ede_ofb();
+ case 168:
+ return EVP_des_ede3_ofb();
+ };
+ }
+ else if (!currentCipherMode.compare("cfb"))
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_cfb();
+ case 112:
+ return EVP_des_ede_cfb();
+ case 168:
+ return EVP_des_ede3_cfb();
+ };
+ }
+
+ ERROR_MSG("Invalid DES cipher mode %s", currentCipherMode.c_str());
+
+ return NULL;
+}
+
+size_t OSSLDES::getBlockSize() const
+{
+ // The block size is 64 bits
+ return 64 >> 3;
+}
+
diff --git a/src/lib/crypto/OSSLDES.h b/src/lib/crypto/OSSLDES.h
--- /dev/null
+++ b/src/lib/crypto/OSSLDES.h
@@ -0,0 +1,58 @@
+/* $Id: OSSLDES.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDES.h
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDES_H
+#define _SOFTHSM_V2_OSSLDES_H
+
+#include <openssl/evp.h>
+#include <string>
+#include "config.h"
+#include "OSSLEVPSymmetricAlgorithm.h"
+
+class OSSLDES : public OSSLEVPSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLDES() { }
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual const EVP_CIPHER* getCipher() const;
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDES_H
+
diff --git a/src/lib/crypto/OSSLDSA.cpp b/src/lib/crypto/OSSLDSA.cpp
--- /dev/null
@@ -0,0 +1,510 @@
+/* $Id: OSSLDSA.cpp 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSA.cpp
+
+ OpenSSL DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSA.h"
+#include "CryptoFactory.h"
+#include "DSAParameters.h"
+#include "OSSLDSAKeyPair.h"
+#include "OSSLUtil.h"
+#include <algorithm>
+#include <openssl/dsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+// Constructor
+OSSLDSA::OSSLDSA()
+{
+ pCurrentHash = NULL;
+}
+
+// Destructor
+OSSLDSA::~OSSLDSA()
+{
+ if (pCurrentHash != NULL)
+ {
+ delete pCurrentHash;
+ }
+}
+
+// Signing functions
+bool OSSLDSA::signInit(PrivateKey* privateKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!lowerMechanism.compare("dsa-sha1"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha1");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+
+ if (pCurrentHash == NULL)
+ {
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(dataToSign))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::signFinal(ByteString& signature)
+{
+ // Save necessary state before calling super class signFinal
+ OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) currentPrivateKey;
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(currentMechanism.size());
+ std::transform(currentMechanism.begin(), currentMechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString hash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(hash);
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (!bFirstResult)
+ {
+ return false;
+ }
+
+ DSA* dsa = pk->getOSSLKey();
+
+ // Resize the data block for the signature to the modulus size of the key
+ signature.resize(DSA_size(dsa));
+
+ // Perform the signature operation
+ unsigned int sigLen = signature.size();
+
+ bool rv = (DSA_sign(0, &hash[0], hash.size(), &signature[0], &sigLen, dsa) == 1);
+
+ signature.resize(sigLen);
+
+ return rv;
+}
+
+// Verification functions
+bool OSSLDSA::verifyInit(PublicKey* publicKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(OSSLDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!lowerMechanism.compare("dsa-sha1"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha1");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+
+ if (pCurrentHash == NULL)
+ {
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(originalData))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::verifyFinal(const ByteString& signature)
+{
+ // Save necessary state before calling super class verifyFinal
+ OSSLDSAPublicKey* pk = (OSSLDSAPublicKey*) currentPublicKey;
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(currentMechanism.size());
+ std::transform(currentMechanism.begin(), currentMechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString hash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(hash);
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (!bFirstResult)
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ bool rv = (DSA_verify(0, &hash[0], hash.size(), (unsigned char*) signature.const_byte_str(), signature.size(), pk->getOSSLKey()) == 1);
+
+ if (!rv) ERROR_MSG("DSA verify failed (0x%08X)", ERR_get_error());
+
+ return rv;
+}
+
+// Encryption functions
+bool OSSLDSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding)
+{
+ ERROR_MSG("DSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLDSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding)
+{
+ ERROR_MSG("DSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng /* = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(DSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for DSA key generation");
+
+ return false;
+ }
+
+ DSAParameters* params = (DSAParameters*) parameters;
+
+ // Generate the key-pair
+ DSA* dsa = DSA_new();
+
+ if (dsa == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL DSA object");
+
+ return false;
+ }
+
+ dsa->p = OSSL::byteString2bn(params->getP());
+ dsa->q = OSSL::byteString2bn(params->getQ());
+ dsa->g = OSSL::byteString2bn(params->getG());
+
+ if (DSA_generate_key(dsa) != 1)
+ {
+ ERROR_MSG("DSA key generation failed (0x%08X)", ERR_get_error());
+
+ DSA_free(dsa);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ OSSLDSAKeyPair* kp = new OSSLDSAKeyPair();
+
+ ((OSSLDSAPublicKey*) kp->getPublicKey())->setFromOSSL(dsa);
+ ((OSSLDSAPrivateKey*) kp->getPrivateKey())->setFromOSSL(dsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ DSA_free(dsa);
+
+ return true;
+}
+
+unsigned long OSSLDSA::getMinKeySize()
+{
+ return 512;
+}
+
+unsigned long OSSLDSA::getMaxKeySize()
+{
+ return OPENSSL_DSA_MAX_MODULUS_BITS;
+}
+
+bool OSSLDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* rng /* = NULL*/)
+{
+ if ((ppParams == NULL) || (parameters == NULL))
+ {
+ return false;
+ }
+
+ size_t bitLen = (size_t) parameters;
+
+ if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
+ {
+ ERROR_MSG("This DSA key size is not supported");
+
+ return false;
+ }
+
+ DSA* dsa = DSA_generate_parameters(bitLen, NULL, 0, NULL, NULL, NULL, NULL);
+
+ if (dsa == NULL)
+ {
+ ERROR_MSG("Failed to generate %d bit DSA parameters", bitLen);
+
+ return false;
+ }
+
+ // Store the DSA parameters
+ DSAParameters* params = new DSAParameters();
+
+ ByteString p = OSSL::bn2ByteString(dsa->p); params->setP(p);
+ ByteString q = OSSL::bn2ByteString(dsa->q); params->setQ(q);
+ ByteString g = OSSL::bn2ByteString(dsa->g); params->setG(g);
+
+ *ppParams = params;
+
+ DSA_free(dsa);
+
+ return true;
+}
+
+bool OSSLDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLDSAKeyPair* kp = new OSSLDSAKeyPair();
+
+ bool rv = true;
+
+ if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLDSAPublicKey* pub = new OSSLDSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLDSAPrivateKey* priv = new OSSLDSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLDSA::newPublicKey()
+{
+ return (PublicKey*) new OSSLDSAPublicKey();
+}
+
+PrivateKey* OSSLDSA::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLDSAPrivateKey();
+}
+
+AsymmetricParameters* OSSLDSA::newParameters()
+{
+ return (AsymmetricParameters*) new DSAParameters();
+}
+
+bool OSSLDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ DSAParameters* params = new DSAParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
diff --git a/src/lib/crypto/OSSLDSA.h b/src/lib/crypto/OSSLDSA.h
--- /dev/null
+++ b/src/lib/crypto/OSSLDSA.h
@@ -0,0 +1,86 @@
+/* $Id: OSSLDSA.h 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSA.h
+
+ OpenSSL DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSA_H
+#define _SOFTHSM_V2_OSSLDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include <openssl/dsa.h>
+
+class OSSLDSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLDSA();
+
+ // Destructor
+ virtual ~OSSLDSA();
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const std::string mechanism);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const std::string mechanism);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ HashAlgorithm* pCurrentHash;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSA_H
+
diff --git a/src/lib/crypto/OSSLDSAKeyPair.cpp b/src/lib/crypto/OSSLDSAKeyPair.cpp
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: OSSLDSAKeyPair.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAKeyPair.cpp
+
+ OpenSSL DSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSAKeyPair.h"
+
+// Set the public key
+void OSSLDSAKeyPair::setPublicKey(OSSLDSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLDSAKeyPair::setPrivateKey(OSSLDSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLDSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLDSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLDSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLDSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/src/lib/crypto/OSSLDSAKeyPair.h b/src/lib/crypto/OSSLDSAKeyPair.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: OSSLDSAKeyPair.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAKeyPair.h
+
+ OpenSSL DSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSAKEYPAIR_H
+#define _SOFTHSM_V2_OSSLDSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLDSAPublicKey.h"
+#include "OSSLDSAPrivateKey.h"
+
+class OSSLDSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLDSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLDSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLDSAPublicKey pubKey;
+
+ // The private key
+ OSSLDSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAKEYPAIR_H
+
diff --git a/src/lib/crypto/OSSLDSAPrivateKey.cpp b/src/lib/crypto/OSSLDSAPrivateKey.cpp
--- /dev/null
@@ -0,0 +1,152 @@
+/* $Id: OSSLDSAPrivateKey.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPrivateKey.cpp
+
+ OpenSSL DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSAPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <string.h>
+
+// Constructors
+OSSLDSAPrivateKey::OSSLDSAPrivateKey()
+{
+ dsa = DSA_new();
+}
+
+OSSLDSAPrivateKey::OSSLDSAPrivateKey(const DSA* inDSA)
+{
+ OSSLDSAPrivateKey();
+ setFromOSSL(inDSA);
+}
+
+// Destructor
+OSSLDSAPrivateKey::~OSSLDSAPrivateKey()
+{
+ DSA_free(dsa);
+}
+
+// The type
+/*static*/ const char* OSSLDSAPrivateKey::type = "OpenSSL DSA Private Key";
+
+// Set from OpenSSL representation
+void OSSLDSAPrivateKey::setFromOSSL(const DSA* dsa)
+{
+ if (dsa->p) { ByteString p = OSSL::bn2ByteString(dsa->p); setP(p); }
+ if (dsa->q) { ByteString q = OSSL::bn2ByteString(dsa->q); setQ(q); }
+ if (dsa->g) { ByteString g = OSSL::bn2ByteString(dsa->g); setG(g); }
+ if (dsa->priv_key) { ByteString x = OSSL::bn2ByteString(dsa->priv_key); setX(x); }
+ if (dsa->pub_key) { ByteString y = OSSL::bn2ByteString(dsa->pub_key); setY(y); }
+}
+
+// Check if the key is of the given type
+bool OSSLDSAPrivateKey::isOfType(const char* type)
+{
+ return !strcmp(OSSLDSAPrivateKey::type, type);
+}
+
+// Setters for the DSA private key components
+void OSSLDSAPrivateKey::setX(const ByteString& x)
+{
+ DSAPrivateKey::setX(x);
+
+ if (dsa->priv_key)
+ {
+ BN_clear_free(dsa->priv_key);
+ dsa->priv_key = NULL;
+ }
+
+ dsa->priv_key = OSSL::byteString2bn(x);
+}
+
+
+// Setters for the DSA public key components
+void OSSLDSAPrivateKey::setP(const ByteString& p)
+{
+ DSAPrivateKey::setP(p);
+
+ if (dsa->p)
+ {
+ BN_clear_free(dsa->p);
+ dsa->p = NULL;
+ }
+
+ dsa->p = OSSL::byteString2bn(p);
+}
+
+void OSSLDSAPrivateKey::setQ(const ByteString& q)
+{
+ DSAPrivateKey::setQ(q);
+
+ if (dsa->q)
+ {
+ BN_clear_free(dsa->q);
+ dsa->q = NULL;
+ }
+
+ dsa->q = OSSL::byteString2bn(q);
+}
+
+void OSSLDSAPrivateKey::setG(const ByteString& g)
+{
+ DSAPrivateKey::setG(g);
+
+ if (dsa->g)
+ {
+ BN_clear_free(dsa->g);
+ dsa->g = NULL;
+ }
+
+ dsa->g = OSSL::byteString2bn(g);
+}
+
+void OSSLDSAPrivateKey::setY(const ByteString& y)
+{
+ DSAPrivateKey::setY(y);
+
+ if (dsa->pub_key)
+ {
+ BN_clear_free(dsa->pub_key);
+ dsa->pub_key = NULL;
+ }
+
+ dsa->pub_key = OSSL::byteString2bn(y);
+}
+
+// Retrieve the OpenSSL representation of the key
+DSA* OSSLDSAPrivateKey::getOSSLKey()
+{
+ return dsa;
+}
+
diff --git a/src/lib/crypto/OSSLDSAPrivateKey.h b/src/lib/crypto/OSSLDSAPrivateKey.h
--- /dev/null
@@ -0,0 +1,80 @@
+/* $Id: OSSLDSAPrivateKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPrivateKey.h
+
+ OpenSSL DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSAPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLDSAPRIVATEKEY_H
+
+#include "config.h"
+#include "DSAPrivateKey.h"
+#include <openssl/dsa.h>
+
+class OSSLDSAPrivateKey : public DSAPrivateKey
+{
+public:
+ // Constructors
+ OSSLDSAPrivateKey();
+
+ OSSLDSAPrivateKey(const DSA* inDSA);
+
+ // Destructor
+ virtual ~OSSLDSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the DSA private key components
+ virtual void setX(const ByteString& x);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setG(const ByteString& g);
+ virtual void setY(const ByteString& y);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const DSA* dsa);
+
+ // Retrieve the OpenSSL representation of the key
+ DSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ DSA* dsa;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPRIVATEKEY_H
+
diff --git a/src/lib/crypto/OSSLDSAPublicKey.cpp b/src/lib/crypto/OSSLDSAPublicKey.cpp
--- /dev/null
@@ -0,0 +1,137 @@
+/* $Id: OSSLDSAPublicKey.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPublicKey.cpp
+
+ OpenSSL DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSAPublicKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <string.h>
+
+// Constructors
+OSSLDSAPublicKey::OSSLDSAPublicKey()
+{
+ dsa = DSA_new();
+}
+
+OSSLDSAPublicKey::OSSLDSAPublicKey(const DSA* inDSA)
+{
+ OSSLDSAPublicKey();
+
+ setFromOSSL(inDSA);
+}
+
+// Destructor
+OSSLDSAPublicKey::~OSSLDSAPublicKey()
+{
+ DSA_free(dsa);
+}
+
+// The type
+/*static*/ const char* OSSLDSAPublicKey::type = "OpenSSL DSA Public Key";
+
+// Set from OpenSSL representation
+void OSSLDSAPublicKey::setFromOSSL(const DSA* dsa)
+{
+ if (dsa->p) { ByteString p = OSSL::bn2ByteString(dsa->p); setP(p); }
+ if (dsa->q) { ByteString q = OSSL::bn2ByteString(dsa->q); setQ(q); }
+ if (dsa->g) { ByteString g = OSSL::bn2ByteString(dsa->g); setG(g); }
+ if (dsa->pub_key) { ByteString y = OSSL::bn2ByteString(dsa->pub_key); setY(y); }
+}
+
+// Check if the key is of the given type
+bool OSSLDSAPublicKey::isOfType(const char* type)
+{
+ return !strcmp(OSSLDSAPublicKey::type, type);
+}
+
+// Setters for the DSA public key components
+void OSSLDSAPublicKey::setP(const ByteString& p)
+{
+ DSAPublicKey::setP(p);
+
+ if (dsa->p)
+ {
+ BN_clear_free(dsa->p);
+ dsa->p = NULL;
+ }
+
+ dsa->p = OSSL::byteString2bn(p);
+}
+
+void OSSLDSAPublicKey::setQ(const ByteString& q)
+{
+ DSAPublicKey::setQ(q);
+
+ if (dsa->q)
+ {
+ BN_clear_free(dsa->q);
+ dsa->q = NULL;
+ }
+
+ dsa->q = OSSL::byteString2bn(q);
+}
+
+void OSSLDSAPublicKey::setG(const ByteString& g)
+{
+ DSAPublicKey::setG(g);
+
+ if (dsa->g)
+ {
+ BN_clear_free(dsa->g);
+ dsa->g = NULL;
+ }
+
+ dsa->g = OSSL::byteString2bn(g);
+}
+
+void OSSLDSAPublicKey::setY(const ByteString& y)
+{
+ DSAPublicKey::setY(y);
+
+ if (dsa->pub_key)
+ {
+ BN_clear_free(dsa->pub_key);
+ dsa->pub_key = NULL;
+ }
+
+ dsa->pub_key = OSSL::byteString2bn(y);
+}
+
+// Retrieve the OpenSSL representation of the key
+DSA* OSSLDSAPublicKey::getOSSLKey()
+{
+ return dsa;
+}
+
diff --git a/src/lib/crypto/OSSLDSAPublicKey.h b/src/lib/crypto/OSSLDSAPublicKey.h
--- /dev/null
@@ -0,0 +1,77 @@
+/* $Id: OSSLDSAPublicKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPublicKey.h
+
+ OpenSSL DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
+#include "config.h"
+#include "DSAPublicKey.h"
+#include <openssl/dsa.h>
+
+class OSSLDSAPublicKey : public DSAPublicKey
+{
+public:
+ // Constructors
+ OSSLDSAPublicKey();
+
+ OSSLDSAPublicKey(const DSA* inDSA);
+
+ // Destructor
+ virtual ~OSSLDSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setG(const ByteString& g);
+ virtual void setY(const ByteString& y);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const DSA* dsa);
+
+ // Retrieve the OpenSSL representation of the key
+ DSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ DSA* dsa;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
diff --git a/src/lib/crypto/OSSLEVPHashAlgorithm.cpp b/src/lib/crypto/OSSLEVPHashAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,119 @@
+/* $Id: OSSLEVPHashAlgorithm.cpp 4918 2010-11-02 16:47:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPHashAlgorithm.cpp
+
+ Base class for OpenSSL hash algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+
+// Destructor
+OSSLEVPHashAlgorithm::~OSSLEVPHashAlgorithm()
+{
+ EVP_MD_CTX_cleanup(&curCTX);
+}
+
+// Hashing functions
+bool OSSLEVPHashAlgorithm::hashInit()
+{
+ if (!HashAlgorithm::hashInit())
+ {
+ return false;
+ }
+
+ // Initialize the context
+ EVP_MD_CTX_init(&curCTX);
+
+ // Initialize EVP digesting
+ if (!EVP_DigestInit_ex(&curCTX, getEVPHash(), NULL))
+ {
+ ERROR_MSG("EVP_DigestInit failed");
+
+ EVP_MD_CTX_cleanup(&curCTX);
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPHashAlgorithm::hashUpdate(const ByteString& data)
+{
+ if (!HashAlgorithm::hashUpdate(data))
+ {
+ return false;
+ }
+
+ // Continue digesting
+ if (!EVP_DigestUpdate(&curCTX, (unsigned char*) data.const_byte_str(), data.size()))
+ {
+ ERROR_MSG("EVP_DigestUpdate failed");
+
+ EVP_MD_CTX_cleanup(&curCTX);
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPHashAlgorithm::hashFinal(ByteString& hashedData)
+{
+ if (!HashAlgorithm::hashFinal(hashedData))
+ {
+ return false;
+ }
+
+ hashedData.resize(EVP_MD_size(getEVPHash()));
+ unsigned int outLen = hashedData.size();
+
+ if (!EVP_DigestFinal_ex(&curCTX, &hashedData[0], &outLen))
+ {
+ ERROR_MSG("EVP_DigestFinal failed");
+
+ EVP_MD_CTX_cleanup(&curCTX);
+
+ return false;
+ }
+
+ hashedData.resize(outLen);
+
+ EVP_MD_CTX_cleanup(&curCTX);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/OSSLEVPHashAlgorithm.h b/src/lib/crypto/OSSLEVPHashAlgorithm.h
--- /dev/null
@@ -0,0 +1,66 @@
+/* $Id: OSSLEVPHashAlgorithm.h 4918 2010-11-02 16:47:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPHashAlgorithm.h
+
+ Base class for OpenSSL hash algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEVPHASHALGORITHM_H
+#define _SOFTHSM_V2_OSSLEVPHASHALGORITHM_H
+
+#include "config.h"
+#include "HashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLEVPHashAlgorithm : public HashAlgorithm
+{
+public:
+ // Base constructors
+ OSSLEVPHashAlgorithm() : HashAlgorithm() { }
+
+ // Destructor
+ ~OSSLEVPHashAlgorithm();
+
+ // Hashing functions
+ virtual bool hashInit();
+ virtual bool hashUpdate(const ByteString& data);
+ virtual bool hashFinal(ByteString& hashedData);
+
+ virtual int getHashSize() = 0;
+protected:
+ virtual const EVP_MD* getEVPHash() const = 0;
+
+private:
+ // Current hashing context
+ EVP_MD_CTX curCTX;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEVPHASHALGORITHM_H
+
diff --git a/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp b/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,369 @@
+/* $Id: OSSLEVPSymmetricAlgorithm.cpp 4924 2010-11-22 13:41:26Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store EVP context in securely allocated memory
+
+/*****************************************************************************
+ OSSLEVPSymmetricAlgorithm.cpp
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLEVPSymmetricAlgorithm.h"
+#include "salloc.h"
+
+// Constructor
+OSSLEVPSymmetricAlgorithm::OSSLEVPSymmetricAlgorithm()
+{
+ pCurCTX = NULL;
+}
+
+// Destructor
+OSSLEVPSymmetricAlgorithm::~OSSLEVPSymmetricAlgorithm()
+{
+ if (pCurCTX != NULL)
+ {
+ sfree(pCurCTX);
+ }
+}
+
+// Encryption functions
+bool OSSLEVPSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const std::string mode /* = "cbc" */, const ByteString& IV /* = ByteString()*/)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::encryptInit(key, mode, IV))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if ((IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Determine the cipher class
+ const EVP_CIPHER* cipher = getCipher();
+
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Failed to initialise EVP encrypt operation");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the EVP context
+ pCurCTX = (EVP_CIPHER_CTX*) salloc(sizeof(EVP_CIPHER_CTX));
+
+ if (pCurCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ int rv = EVP_EncryptInit(pCurCTX, cipher, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str());
+
+ if (!rv)
+ {
+ ERROR_MSG("Failed to initialise EVP encrypt operation");
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData))
+ {
+ if (pCurCTX != NULL)
+ {
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+ }
+
+ return false;
+ }
+
+ // Prepare the output block
+ encryptedData.resize(data.size() + getBlockSize() - 1);
+
+ int outLen = encryptedData.size();
+ if (!EVP_EncryptUpdate(pCurCTX, &encryptedData[0], &outLen, (unsigned char*) data.const_byte_str(), data.size()))
+ {
+ ERROR_MSG("EVP_EncryptUpdate failed");
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ // Resize the output block
+ encryptedData.resize(outLen);
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::encryptFinal(ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptFinal(encryptedData))
+ {
+ if (pCurCTX != NULL)
+ {
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+ }
+
+ return false;
+ }
+
+ // Prepare the output block
+ encryptedData.resize(getBlockSize());
+
+ int outLen = encryptedData.size();
+
+ if (!EVP_EncryptFinal(pCurCTX, &encryptedData[0], &outLen))
+ {
+ ERROR_MSG("EVP_EncryptFinal failed");
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ encryptedData.resize(outLen);
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ return true;
+}
+
+// Decryption functions
+bool OSSLEVPSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const std::string mode /* = "cbc" */, const ByteString& IV /* = ByteString() */)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::decryptInit(key, mode, IV))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if ((IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Determine the cipher class
+ const EVP_CIPHER* cipher = getCipher();
+
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Failed to initialise EVP decrypt operation");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the EVP context
+ pCurCTX = (EVP_CIPHER_CTX*) salloc(sizeof(EVP_CIPHER_CTX));
+
+ if (pCurCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ int rv = EVP_DecryptInit(pCurCTX, cipher, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str());
+
+ if (!rv)
+ {
+ ERROR_MSG("Failed to initialise EVP decrypt operation");
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data)
+{
+ if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data))
+ {
+ if (pCurCTX != NULL)
+ {
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+ }
+
+ return false;
+ }
+
+ // Prepare the output block
+ data.resize(encryptedData.size() + getBlockSize() - 1);
+
+ int outLen = data.size();
+
+ DEBUG_MSG("Decrypting %d bytes into buffer of %d bytes", encryptedData.size(), data.size());
+
+ if (!EVP_DecryptUpdate(pCurCTX, &data[0], &outLen, (unsigned char*) encryptedData.const_byte_str(), encryptedData.size()))
+ {
+ ERROR_MSG("EVP_DecryptUpdate failed");
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ DEBUG_MSG("Decrypt returned %d bytes of data", outLen);
+
+ // Resize the output block
+ data.resize(outLen);
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::decryptFinal(ByteString& data)
+{
+ if (!SymmetricAlgorithm::decryptFinal(data))
+ {
+ if (pCurCTX != NULL)
+ {
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+ }
+
+ return false;
+ }
+
+ // Prepare the output block
+ data.resize(getBlockSize());
+
+ int outLen = data.size();
+ int rv;
+
+ if (!(rv = EVP_DecryptFinal(pCurCTX, &data[0], &outLen)))
+ {
+ ERROR_MSG("EVP_DecryptFinal failed (0x%08X)", rv);
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ data.resize(outLen);
+
+ EVP_CIPHER_CTX_cleanup(pCurCTX);
+ sfree(pCurCTX);
+ pCurCTX = NULL;
+
+ return true;
+}
+
diff --git a/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h b/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h
--- /dev/null
@@ -0,0 +1,76 @@
+/* $Id: OSSLEVPSymmetricAlgorithm.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPSymmetricAlgorithm.h
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H
+
+#include <openssl/evp.h>
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "SymmetricAlgorithm.h"
+
+class OSSLEVPSymmetricAlgorithm : public SymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLEVPSymmetricAlgorithm();
+
+ // Destructor
+ virtual ~OSSLEVPSymmetricAlgorithm();
+
+ // Encryption functions
+ virtual bool encryptInit(const SymmetricKey* key, const std::string mode = "cbc", const ByteString& IV = ByteString());
+ virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData);
+ virtual bool encryptFinal(ByteString& encryptedData);
+
+ // Decryption functions
+ virtual bool decryptInit(const SymmetricKey* key, const std::string mode = "cbc", const ByteString& IV = ByteString());
+ virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data);
+ virtual bool decryptFinal(ByteString& data);
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual const EVP_CIPHER* getCipher() const = 0;
+
+ // Return the block size
+ virtual size_t getBlockSize() const = 0;
+
+private:
+ // The current EVP context
+ EVP_CIPHER_CTX* pCurCTX;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H
+
diff --git a/src/lib/crypto/OSSLMD5.cpp b/src/lib/crypto/OSSLMD5.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: OSSLMD5.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLMD5.h
+
+ OpenSSL MD5 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLMD5.h"
+#include <openssl/evp.h>
+
+int OSSLMD5::getHashSize()
+{
+ return 16;
+}
+
+const EVP_MD* OSSLMD5::getEVPHash() const
+{
+ return EVP_md5();
+}
+
diff --git a/src/lib/crypto/OSSLMD5.h b/src/lib/crypto/OSSLMD5.h
--- /dev/null
+++ b/src/lib/crypto/OSSLMD5.h
@@ -0,0 +1,50 @@
+/* $Id: OSSLMD5.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLMD5.h
+
+ OpenSSL MD5 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLMD5_H
+#define _SOFTHSM_V2_OSSLMD5_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLMD5 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLMD5_H
+
diff --git a/src/lib/crypto/OSSLRNG.cpp b/src/lib/crypto/OSSLRNG.cpp
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: OSSLRNG.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRNG.cpp
+
+ OpenSSL random number generator class
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLRNG.h"
+#include <openssl/rand.h>
+
+// Generate random data
+bool OSSLRNG::generateRandom(ByteString& data, const size_t len)
+{
+ data.wipe(len);
+
+ return RAND_bytes(&data[0], len);
+}
+
+// Seed the random pool
+void OSSLRNG::seed(ByteString& seedData)
+{
+ RAND_seed(seedData.byte_str(), seedData.size());
+}
+
diff --git a/src/lib/crypto/OSSLRNG.h b/src/lib/crypto/OSSLRNG.h
--- /dev/null
+++ b/src/lib/crypto/OSSLRNG.h
@@ -0,0 +1,55 @@
+/* $Id: OSSLRNG.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRNG.h
+
+ OpenSSL random number generator class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRNG_H
+#define _SOFTHSM_V2_OSSLRNG_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "RNG.h"
+
+class OSSLRNG : public RNG
+{
+public:
+ // Generate random data
+ virtual bool generateRandom(ByteString& data, const size_t len);
+
+ // Seed the random pool
+ virtual void seed(ByteString& seedData);
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_OSSLRNG_H
+
diff --git a/src/lib/crypto/OSSLRSA.cpp b/src/lib/crypto/OSSLRSA.cpp
--- /dev/null
@@ -0,0 +1,1026 @@
+/* $Id: OSSLRSA.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSA.cpp
+
+ OpenSSL RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLRSA.h"
+#include "CryptoFactory.h"
+#include "RSAParameters.h"
+#include "OSSLRSAKeyPair.h"
+#include <algorithm>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+// Constructor
+OSSLRSA::OSSLRSA()
+{
+ pCurrentHash = NULL;
+ pSecondHash = NULL;
+}
+
+// Destructor
+OSSLRSA::~OSSLRSA()
+{
+ if (pCurrentHash != NULL)
+ {
+ delete pCurrentHash;
+ }
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+ }
+}
+
+// Signing functions
+bool OSSLRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism)
+{
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!lowerMechanism.compare("rsa-pkcs"))
+ {
+ // Separate implementation for RSA PKCS #1 signing without hash computation
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // In case of PKCS #1 signing the length of the input data may not exceed 40% of the
+ // modulus size
+ OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;
+
+ size_t allowedLen = osslKey->getN().size() - 11;
+
+ if (dataToSign.size() > allowedLen)
+ {
+ ERROR_MSG("Data to sign exceeds maximum for PKCS #1 signature");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ signature.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");
+
+ return false;
+ }
+
+ int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_PKCS1_PADDING);
+
+ RSA_blinding_off(rsa);
+
+ if (sigLen == -1)
+ {
+ ERROR_MSG("An error occurred while performing a PKCS #1 signature");
+
+ return false;
+ }
+
+ signature.resize(sigLen);
+
+ return true;
+ }
+ else if (!lowerMechanism.compare("rsa-raw"))
+ {
+ // Separate implementation for raw RSA signing
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // In case of raw RSA, the length of the input data must match the length of the modulus
+ OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;
+
+ if (dataToSign.size() != osslKey->getN().size())
+ {
+ ERROR_MSG("Size of data to sign does not match the modulus size");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ signature.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");
+
+ return false;
+ }
+
+ int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_NO_PADDING);
+
+ RSA_blinding_off(rsa);
+
+ if (sigLen == -1)
+ {
+ ERROR_MSG("An error occurred while performing a raw RSA signature");
+
+ return false;
+ }
+
+ signature.resize(sigLen);
+
+ return true;
+ }
+ else
+ {
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism);
+ }
+}
+
+bool OSSLRSA::signInit(PrivateKey* privateKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!lowerMechanism.compare("rsa-md5-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("md5");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha1-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha1");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha256-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha256");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha384-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha384");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha512-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha512");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-ssl"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("md5");
+ pSecondHash = CryptoFactory::i()->getHashAlgorithm("sha1");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+
+ if (!pSecondHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ delete pSecondHash;
+ pSecondHash = NULL;
+ }
+ }
+
+ if (pCurrentHash == NULL)
+ {
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLRSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(dataToSign))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ if ((pSecondHash != NULL) && !pSecondHash->hashUpdate(dataToSign))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ delete pSecondHash;
+ pSecondHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLRSA::signFinal(ByteString& signature)
+{
+ // Save necessary state before calling super class signFinal
+ OSSLRSAPrivateKey* pk = (OSSLRSAPrivateKey*) currentPrivateKey;
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(currentMechanism.size());
+ std::transform(currentMechanism.begin(), currentMechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString firstHash, secondHash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(firstHash);
+ bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true;
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+
+ pSecondHash = NULL;
+ }
+
+ if (!bFirstResult || !bSecondResult)
+ {
+ return false;
+ }
+
+ ByteString digest = firstHash + secondHash;
+
+ // Resize the data block for the signature to the modulus size of the key
+ signature.resize(pk->getN().size());
+
+ // Determine the signature NID type
+ int type = 0;
+
+ if (!lowerMechanism.compare("rsa-md5-pkcs"))
+ {
+ type = NID_md5;
+ }
+ else if (!lowerMechanism.compare("rsa-sha1-pkcs"))
+ {
+ type = NID_sha1;
+ }
+ else if (!lowerMechanism.compare("rsa-sha256-pkcs"))
+ {
+ type = NID_sha256;
+ }
+ else if (!lowerMechanism.compare("rsa-sha384-pkcs"))
+ {
+ type = NID_sha384;
+ }
+ else if (!lowerMechanism.compare("rsa-sha512-pkcs"))
+ {
+ type = NID_sha512;
+ }
+ else if (!lowerMechanism.compare("rsa-ssl"))
+ {
+ type = NID_md5_sha1;
+ }
+
+ // Perform the signature operation
+ unsigned int sigLen = signature.size();
+
+ RSA* rsa = pk->getOSSLKey();
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn blinding on for OpenSSL RSA key");
+
+ return false;
+ }
+
+ bool rv = (RSA_sign(type, &digest[0], digest.size(), &signature[0], &sigLen, pk->getOSSLKey()) == 1);
+
+ RSA_blinding_off(rsa);
+
+ signature.resize(sigLen);
+
+ return rv;
+}
+
+// Verification functions
+bool OSSLRSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism)
+{
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!lowerMechanism.compare("rsa-pkcs"))
+ {
+ // Specific implementation for PKCS #1 only verification; originalData is assumed to contain
+ // a digestInfo structure and verification is performed by comparing originalData to the data
+ // recovered from the signature
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the RSA public key operation
+ OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;
+
+ ByteString recoveredData;
+
+ recoveredData.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_PKCS1_PADDING);
+
+ if (retLen == -1)
+ {
+ ERROR_MSG("Public key operation failed");
+
+ return false;
+ }
+
+ recoveredData.resize(retLen);
+
+ return (originalData == recoveredData);
+ }
+ else if (!lowerMechanism.compare("rsa-raw"))
+ {
+ // Specific implementation for raw RSA verifiction; originalData is assumed to contain the
+ // full input data used to compute the signature and verification is performed by comparing
+ // originalData to the data recovered from the signature
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the RSA public key operation
+ OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;
+
+ ByteString recoveredData;
+
+ recoveredData.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_NO_PADDING);
+
+ if (retLen == -1)
+ {
+ ERROR_MSG("Public key operation failed");
+
+ return false;
+ }
+
+ recoveredData.resize(retLen);
+
+ return (originalData == recoveredData);
+ }
+ else
+ {
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism);
+ }
+}
+
+bool OSSLRSA::verifyInit(PublicKey* publicKey, const std::string mechanism)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(mechanism.size());
+ std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!lowerMechanism.compare("rsa-md5-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("md5");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha1-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha1");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha256-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha256");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha384-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha384");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-sha512-pkcs"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("sha512");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+ }
+ else if (!lowerMechanism.compare("rsa-ssl"))
+ {
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm("md5");
+ pSecondHash = CryptoFactory::i()->getHashAlgorithm("sha1");
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+
+ if (!pSecondHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ delete pSecondHash;
+ pSecondHash = NULL;
+ }
+ }
+
+ if (pCurrentHash == NULL)
+ {
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLRSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(originalData))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ if ((pSecondHash != NULL) && !pSecondHash->hashUpdate(originalData))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ delete pSecondHash;
+ pSecondHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLRSA::verifyFinal(const ByteString& signature)
+{
+ // Save necessary state before calling super class verifyFinal
+ OSSLRSAPublicKey* pk = (OSSLRSAPublicKey*) currentPublicKey;
+
+ std::string lowerMechanism;
+ lowerMechanism.resize(currentMechanism.size());
+ std::transform(currentMechanism.begin(), currentMechanism.end(), lowerMechanism.begin(), tolower);
+
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString firstHash, secondHash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(firstHash);
+ bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true;
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+
+ pSecondHash = NULL;
+ }
+
+ if (!bFirstResult || !bSecondResult)
+ {
+ return false;
+ }
+
+ ByteString digest = firstHash + secondHash;
+
+ // Determine the signature NID type
+ int type = 0;
+
+ if (!lowerMechanism.compare("rsa-md5-pkcs"))
+ {
+ type = NID_md5;
+ }
+ else if (!lowerMechanism.compare("rsa-sha1-pkcs"))
+ {
+ type = NID_sha1;
+ }
+ else if (!lowerMechanism.compare("rsa-sha256-pkcs"))
+ {
+ type = NID_sha256;
+ }
+ else if (!lowerMechanism.compare("rsa-sha384-pkcs"))
+ {
+ type = NID_sha384;
+ }
+ else if (!lowerMechanism.compare("rsa-sha512-pkcs"))
+ {
+ type = NID_sha512;
+ }
+ else if (!lowerMechanism.compare("rsa-ssl"))
+ {
+ type = NID_md5_sha1;
+ }
+
+ // Perform the verify operation
+ bool rv = (RSA_verify(type, &digest[0], digest.size(), (unsigned char*) signature.const_byte_str(), signature.size(), pk->getOSSLKey()) == 1);
+
+ if (!rv) ERROR_MSG("RSA verify failed (0x%08X)", ERR_get_error());
+
+ return rv;
+}
+
+// Encryption functions
+bool OSSLRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding)
+{
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ std::string lowerPadding;
+ lowerPadding.resize(padding.size());
+ std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower);
+
+ // Retrieve the OpenSSL key object
+ RSA* rsa = ((OSSLRSAPublicKey*) publicKey)->getOSSLKey();
+
+ // Check the data and padding algorithm
+ int osslPadding = 0;
+
+ if (!lowerPadding.compare("rsa-pkcs"))
+ {
+ // The size of the input data cannot be more than the modulus
+ // length of the key - 11
+ if (data.size() > (size_t) (RSA_size(rsa) - 11))
+ {
+ ERROR_MSG("Too much data supplied for RSA PKCS #1 encryption");
+
+ return false;
+ }
+
+ osslPadding = RSA_PKCS1_PADDING;
+ }
+ else if (!lowerPadding.compare("rsa-pkcs-oaep"))
+ {
+ // The size of the input data cannot be more than the modulus
+ // length of the key - 41
+ if (data.size() > (size_t) (RSA_size(rsa) - 41))
+ {
+ ERROR_MSG("Too much data supplied for RSA OAEP encryption");
+
+ return false;
+ }
+
+ osslPadding = RSA_PKCS1_OAEP_PADDING;
+ }
+ else if (!lowerPadding.compare("rsa-raw"))
+ {
+ // The size of the input data should be exactly equal to the modulus length
+ if (data.size() != (size_t) RSA_size(rsa))
+ {
+ ERROR_MSG("Incorrect amount of input data supplied for raw RSA encryption");
+
+ return false;
+ }
+
+ osslPadding = RSA_NO_PADDING;
+ }
+ else
+ {
+ ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str());
+
+ return false;
+ }
+
+ // Perform the RSA operation
+ encryptedData.resize(RSA_size(rsa));
+
+ if (RSA_public_encrypt(data.size(), (unsigned char*) data.const_byte_str(), &encryptedData[0], rsa, osslPadding) == -1)
+ {
+ ERROR_MSG("RSA public key encryption failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Decryption functions
+bool OSSLRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding)
+{
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Retrieve the OpenSSL key object
+ RSA* rsa = ((OSSLRSAPrivateKey*) privateKey)->getOSSLKey();
+
+ // Check the input size
+ if (encryptedData.size() != (size_t) RSA_size(rsa))
+ {
+ ERROR_MSG("Invalid amount of input data supplied for RSA decryption");
+
+ return false;
+ }
+
+ std::string lowerPadding;
+ lowerPadding.resize(padding.size());
+ std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower);
+
+ // Determine the OpenSSL padding algorithm
+ int osslPadding = 0;
+
+ if (!lowerPadding.compare("rsa-pkcs"))
+ {
+ osslPadding = RSA_PKCS1_PADDING;
+ }
+ else if (!lowerPadding.compare("rsa-pkcs-oaep"))
+ {
+ osslPadding = RSA_PKCS1_OAEP_PADDING;
+ }
+ else if (!lowerPadding.compare("rsa-raw"))
+ {
+ osslPadding = RSA_NO_PADDING;
+ }
+ else
+ {
+ ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str());
+
+ return false;
+ }
+
+ // Perform the RSA operation
+ data.resize(RSA_size(rsa));
+
+ int decSize = RSA_private_decrypt(encryptedData.size(), (unsigned char*) encryptedData.const_byte_str(), &data[0], rsa, osslPadding);
+
+ if (decSize == -1)
+ {
+ ERROR_MSG("RSA private key decryption failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ data.resize(decSize);
+
+ return true;
+}
+
+// Key factory
+bool OSSLRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng /* = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(RSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for RSA key generation");
+
+ return false;
+ }
+
+ RSAParameters* params = (RSAParameters*) parameters;
+
+ if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize())
+ {
+ ERROR_MSG("This RSA key size is not supported");
+
+ return false;
+ }
+
+ if (params->getBitLength() < 1024)
+ {
+ WARNING_MSG("Using an RSA key size < 1024 bits is not recommended");
+ }
+
+ // Retrieve the desired public exponent
+ unsigned long e = params->getE().long_val();
+
+ // Check the public exponent
+ if ((e == 0) || (e % 2 != 1))
+ {
+ ERROR_MSG("Invalid RSA public exponent %d", e);
+
+ return false;
+ }
+
+ // Generate the key-pair
+ RSA* rsa = RSA_generate_key(params->getBitLength(), e, NULL, NULL);
+
+ // Check if the key was successfully generated
+ if (rsa == NULL)
+ {
+ ERROR_MSG("RSA key generation failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ OSSLRSAKeyPair* kp = new OSSLRSAKeyPair();
+
+ ((OSSLRSAPublicKey*) kp->getPublicKey())->setFromOSSL(rsa);
+ ((OSSLRSAPrivateKey*) kp->getPrivateKey())->setFromOSSL(rsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ RSA_free(rsa);
+
+ return true;
+}
+
+unsigned long OSSLRSA::getMinKeySize()
+{
+ return 512;
+}
+
+unsigned long OSSLRSA::getMaxKeySize()
+{
+ return OPENSSL_RSA_MAX_MODULUS_BITS;
+}
+
+bool OSSLRSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLRSAKeyPair* kp = new OSSLRSAKeyPair();
+
+ bool rv = true;
+
+ if (!((RSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((RSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLRSAPublicKey* pub = new OSSLRSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLRSAPrivateKey* priv = new OSSLRSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLRSA::newPublicKey()
+{
+ return (PublicKey*) new OSSLRSAPublicKey();
+}
+
+PrivateKey* OSSLRSA::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLRSAPrivateKey();
+}
+
+AsymmetricParameters* OSSLRSA::newParameters()
+{
+ return (AsymmetricParameters*) new RSAParameters();
+}
+
diff --git a/src/lib/crypto/OSSLRSA.h b/src/lib/crypto/OSSLRSA.h
--- /dev/null
+++ b/src/lib/crypto/OSSLRSA.h
@@ -0,0 +1,87 @@
+/* $Id: OSSLRSA.h 4890 2010-09-10 08:29:56Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSA.h
+
+ OpenSSL RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSA_H
+#define _SOFTHSM_V2_OSSLRSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include <openssl/rsa.h>
+
+class OSSLRSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLRSA();
+
+ // Destructor
+ virtual ~OSSLRSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism);
+ virtual bool signInit(PrivateKey* privateKey, const std::string mechanism);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism);
+ virtual bool verifyInit(PublicKey* publicKey, const std::string mechanism);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ HashAlgorithm* pCurrentHash;
+ HashAlgorithm* pSecondHash;
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSA_H
+
diff --git a/src/lib/crypto/OSSLRSAKeyPair.cpp b/src/lib/crypto/OSSLRSAKeyPair.cpp
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: OSSLRSAKeyPair.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAKeyPair.cpp
+
+ OpenSSL RSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLRSAKeyPair.h"
+
+// Set the public key
+void OSSLRSAKeyPair::setPublicKey(OSSLRSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLRSAKeyPair::setPrivateKey(OSSLRSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLRSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLRSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLRSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLRSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/src/lib/crypto/OSSLRSAKeyPair.h b/src/lib/crypto/OSSLRSAKeyPair.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: OSSLRSAKeyPair.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAKeyPair.h
+
+ OpenSSL RSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSAKEYPAIR_H
+#define _SOFTHSM_V2_OSSLRSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLRSAPublicKey.h"
+#include "OSSLRSAPrivateKey.h"
+
+class OSSLRSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLRSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLRSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLRSAPublicKey pubKey;
+
+ // The private key
+ OSSLRSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAKEYPAIR_H
+
diff --git a/src/lib/crypto/OSSLRSAPrivateKey.cpp b/src/lib/crypto/OSSLRSAPrivateKey.cpp
--- /dev/null
@@ -0,0 +1,195 @@
+/* $Id: OSSLRSAPrivateKey.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPrivateKey.cpp
+
+ OpenSSL RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLRSAPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <string.h>
+
+// Constructors
+OSSLRSAPrivateKey::OSSLRSAPrivateKey()
+{
+ rsa = RSA_new();
+}
+
+OSSLRSAPrivateKey::OSSLRSAPrivateKey(const RSA* inRSA)
+{
+ OSSLRSAPrivateKey();
+
+ setFromOSSL(inRSA);
+}
+
+// Destructor
+OSSLRSAPrivateKey::~OSSLRSAPrivateKey()
+{
+ RSA_free(rsa);
+}
+
+// The type
+/*static*/ const char* OSSLRSAPrivateKey::type = "OpenSSL RSA Private Key";
+
+// Set from OpenSSL representation
+void OSSLRSAPrivateKey::setFromOSSL(const RSA* rsa)
+{
+ if (rsa->p) { ByteString p = OSSL::bn2ByteString(rsa->p); setP(p); }
+ if (rsa->q) { ByteString q = OSSL::bn2ByteString(rsa->q); setQ(q); }
+ if (rsa->dmp1) { ByteString dp1 = OSSL::bn2ByteString(rsa->dmp1); setDP1(dp1); }
+ if (rsa->dmq1) { ByteString dq1 = OSSL::bn2ByteString(rsa->dmq1); setDQ1(dq1); }
+ if (rsa->iqmp) { ByteString pq = OSSL::bn2ByteString(rsa->iqmp); setPQ(pq); }
+ if (rsa->d) { ByteString d = OSSL::bn2ByteString(rsa->d); setD(d); }
+ if (rsa->n) { ByteString n = OSSL::bn2ByteString(rsa->n); setN(n); }
+ if (rsa->e) { ByteString e = OSSL::bn2ByteString(rsa->e); setE(e); }
+}
+
+// Check if the key is of the given type
+bool OSSLRSAPrivateKey::isOfType(const char* type)
+{
+ return !strcmp(OSSLRSAPrivateKey::type, type);
+}
+
+// Setters for the RSA private key components
+void OSSLRSAPrivateKey::setP(const ByteString& p)
+{
+ RSAPrivateKey::setP(p);
+
+ if (rsa->p)
+ {
+ BN_clear_free(rsa->p);
+ rsa->p = NULL;
+ }
+
+ rsa->p = OSSL::byteString2bn(p);
+}
+
+void OSSLRSAPrivateKey::setQ(const ByteString& q)
+{
+ RSAPrivateKey::setQ(q);
+
+ if (rsa->q)
+ {
+ BN_clear_free(rsa->q);
+ rsa->q = NULL;
+ }
+
+ rsa->q = OSSL::byteString2bn(q);
+}
+
+void OSSLRSAPrivateKey::setPQ(const ByteString& pq)
+{
+ RSAPrivateKey::setPQ(pq);
+
+ if (rsa->iqmp)
+ {
+ BN_clear_free(rsa->iqmp);
+ rsa->iqmp = NULL;
+ }
+
+ rsa->iqmp = OSSL::byteString2bn(pq);
+}
+
+void OSSLRSAPrivateKey::setDP1(const ByteString& dp1)
+{
+ RSAPrivateKey::setDP1(dp1);
+
+ if (rsa->dmp1)
+ {
+ BN_clear_free(rsa->dmp1);
+ rsa->dmp1 = NULL;
+ }
+
+ rsa->dmp1 = OSSL::byteString2bn(dp1);
+}
+
+void OSSLRSAPrivateKey::setDQ1(const ByteString& dq1)
+{
+ RSAPrivateKey::setDQ1(dq1);
+
+ if (rsa->dmq1)
+ {
+ BN_clear_free(rsa->dmq1);
+ rsa->dmq1 = NULL;
+ }
+
+ rsa->dmq1 = OSSL::byteString2bn(dq1);
+}
+
+void OSSLRSAPrivateKey::setD(const ByteString& d)
+{
+ RSAPrivateKey::setD(d);
+
+ if (rsa->d)
+ {
+ BN_clear_free(rsa->d);
+ rsa->d = NULL;
+ }
+
+ rsa->d = OSSL::byteString2bn(d);
+}
+
+
+// Setters for the RSA public key components
+void OSSLRSAPrivateKey::setN(const ByteString& n)
+{
+ RSAPrivateKey::setN(n);
+
+ if (rsa->n)
+ {
+ BN_clear_free(rsa->n);
+ rsa->n = NULL;
+ }
+
+ rsa->n = OSSL::byteString2bn(n);
+}
+
+void OSSLRSAPrivateKey::setE(const ByteString& e)
+{
+ RSAPrivateKey::setE(e);
+
+ if (rsa->e)
+ {
+ BN_clear_free(rsa->e);
+ rsa->e = NULL;
+ }
+
+ rsa->e = OSSL::byteString2bn(e);
+}
+
+// Retrieve the OpenSSL representation of the key
+RSA* OSSLRSAPrivateKey::getOSSLKey()
+{
+ return rsa;
+}
+
diff --git a/src/lib/crypto/OSSLRSAPrivateKey.h b/src/lib/crypto/OSSLRSAPrivateKey.h
--- /dev/null
@@ -0,0 +1,83 @@
+/* $Id: OSSLRSAPrivateKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPrivateKey.h
+
+ OpenSSL RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+
+#include "config.h"
+#include "RSAPrivateKey.h"
+#include <openssl/rsa.h>
+
+class OSSLRSAPrivateKey : public RSAPrivateKey
+{
+public:
+ // Constructors
+ OSSLRSAPrivateKey();
+
+ OSSLRSAPrivateKey(const RSA* inRSA);
+
+ // Destructor
+ virtual ~OSSLRSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the RSA private key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setPQ(const ByteString& pq);
+ virtual void setDP1(const ByteString& dp1);
+ virtual void setDQ1(const ByteString& dq1);
+ virtual void setD(const ByteString& d);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& n);
+ virtual void setE(const ByteString& e);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const RSA* rsa);
+
+ // Retrieve the OpenSSL representation of the key
+ RSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ RSA* rsa;
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+
diff --git a/src/lib/crypto/OSSLRSAPublicKey.cpp b/src/lib/crypto/OSSLRSAPublicKey.cpp
--- /dev/null
@@ -0,0 +1,109 @@
+/* $Id: OSSLRSAPublicKey.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPublicKey.cpp
+
+ OpenSSL RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLRSAPublicKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <string.h>
+
+// Constructors
+OSSLRSAPublicKey::OSSLRSAPublicKey()
+{
+ rsa = RSA_new();
+}
+
+OSSLRSAPublicKey::OSSLRSAPublicKey(const RSA* inRSA)
+{
+ OSSLRSAPublicKey();
+
+ setFromOSSL(inRSA);
+}
+
+// Destructor
+OSSLRSAPublicKey::~OSSLRSAPublicKey()
+{
+ RSA_free(rsa);
+}
+
+// The type
+/*static*/ const char* OSSLRSAPublicKey::type = "OpenSSL RSA Public Key";
+
+// Check if the key is of the given type
+bool OSSLRSAPublicKey::isOfType(const char* type)
+{
+ return !strcmp(OSSLRSAPublicKey::type, type);
+}
+
+// Set from OpenSSL representation
+void OSSLRSAPublicKey::setFromOSSL(const RSA* rsa)
+{
+ if (rsa->n) { ByteString n = OSSL::bn2ByteString(rsa->n); setN(n); }
+ if (rsa->e) { ByteString e = OSSL::bn2ByteString(rsa->e); setE(e); }
+}
+
+// Setters for the RSA public key components
+void OSSLRSAPublicKey::setN(const ByteString& n)
+{
+ RSAPublicKey::setN(n);
+
+ if (rsa->n)
+ {
+ BN_clear_free(rsa->n);
+ rsa->n = NULL;
+ }
+
+ rsa->n = OSSL::byteString2bn(n);
+}
+
+void OSSLRSAPublicKey::setE(const ByteString& e)
+{
+ RSAPublicKey::setE(e);
+
+ if (rsa->e)
+ {
+ BN_clear_free(rsa->e);
+ rsa->e = NULL;
+ }
+
+ rsa->e = OSSL::byteString2bn(e);
+}
+
+// Retrieve the OpenSSL representation of the key
+RSA* OSSLRSAPublicKey::getOSSLKey()
+{
+ return rsa;
+}
+
diff --git a/src/lib/crypto/OSSLRSAPublicKey.h b/src/lib/crypto/OSSLRSAPublicKey.h
--- /dev/null
@@ -0,0 +1,75 @@
+/* $Id: OSSLRSAPublicKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPublicKey.h
+
+ OpenSSL RSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSAPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLRSAPUBLICKEY_H
+
+#include "config.h"
+#include "RSAPublicKey.h"
+#include <openssl/rsa.h>
+
+class OSSLRSAPublicKey : public RSAPublicKey
+{
+public:
+ // Constructors
+ OSSLRSAPublicKey();
+
+ OSSLRSAPublicKey(const RSA* inRSA);
+
+ // Destructor
+ virtual ~OSSLRSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& n);
+ virtual void setE(const ByteString& e);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const RSA* rsa);
+
+ // Retrieve the OpenSSL representation of the key
+ RSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ RSA* rsa;
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAPUBLICKEY_H
+
diff --git a/src/lib/crypto/OSSLSHA1.cpp b/src/lib/crypto/OSSLSHA1.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: OSSLSHA1.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA1.h
+
+ OpenSSL SHA1 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA1.h"
+#include <openssl/evp.h>
+
+int OSSLSHA1::getHashSize()
+{
+ return 20;
+}
+
+const EVP_MD* OSSLSHA1::getEVPHash() const
+{
+ return EVP_sha1();
+}
+
diff --git a/src/lib/crypto/OSSLSHA1.h b/src/lib/crypto/OSSLSHA1.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: OSSLSHA1.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA1.h
+
+ OpenSSL SHA1 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA1_H
+#define _SOFTHSM_V2_OSSLSHA1_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA1 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA1_H
+
diff --git a/src/lib/crypto/OSSLSHA224.cpp b/src/lib/crypto/OSSLSHA224.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: OSSLSHA224.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA224.h
+
+ OpenSSL SHA224 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA224.h"
+#include <openssl/evp.h>
+
+int OSSLSHA224::getHashSize()
+{
+ return 28;
+}
+
+const EVP_MD* OSSLSHA224::getEVPHash() const
+{
+ return EVP_sha224();
+}
+
diff --git a/src/lib/crypto/OSSLSHA224.h b/src/lib/crypto/OSSLSHA224.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: OSSLSHA224.h 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA224.h
+
+ OpenSSL SHA224 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA224_H
+#define _SOFTHSM_V2_OSSLSHA224_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA224 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA224_H
+
diff --git a/src/lib/crypto/OSSLSHA256.cpp b/src/lib/crypto/OSSLSHA256.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: OSSLSHA256.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA256.h
+
+ OpenSSL SHA256 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA256.h"
+#include <openssl/evp.h>
+
+int OSSLSHA256::getHashSize()
+{
+ return 32;
+}
+
+const EVP_MD* OSSLSHA256::getEVPHash() const
+{
+ return EVP_sha256();
+}
+
diff --git a/src/lib/crypto/OSSLSHA256.h b/src/lib/crypto/OSSLSHA256.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: OSSLSHA256.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA256.h
+
+ OpenSSL SHA256 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA256_H
+#define _SOFTHSM_V2_OSSLSHA256_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA256 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA256_H
+
diff --git a/src/lib/crypto/OSSLSHA384.cpp b/src/lib/crypto/OSSLSHA384.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: OSSLSHA384.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA384.h
+
+ OpenSSL SHA384 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA384.h"
+#include <openssl/evp.h>
+
+int OSSLSHA384::getHashSize()
+{
+ return 48;
+}
+
+const EVP_MD* OSSLSHA384::getEVPHash() const
+{
+ return EVP_sha384();
+}
+
diff --git a/src/lib/crypto/OSSLSHA384.h b/src/lib/crypto/OSSLSHA384.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: OSSLSHA384.h 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA384.h
+
+ OpenSSL SHA384 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA384_H
+#define _SOFTHSM_V2_OSSLSHA384_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA384 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA384_H
+
diff --git a/src/lib/crypto/OSSLSHA512.cpp b/src/lib/crypto/OSSLSHA512.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: OSSLSHA512.cpp 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA512.h
+
+ OpenSSL SHA512 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA512.h"
+#include <openssl/evp.h>
+
+int OSSLSHA512::getHashSize()
+{
+ return 64;
+}
+
+const EVP_MD* OSSLSHA512::getEVPHash() const
+{
+ return EVP_sha512();
+}
+
diff --git a/src/lib/crypto/OSSLSHA512.h b/src/lib/crypto/OSSLSHA512.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: OSSLSHA512.h 4916 2010-10-01 15:27:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA512.h
+
+ OpenSSL SHA512 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA512_H
+#define _SOFTHSM_V2_OSSLSHA512_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA512 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA512_H
+
diff --git a/src/lib/crypto/OSSLUtil.cpp b/src/lib/crypto/OSSLUtil.cpp
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: OSSLUtil.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLUtil.h
+
+ OpenSSL convenience functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLUtil.h"
+
+// Convert an OpenSSL BIGNUM to a ByteString
+ByteString OSSL::bn2ByteString(const BIGNUM* bn)
+{
+ ByteString rv;
+
+ if (bn != NULL)
+ {
+ rv.resize(BN_num_bytes(bn));
+ BN_bn2bin(bn, &rv[0]);
+ }
+
+ return rv;
+}
+
+// Convert a ByteString to an OpenSSL BIGNUM
+BIGNUM* OSSL::byteString2bn(const ByteString& byteString)
+{
+ return BN_bin2bn(byteString.const_byte_str(), byteString.size(), NULL);
+}
+
diff --git a/src/lib/crypto/OSSLUtil.h b/src/lib/crypto/OSSLUtil.h
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: OSSLUtil.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLUtil.h
+
+ OpenSSL convenience functions
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLUTIL_H
+#define _SOFTHSM_V2_OSSLUTIL_H
+
+#include "config.h"
+#include "ByteString.h"
+#include <openssl/bn.h>
+
+namespace OSSL
+{
+ // Convert an OpenSSL BIGNUM to a ByteString
+ ByteString bn2ByteString(const BIGNUM* bn);
+
+ // Convert a ByteString to an OpenSSL BIGNUM
+ BIGNUM* byteString2bn(const ByteString& byteString);
+}
+
+#endif // !_SOFTHSM_V2_OSSLUTIL_H
+
diff --git a/src/lib/crypto/PrivateKey.h b/src/lib/crypto/PrivateKey.h
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id: PrivateKey.h 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ PrivateKey.h
+
+ Base class for private key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_PRIVATEKEY_H
+#define _SOFTHSM_V2_PRIVATEKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include <string>
+
+class PrivateKey : public Serialisable
+{
+public:
+ // Base constructors
+ PrivateKey() { }
+
+ PrivateKey(const PrivateKey& in);
+
+ // Destructor
+ virtual ~PrivateKey() { }
+
+ // Check if the private key is of the given type
+ virtual bool isOfType(const char* type) = 0;
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const = 0;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const = 0;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+};
+
+#endif // !_SOFTHSM_V2_PRIVATEKEY_H
+
diff --git a/src/lib/crypto/PublicKey.h b/src/lib/crypto/PublicKey.h
--- /dev/null
@@ -0,0 +1,67 @@
+/* $Id: PublicKey.h 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ PublicKey.h
+
+ Base class for public key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_PUBLICKEY_H
+#define _SOFTHSM_V2_PUBLICKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+
+class PublicKey : public Serialisable
+{
+public:
+ // Base constructors
+ PublicKey() { }
+
+ PublicKey(const PublicKey& in) { }
+
+ // Destructor
+ virtual ~PublicKey() { }
+
+ // Check if it is of the given type
+ virtual bool isOfType(const char* type) = 0;
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const = 0;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const = 0;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+};
+
+#endif // !_SOFTHSM_V2_PUBLICKEY_H
+
diff --git a/src/lib/crypto/RNG.h b/src/lib/crypto/RNG.h
--- /dev/null
+++ b/src/lib/crypto/RNG.h
@@ -0,0 +1,60 @@
+/* $Id: RNG.h 4786 2010-05-22 17:24:36Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RNG.h
+
+ Base class for random number generator classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RNG_H
+#define _SOFTHSM_V2_RNG_H
+
+#include "config.h"
+#include "ByteString.h"
+
+class RNG
+{
+public:
+ // Base constructor
+ RNG() { }
+
+ // Destructor
+ virtual ~RNG() { }
+
+ // Generate random data
+ virtual bool generateRandom(ByteString& data, const size_t len) = 0;
+
+ // Seed the random pool
+ virtual void seed(ByteString& seedData) = 0;
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_RNG_H
+
diff --git a/src/lib/crypto/RSAParameters.cpp b/src/lib/crypto/RSAParameters.cpp
--- /dev/null
@@ -0,0 +1,78 @@
+/* $Id: RSAParameters.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAParameters.h
+
+ RSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "RSAParameters.h"
+#include <string.h>
+
+// The type
+/*static*/ const char* RSAParameters::type = "Generic RSA parameters";
+
+// Set the public exponent
+void RSAParameters::setE(const ByteString& e)
+{
+ this->e = e;
+}
+
+// Set the bit length
+void RSAParameters::setBitLength(const size_t bitLen)
+{
+ this->bitLen = bitLen;
+}
+
+// Get the public exponent
+const ByteString& RSAParameters::getE() const
+{
+ return e;
+}
+
+// Get the bit length
+size_t RSAParameters::getBitLength() const
+{
+ return bitLen;
+}
+
+// Are the parameters of the given type?
+bool RSAParameters::areOfType(const char* type)
+{
+ return (strcmp(type, RSAParameters::type) == 0);
+}
+
+// Serialisation
+ByteString RSAParameters::serialise() const
+{
+ return ByteString();
+}
+
diff --git a/src/lib/crypto/RSAParameters.h b/src/lib/crypto/RSAParameters.h
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id: RSAParameters.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAParameters.h
+
+ RSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSAPARAMETERS_H
+#define _SOFTHSM_V2_RSAPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "AsymmetricParameters.h"
+
+class RSAParameters : public AsymmetricParameters
+{
+public:
+ // The type
+ static const char* type;
+
+ // Set the public exponent
+ void setE(const ByteString& e);
+
+ // Set the bit length
+ void setBitLength(const size_t bitLen);
+
+ // Get the public exponent
+ const ByteString& getE() const;
+
+ // Get the bit length
+ size_t getBitLength() const;
+
+ // Are the parameters of the given type?
+ virtual bool areOfType(const char* type);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+
+private:
+ ByteString e;
+ size_t bitLen;
+};
+
+#endif // !_SOFTHSM_V2_RSAPARAMETERS_H
+
diff --git a/src/lib/crypto/RSAPrivateKey.cpp b/src/lib/crypto/RSAPrivateKey.cpp
--- /dev/null
@@ -0,0 +1,188 @@
+/* $Id: RSAPrivateKey.cpp 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPrivateKey.cpp
+
+ RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "RSAPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* RSAPrivateKey::type = "Abstract RSA private key";
+
+// Check if the key is of the given type
+bool RSAPrivateKey::isOfType(const char* type)
+{
+ return !strcmp(this->type, type);
+}
+
+// Get the bit length
+unsigned long RSAPrivateKey::getBitLength() const
+{
+ return getN().bits();
+}
+
+// Get the output length
+unsigned long RSAPrivateKey::getOutputLength() const
+{
+ // Also handle odd number of bits (bits % 8 != 0)
+ return (getBitLength() + 7) / 8;
+}
+
+// Setters for the RSA private key components
+void RSAPrivateKey::setP(const ByteString& p)
+{
+ this->p = p;
+}
+
+void RSAPrivateKey::setQ(const ByteString& q)
+{
+ this->q = q;
+}
+
+void RSAPrivateKey::setPQ(const ByteString& pq)
+{
+ this->pq = pq;
+}
+
+void RSAPrivateKey::setDP1(const ByteString& dp1)
+{
+ this->dp1 = dp1;
+}
+
+void RSAPrivateKey::setDQ1(const ByteString& dq1)
+{
+ this->dq1 = dq1;
+}
+
+void RSAPrivateKey::setD(const ByteString& d)
+{
+ this->d = d;
+}
+
+// Setters for the RSA public key components
+void RSAPrivateKey::setN(const ByteString& n)
+{
+ this->n = n;
+}
+
+void RSAPrivateKey::setE(const ByteString& e)
+{
+ this->e = e;
+}
+
+// Getters for the RSA private key components
+const ByteString& RSAPrivateKey::getP() const
+{
+ return p;
+}
+
+const ByteString& RSAPrivateKey::getQ() const
+{
+ return q;
+}
+
+const ByteString& RSAPrivateKey::getPQ() const
+{
+ return pq;
+}
+
+const ByteString& RSAPrivateKey::getDP1() const
+{
+ return dp1;
+}
+
+const ByteString& RSAPrivateKey::getDQ1() const
+{
+ return dq1;
+}
+
+const ByteString& RSAPrivateKey::getD() const
+{
+ return d;
+}
+
+// Getters for the RSA public key components
+const ByteString& RSAPrivateKey::getN() const
+{
+ return n;
+}
+
+const ByteString& RSAPrivateKey::getE() const
+{
+ return e;
+}
+
+// Serialisation
+ByteString RSAPrivateKey::serialise() const
+{
+ return p.serialise() +
+ q.serialise() +
+ pq.serialise() +
+ dp1.serialise() +
+ dq1.serialise() +
+ d.serialise() +
+ n.serialise() +
+ e.serialise();
+}
+
+bool RSAPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dPQ = ByteString::chainDeserialise(serialised);
+ ByteString dDP1 = ByteString::chainDeserialise(serialised);
+ ByteString dDQ1 = ByteString::chainDeserialise(serialised);
+ ByteString dD = ByteString::chainDeserialise(serialised);
+ ByteString dN = ByteString::chainDeserialise(serialised);
+ ByteString dE = ByteString::chainDeserialise(serialised);
+
+ if ((dD.size() == 0) ||
+ (dN.size() == 0) ||
+ (dE.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setPQ(dPQ);
+ setDP1(dDP1);
+ setDQ1(dDQ1);
+ setD(dD);
+ setN(dN);
+ setE(dE);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/RSAPrivateKey.h b/src/lib/crypto/RSAPrivateKey.h
--- /dev/null
@@ -0,0 +1,93 @@
+/* $Id: RSAPrivateKey.h 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPrivateKey.h
+
+ RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSAPRIVATEKEY_H
+#define _SOFTHSM_V2_RSAPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class RSAPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the RSA private key components
+ virtual void setP(const ByteString& p);
+ virtual void setQ(const ByteString& q);
+ virtual void setPQ(const ByteString& pq);
+ virtual void setDP1(const ByteString& dp1);
+ virtual void setDQ1(const ByteString& dq1);
+ virtual void setD(const ByteString& d);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& n);
+ virtual void setE(const ByteString& e);
+
+ // Getters for the RSA private key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getPQ() const;
+ virtual const ByteString& getDP1() const;
+ virtual const ByteString& getDQ1() const;
+ virtual const ByteString& getD() const;
+
+ // Getters for the RSA public key components
+ virtual const ByteString& getN() const;
+ virtual const ByteString& getE() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString p,q,pq,dp1,dq1,d;
+
+ // Public components
+ ByteString n,e;
+};
+
+#endif // !_SOFTHSM_V2_RSAPRIVATEKEY_H
+
diff --git a/src/lib/crypto/RSAPublicKey.cpp b/src/lib/crypto/RSAPublicKey.cpp
--- /dev/null
@@ -0,0 +1,107 @@
+/* $Id: RSAPublicKey.cpp 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPublicKey.cpp
+
+ RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "RSAPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* RSAPublicKey::type = "Abstract RSA public key";
+
+// Check if the key is of the given type
+bool RSAPublicKey::isOfType(const char* type)
+{
+ return !strcmp(this->type, type);
+}
+
+// Get the bit length
+unsigned long RSAPublicKey::getBitLength() const
+{
+ return getN().bits();
+}
+
+// Get the output length
+unsigned long RSAPublicKey::getOutputLength() const
+{
+ // Also handle odd number of bits (bits % 8 != 0)
+ return (getBitLength() + 7) / 8;
+}
+
+// Setters for the RSA public key components
+void RSAPublicKey::setN(const ByteString& n)
+{
+ this->n = n;
+}
+
+void RSAPublicKey::setE(const ByteString& e)
+{
+ this->e = e;
+}
+
+// Getters for the RSA public key components
+const ByteString& RSAPublicKey::getN() const
+{
+ return n;
+}
+
+const ByteString& RSAPublicKey::getE() const
+{
+ return e;
+}
+
+// Serialisation
+ByteString RSAPublicKey::serialise() const
+{
+ return n.serialise() +
+ e.serialise();
+}
+
+bool RSAPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dN = ByteString::chainDeserialise(serialised);
+ ByteString dE = ByteString::chainDeserialise(serialised);
+
+ if ((dN.size() == 0) ||
+ (dE.size() == 0))
+ {
+ return false;
+ }
+
+ setN(dN);
+ setE(dE);
+
+ return true;
+}
+
diff --git a/src/lib/crypto/RSAPublicKey.h b/src/lib/crypto/RSAPublicKey.h
--- /dev/null
@@ -0,0 +1,74 @@
+/* $Id: RSAPublicKey.h 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPublicKey.h
+
+ RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSAPUBLICKEY_H
+#define _SOFTHSM_V2_RSAPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class RSAPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* type);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& n);
+ virtual void setE(const ByteString& e);
+
+ // Getters for the RSA public key components
+ virtual const ByteString& getN() const;
+ virtual const ByteString& getE() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString n,e;
+};
+
+#endif // !_SOFTHSM_V2_RSAPUBLICKEY_H
+
diff --git a/src/lib/crypto/SymmetricAlgorithm.cpp b/src/lib/crypto/SymmetricAlgorithm.cpp
--- /dev/null
@@ -0,0 +1,152 @@
+/* $Id: SymmetricAlgorithm.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithm.cpp
+
+ Base class for symmetric algorithm classes
+ *****************************************************************************/
+
+#include "SymmetricAlgorithm.h"
+#include <algorithm>
+#include <string.h>
+
+SymmetricAlgorithm::SymmetricAlgorithm()
+{
+ currentCipherMode = "invalid";
+ currentKey = NULL;
+ currentOperation = NONE;
+}
+
+bool SymmetricAlgorithm::encryptInit(const SymmetricKey* key, const std::string mode /* = "CBC" */, const ByteString& IV /* = ByteString() */)
+{
+ if ((key == NULL) || (currentOperation != NONE))
+ {
+ return false;
+ }
+
+ currentKey = key;
+ currentCipherMode.clear();
+ currentCipherMode.resize(mode.size());
+ transform(mode.begin(), mode.end(), currentCipherMode.begin(), tolower);
+ currentOperation = ENCRYPT;
+
+ return true;
+}
+
+bool SymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData)
+{
+ if (currentOperation != ENCRYPT)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool SymmetricAlgorithm::encryptFinal(ByteString& encryptedData)
+{
+ if (currentOperation != ENCRYPT)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+
+ return true;
+}
+
+bool SymmetricAlgorithm::decryptInit(const SymmetricKey* key, const std::string mode /* = "CBC" */, const ByteString& IV /* = ByteString() */)
+{
+ if ((key == NULL) || (currentOperation != NONE))
+ {
+ return false;
+ }
+
+ currentKey = key;
+ currentCipherMode.clear();
+ currentCipherMode.resize(mode.size());
+ transform(mode.begin(), mode.end(), currentCipherMode.begin(), tolower);
+ currentOperation = DECRYPT;
+
+ return true;
+}
+
+
+bool SymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data)
+{
+ if (currentOperation != DECRYPT)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool SymmetricAlgorithm::decryptFinal(ByteString& data)
+{
+ if (currentOperation != DECRYPT)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+
+ return true;
+}
+
+// Key factory
+bool SymmetricAlgorithm::generateKey(SymmetricKey& key, RNG* rng /* = NULL */)
+{
+ if (rng == NULL)
+ {
+ return false;
+ }
+
+ if (key.getBitLen() == 0)
+ {
+ return false;
+ }
+
+ ByteString keyBits;
+
+ if (!rng->generateRandom(keyBits, key.getBitLen()/8))
+ {
+ return false;
+ }
+
+ key.setKeyBits(keyBits);
+
+ return true;
+}
+
+bool SymmetricAlgorithm::reconstructKey(SymmetricKey& key, const ByteString& serialisedData)
+{
+ return key.setKeyBits(serialisedData);
+}
+
diff --git a/src/lib/crypto/SymmetricAlgorithm.h b/src/lib/crypto/SymmetricAlgorithm.h
--- /dev/null
@@ -0,0 +1,84 @@
+/* $Id: SymmetricAlgorithm.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithm.h
+
+ Base class for symmetric algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_SYMMETRICALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "RNG.h"
+
+class SymmetricAlgorithm
+{
+public:
+ // Base constructors
+ SymmetricAlgorithm();
+
+ // Destructor
+ virtual ~SymmetricAlgorithm() { }
+
+ // Encryption functions
+ virtual bool encryptInit(const SymmetricKey* key, const std::string mode = "cbc", const ByteString& IV = ByteString());
+ virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData);
+ virtual bool encryptFinal(ByteString& encryptedData);
+
+ // Decryption functions
+ virtual bool decryptInit(const SymmetricKey* key, const std::string mode = "cbc", const ByteString& IV = ByteString());
+ virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data);
+ virtual bool decryptFinal(ByteString& data);
+
+ // Key factory
+ virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL);
+ virtual bool reconstructKey(SymmetricKey& key, const ByteString& serialisedData);
+
+protected:
+ // The current cipher mode
+ std::string currentCipherMode;
+
+ // The current key
+ const SymmetricKey* currentKey;
+
+ // The current operation
+ enum
+ {
+ NONE,
+ ENCRYPT,
+ DECRYPT
+ }
+ currentOperation;
+};
+
+#endif // !_SOFTHSM_V2_SYMMETRICALGORITHM_H
+
diff --git a/src/lib/crypto/SymmetricKey.cpp b/src/lib/crypto/SymmetricKey.cpp
--- /dev/null
@@ -0,0 +1,82 @@
+/* $Id: SymmetricKey.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricKey.cpp
+
+ Base class for symmetric key classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "SymmetricKey.h"
+
+// Base constructors
+SymmetricKey::SymmetricKey(size_t bitLen /* = 0 */)
+{
+ this->bitLen = bitLen;
+}
+
+SymmetricKey::SymmetricKey(const SymmetricKey& in)
+{
+ keyData = in.keyData;
+ bitLen = in.bitLen;
+}
+
+// Set the key
+bool SymmetricKey::setKeyBits(const ByteString& keybits)
+{
+ if ((bitLen > 0) && ((keybits.size() * 8) != bitLen))
+ {
+ return false;
+ }
+
+ keyData = keybits;
+
+ return true;
+}
+
+// Get the key
+const ByteString& SymmetricKey::getKeyBits() const
+{
+ return keyData;
+}
+
+// Serialisation
+ByteString SymmetricKey::serialise() const
+{
+ return keyData;
+}
+
+// Retrieve the bit length
+size_t SymmetricKey::getBitLen() const
+{
+ return bitLen;
+}
+
diff --git a/src/lib/crypto/SymmetricKey.h b/src/lib/crypto/SymmetricKey.h
--- /dev/null
@@ -0,0 +1,74 @@
+/* $Id: SymmetricKey.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricKey.h
+
+ Base class for symmetric key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SYMMETRICKEY_H
+#define _SOFTHSM_V2_SYMMETRICKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+
+class SymmetricKey : public Serialisable
+{
+public:
+ // Base constructors
+ SymmetricKey(size_t bitLen = 0);
+
+ SymmetricKey(const SymmetricKey& in);
+
+ // Destructor
+ virtual ~SymmetricKey() { }
+
+ // Set the key
+ virtual bool setKeyBits(const ByteString& keybits);
+
+ // Get the key
+ virtual const ByteString& getKeyBits() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+
+ // Retrieve the bit length
+ virtual size_t getBitLen() const;
+
+protected:
+ // The key
+ ByteString keyData;
+
+ // The key length in bits
+ size_t bitLen;
+};
+
+#endif // !_SOFTHSM_V2_SYMMETRICKEY_H
+
diff --git a/src/lib/crypto/test/AESTests.cpp b/src/lib/crypto/test/AESTests.cpp
--- /dev/null
@@ -0,0 +1,455 @@
+/* $Id: AESTests.cpp 4795 2010-05-24 18:48:50Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESTests.cpp
+
+ Contains test cases to test the AES implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "AESTests.h"
+#include "CryptoFactory.h"
+#include "AESKey.h"
+#include <stdio.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AESTests);
+
+void AESTests::setUp()
+{
+ aes = NULL;
+
+ aes = CryptoFactory::i()->getSymmetricAlgorithm("aes");
+
+ // Check the return value
+ CPPUNIT_ASSERT(aes != NULL);
+}
+
+void AESTests::tearDown()
+{
+ if (aes != NULL)
+ {
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+ }
+
+ fflush(stdout);
+}
+
+void AESTests::testCBC()
+{
+ char testKeys128[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "89436760984679018453504364534464",
+ "49587346983643545706904580436731"
+ };
+
+ char testKeys192[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101213141516171819",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "096874395874290867409857496743857632098479834634",
+ "439867439058743095864395348375043296845094854983"
+ };
+
+ char testKeys256[][65] =
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
+ "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
+ "4394398576098257436095746985679043867498572406874967416846341641",
+ "4369006859867098670492857409386741095643756930847023587048579014"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testIV[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "69836472094875029486750948672066",
+ "48670943876904867104398574908554"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ char commandLine[2048];
+
+ ByteString keyData128(testKeys128[i]);
+ ByteString keyData192(testKeys192[i]);
+ ByteString keyData256(testKeys256[i]);
+
+ AESKey aesKey128(128);
+ CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128));
+ AESKey aesKey192(192);
+ CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192));
+ AESKey aesKey256(256);
+ CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 128-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl aes-128-cbc -in shsmv2-aestest.tmp -out shsmv2-aestest-out.tmp -K %s -iv %s",
+ testKeys128[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, "cbc", IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, "cbc", IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 192-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl aes-192-cbc -in shsmv2-aestest.tmp -out shsmv2-aestest-out.tmp -K %s -iv %s",
+ testKeys192[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, "cbc", IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, "cbc", IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 256-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl aes-256-cbc -in shsmv2-aestest.tmp -out shsmv2-aestest-out.tmp -K %s -iv %s",
+ testKeys256[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, "cbc", IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, "cbc", IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void AESTests::testECB()
+{
+ char testKeys128[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "89436760984679018453504364534464",
+ "49587346983643545706904580436731"
+ };
+
+ char testKeys192[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101213141516171819",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "096874395874290867409857496743857632098479834634",
+ "439867439058743095864395348375043296845094854983"
+ };
+
+ char testKeys256[][65] =
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
+ "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
+ "4394398576098257436095746985679043867498572406874967416846341641",
+ "4369006859867098670492857409386741095643756930847023587048579014"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testIV[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "69836472094875029486750948672066",
+ "48670943876904867104398574908554"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ char commandLine[2048];
+
+ ByteString keyData128(testKeys128[i]);
+ ByteString keyData192(testKeys192[i]);
+ ByteString keyData256(testKeys256[i]);
+
+ AESKey aesKey128(128);
+ CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128));
+ AESKey aesKey192(192);
+ CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192));
+ AESKey aesKey256(256);
+ CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 128-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl aes-128-ecb -in shsmv2-aestest.tmp -out shsmv2-aestest-out.tmp -K %s -iv %s",
+ testKeys128[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, "ecb", IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, "ecb", IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 192-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl aes-192-ecb -in shsmv2-aestest.tmp -out shsmv2-aestest-out.tmp -K %s -iv %s",
+ testKeys192[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, "ecb", IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, "ecb", IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 256-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl aes-256-ecb -in shsmv2-aestest.tmp -out shsmv2-aestest-out.tmp -K %s -iv %s",
+ testKeys256[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, "ecb", IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, "ecb", IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void AESTests::writeTmpFile(ByteString& data)
+{
+ FILE* out = fopen("shsmv2-aestest.tmp", "w");
+ CPPUNIT_ASSERT(out != NULL);
+
+ CPPUNIT_ASSERT(fwrite(&data[0], 1, data.size(), out) == data.size());
+ CPPUNIT_ASSERT(!fclose(out));
+}
+
+void AESTests::readTmpFile(ByteString& data)
+{
+ unsigned char buf[256];
+
+ data.wipe();
+
+ FILE* in = fopen("shsmv2-aestest-out.tmp", "r");
+ CPPUNIT_ASSERT(in != NULL);
+
+ int read = 0;
+
+ do
+ {
+ read = fread(buf, 1, 256, in);
+
+ data += ByteString(buf, read);
+ }
+ while (read > 0);
+
+ CPPUNIT_ASSERT(read == 0);
+ CPPUNIT_ASSERT(!fclose(in));
+}
+
diff --git a/src/lib/crypto/test/AESTests.h b/src/lib/crypto/test/AESTests.h
--- /dev/null
@@ -0,0 +1,65 @@
+/* $Id: AESTests.h 4756 2010-03-08 21:02:27Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESTests.h
+
+ Contains test cases to test the AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_AESTESTS_H
+#define _SOFTHSM_V2_AESTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "SymmetricAlgorithm.h"
+
+class AESTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(AESTests);
+ CPPUNIT_TEST(testCBC);
+ CPPUNIT_TEST(testECB);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCBC();
+ void testECB();
+
+ void setUp();
+ void tearDown();
+
+private:
+ void writeTmpFile(ByteString& data);
+
+ void readTmpFile(ByteString& data);
+
+ // AES instance
+ SymmetricAlgorithm* aes;
+};
+
+#endif // !_SOFTHSM_V2_AESTESTS_H
+
diff --git a/src/lib/crypto/test/DESTests.cpp b/src/lib/crypto/test/DESTests.cpp
--- /dev/null
@@ -0,0 +1,827 @@
+/* $Id: DESTests.cpp 4795 2010-05-24 18:48:50Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESTests.cpp
+
+ Contains test cases to test the DES implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DESTests.h"
+#include "CryptoFactory.h"
+#include "DESKey.h"
+#include <stdio.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DESTests);
+
+void DESTests::setUp()
+{
+ des = NULL;
+
+ des = CryptoFactory::i()->getSymmetricAlgorithm("des");
+
+ // Check the return value
+ CPPUNIT_ASSERT(des != NULL);
+}
+
+void DESTests::tearDown()
+{
+ if (des != NULL)
+ {
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ }
+
+ fflush(stdout);
+}
+
+void DESTests::testCBC()
+{
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ char commandLine[2048];
+
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 56-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-cbc -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys56[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, "cbc", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, "cbc", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede-cbc -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys112[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, "cbc", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, "cbc", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 168-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede3-cbc -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys168[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, "cbc", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, "cbc", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::testECB()
+{
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ char commandLine[2048];
+
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 56-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ecb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys56[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, "ecb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, "ecb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys112[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, "ecb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, "ecb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 168-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede3 -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys168[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, "ecb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, "ecb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::testOFB()
+{
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ char commandLine[2048];
+
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 56-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ofb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys56[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, "ofb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, "ofb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede-ofb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys112[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, "ofb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, "ofb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 168-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede3-ofb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys168[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, "ofb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, "ofb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::testCFB()
+{
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ char commandLine[2048];
+
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 56-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-cfb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys56[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, "cfb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, "cfb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede-cfb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys112[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, "cfb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, "cfb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 168-bit key
+
+ // First, use the OpenSSL command line tool to encrypt the test data
+ writeTmpFile(plainText);
+
+ sprintf(commandLine, "openssl des-ede3-cfb -in shsmv2-destest.tmp -out shsmv2-destest-out.tmp -K %s -iv %s",
+ testKeys168[i], testIV[i]);
+
+ CPPUNIT_ASSERT(!system(commandLine));
+
+ readTmpFile(cipherText);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, "cfb", IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, "cfb", IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::writeTmpFile(ByteString& data)
+{
+ FILE* out = fopen("shsmv2-destest.tmp", "w");
+ CPPUNIT_ASSERT(out != NULL);
+
+ CPPUNIT_ASSERT(fwrite(&data[0], 1, data.size(), out) == data.size());
+ CPPUNIT_ASSERT(!fclose(out));
+}
+
+void DESTests::readTmpFile(ByteString& data)
+{
+ unsigned char buf[256];
+
+ data.wipe();
+
+ FILE* in = fopen("shsmv2-destest-out.tmp", "r");
+ CPPUNIT_ASSERT(in != NULL);
+
+ int read = 0;
+
+ do
+ {
+ read = fread(buf, 1, 256, in);
+
+ data += ByteString(buf, read);
+ }
+ while (read > 0);
+
+ CPPUNIT_ASSERT(read == 0);
+ CPPUNIT_ASSERT(!fclose(in));
+}
+
diff --git a/src/lib/crypto/test/DESTests.h b/src/lib/crypto/test/DESTests.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: DESTests.h 4757 2010-03-10 13:40:30Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESTests.h
+
+ Contains test cases to test the DES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DESTESTS_H
+#define _SOFTHSM_V2_DESTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "SymmetricAlgorithm.h"
+
+class DESTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DESTests);
+ CPPUNIT_TEST(testCBC);
+ CPPUNIT_TEST(testECB);
+ CPPUNIT_TEST(testOFB);
+ CPPUNIT_TEST(testCFB);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCBC();
+ void testECB();
+ void testOFB();
+ void testCFB();
+
+ void setUp();
+ void tearDown();
+
+private:
+ void writeTmpFile(ByteString& data);
+
+ void readTmpFile(ByteString& data);
+
+ // DES instance
+ SymmetricAlgorithm* des;
+};
+
+#endif // !_SOFTHSM_V2_DESTESTS_H
+
diff --git a/src/lib/crypto/test/DSATests.cpp b/src/lib/crypto/test/DSATests.cpp
--- /dev/null
@@ -0,0 +1,227 @@
+/* $Id: DSATests.cpp 6750 2012-10-22 12:39:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSATests.cpp
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DSATests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#include "DSAParameters.h"
+#include "DSAPublicKey.h"
+#include "DSAPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DSATests);
+
+void DSATests::setUp()
+{
+ dsa = NULL;
+
+ dsa = CryptoFactory::i()->getAsymmetricAlgorithm("DSA");
+
+ // Check the DSA object
+ CPPUNIT_ASSERT(dsa != NULL);
+}
+
+void DSATests::tearDown()
+{
+ if (dsa != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ }
+
+ fflush(stdout);
+}
+
+void DSATests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(512);
+ keySizes.push_back(768);
+ keySizes.push_back(1024);
+
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ // Generate parameters
+ DSAParameters* p;
+ AsymmetricParameters** ap = (AsymmetricParameters**) &p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) *k));
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p));
+
+ DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
+ DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getBitLength() == *k);
+ CPPUNIT_ASSERT(priv->getBitLength() == *k);
+
+ dsa->recycleParameters(p);
+ dsa->recycleKeyPair(kp);
+ }
+}
+
+void DSATests::testSerialisation()
+{
+ // Generate 1024-bit parameters for testing
+ DSAParameters* p;
+ AsymmetricParameters** ap = (AsymmetricParameters**) &p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) 1024));
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dP;
+
+ CPPUNIT_ASSERT(dsa->reconstructParameters(&dP, serialisedParams));
+
+ CPPUNIT_ASSERT(dP->areOfType(DSAParameters::type));
+
+ DSAParameters* ddP = (DSAParameters*) dP;
+
+ CPPUNIT_ASSERT(p->getP() == ddP->getP());
+ CPPUNIT_ASSERT(p->getQ() == ddP->getQ());
+ CPPUNIT_ASSERT(p->getG() == ddP->getG());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, dP));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(dsa->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ DSAPrivateKey* privKey = (DSAPrivateKey*) kp->getPrivateKey();
+ DSAPublicKey* pubKey = (DSAPublicKey*) kp->getPublicKey();
+
+ DSAPrivateKey* dPrivKey = (DSAPrivateKey*) dKP->getPrivateKey();
+ DSAPublicKey* dPubKey = (DSAPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP());
+ CPPUNIT_ASSERT(privKey->getQ() == dPrivKey->getQ());
+ CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG());
+ CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX());
+ CPPUNIT_ASSERT(privKey->getY() == dPrivKey->getY());
+
+ CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP());
+ CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ());
+ CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG());
+ CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY());
+
+ dsa->recycleParameters(p);
+ dsa->recycleParameters(dP);
+ dsa->recycleKeyPair(kp);
+ dsa->recycleKeyPair(dKP);
+}
+
+void DSATests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(512);
+ keySizes.push_back(768);
+ keySizes.push_back(1024);
+
+ // Mechanisms to test
+ std::vector<const char*> mechanisms;
+ mechanisms.push_back("dsa-sha1");
+
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ // Generate parameters
+ AsymmetricParameters* p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) *k));
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ for (std::vector<const char*>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++)
+ {
+ ByteString blockSignature, singlePartSignature;
+
+ // Sign the data in blocks
+ CPPUNIT_ASSERT(dsa->signInit(kp->getPrivateKey(), *m));
+ CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(0, 134)));
+ CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134, 289)));
+ CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134 + 289)));
+ CPPUNIT_ASSERT(dsa->signFinal(blockSignature));
+
+ // Sign the data in one pass
+ CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m));
+
+ // Now perform multi-pass verification
+ CPPUNIT_ASSERT(dsa->verifyInit(kp->getPublicKey(), *m));
+ CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(0, 125)));
+ CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125, 247)));
+ CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125 + 247)));
+ CPPUNIT_ASSERT(dsa->verifyFinal(blockSignature));
+
+ // And single-pass verification
+ CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m));
+ }
+
+ dsa->recycleKeyPair(kp);
+ dsa->recycleParameters(p);
+ }
+}
+
+void DSATests::testSignVerifyKnownVector()
+{
+ // TODO
+}
+
diff --git a/src/lib/crypto/test/DSATests.h b/src/lib/crypto/test/DSATests.h
--- /dev/null
@@ -0,0 +1,65 @@
+/* $Id: DSATests.h 4770 2010-03-27 13:21:59Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSATests.h
+
+ Contains test cases to test the DSA class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSATESTS_H
+#define _SOFTHSM_V2_DSATESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class DSATests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DSATests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // DSA instance
+ AsymmetricAlgorithm* dsa;
+};
+
+#endif // !_SOFTHSM_V2_DSATESTS_H
+
diff --git a/src/lib/crypto/test/HashTests.cpp b/src/lib/crypto/test/HashTests.cpp
--- /dev/null
@@ -0,0 +1,362 @@
+/* $Id: HashTests.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashTests.cpp
+
+ Contains test cases to test the hash implementations
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "HashTests.h"
+#include "CryptoFactory.h"
+#include <stdio.h>
+#include "HashAlgorithm.h"
+#include "RNG.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HashTests);
+
+void HashTests::setUp()
+{
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::tearDown()
+{
+ if (hash != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ }
+
+ fflush(stdout);
+}
+
+void HashTests::testMD5()
+{
+ // Get an RNG and MD5 hash instance
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("md5")) != NULL);
+
+ // Generate some random input data
+ ByteString b;
+ ByteString osslHash, shsmHash;
+
+ CPPUNIT_ASSERT(rng->generateRandom(b, 52237));
+
+ // Write it to file
+ writeTmpFile(b);
+
+ // Use OpenSSL externally to hash it
+ CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl md5 -binary > shsmv2-hashtest-out.tmp") == 0);
+
+ // Read the hash from file
+ readTmpFile(osslHash);
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a single part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA1()
+{
+ // Get an RNG and SHA1 hash instance
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("sha1")) != NULL);
+
+ // Generate some random input data
+ ByteString b;
+ ByteString osslHash, shsmHash;
+
+ CPPUNIT_ASSERT(rng->generateRandom(b, 32598));
+
+ // Write it to file
+ writeTmpFile(b);
+
+ // Use OpenSSL externally to hash it
+ CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl sha1 -binary > shsmv2-hashtest-out.tmp") == 0);
+
+ // Read the hash from file
+ readTmpFile(osslHash);
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a single part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA224()
+{
+ // Get an RNG and SHA224 hash instance
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("sha224")) != NULL);
+
+ // Generate some random input data
+ ByteString b;
+ ByteString osslHash, shsmHash;
+
+ CPPUNIT_ASSERT(rng->generateRandom(b, 53287));
+
+ // Write it to file
+ writeTmpFile(b);
+
+ // Use OpenSSL externally to hash it
+ CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl sha -sha224 -binary > shsmv2-hashtest-out.tmp") == 0);
+
+ // Read the hash from file
+ readTmpFile(osslHash);
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a single part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA256()
+{
+ // Get an RNG and SHA256 hash instance
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("sha256")) != NULL);
+
+ // Generate some random input data
+ ByteString b;
+ ByteString osslHash, shsmHash;
+
+ CPPUNIT_ASSERT(rng->generateRandom(b, 53287));
+
+ // Write it to file
+ writeTmpFile(b);
+
+ // Use OpenSSL externally to hash it
+ CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl sha -sha256 -binary > shsmv2-hashtest-out.tmp") == 0);
+
+ // Read the hash from file
+ readTmpFile(osslHash);
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a single part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA384()
+{
+ // Get an RNG and SHA384 hash instance
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("sha384")) != NULL);
+
+ // Generate some random input data
+ ByteString b;
+ ByteString osslHash, shsmHash;
+
+ CPPUNIT_ASSERT(rng->generateRandom(b, 53287));
+
+ // Write it to file
+ writeTmpFile(b);
+
+ // Use OpenSSL externally to hash it
+ CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl sha -sha384 -binary > shsmv2-hashtest-out.tmp") == 0);
+
+ // Read the hash from file
+ readTmpFile(osslHash);
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a single part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA512()
+{
+ // Get an RNG and SHA512 hash instance
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("sha512")) != NULL);
+
+ // Generate some random input data
+ ByteString b;
+ ByteString osslHash, shsmHash;
+
+ CPPUNIT_ASSERT(rng->generateRandom(b, 35298));
+
+ // Write it to file
+ writeTmpFile(b);
+
+ // Use OpenSSL externally to hash it
+ CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl sha -sha512 -binary > shsmv2-hashtest-out.tmp") == 0);
+
+ // Read the hash from file
+ readTmpFile(osslHash);
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a single part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::writeTmpFile(ByteString& data)
+{
+ FILE* out = fopen("shsmv2-hashtest.tmp", "w");
+ CPPUNIT_ASSERT(out != NULL);
+
+ CPPUNIT_ASSERT(fwrite(&data[0], 1, data.size(), out) == data.size());
+ CPPUNIT_ASSERT(!fclose(out));
+}
+
+void HashTests::readTmpFile(ByteString& data)
+{
+ unsigned char buf[256];
+
+ data.wipe();
+
+ FILE* in = fopen("shsmv2-hashtest-out.tmp", "r");
+ CPPUNIT_ASSERT(in != NULL);
+
+ int read = 0;
+
+ do
+ {
+ read = fread(buf, 1, 256, in);
+
+ data += ByteString(buf, read);
+ }
+ while (read > 0);
+
+ CPPUNIT_ASSERT(read == 0);
+ CPPUNIT_ASSERT(!fclose(in));
+}
+
diff --git a/src/lib/crypto/test/HashTests.h b/src/lib/crypto/test/HashTests.h
--- /dev/null
@@ -0,0 +1,75 @@
+/* $Id: HashTests.h 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashTests.h
+
+ Contains test cases to test the hash implementations
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HASHTESTS_H
+#define _SOFTHSM_V2_HASHTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "HashAlgorithm.h"
+#include "RNG.h"
+
+class HashTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(HashTests);
+ CPPUNIT_TEST(testMD5);
+ CPPUNIT_TEST(testSHA1);
+ CPPUNIT_TEST(testSHA224);
+ CPPUNIT_TEST(testSHA256);
+ CPPUNIT_TEST(testSHA384);
+ CPPUNIT_TEST(testSHA512);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testMD5();
+ void testSHA1();
+ void testSHA224();
+ void testSHA256();
+ void testSHA384();
+ void testSHA512();
+
+ void setUp();
+ void tearDown();
+
+private:
+ void writeTmpFile(ByteString& data);
+
+ void readTmpFile(ByteString& data);
+
+ HashAlgorithm* hash;
+
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_HASHTESTS_H
+
diff --git a/src/lib/crypto/test/Makefile.am b/src/lib/crypto/test/Makefile.am
--- /dev/null
@@ -0,0 +1,35 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../cryptoki_compat \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = cryptotest
+
+cryptotest_SOURCES = cryptotest.cpp \
+ AESTests.cpp \
+ DESTests.cpp \
+ DSATests.cpp \
+ HashTests.cpp \
+ RNGTests.cpp \
+ RSATests.cpp \
+ chisq.c \
+ ent.c \
+ iso8859.c \
+ randtest.c
+
+cryptotest_LDADD = ../../libsofthsm_convarch.la
+
+cryptotest_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs`
+
+TESTS = cryptotest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/crypto/test/RNGTests.cpp b/src/lib/crypto/test/RNGTests.cpp
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id: RNGTests.cpp 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RNGTests.cpp
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNGTests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "ent.h"
+#include <stdio.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RNGTests);
+
+void RNGTests::setUp()
+{
+ rng = NULL;
+
+ rng = CryptoFactory::i()->getRNG();
+
+ // Check the RNG
+ CPPUNIT_ASSERT(rng != NULL);
+}
+
+void RNGTests::tearDown()
+{
+ fflush(stdout);
+}
+
+void RNGTests::testSimpleComparison()
+{
+ ByteString a,b;
+
+ CPPUNIT_ASSERT(rng->generateRandom(a, 256));
+ CPPUNIT_ASSERT(rng->generateRandom(b, 256));
+ CPPUNIT_ASSERT(a.size() == 256);
+ CPPUNIT_ASSERT(b.size() == 256);
+ CPPUNIT_ASSERT(a != b);
+}
+
+void RNGTests::testEnt()
+{
+ ByteString a;
+ double entropy, chiProbability, arithMean, montePi, serialCorrelation;
+
+ // Generate 10MB of random data
+ CPPUNIT_ASSERT(rng->generateRandom(a, 10*1024*1024));
+
+ // Perform entropy tests
+ doEnt(a.byte_str(), a.size(), &entropy, &chiProbability, &arithMean, &montePi, &serialCorrelation);
+
+ // Check entropy
+ CPPUNIT_ASSERT(entropy >= 7.999);
+ CPPUNIT_ASSERT((arithMean >= 127.4) && (arithMean <= 127.6));
+ CPPUNIT_ASSERT(serialCorrelation <= 0.001);
+}
+
diff --git a/src/lib/crypto/test/RNGTests.h b/src/lib/crypto/test/RNGTests.h
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id: RNGTests.h 4751 2010-03-05 16:28:06Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RNGTests.h
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RNGTESTS_H
+#define _SOFTHSM_V2_RNGTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+
+class RNGTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RNGTests);
+ CPPUNIT_TEST(testSimpleComparison);
+ CPPUNIT_TEST(testEnt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSimpleComparison();
+ void testEnt();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // RNG instance
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_RNGTESTS_H
+
diff --git a/src/lib/crypto/test/RSATests.cpp b/src/lib/crypto/test/RSATests.cpp
--- /dev/null
@@ -0,0 +1,506 @@
+/* $Id: RSATests.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSATests.cpp
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RSATests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#include "RSAParameters.h"
+#include "RSAPublicKey.h"
+#include "RSAPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RSATests);
+
+void RSATests::setUp()
+{
+ rsa = NULL;
+
+ rsa = CryptoFactory::i()->getAsymmetricAlgorithm("RSA");
+
+ // Check the RSA object
+ CPPUNIT_ASSERT(rsa != NULL);
+}
+
+void RSATests::tearDown()
+{
+ if (rsa != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+ }
+
+ fflush(stdout);
+}
+
+void RSATests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ // Public exponents to test
+ std::vector<ByteString> exponents;
+ exponents.push_back("010001");
+ exponents.push_back("03");
+ exponents.push_back("0B");
+ exponents.push_back("11");
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1023);
+ keySizes.push_back(1024);
+ keySizes.push_back(1025);
+ keySizes.push_back(1280);
+ keySizes.push_back(2048);
+ //keySizes.push_back(4096);
+
+ for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
+ {
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ p.setE(*e);
+ p.setBitLength(*k);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+
+ RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getBitLength() == *k);
+ CPPUNIT_ASSERT(priv->getBitLength() == *k);
+ CPPUNIT_ASSERT(pub->getE() == *e);
+ CPPUNIT_ASSERT(priv->getE() == *e);
+
+ rsa->recycleKeyPair(kp);
+ }
+ }
+}
+
+void RSATests::testSerialisation()
+{
+ // Generate a 1024-bit key-pair for testing
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ p.setE("010001");
+ p.setBitLength(1024);
+
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ CPPUNIT_ASSERT(serialisedKP.size() != 0);
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(rsa->reconstructKeyPair(&dKP, serialisedKP));
+ CPPUNIT_ASSERT(serialisedKP.size() == 0);
+ CPPUNIT_ASSERT(dKP != NULL);
+
+ RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+
+ RSAPublicKey* dPub = (RSAPublicKey*) dKP->getPublicKey();
+ RSAPrivateKey* dPriv = (RSAPrivateKey*) dKP->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getN() == dPub->getN());
+ CPPUNIT_ASSERT(pub->getE() == dPub->getE());
+
+ CPPUNIT_ASSERT(priv->getP() == dPriv->getP());
+ CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ());
+ CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ());
+ CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1());
+ CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1());
+ CPPUNIT_ASSERT(priv->getD() == dPriv->getD());
+ CPPUNIT_ASSERT(priv->getN() == dPriv->getN());
+ CPPUNIT_ASSERT(priv->getE() == dPriv->getE());
+
+ // Serialise and deserialise the public key
+ ByteString serialisedPub = pub->serialise();
+
+ RSAPublicKey* desPub;
+
+ CPPUNIT_ASSERT(rsa->reconstructPublicKey((PublicKey**) &desPub, serialisedPub));
+ CPPUNIT_ASSERT(serialisedPub.size() == 0);
+ CPPUNIT_ASSERT(desPub != NULL);
+
+ CPPUNIT_ASSERT(pub->getN() == desPub->getN());
+ CPPUNIT_ASSERT(pub->getE() == desPub->getE());
+
+ // Serialise and deserialise the private key
+ ByteString serialisedPriv = priv->serialise();
+
+ RSAPrivateKey* desPriv;
+
+ CPPUNIT_ASSERT(rsa->reconstructPrivateKey((PrivateKey**) &desPriv, serialisedPriv));
+ CPPUNIT_ASSERT(serialisedPriv.size() == 0);
+ CPPUNIT_ASSERT(desPriv != NULL);
+
+ CPPUNIT_ASSERT(priv->getP() == desPriv->getP());
+ CPPUNIT_ASSERT(priv->getQ() == desPriv->getQ());
+ CPPUNIT_ASSERT(priv->getPQ() == desPriv->getPQ());
+ CPPUNIT_ASSERT(priv->getDP1() == desPriv->getDP1());
+ CPPUNIT_ASSERT(priv->getDQ1() == desPriv->getDQ1());
+ CPPUNIT_ASSERT(priv->getD() == desPriv->getD());
+ CPPUNIT_ASSERT(priv->getN() == desPriv->getN());
+ CPPUNIT_ASSERT(priv->getE() == desPriv->getE());
+
+ rsa->recycleKeyPair(kp);
+ rsa->recycleKeyPair(dKP);
+ rsa->recyclePublicKey(desPub);
+ rsa->recyclePrivateKey(desPriv);
+}
+
+void RSATests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ // Public exponents to test
+ std::vector<ByteString> exponents;
+ exponents.push_back("010001");
+ exponents.push_back("03");
+ exponents.push_back("0B");
+ exponents.push_back("11");
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+ keySizes.push_back(1280);
+ keySizes.push_back(2048);
+ //keySizes.push_back(4096);
+
+ // Mechanisms to test
+ std::vector<const char*> mechanisms;
+ mechanisms.push_back("rsa-md5-pkcs");
+ mechanisms.push_back("rsa-sha1-pkcs");
+ mechanisms.push_back("rsa-sha256-pkcs");
+ mechanisms.push_back("rsa-sha384-pkcs");
+ mechanisms.push_back("rsa-sha512-pkcs");
+ mechanisms.push_back("rsa-ssl");
+
+ for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
+ {
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ p.setE(*e);
+ p.setBitLength(*k);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ // Test mechanisms that perform internal hashing
+ for (std::vector<const char*>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++)
+ {
+ ByteString blockSignature, singlePartSignature;
+
+ // Sign the data in blocks
+ CPPUNIT_ASSERT(rsa->signInit(kp->getPrivateKey(), *m));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(0, 134)));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134, 289)));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134 + 289)));
+ CPPUNIT_ASSERT(rsa->signFinal(blockSignature));
+
+ // Sign the data in one pass
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m));
+
+ // If it is not a PSS signature, check if the two signatures match
+ if (strstr(*m, "pss") == NULL)
+ {
+ // Check if the two signatures match
+ CPPUNIT_ASSERT(blockSignature == singlePartSignature);
+ }
+
+ // Now perform multi-pass verification
+ CPPUNIT_ASSERT(rsa->verifyInit(kp->getPublicKey(), *m));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(0, 125)));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125, 247)));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125 + 247)));
+ CPPUNIT_ASSERT(rsa->verifyFinal(blockSignature));
+
+ // And single-pass verification
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m));
+ }
+
+ // Test mechanisms that do not perform internal hashing
+
+ // Test PKCS #1 signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 35));
+
+ // Sign the data
+ ByteString signature;
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, "rsa-pkcs"));
+
+ // Verify the signature
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, "rsa-pkcs"));
+
+ // Test raw RSA signing
+ size_t byteSize = *k >> 3;
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, byteSize));
+
+ // Strip the topmost bit
+ dataToSign[0] &= 0x7F;
+
+ // Sign the data
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, "rsa-raw"));
+
+ // Verify the signature
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, "rsa-raw"));
+
+ rsa->recycleKeyPair(kp);
+ }
+ }
+}
+
+void RSATests::testSignVerifyKnownVector()
+{
+ // These test vectors were taken from the Crypto++ set of test vectors
+ // Crypto++ can be downloaded from www.cryptopp.com
+
+ RSAPublicKey* pubKey1 = (RSAPublicKey*) rsa->newPublicKey();
+ RSAPublicKey* pubKey2 = (RSAPublicKey*) rsa->newPublicKey();
+ RSAPrivateKey* privKey1_1 = (RSAPrivateKey*) rsa->newPrivateKey();
+ RSAPrivateKey* privKey1_2 = (RSAPrivateKey*) rsa->newPrivateKey();
+ RSAPrivateKey* privKey2_1 = (RSAPrivateKey*) rsa->newPrivateKey();
+ RSAPrivateKey* privKey2_2 = (RSAPrivateKey*) rsa->newPrivateKey();
+
+ // Reconstruct public and private key #1
+ ByteString n1 = "0A66791DC6988168DE7AB77419BB7FB0C001C62710270075142942E19A8D8C51D053B3E3782A1DE5DC5AF4EBE99468170114A1DFE67CDC9A9AF55D655620BBAB";
+ ByteString e1 = "010001";
+ ByteString d1 = "0123C5B61BA36EDB1D3679904199A89EA80C09B9122E1400C09ADCF7784676D01D23356A7D44D6BD8BD50E94BFC723FA87D8862B75177691C11D757692DF8881";
+ ByteString p1 = "33D48445C859E52340DE704BCDDA065FBB4058D740BD1D67D29E9C146C11CF61";
+ ByteString q1 = "335E8408866B0FD38DC7002D3F972C67389A65D5D8306566D5C4F2A5AA52628B";
+ ByteString dp11 = "045EC90071525325D3D46DB79695E9AFACC4523964360E02B119BAA366316241";
+ ByteString dq11 = "15EB327360C7B60D12E5E2D16BDCD97981D17FBA6B70DB13B20B436E24EADA59";
+ ByteString pq1 = "2CA6366D72781DFA24D34A9A24CBC2AE927A9958AF426563FF63FB11658A461D";
+
+ pubKey1->setN(n1);
+ pubKey1->setE(e1);
+ privKey1_1->setN(n1);
+ privKey1_1->setE(e1);
+ privKey1_1->setD(d1);
+ privKey1_1->setP(p1);
+ privKey1_1->setQ(q1);
+ privKey1_1->setDP1(dp11);
+ privKey1_1->setDQ1(dq11);
+ privKey1_1->setPQ(pq1);
+
+ // The same key but without CRT factors
+ privKey1_2->setN(n1);
+ privKey1_2->setE(e1);
+ privKey1_2->setD(d1);
+
+ // Reconstruct public and private key #2
+ ByteString n2 = "A885B6F851A8079AB8A281DB0297148511EE0D8C07C0D4AE6D6FED461488E0D41E3FF8F281B06A3240B5007A5C2AB4FB6BE8AF88F119DB998368DDDC9710ABED";
+ ByteString e2 = "010001";
+ ByteString d2 = "2B259D2CA3DF851EE891F6F4678BDDFD9A131C95D3305C63D2723B4A5B9C960F5EC8BB7DCDDBEBD8B6A38767D64AD451E9383E0891E4EE7506100481F2B49323";
+ ByteString p2 = "D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF";
+ ByteString q2 = "C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3";
+ ByteString dp12 = "5D8EA4C8AF83A70634D5920C3DB66D908AC3AF57A597FD75BC9BBB856181C185";
+ ByteString dq12 = "C598E54DAEC8ABC1E907769A6C2BD01653ED0C9960E1EDB7E186FDA922883A99";
+ ByteString pq2 = "7C6F27B5B51B78AD80FB36E700990CF307866F2943124CBD93D97C137794C104";
+
+ pubKey2->setN(n2);
+ pubKey2->setE(e2);
+ privKey2_1->setN(n2);
+ privKey2_1->setE(e2);
+ privKey2_1->setD(d2);
+ privKey2_1->setP(p2);
+ privKey2_1->setQ(q2);
+ privKey2_1->setDP1(dp12);
+ privKey2_1->setDQ1(dq12);
+ privKey2_1->setPQ(pq2);
+
+ // The same key but without CRT factors
+ privKey2_2->setN(n2);
+ privKey2_2->setE(e2);
+ privKey2_2->setD(d2);
+
+ // Test with key #1
+ const char* testValue1 = "Everyone gets Friday off.";
+
+ ByteString dataToSign1((const unsigned char*) testValue1, strlen(testValue1));
+
+ ByteString expectedSignature1 = "0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81";
+ ByteString signature1_1;
+ ByteString signature1_2;
+
+ CPPUNIT_ASSERT(rsa->signInit(privKey1_1, "rsa-sha1-pkcs"));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1));
+ CPPUNIT_ASSERT(rsa->signFinal(signature1_1));
+
+#ifndef WITH_BOTAN
+ CPPUNIT_ASSERT(rsa->signInit(privKey1_2, "rsa-sha1-pkcs"));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1));
+ CPPUNIT_ASSERT(rsa->signFinal(signature1_2));
+
+ CPPUNIT_ASSERT(signature1_1 == signature1_2);
+#endif
+ CPPUNIT_ASSERT(signature1_1 == expectedSignature1);
+
+ CPPUNIT_ASSERT(rsa->verifyInit(pubKey1, "rsa-sha1-pkcs"));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign1));
+ CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature1));
+
+ // Test with key #2
+ const char* testValue2 = "test";
+
+ ByteString dataToSign2((const unsigned char*) testValue2, strlen(testValue2));
+
+ ByteString expectedSignature2 = "A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296CF612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE";
+ ByteString signature2_1;
+ ByteString signature2_2;
+
+ CPPUNIT_ASSERT(rsa->signInit(privKey2_1, "rsa-sha1-pkcs"));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2));
+ CPPUNIT_ASSERT(rsa->signFinal(signature2_1));
+
+#ifndef WITH_BOTAN
+ CPPUNIT_ASSERT(rsa->signInit(privKey2_2, "rsa-sha1-pkcs"));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2));
+ CPPUNIT_ASSERT(rsa->signFinal(signature2_2));
+
+ CPPUNIT_ASSERT(signature2_1 == signature2_2);
+#endif
+ CPPUNIT_ASSERT(signature2_1 == expectedSignature2);
+
+ CPPUNIT_ASSERT(rsa->verifyInit(pubKey2, "rsa-sha1-pkcs"));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign2));
+ CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature2));
+
+ rsa->recyclePublicKey(pubKey1);
+ rsa->recyclePublicKey(pubKey2);
+ rsa->recyclePrivateKey(privKey1_1);
+ rsa->recyclePrivateKey(privKey1_2);
+ rsa->recyclePrivateKey(privKey2_1);
+ rsa->recyclePrivateKey(privKey2_2);
+}
+
+void RSATests::testEncryptDecrypt()
+{
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ // Public exponents to test
+ std::vector<ByteString> exponents;
+ exponents.push_back("010001");
+ exponents.push_back("03");
+ exponents.push_back("0B");
+ exponents.push_back("11");
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+ keySizes.push_back(1280);
+ keySizes.push_back(2048);
+ //keySizes.push_back(4096);
+
+ // Paddings to test
+ std::vector<const char*> paddings;
+ paddings.push_back("rsa-pkcs");
+ paddings.push_back("rsa-pkcs-oaep");
+ paddings.push_back("rsa-raw");
+
+ for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
+ {
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ p.setE(*e);
+ p.setBitLength(*k);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ for (std::vector<const char*>::iterator pad = paddings.begin(); pad != paddings.end(); pad++)
+ {
+ // Generate some test data to encrypt based on the selected padding
+ ByteString testData;
+
+ if (!strcmp(*pad, "rsa-pkcs"))
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 12));
+ }
+ else if (!strcmp(*pad, "rsa-pkcs-oaep"))
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 42));
+ }
+ else if (!strcmp(*pad, "rsa-raw"))
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(testData, *k >> 3));
+ testData[0] &= 0x0F;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(true == false);
+ }
+
+ // Encrypt the data
+ ByteString encryptedData;
+
+ CPPUNIT_ASSERT(rsa->encrypt(kp->getPublicKey(), testData, encryptedData, *pad));
+
+ // The encrypted data length should equal the modulus length
+ CPPUNIT_ASSERT(encryptedData.size() == (*k >> 3));
+ CPPUNIT_ASSERT(encryptedData != testData);
+
+ // Now decrypt the data
+ ByteString decryptedData;
+
+ CPPUNIT_ASSERT(rsa->decrypt(kp->getPrivateKey(), encryptedData, decryptedData, *pad));
+
+ // Check that the data was properly decrypted
+ CPPUNIT_ASSERT(decryptedData == testData);
+ }
+
+ rsa->recycleKeyPair(kp);
+ }
+ }
+}
+
diff --git a/src/lib/crypto/test/RSATests.h b/src/lib/crypto/test/RSATests.h
--- /dev/null
@@ -0,0 +1,67 @@
+/* $Id: RSATests.h 4768 2010-03-25 11:17:52Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSATests.h
+
+ Contains test cases to test the RSA class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSATESTS_H
+#define _SOFTHSM_V2_RSATESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class RSATests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RSATests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST(testEncryptDecrypt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+ void testEncryptDecrypt();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // RSA instance
+ AsymmetricAlgorithm* rsa;
+};
+
+#endif // !_SOFTHSM_V2_RSATESTS_H
+
diff --git a/src/lib/crypto/test/chisq.c b/src/lib/crypto/test/chisq.c
--- /dev/null
@@ -0,0 +1,145 @@
+/* $Id: chisq.c 4746 2010-03-04 17:16:05Z rijswijk $ */
+
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/*
+
+ Compute probability of measured Chi Square value.
+
+ This code was developed by Gary Perlman of the Wang
+ Institute (full citation below) and has been minimally
+ modified for use in this program.
+
+*/
+
+#include <math.h>
+
+/*HEADER
+ Module: z.c
+ Purpose: compute approximations to normal z distribution probabilities
+ Programmer: Gary Perlman
+ Organization: Wang Institute, Tyngsboro, MA 01879
+ Copyright: none
+ Tabstops: 4
+*/
+
+#define Z_MAX 6.0 /* maximum meaningful z value */
+
+/*FUNCTION poz: probability of normal z value */
+/*ALGORITHM
+ Adapted from a polynomial approximation in:
+ Ibbetson D, Algorithm 209
+ Collected Algorithms of the CACM 1963 p. 616
+ Note:
+ This routine has six digit accuracy, so it is only useful for absolute
+ z values < 6. For z values >= to 6.0, poz() returns 0.0.
+*/
+static double /*VAR returns cumulative probability from -oo to z */
+poz(const double z) /*VAR normal z value */
+{
+ double y, x, w;
+
+ if (z == 0.0) {
+ x = 0.0;
+ } else {
+ y = 0.5 * fabs(z);
+ if (y >= (Z_MAX * 0.5)) {
+ x = 1.0;
+ } else if (y < 1.0) {
+ w = y * y;
+ x = ((((((((0.000124818987 * w
+ -0.001075204047) * w +0.005198775019) * w
+ -0.019198292004) * w +0.059054035642) * w
+ -0.151968751364) * w +0.319152932694) * w
+ -0.531923007300) * w +0.797884560593) * y * 2.0;
+ } else {
+ y -= 2.0;
+ x = (((((((((((((-0.000045255659 * y
+ +0.000152529290) * y -0.000019538132) * y
+ -0.000676904986) * y +0.001390604284) * y
+ -0.000794620820) * y -0.002034254874) * y
+ +0.006549791214) * y -0.010557625006) * y
+ +0.011630447319) * y -0.009279453341) * y
+ +0.005353579108) * y -0.002141268741) * y
+ +0.000535310849) * y +0.999936657524;
+ }
+ }
+ return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5));
+}
+
+/*
+ Module: chisq.c
+ Purpose: compute approximations to chisquare distribution probabilities
+ Contents: pochisq()
+ Uses: poz() in z.c (Algorithm 209)
+ Programmer: Gary Perlman
+ Organization: Wang Institute, Tyngsboro, MA 01879
+ Copyright: none
+ Tabstops: 4
+*/
+
+#define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */
+#define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */
+#define BIGX 20.0 /* max value to represent exp (x) */
+#define ex(x) (((x) < -BIGX) ? 0.0 : exp(x))
+
+/*FUNCTION pochisq: probability of chi sqaure value */
+/*ALGORITHM Compute probability of chi square value.
+ Adapted from:
+ Hill, I. D. and Pike, M. C. Algorithm 299
+ Collected Algorithms for the CACM 1967 p. 243
+ Updated for rounding errors based on remark in
+ ACM TOMS June 1985, page 185
+*/
+
+double pochisq(
+ const double ax, /* obtained chi-square value */
+ const int df /* degrees of freedom */
+ )
+{
+ double x = ax;
+ double a, y, s;
+ double e, c, z;
+ int even; /* true if df is an even number */
+
+ if (x <= 0.0 || df < 1) {
+ return 1.0;
+ }
+
+ a = 0.5 * x;
+ even = (2 * (df / 2)) == df;
+ if (df > 1) {
+ y = ex(-a);
+ }
+ s = (even ? y : (2.0 * poz(-sqrt(x))));
+ if (df > 2) {
+ x = 0.5 * (df - 1.0);
+ z = (even ? 1.0 : 0.5);
+ if (a > BIGX) {
+ e = (even ? 0.0 : LOG_SQRT_PI);
+ c = log(a);
+ while (z <= x) {
+ e = log(z) + e;
+ s += ex(c * z - a - e);
+ z += 1.0;
+ }
+ return (s);
+ } else {
+ e = (even ? 1.0 : (I_SQRT_PI / sqrt(a)));
+ c = 0.0;
+ while (z <= x) {
+ e = e * (a / z);
+ c = c + e;
+ z += 1.0;
+ }
+ return (c * y + s);
+ }
+ } else {
+ return s;
+ }
+}
diff --git a/src/lib/crypto/test/cryptotest.cpp b/src/lib/crypto/test/cryptotest.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: cryptotest.cpp 6738 2012-10-15 21:28:14Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ cryptotest.cpp
+
+ The main test executor for tests on the cryptographic functions in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/crypto/test/ent.c b/src/lib/crypto/test/ent.c
--- /dev/null
@@ -0,0 +1,110 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/*
+ ENT -- Entropy calculation and analysis of putative
+ random sequences.
+
+ Designed and implemented by John "Random" Walker in May 1985.
+
+ Multiple analyses of random sequences added in December 1985.
+
+ Bit stream analysis added in September 1997.
+
+ Terse mode output, getopt() command line processing,
+ optional stdin input, and HTML documentation added in
+ October 1998.
+
+ Documentation for the -t (terse output) option added
+ in July 2006.
+
+ Replaced table look-up for chi square to probability
+ conversion with algorithmic computation in January 2008.
+
+ For additional information and the latest version,
+ see http://www.fourmilab.ch/random/
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "iso8859.h"
+#include "randtest.h"
+
+#define UPDATE "January 28th, 2008"
+
+#define FALSE 0
+#define TRUE 1
+
+#ifdef M_PI
+#define PI M_PI
+#else
+#define PI 3.14159265358979323846
+#endif
+
+extern double pochisq(const double ax, const int df);
+
+/* Main program */
+
+void doEnt
+(
+ unsigned char* data,
+ size_t len,
+ double* pEntropy,
+ double* pChiProbability,
+ double* pArithMean,
+ double* pMontePi,
+ double* pSerialCorrelation
+)
+{
+ size_t s;
+ long ccount[256]; /* Bins to count occurrences of values */
+ double montepi, chip,
+ scc, ent, mean, chisq;
+
+ /* Initialise for calculations */
+
+ rt_init(FALSE);
+
+ /* Scan input file and count character occurrences */
+
+ for (s = 0; s < len; s++)
+ {
+ unsigned char ocb = data[s];
+
+ ccount[ocb]++; /* Update counter for this bin */
+ rt_add(&ocb, 1);
+ }
+
+ /* Complete calculation and return sequence metrics */
+
+ rt_end(&ent, &chisq, &mean, &montepi, &scc);
+
+ /* Calculate probability of observed distribution occurring from
+ the results of the Chi-Square test */
+
+ chip = pochisq(chisq, 255);
+
+ /* Print bin counts if requested */
+
+ /* Return calculated results */
+
+ *pEntropy = ent;
+ *pChiProbability = chip;
+ *pArithMean = mean;
+ *pMontePi = montepi;
+ *pSerialCorrelation = scc;
+}
diff --git a/src/lib/crypto/test/ent.h b/src/lib/crypto/test/ent.h
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: ent.h 4746 2010-03-04 17:16:05Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ent.h
+
+ Header file to give access to the modified ent.c implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ENT_H
+#define _SOFTHSM_V2_ENT_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void doEnt
+(
+ unsigned char* data,
+ size_t len,
+ double* pEntropy,
+ double* pChiProbability,
+ double* pArithMean,
+ double* pMontePi,
+ double* pSerialCorrelation
+);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // !_SOFTHSM_V2_ENT_H
+
diff --git a/src/lib/crypto/test/iso8859.c b/src/lib/crypto/test/iso8859.c
--- /dev/null
@@ -0,0 +1,25 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/* ISO 8859/1 Latin-1 alphabetic and upper and lower case bit vector tables. */
+
+/* LINTLIBRARY */
+
+unsigned char isoalpha[32] = {
+ 0,0,0,0,0,0,0,0,127,255,255,224,127,255,255,224,0,0,0,0,0,0,0,0,255,255,
+ 254,255,255,255,254,255
+};
+
+unsigned char isoupper[32] = {
+ 0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,0,255,255,254,254,
+ 0,0,0,0
+};
+
+unsigned char isolower[32] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,1,255,255,
+ 254,255
+};
diff --git a/src/lib/crypto/test/iso8859.h b/src/lib/crypto/test/iso8859.h
--- /dev/null
@@ -0,0 +1,23 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/* ISO 8859/1 Latin-1 "ctype" macro replacements. */
+
+extern unsigned char isoalpha[32], isoupper[32], isolower[32];
+
+#define isISOspace(x) ((isascii(((unsigned char) (x))) && isspace(((unsigned char) (x)))) || ((x) == 0xA0))
+#define isISOalpha(x) ((isoalpha[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0)
+#define isISOupper(x) ((isoupper[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0)
+#define isISOlower(x) ((isolower[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0)
+#define isISOprint(x) ((((x) >= ' ') && ((x) <= '~')) || ((x) >= 0xA0))
+#define toISOupper(x) (isISOlower(x) ? (isascii(((unsigned char) (x))) ? \
+ toupper(x) : (((((unsigned char) (x)) != 0xDF) && \
+ (((unsigned char) (x)) != 0xFF)) ? \
+ (((unsigned char) (x)) - 0x20) : (x))) : (x))
+#define toISOlower(x) (isISOupper(x) ? (isascii(((unsigned char) (x))) ? \
+ tolower(x) : (((unsigned char) (x)) + 0x20)) \
+ : (x))
diff --git a/src/lib/crypto/test/randtest.c b/src/lib/crypto/test/randtest.c
--- /dev/null
@@ -0,0 +1,190 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/*
+
+ Apply various randomness tests to a stream of bytes
+
+ by John Walker -- September 1996
+ http://www.fourmilab.ch/
+
+*/
+
+#include <math.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#define log2of10 3.32192809488736234787
+
+static int binary = FALSE; /* Treat input as a bitstream */
+
+static long ccount[256], /* Bins to count occurrences of values */
+ totalc = 0; /* Total bytes counted */
+static double prob[256]; /* Probabilities per bin for entropy */
+
+/* RT_LOG2 -- Calculate log to the base 2 */
+
+static double rt_log2(double x)
+{
+ return log2of10 * log10(x);
+}
+
+#define MONTEN 6 /* Bytes used as Monte Carlo
+ co-ordinates. This should be no more
+ bits than the mantissa of your
+ "double" floating point type. */
+
+static int mp, sccfirst;
+static unsigned int monte[MONTEN];
+static long inmont, mcount;
+static double cexp, incirc, montex, montey, montepi,
+ scc, sccun, sccu0, scclast, scct1, scct2, scct3,
+ ent, chisq, datasum;
+
+/* RT_INIT -- Initialise random test counters. */
+
+void rt_init(int binmode)
+{
+ int i;
+
+ binary = binmode; /* Set binary / byte mode */
+
+ /* Initialise for calculations */
+
+ ent = 0.0; /* Clear entropy accumulator */
+ chisq = 0.0; /* Clear Chi-Square */
+ datasum = 0.0; /* Clear sum of bytes for arithmetic mean */
+
+ mp = 0; /* Reset Monte Carlo accumulator pointer */
+ mcount = 0; /* Clear Monte Carlo tries */
+ inmont = 0; /* Clear Monte Carlo inside count */
+ incirc = 65535.0 * 65535.0;/* In-circle distance for Monte Carlo */
+
+ sccfirst = TRUE; /* Mark first time for serial correlation */
+ scct1 = scct2 = scct3 = 0.0; /* Clear serial correlation terms */
+
+ incirc = pow(pow(256.0, (double) (MONTEN / 2)) - 1, 2.0);
+
+ for (i = 0; i < 256; i++) {
+ ccount[i] = 0;
+ }
+ totalc = 0;
+}
+
+/* RT_ADD -- Add one or more bytes to accumulation. */
+
+void rt_add(void *buf, int bufl)
+{
+ unsigned char *bp = buf;
+ int oc, c, bean;
+
+ while (bean = 0, (bufl-- > 0)) {
+ oc = *bp++;
+
+ do {
+ if (binary) {
+ c = !!(oc & 0x80);
+ } else {
+ c = oc;
+ }
+ ccount[c]++; /* Update counter for this bin */
+ totalc++;
+
+ /* Update inside / outside circle counts for Monte Carlo
+ computation of PI */
+
+ if (bean == 0) {
+ monte[mp++] = oc; /* Save character for Monte Carlo */
+ if (mp >= MONTEN) { /* Calculate every MONTEN character */
+ int mj;
+
+ mp = 0;
+ mcount++;
+ montex = montey = 0;
+ for (mj = 0; mj < MONTEN / 2; mj++) {
+ montex = (montex * 256.0) + monte[mj];
+ montey = (montey * 256.0) + monte[(MONTEN / 2) + mj];
+ }
+ if ((montex * montex + montey * montey) <= incirc) {
+ inmont++;
+ }
+ }
+ }
+
+ /* Update calculation of serial correlation coefficient */
+
+ sccun = c;
+ if (sccfirst) {
+ sccfirst = FALSE;
+ scclast = 0;
+ sccu0 = sccun;
+ } else {
+ scct1 = scct1 + scclast * sccun;
+ }
+ scct2 = scct2 + sccun;
+ scct3 = scct3 + (sccun * sccun);
+ scclast = sccun;
+ oc <<= 1;
+ } while (binary && (++bean < 8));
+ }
+}
+
+/* RT_END -- Complete calculation and return results. */
+
+void rt_end(double *r_ent, double *r_chisq, double *r_mean,
+ double *r_montepicalc, double *r_scc)
+{
+ int i;
+
+ /* Complete calculation of serial correlation coefficient */
+
+ scct1 = scct1 + scclast * sccu0;
+ scct2 = scct2 * scct2;
+ scc = totalc * scct3 - scct2;
+ if (scc == 0.0) {
+ scc = -100000;
+ } else {
+ scc = (totalc * scct1 - scct2) / scc;
+ }
+
+ /* Scan bins and calculate probability for each bin and
+ Chi-Square distribution. The probability will be reused
+ in the entropy calculation below. While we're at it,
+ we sum of all the data which will be used to compute the
+ mean. */
+
+ cexp = totalc / (binary ? 2.0 : 256.0); /* Expected count per bin */
+ for (i = 0; i < (binary ? 2 : 256); i++) {
+ double a = ccount[i] - cexp;;
+
+ prob[i] = ((double) ccount[i]) / totalc;
+ chisq += (a * a) / cexp;
+ datasum += ((double) i) * ccount[i];
+ }
+
+ /* Calculate entropy */
+
+ for (i = 0; i < (binary ? 2 : 256); i++) {
+ if (prob[i] > 0.0) {
+ ent += prob[i] * rt_log2(1 / prob[i]);
+ }
+ }
+
+ /* Calculate Monte Carlo value for PI from percentage of hits
+ within the circle */
+
+ montepi = 4.0 * (((double) inmont) / mcount);
+
+ /* Return results through arguments */
+
+ *r_ent = ent;
+ *r_chisq = chisq;
+ *r_mean = datasum / totalc;
+ *r_montepicalc = montepi;
+ *r_scc = scc;
+}
diff --git a/src/lib/crypto/test/randtest.h b/src/lib/crypto/test/randtest.h
--- /dev/null
@@ -0,0 +1,13 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/* Random test function prototypes */
+
+extern void rt_init(int binmode);
+extern void rt_add(void *buf, int bufl);
+extern void rt_end(double *r_ent, double *r_chisq, double *r_mean,
+ double *r_montepicalc, double *r_scc);
diff --git a/src/lib/cryptoki.h b/src/lib/cryptoki.h
--- /dev/null
+++ b/src/lib/cryptoki.h
@@ -0,0 +1,47 @@
+/* $Id: cryptoki.h 4748 2010-03-05 12:51:02Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ cryptoki.h
+
+ This include file turns on export of functions by the SoftHSM v2 library by
+ setting the #define symbol CRYPTOKI_EXPORTS before the main PKCS #11 header
+ file is included. Include this header file in alle SoftHSM v2 code that
+ links into a PKCS #11 library; currently that will only by softhsm.cpp
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_CRYPTOKI_H
+#define _SOFTHSM_V2_CRYPTOKI_H
+
+#define CRYPTOKI_EXPORTS
+#define CRYPTOKI_COMPAT
+
+#include "pkcs11.h"
+
+#endif // !_SOFTHSM_V2_CRYPTOKI_H
+
diff --git a/src/lib/cryptoki_compat/pkcs11.h b/src/lib/cryptoki_compat/pkcs11.h
--- /dev/null
@@ -0,0 +1,1613 @@
+/* pkcs11.h
+ Copyright 2006, 2007 g10 Code GmbH
+ Copyright 2006 Andreas Jellinghaus
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. */
+
+/* Please submit changes back to the Scute project at
+ http://www.scute.org/ (or send them to marcus@g10code.com), so that
+ they can be picked up by other projects from there as well. */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+ RSA Security Inc. It is mostly a drop-in replacement, with the
+ following change:
+
+ This header file does not require any macro definitions by the user
+ (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros
+ for you (if useful, some are missing, let me know if you need
+ more).
+
+ There is an additional API available that does comply better to the
+ GNU coding standard. It can be switched on by defining
+ CRYPTOKI_GNU before including this header file. For this, the
+ following changes are made to the specification:
+
+ All structure types are changed to a "struct ck_foo" where CK_FOO
+ is the type name in PKCS #11.
+
+ All non-structure types are changed to ck_foo_t where CK_FOO is the
+ lowercase version of the type name in PKCS #11. The basic types
+ (CK_ULONG et al.) are removed without substitute.
+
+ All members of structures are modified in the following way: Type
+ indication prefixes are removed, and underscore characters are
+ inserted before words. Then the result is lowercased.
+
+ Note that function names are still in the original case, as they
+ need for ABI compatibility.
+
+ CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use
+ <stdbool.h>.
+
+ If CRYPTOKI_COMPAT is defined before including this header file,
+ then none of the API changes above take place, and the API is the
+ one defined by the PKCS #11 standard. */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The version of cryptoki we implement. The revision is changed with
+ each modification of this file. If you do not use the "official"
+ version of this file, please consider deleting the revision macro
+ (you may use a macro with a different name to keep track of your
+ versions). */
+#define CRYPTOKI_VERSION_MAJOR 2
+#define CRYPTOKI_VERSION_MINOR 20
+#define CRYPTOKI_VERSION_REVISION 7
+
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+ given. */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif
+#endif
+
+/* System dependencies. */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below. */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else
+#define CK_SPEC __declspec(dllimport)
+#endif
+
+#else
+
+#define CK_SPEC
+
+#endif
+
+\f
+#ifdef CRYPTOKI_COMPAT
+ /* If we are in compatibility mode, switch all exposed names to the
+ PKCS #11 variant. There are corresponding #undefs below. */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define hash_alg hashAlg
+#define source_data pSourceData
+#define source_data_len ulSourceDataLen
+
+#define slen sLen
+
+#define ck_ec_kdf_type_t CK_EC_KDF_TYPE
+
+#define shared_data_len ulSharedDataLen
+#define shared_data pSharedData
+#define public_data_len ulPublicDataLen
+#define public_data pPublicData
+
+#define private_data_len ulPrivateDataLen
+#define private_data hPrivateData
+#define public_data_len2 ulPublicDataLen2
+#define public_data2 pPublicData2
+
+#define public_key publicKey
+
+#define ck_x9_42_dh_kdf_type_t CK_X9_42_DH_KDF_TYPE
+
+#define other_info_len ulOtherInfoLen
+#define other_info pOtherInfo
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+\f
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version
+{
+ unsigned char major;
+ unsigned char minor;
+};
+
+
+struct ck_info
+{
+ struct ck_version cryptoki_version;
+ unsigned char manufacturer_id[32];
+ ck_flags_t flags;
+ unsigned char library_description[32];
+ struct ck_version library_version;
+};
+
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER (0)
+#define CKN_OTP_CHANGED (1)
+
+typedef unsigned long ck_slot_id_t;
+
+
+struct ck_slot_info
+{
+ unsigned char slot_description[64];
+ unsigned char manufacturer_id[32];
+ ck_flags_t flags;
+ struct ck_version hardware_version;
+ struct ck_version firmware_version;
+};
+
+
+#define CKF_TOKEN_PRESENT (1 << 0)
+#define CKF_REMOVABLE_DEVICE (1 << 1)
+#define CKF_HW_SLOT (1 << 2)
+#define CKF_ARRAY_ATTRIBUTE (1 << 30)
+
+
+struct ck_token_info
+{
+ unsigned char label[32];
+ unsigned char manufacturer_id[32];
+ unsigned char model[16];
+ unsigned char serial_number[16];
+ ck_flags_t flags;
+ unsigned long max_session_count;
+ unsigned long session_count;
+ unsigned long max_rw_session_count;
+ unsigned long rw_session_count;
+ unsigned long max_pin_len;
+ unsigned long min_pin_len;
+ unsigned long total_public_memory;
+ unsigned long free_public_memory;
+ unsigned long total_private_memory;
+ unsigned long free_private_memory;
+ struct ck_version hardware_version;
+ struct ck_version firmware_version;
+ unsigned char utc_time[16];
+};
+
+
+#define CKF_RNG (1 << 0)
+#define CKF_WRITE_PROTECTED (1 << 1)
+#define CKF_LOGIN_REQUIRED (1 << 2)
+#define CKF_USER_PIN_INITIALIZED (1 << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5)
+#define CKF_CLOCK_ON_TOKEN (1 << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9)
+#define CKF_TOKEN_INITIALIZED (1 << 10)
+#define CKF_SECONDARY_AUTHENTICATION (1 << 11)
+#define CKF_USER_PIN_COUNT_LOW (1 << 16)
+#define CKF_USER_PIN_FINAL_TRY (1 << 17)
+#define CKF_USER_PIN_LOCKED (1 << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19)
+#define CKF_SO_PIN_COUNT_LOW (1 << 20)
+#define CKF_SO_PIN_FINAL_TRY (1 << 21)
+#define CKF_SO_PIN_LOCKED (1 << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23)
+
+#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1)
+#define CK_EFFECTIVELY_INFINITE (0)
+
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE (0)
+
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO (0)
+#define CKU_USER (1)
+#define CKU_CONTEXT_SPECIFIC (2)
+
+
+typedef unsigned long ck_state_t;
+
+#define CKS_RO_PUBLIC_SESSION (0)
+#define CKS_RO_USER_FUNCTIONS (1)
+#define CKS_RW_PUBLIC_SESSION (2)
+#define CKS_RW_USER_FUNCTIONS (3)
+#define CKS_RW_SO_FUNCTIONS (4)
+
+
+struct ck_session_info
+{
+ ck_slot_id_t slot_id;
+ ck_state_t state;
+ ck_flags_t flags;
+ unsigned long device_error;
+};
+
+#define CKF_RW_SESSION (1 << 1)
+#define CKF_SERIAL_SESSION (1 << 2)
+
+
+typedef unsigned long ck_object_handle_t;
+
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA (0)
+#define CKO_CERTIFICATE (1)
+#define CKO_PUBLIC_KEY (2)
+#define CKO_PRIVATE_KEY (3)
+#define CKO_SECRET_KEY (4)
+#define CKO_HW_FEATURE (5)
+#define CKO_DOMAIN_PARAMETERS (6)
+#define CKO_MECHANISM (7)
+#define CKO_OTP_KEY (8)
+#define CKO_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER (1)
+#define CKH_CLOCK (2)
+#define CKH_USER_INTERFACE (3)
+#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA (0)
+#define CKK_DSA (1)
+#define CKK_DH (2)
+#define CKK_ECDSA (3)
+#define CKK_EC (3)
+#define CKK_X9_42_DH (4)
+#define CKK_KEA (5)
+#define CKK_GENERIC_SECRET (0x10)
+#define CKK_RC2 (0x11)
+#define CKK_RC4 (0x12)
+#define CKK_DES (0x13)
+#define CKK_DES2 (0x14)
+#define CKK_DES3 (0x15)
+#define CKK_CAST (0x16)
+#define CKK_CAST3 (0x17)
+#define CKK_CAST128 (0x18)
+#define CKK_RC5 (0x19)
+#define CKK_IDEA (0x1a)
+#define CKK_SKIPJACK (0x1b)
+#define CKK_BATON (0x1c)
+#define CKK_JUNIPER (0x1d)
+#define CKK_CDMF (0x1e)
+#define CKK_AES (0x1f)
+#define CKK_BLOWFISH (0x20)
+#define CKK_TWOFISH (0x21)
+#define CKK_SECURID (0x22)
+#define CKK_HOTP (0x23)
+#define CKK_ACTI (0x24)
+#define CKK_CAMELLIA (0x25)
+#define CKK_ARIA (0x26)
+#define CKK_MD5_HMAC (0x27)
+#define CKK_SHA_1_HMAC (0x28)
+#define CKK_RIPEMD128_HMAC (0x29)
+#define CKK_RIPEMD160_HMAC (0x2A)
+#define CKK_SHA256_HMAC (0x2B)
+#define CKK_SHA384_HMAC (0x2C)
+#define CKK_SHA512_HMAC (0x2D)
+#define CKK_SHA224_HMAC (0x2E)
+#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509 (0)
+#define CKC_X_509_ATTR_CERT (1)
+#define CKC_WTLS (2)
+#define CKC_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+#define CK_OTP_FORMAT_DECIMAL (0)
+#define CK_OTP_FORMAT_HEXADECIMAL (1)
+#define CK_OTP_FORMAT_ALPHANUMERIC (2)
+#define CK_OTP_FORMAT_BINARY (3)
+
+#define CK_OTP_PARAM_IGNORED (0)
+#define CK_OTP_PARAM_OPTIONAL (1)
+#define CK_OTP_PARAM_MANDATORY (2)
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS (0)
+#define CKA_TOKEN (1)
+#define CKA_PRIVATE (2)
+#define CKA_LABEL (3)
+#define CKA_APPLICATION (0x10)
+#define CKA_VALUE (0x11)
+#define CKA_OBJECT_ID (0x12)
+#define CKA_CERTIFICATE_TYPE (0x80)
+#define CKA_ISSUER (0x81)
+#define CKA_SERIAL_NUMBER (0x82)
+#define CKA_AC_ISSUER (0x83)
+#define CKA_OWNER (0x84)
+#define CKA_ATTR_TYPES (0x85)
+#define CKA_TRUSTED (0x86)
+#define CKA_CERTIFICATE_CATEGORY (0x87)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88)
+#define CKA_URL (0x89)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b)
+#define CKA_NAME_HASH_ALGORITHM (0x8c)
+#define CKA_CHECK_VALUE (0x90)
+#define CKA_KEY_TYPE (0x100)
+#define CKA_SUBJECT (0x101)
+#define CKA_ID (0x102)
+#define CKA_SENSITIVE (0x103)
+#define CKA_ENCRYPT (0x104)
+#define CKA_DECRYPT (0x105)
+#define CKA_WRAP (0x106)
+#define CKA_UNWRAP (0x107)
+#define CKA_SIGN (0x108)
+#define CKA_SIGN_RECOVER (0x109)
+#define CKA_VERIFY (0x10a)
+#define CKA_VERIFY_RECOVER (0x10b)
+#define CKA_DERIVE (0x10c)
+#define CKA_START_DATE (0x110)
+#define CKA_END_DATE (0x111)
+#define CKA_MODULUS (0x120)
+#define CKA_MODULUS_BITS (0x121)
+#define CKA_PUBLIC_EXPONENT (0x122)
+#define CKA_PRIVATE_EXPONENT (0x123)
+#define CKA_PRIME_1 (0x124)
+#define CKA_PRIME_2 (0x125)
+#define CKA_EXPONENT_1 (0x126)
+#define CKA_EXPONENT_2 (0x127)
+#define CKA_COEFFICIENT (0x128)
+#define CKA_PRIME (0x130)
+#define CKA_SUBPRIME (0x131)
+#define CKA_BASE (0x132)
+#define CKA_PRIME_BITS (0x133)
+#define CKA_SUB_PRIME_BITS (0x134)
+#define CKA_VALUE_BITS (0x160)
+#define CKA_VALUE_LEN (0x161)
+#define CKA_EXTRACTABLE (0x162)
+#define CKA_LOCAL (0x163)
+#define CKA_NEVER_EXTRACTABLE (0x164)
+#define CKA_ALWAYS_SENSITIVE (0x165)
+#define CKA_KEY_GEN_MECHANISM (0x166)
+#define CKA_MODIFIABLE (0x170)
+#define CKA_COPYABLE (0x171)
+#define CKA_ECDSA_PARAMS (0x180)
+#define CKA_EC_PARAMS (0x180)
+#define CKA_EC_POINT (0x181)
+#define CKA_SECONDARY_AUTH (0x200)
+#define CKA_AUTH_PIN_FLAGS (0x201)
+#define CKA_ALWAYS_AUTHENTICATE (0x202)
+#define CKA_WRAP_WITH_TRUSTED (0x210)
+#define CKA_OTP_FORMAT (0x220)
+#define CKA_OTP_LENGTH (0x221)
+#define CKA_OTP_TIME_INTERVAL (0x222)
+#define CKA_OTP_USER_FRIENDLY_MODE (0x223)
+#define CKA_OTP_CHALLENGE_REQUIREMENT (0x224)
+#define CKA_OTP_TIME_REQUIREMENT (0x225)
+#define CKA_OTP_COUNTER_REQUIREMENT (0x226)
+#define CKA_OTP_PIN_REQUIREMENT (0x227)
+#define CKA_OTP_COUNTER (0x22E)
+#define CKA_OTP_TIME (0x22F)
+#define CKA_OTP_USER_IDENTIFIER (0x22A)
+#define CKA_OTP_SERVICE_IDENTIFIER (0x22B)
+#define CKA_OTP_SERVICE_LOGO (0x22C)
+#define CKA_OTP_SERVICE_LOGO_TYPE (0x22D)
+#define CKA_HW_FEATURE_TYPE (0x300)
+#define CKA_RESET_ON_INIT (0x301)
+#define CKA_HAS_RESET (0x302)
+#define CKA_PIXEL_X (0x400)
+#define CKA_PIXEL_Y (0x401)
+#define CKA_RESOLUTION (0x402)
+#define CKA_CHAR_ROWS (0x403)
+#define CKA_CHAR_COLUMNS (0x404)
+#define CKA_COLOR (0x405)
+#define CKA_BITS_PER_PIXEL (0x406)
+#define CKA_CHAR_SETS (0x480)
+#define CKA_ENCODING_METHODS (0x481)
+#define CKA_MIME_TYPES (0x482)
+#define CKA_MECHANISM_TYPE (0x500)
+#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501)
+#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503)
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212)
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600)
+#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+struct ck_attribute
+{
+ ck_attribute_type_t type;
+ void *value;
+ unsigned long value_len;
+};
+
+
+struct ck_date
+{
+ unsigned char year[4];
+ unsigned char month[2];
+ unsigned char day[2];
+};
+
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN (0)
+#define CKM_RSA_PKCS (1)
+#define CKM_RSA_9796 (2)
+#define CKM_RSA_X_509 (3)
+#define CKM_MD2_RSA_PKCS (4)
+#define CKM_MD5_RSA_PKCS (5)
+#define CKM_SHA1_RSA_PKCS (6)
+#define CKM_RIPEMD128_RSA_PKCS (7)
+#define CKM_RIPEMD160_RSA_PKCS (8)
+#define CKM_RSA_PKCS_OAEP (9)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa)
+#define CKM_RSA_X9_31 (0xb)
+#define CKM_SHA1_RSA_X9_31 (0xc)
+#define CKM_RSA_PKCS_PSS (0xd)
+#define CKM_SHA1_RSA_PKCS_PSS (0xe)
+#define CKM_DSA_KEY_PAIR_GEN (0x10)
+#define CKM_DSA (0x11)
+#define CKM_DSA_SHA1 (0x12)
+#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20)
+#define CKM_DH_PKCS_DERIVE (0x21)
+#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30)
+#define CKM_X9_42_DH_DERIVE (0x31)
+#define CKM_X9_42_DH_HYBRID_DERIVE (0x32)
+#define CKM_X9_42_MQV_DERIVE (0x33)
+#define CKM_SHA256_RSA_PKCS (0x40)
+#define CKM_SHA384_RSA_PKCS (0x41)
+#define CKM_SHA512_RSA_PKCS (0x42)
+#define CKM_SHA256_RSA_PKCS_PSS (0x43)
+#define CKM_SHA384_RSA_PKCS_PSS (0x44)
+#define CKM_SHA512_RSA_PKCS_PSS (0x45)
+#define CKM_SHA224_RSA_PKCS (0x46)
+#define CKM_SHA224_RSA_PKCS_PSS (0x47)
+#define CKM_RC2_KEY_GEN (0x100)
+#define CKM_RC2_ECB (0x101)
+#define CKM_RC2_CBC (0x102)
+#define CKM_RC2_MAC (0x103)
+#define CKM_RC2_MAC_GENERAL (0x104)
+#define CKM_RC2_CBC_PAD (0x105)
+#define CKM_RC4_KEY_GEN (0x110)
+#define CKM_RC4 (0x111)
+#define CKM_DES_KEY_GEN (0x120)
+#define CKM_DES_ECB (0x121)
+#define CKM_DES_CBC (0x122)
+#define CKM_DES_MAC (0x123)
+#define CKM_DES_MAC_GENERAL (0x124)
+#define CKM_DES_CBC_PAD (0x125)
+#define CKM_DES2_KEY_GEN (0x130)
+#define CKM_DES3_KEY_GEN (0x131)
+#define CKM_DES3_ECB (0x132)
+#define CKM_DES3_CBC (0x133)
+#define CKM_DES3_MAC (0x134)
+#define CKM_DES3_MAC_GENERAL (0x135)
+#define CKM_DES3_CBC_PAD (0x136)
+#define CKM_CDMF_KEY_GEN (0x140)
+#define CKM_CDMF_ECB (0x141)
+#define CKM_CDMF_CBC (0x142)
+#define CKM_CDMF_MAC (0x143)
+#define CKM_CDMF_MAC_GENERAL (0x144)
+#define CKM_CDMF_CBC_PAD (0x145)
+#define CKM_DES_OFB64 (0x150)
+#define CKM_DES_OFB8 (0x151)
+#define CKM_DES_CFB64 (0x152)
+#define CKM_DES_CFB8 (0x153)
+#define CKM_MD2 (0x200)
+#define CKM_MD2_HMAC (0x201)
+#define CKM_MD2_HMAC_GENERAL (0x202)
+#define CKM_MD5 (0x210)
+#define CKM_MD5_HMAC (0x211)
+#define CKM_MD5_HMAC_GENERAL (0x212)
+#define CKM_SHA_1 (0x220)
+#define CKM_SHA_1_HMAC (0x221)
+#define CKM_SHA_1_HMAC_GENERAL (0x222)
+#define CKM_RIPEMD128 (0x230)
+#define CKM_RIPEMD128_HMAC (0x231)
+#define CKM_RIPEMD128_HMAC_GENERAL (0x232)
+#define CKM_RIPEMD160 (0x240)
+#define CKM_RIPEMD160_HMAC (0x241)
+#define CKM_RIPEMD160_HMAC_GENERAL (0x242)
+#define CKM_SHA256 (0x250)
+#define CKM_SHA256_HMAC (0x251)
+#define CKM_SHA256_HMAC_GENERAL (0x252)
+#define CKM_SHA224 (0x255)
+#define CKM_SHA224_HMAC (0x256)
+#define CKM_SHA224_HMAC_GENERAL (0x257)
+#define CKM_SHA384 (0x260)
+#define CKM_SHA384_HMAC (0x261)
+#define CKM_SHA384_HMAC_GENERAL (0x262)
+#define CKM_SHA512 (0x270)
+#define CKM_SHA512_HMAC (0x271)
+#define CKM_SHA512_HMAC_GENERAL (0x272)
+#define CKM_SECURID_KEY_GEN (0x280)
+#define CKM_SECURID (0x281)
+#define CKM_HOTP_KEY_GEN (0x290)
+#define CKM_HOTP (0x291)
+#define CKM_ACTI (0x2A0)
+#define CKM_ACTI_KEY_GEN (0x2A1)
+#define CKM_CAST_KEY_GEN (0x300)
+#define CKM_CAST_ECB (0x301)
+#define CKM_CAST_CBC (0x302)
+#define CKM_CAST_MAC (0x303)
+#define CKM_CAST_MAC_GENERAL (0x304)
+#define CKM_CAST_CBC_PAD (0x305)
+#define CKM_CAST3_KEY_GEN (0x310)
+#define CKM_CAST3_ECB (0x311)
+#define CKM_CAST3_CBC (0x312)
+#define CKM_CAST3_MAC (0x313)
+#define CKM_CAST3_MAC_GENERAL (0x314)
+#define CKM_CAST3_CBC_PAD (0x315)
+#define CKM_CAST5_KEY_GEN (0x320)
+#define CKM_CAST128_KEY_GEN (0x320)
+#define CKM_CAST5_ECB (0x321)
+#define CKM_CAST128_ECB (0x321)
+#define CKM_CAST5_CBC (0x322)
+#define CKM_CAST128_CBC (0x322)
+#define CKM_CAST5_MAC (0x323)
+#define CKM_CAST128_MAC (0x323)
+#define CKM_CAST5_MAC_GENERAL (0x324)
+#define CKM_CAST128_MAC_GENERAL (0x324)
+#define CKM_CAST5_CBC_PAD (0x325)
+#define CKM_CAST128_CBC_PAD (0x325)
+#define CKM_RC5_KEY_GEN (0x330)
+#define CKM_RC5_ECB (0x331)
+#define CKM_RC5_CBC (0x332)
+#define CKM_RC5_MAC (0x333)
+#define CKM_RC5_MAC_GENERAL (0x334)
+#define CKM_RC5_CBC_PAD (0x335)
+#define CKM_IDEA_KEY_GEN (0x340)
+#define CKM_IDEA_ECB (0x341)
+#define CKM_IDEA_CBC (0x342)
+#define CKM_IDEA_MAC (0x343)
+#define CKM_IDEA_MAC_GENERAL (0x344)
+#define CKM_IDEA_CBC_PAD (0x345)
+#define CKM_GENERIC_SECRET_KEY_GEN (0x350)
+#define CKM_CONCATENATE_BASE_AND_KEY (0x360)
+#define CKM_CONCATENATE_BASE_AND_DATA (0x362)
+#define CKM_CONCATENATE_DATA_AND_BASE (0x363)
+#define CKM_XOR_BASE_AND_DATA (0x364)
+#define CKM_EXTRACT_KEY_FROM_KEY (0x365)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370)
+#define CKM_SSL3_MASTER_KEY_DERIVE (0x371)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373)
+#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374)
+#define CKM_TLS_MASTER_KEY_DERIVE (0x375)
+#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377)
+#define CKM_TLS_PRF (0x378)
+#define CKM_SSL3_MD5_MAC (0x380)
+#define CKM_SSL3_SHA1_MAC (0x381)
+#define CKM_MD5_KEY_DERIVATION (0x390)
+#define CKM_MD2_KEY_DERIVATION (0x391)
+#define CKM_SHA1_KEY_DERIVATION (0x392)
+#define CKM_SHA256_KEY_DERIVATION (0x393)
+#define CKM_SHA384_KEY_DERIVATION (0x394)
+#define CKM_SHA512_KEY_DERIVATION (0x395)
+#define CKM_SHA224_KEY_DERIVATION (0x396)
+#define CKM_PBE_MD2_DES_CBC (0x3a0)
+#define CKM_PBE_MD5_DES_CBC (0x3a1)
+#define CKM_PBE_MD5_CAST_CBC (0x3a2)
+#define CKM_PBE_MD5_CAST3_CBC (0x3a3)
+#define CKM_PBE_MD5_CAST5_CBC (0x3a4)
+#define CKM_PBE_MD5_CAST128_CBC (0x3a4)
+#define CKM_PBE_SHA1_CAST5_CBC (0x3a5)
+#define CKM_PBE_SHA1_CAST128_CBC (0x3a5)
+#define CKM_PBE_SHA1_RC4_128 (0x3a6)
+#define CKM_PBE_SHA1_RC4_40 (0x3a7)
+#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8)
+#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9)
+#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa)
+#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab)
+#define CKM_PKCS5_PBKD2 (0x3b0)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0)
+#define CKM_WTLS_PRE_MASTER_KEY_GEN (0x3d0)
+#define CKM_WTLS_MASTER_KEY_DERIVE (0x3d1)
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC (0x3d2)
+#define CKM_WTLS_PRF (0x3d3)
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE (0x3d4)
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE (0x3d5)
+#define CKM_KEY_WRAP_LYNKS (0x400)
+#define CKM_KEY_WRAP_SET_OAEP (0x401)
+#define CKM_CMS_SIG (0x500)
+#define CKM_KIP_DERIVE (0x510)
+#define CKM_KIP_WRAP (0x511)
+#define CKM_KIP_MAC (0x512)
+#define CKM_CAMELLIA_KEY_GEN (0x550)
+#define CKM_CAMELLIA_ECB (0x551)
+#define CKM_CAMELLIA_CBC (0x552)
+#define CKM_CAMELLIA_MAC (0x553)
+#define CKM_CAMELLIA_MAC_GENERAL (0x554)
+#define CKM_CAMELLIA_CBC_PAD (0x555)
+#define CKM_CAMELLIA_ECB_ENCRYPT_DATA (0x556)
+#define CKM_CAMELLIA_CBC_ENCRYPT_DATA (0x557)
+#define CKM_CAMELLIA_CTR (0x558)
+#define CKM_ARIA_KEY_GEN (0x560)
+#define CKM_ARIA_ECB (0x561)
+#define CKM_ARIA_CBC (0x562)
+#define CKM_ARIA_MAC (0x563)
+#define CKM_ARIA_MAC_GENERAL (0x564)
+#define CKM_ARIA_CBC_PAD (0x565)
+#define CKM_ARIA_ECB_ENCRYPT_DATA (0x566)
+#define CKM_ARIA_CBC_ENCRYPT_DATA (0x567)
+#define CKM_SKIPJACK_KEY_GEN (0x1000)
+#define CKM_SKIPJACK_ECB64 (0x1001)
+#define CKM_SKIPJACK_CBC64 (0x1002)
+#define CKM_SKIPJACK_OFB64 (0x1003)
+#define CKM_SKIPJACK_CFB64 (0x1004)
+#define CKM_SKIPJACK_CFB32 (0x1005)
+#define CKM_SKIPJACK_CFB16 (0x1006)
+#define CKM_SKIPJACK_CFB8 (0x1007)
+#define CKM_SKIPJACK_WRAP (0x1008)
+#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009)
+#define CKM_SKIPJACK_RELAYX (0x100a)
+#define CKM_KEA_KEY_PAIR_GEN (0x1010)
+#define CKM_KEA_KEY_DERIVE (0x1011)
+#define CKM_FORTEZZA_TIMESTAMP (0x1020)
+#define CKM_BATON_KEY_GEN (0x1030)
+#define CKM_BATON_ECB128 (0x1031)
+#define CKM_BATON_ECB96 (0x1032)
+#define CKM_BATON_CBC128 (0x1033)
+#define CKM_BATON_COUNTER (0x1034)
+#define CKM_BATON_SHUFFLE (0x1035)
+#define CKM_BATON_WRAP (0x1036)
+#define CKM_ECDSA_KEY_PAIR_GEN (0x1040)
+#define CKM_EC_KEY_PAIR_GEN (0x1040)
+#define CKM_ECDSA (0x1041)
+#define CKM_ECDSA_SHA1 (0x1042)
+#define CKM_ECDH1_DERIVE (0x1050)
+#define CKM_ECDH1_COFACTOR_DERIVE (0x1051)
+#define CKM_ECMQV_DERIVE (0x1052)
+#define CKM_JUNIPER_KEY_GEN (0x1060)
+#define CKM_JUNIPER_ECB128 (0x1061)
+#define CKM_JUNIPER_CBC128 (0x1062)
+#define CKM_JUNIPER_COUNTER (0x1063)
+#define CKM_JUNIPER_SHUFFLE (0x1064)
+#define CKM_JUNIPER_WRAP (0x1065)
+#define CKM_FASTHASH (0x1070)
+#define CKM_AES_KEY_GEN (0x1080)
+#define CKM_AES_ECB (0x1081)
+#define CKM_AES_CBC (0x1082)
+#define CKM_AES_MAC (0x1083)
+#define CKM_AES_MAC_GENERAL (0x1084)
+#define CKM_AES_CBC_PAD (0x1085)
+#define CKM_AES_CTR (0x1086)
+#define CKM_BLOWFISH_KEY_GEN (0x1090)
+#define CKM_BLOWFISH_CBC (0x1091)
+#define CKM_TWOFISH_KEY_GEN (0x1092)
+#define CKM_TWOFISH_CBC (0x1093)
+#define CKM_DES_ECB_ENCRYPT_DATA (0x1100)
+#define CKM_DES_CBC_ENCRYPT_DATA (0x1101)
+#define CKM_DES3_ECB_ENCRYPT_DATA (0x1102)
+#define CKM_DES3_CBC_ENCRYPT_DATA (0x1103)
+#define CKM_AES_ECB_ENCRYPT_DATA (0x1104)
+#define CKM_AES_CBC_ENCRYPT_DATA (0x1105)
+#define CKM_DSA_PARAMETER_GEN (0x2000)
+#define CKM_DH_PKCS_PARAMETER_GEN (0x2001)
+#define CKM_X9_42_DH_PARAMETER_GEN (0x2002)
+#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+struct ck_mechanism
+{
+ ck_mechanism_type_t mechanism;
+ void *parameter;
+ unsigned long parameter_len;
+};
+
+
+struct ck_mechanism_info
+{
+ unsigned long min_key_size;
+ unsigned long max_key_size;
+ ck_flags_t flags;
+};
+
+/* The following MGFs are defined */
+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
+ * are new for v2.20 */
+#define CKG_MGF1_SHA1 (0x00000001)
+#define CKG_MGF1_SHA256 (0x00000002)
+#define CKG_MGF1_SHA384 (0x00000003)
+#define CKG_MGF1_SHA512 (0x00000004)
+/* v2.20 amendment 3 */
+#define CKG_MGF1_SHA224 (0x00000005)
+
+struct ck_rsa_pkcs_oaep_params {
+ ck_mechanism_type_t hash_alg;
+ unsigned long mgf;
+ unsigned long source;
+ void *source_data;
+ unsigned long source_data_len;
+};
+
+struct ck_rsa_pkcs_pss_params {
+ ck_mechanism_type_t hash_alg;
+ unsigned long mgf;
+ unsigned long slen;
+};
+
+typedef unsigned long ck_ec_kdf_type_t;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL (0x00000001)
+#define CKD_SHA1_KDF (0x00000002)
+
+struct ck_ecdh1_derive_params {
+ ck_ec_kdf_type_t kdf;
+ unsigned long shared_data_len;
+ unsigned char *shared_data;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+};
+
+struct ck_ecdh2_derive_params {
+ ck_ec_kdf_type_t kdf;
+ unsigned long shared_data_len;
+ unsigned char *shared_data;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+ unsigned long private_data_len;
+ ck_object_handle_t private_data;
+ unsigned long public_data_len2;
+ unsigned char *public_data2;
+};
+
+struct ck_ecmqv_derive_params {
+ ck_ec_kdf_type_t kdf;
+ unsigned long shared_data_len;
+ unsigned char *shared_data;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+ unsigned long private_data_len;
+ ck_object_handle_t private_data;
+ unsigned long public_data_len2;
+ unsigned char *public_data2;
+ ck_object_handle_t public_key;
+};
+
+typedef unsigned long ck_x9_42_dh_kdf_type_t;
+
+/* The following X9.42 DH key derivation functions are defined */
+#define CKD_SHA1_KDF_ASN1 (0x00000003)
+#define CKD_SHA1_KDF_CONCATENATE (0x00000004)
+
+struct ck_x9_42_dh1_derive_params {
+ ck_x9_42_dh_kdf_type_t kdf;
+ unsigned long other_info_len;
+ unsigned char *other_info;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+};
+
+struct ck_x9_42_dh2_derive_params {
+ ck_x9_42_dh_kdf_type_t kdf;
+ unsigned long other_info_len;
+ unsigned char *other_info;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+ unsigned long private_data_len;
+ ck_object_handle_t private_data;
+ unsigned long public_data_len2;
+ unsigned char *public_data2;
+};
+
+struct ck_x9_42_mqv_derive_params {
+ ck_x9_42_dh_kdf_type_t kdf;
+ unsigned long other_info_len;
+ unsigned char *other_info;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+ unsigned long private_data_len;
+ ck_object_handle_t private_data;
+ unsigned long public_data_len2;
+ unsigned char *public_data2;
+ ck_object_handle_t public_key;
+};
+
+#define CKF_HW (1 << 0)
+#define CKF_ENCRYPT (1 << 8)
+#define CKF_DECRYPT (1 << 9)
+#define CKF_DIGEST (1 << 10)
+#define CKF_SIGN (1 << 11)
+#define CKF_SIGN_RECOVER (1 << 12)
+#define CKF_VERIFY (1 << 13)
+#define CKF_VERIFY_RECOVER (1 << 14)
+#define CKF_GENERATE (1 << 15)
+#define CKF_GENERATE_KEY_PAIR (1 << 16)
+#define CKF_WRAP (1 << 17)
+#define CKF_UNWRAP (1 << 18)
+#define CKF_DERIVE (1 << 19)
+#define CKF_EC_F_P (1 << 20)
+#define CKF_EC_F_2M (1 << 21)
+#define CKF_EC_ECPARAMETERS (1 << 22)
+#define CKF_EC_NAMEDCURVE (1 << 23)
+#define CKF_EC_UNCOMPRESS (1 << 24)
+#define CKF_EC_COMPRESS (1 << 25)
+#define CKF_EXTENSION ((unsigned long) (1 << 31))
+
+
+/* Flags for C_WaitForSlotEvent. */
+#define CKF_DONT_BLOCK (1)
+
+
+typedef unsigned long ck_rv_t;
+
+
+typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session,
+ ck_notification_t event, void *application);
+
+/* Forward reference. */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args) \
+typedef ck_rv_t (*CK_ ## name) args; \
+ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info));
+_CK_DECLARE_FUNCTION (C_GetFunctionList,
+ (struct ck_function_list **function_list));
+
+_CK_DECLARE_FUNCTION (C_GetSlotList,
+ (unsigned char token_present, ck_slot_id_t *slot_list,
+ unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetSlotInfo,
+ (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION (C_GetTokenInfo,
+ (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION (C_WaitForSlotEvent,
+ (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION (C_GetMechanismList,
+ (ck_slot_id_t slot_id,
+ ck_mechanism_type_t *mechanism_list,
+ unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetMechanismInfo,
+ (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+ struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION (C_InitToken,
+ (ck_slot_id_t slot_id, unsigned char *pin,
+ unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION (C_InitPIN,
+ (ck_session_handle_t session, unsigned char *pin,
+ unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_SetPIN,
+ (ck_session_handle_t session, unsigned char *old_pin,
+ unsigned long old_len, unsigned char *new_pin,
+ unsigned long new_len));
+
+_CK_DECLARE_FUNCTION (C_OpenSession,
+ (ck_slot_id_t slot_id, ck_flags_t flags,
+ void *application, ck_notify_t notify,
+ ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION (C_GetSessionInfo,
+ (ck_session_handle_t session,
+ struct ck_session_info *info));
+_CK_DECLARE_FUNCTION (C_GetOperationState,
+ (ck_session_handle_t session,
+ unsigned char *operation_state,
+ unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION (C_SetOperationState,
+ (ck_session_handle_t session,
+ unsigned char *operation_state,
+ unsigned long operation_state_len,
+ ck_object_handle_t encryption_key,
+ ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION (C_Login,
+ (ck_session_handle_t session, ck_user_type_t user_type,
+ unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_CreateObject,
+ (ck_session_handle_t session,
+ struct ck_attribute *templ,
+ unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION (C_CopyObject,
+ (ck_session_handle_t session, ck_object_handle_t object,
+ struct ck_attribute *templ, unsigned long count,
+ ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION (C_DestroyObject,
+ (ck_session_handle_t session,
+ ck_object_handle_t object));
+_CK_DECLARE_FUNCTION (C_GetObjectSize,
+ (ck_session_handle_t session,
+ ck_object_handle_t object,
+ unsigned long *size));
+_CK_DECLARE_FUNCTION (C_GetAttributeValue,
+ (ck_session_handle_t session,
+ ck_object_handle_t object,
+ struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION (C_SetAttributeValue,
+ (ck_session_handle_t session,
+ ck_object_handle_t object,
+ struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjectsInit,
+ (ck_session_handle_t session,
+ struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjects,
+ (ck_session_handle_t session,
+ ck_object_handle_t *object,
+ unsigned long max_object_count,
+ unsigned long *object_count));
+_CK_DECLARE_FUNCTION (C_FindObjectsFinal,
+ (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_EncryptInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Encrypt,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *encrypted_data,
+ unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION (C_EncryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len,
+ unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_EncryptFinal,
+ (ck_session_handle_t session,
+ unsigned char *last_encrypted_part,
+ unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION (C_DecryptInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Decrypt,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_data,
+ unsigned long encrypted_data_len,
+ unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION (C_DecryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len,
+ unsigned char *part, unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_DecryptFinal,
+ (ck_session_handle_t session,
+ unsigned char *last_part,
+ unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION (C_DigestInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION (C_Digest,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *digest,
+ unsigned long *digest_len));
+_CK_DECLARE_FUNCTION (C_DigestUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_DigestKey,
+ (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_DigestFinal,
+ (ck_session_handle_t session,
+ unsigned char *digest,
+ unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION (C_SignInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Sign,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *signature,
+ unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_SignFinal,
+ (ck_session_handle_t session,
+ unsigned char *signature,
+ unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignRecoverInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_SignRecover,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *signature,
+ unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION (C_VerifyInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Verify,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *signature,
+ unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_VerifyFinal,
+ (ck_session_handle_t session,
+ unsigned char *signature,
+ unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyRecoverInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_VerifyRecover,
+ (ck_session_handle_t session,
+ unsigned char *signature,
+ unsigned long signature_len,
+ unsigned char *data,
+ unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len,
+ unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len,
+ unsigned char *part,
+ unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_SignEncryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len,
+ unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len,
+ unsigned char *part,
+ unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION (C_GenerateKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ struct ck_attribute *templ,
+ unsigned long count,
+ ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_GenerateKeyPair,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ struct ck_attribute *public_key_template,
+ unsigned long public_key_attribute_count,
+ struct ck_attribute *private_key_template,
+ unsigned long private_key_attribute_count,
+ ck_object_handle_t *public_key,
+ ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION (C_WrapKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t wrapping_key,
+ ck_object_handle_t key,
+ unsigned char *wrapped_key,
+ unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION (C_UnwrapKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t unwrapping_key,
+ unsigned char *wrapped_key,
+ unsigned long wrapped_key_len,
+ struct ck_attribute *templ,
+ unsigned long attribute_count,
+ ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_DeriveKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t base_key,
+ struct ck_attribute *templ,
+ unsigned long attribute_count,
+ ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION (C_SeedRandom,
+ (ck_session_handle_t session, unsigned char *seed,
+ unsigned long seed_len));
+_CK_DECLARE_FUNCTION (C_GenerateRandom,
+ (ck_session_handle_t session,
+ unsigned char *random_data,
+ unsigned long random_len));
+
+_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session));
+
+
+struct ck_function_list
+{
+ struct ck_version version;
+ CK_C_Initialize C_Initialize;
+ CK_C_Finalize C_Finalize;
+ CK_C_GetInfo C_GetInfo;
+ CK_C_GetFunctionList C_GetFunctionList;
+ CK_C_GetSlotList C_GetSlotList;
+ CK_C_GetSlotInfo C_GetSlotInfo;
+ CK_C_GetTokenInfo C_GetTokenInfo;
+ CK_C_GetMechanismList C_GetMechanismList;
+ CK_C_GetMechanismInfo C_GetMechanismInfo;
+ CK_C_InitToken C_InitToken;
+ CK_C_InitPIN C_InitPIN;
+ CK_C_SetPIN C_SetPIN;
+ CK_C_OpenSession C_OpenSession;
+ CK_C_CloseSession C_CloseSession;
+ CK_C_CloseAllSessions C_CloseAllSessions;
+ CK_C_GetSessionInfo C_GetSessionInfo;
+ CK_C_GetOperationState C_GetOperationState;
+ CK_C_SetOperationState C_SetOperationState;
+ CK_C_Login C_Login;
+ CK_C_Logout C_Logout;
+ CK_C_CreateObject C_CreateObject;
+ CK_C_CopyObject C_CopyObject;
+ CK_C_DestroyObject C_DestroyObject;
+ CK_C_GetObjectSize C_GetObjectSize;
+ CK_C_GetAttributeValue C_GetAttributeValue;
+ CK_C_SetAttributeValue C_SetAttributeValue;
+ CK_C_FindObjectsInit C_FindObjectsInit;
+ CK_C_FindObjects C_FindObjects;
+ CK_C_FindObjectsFinal C_FindObjectsFinal;
+ CK_C_EncryptInit C_EncryptInit;
+ CK_C_Encrypt C_Encrypt;
+ CK_C_EncryptUpdate C_EncryptUpdate;
+ CK_C_EncryptFinal C_EncryptFinal;
+ CK_C_DecryptInit C_DecryptInit;
+ CK_C_Decrypt C_Decrypt;
+ CK_C_DecryptUpdate C_DecryptUpdate;
+ CK_C_DecryptFinal C_DecryptFinal;
+ CK_C_DigestInit C_DigestInit;
+ CK_C_Digest C_Digest;
+ CK_C_DigestUpdate C_DigestUpdate;
+ CK_C_DigestKey C_DigestKey;
+ CK_C_DigestFinal C_DigestFinal;
+ CK_C_SignInit C_SignInit;
+ CK_C_Sign C_Sign;
+ CK_C_SignUpdate C_SignUpdate;
+ CK_C_SignFinal C_SignFinal;
+ CK_C_SignRecoverInit C_SignRecoverInit;
+ CK_C_SignRecover C_SignRecover;
+ CK_C_VerifyInit C_VerifyInit;
+ CK_C_Verify C_Verify;
+ CK_C_VerifyUpdate C_VerifyUpdate;
+ CK_C_VerifyFinal C_VerifyFinal;
+ CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+ CK_C_VerifyRecover C_VerifyRecover;
+ CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+ CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+ CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+ CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+ CK_C_GenerateKey C_GenerateKey;
+ CK_C_GenerateKeyPair C_GenerateKeyPair;
+ CK_C_WrapKey C_WrapKey;
+ CK_C_UnwrapKey C_UnwrapKey;
+ CK_C_DeriveKey C_DeriveKey;
+ CK_C_SeedRandom C_SeedRandom;
+ CK_C_GenerateRandom C_GenerateRandom;
+ CK_C_GetFunctionStatus C_GetFunctionStatus;
+ CK_C_CancelFunction C_CancelFunction;
+ CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+
+typedef ck_rv_t (*ck_createmutex_t) (void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t) (void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t) (void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex);
+
+
+struct ck_c_initialize_args
+{
+ ck_createmutex_t create_mutex;
+ ck_destroymutex_t destroy_mutex;
+ ck_lockmutex_t lock_mutex;
+ ck_unlockmutex_t unlock_mutex;
+ ck_flags_t flags;
+ void *reserved;
+};
+
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0)
+#define CKF_OS_LOCKING_OK (1 << 1)
+
+#define CKR_OK (0)
+#define CKR_CANCEL (1)
+#define CKR_HOST_MEMORY (2)
+#define CKR_SLOT_ID_INVALID (3)
+#define CKR_GENERAL_ERROR (5)
+#define CKR_FUNCTION_FAILED (6)
+#define CKR_ARGUMENTS_BAD (7)
+#define CKR_NO_EVENT (8)
+#define CKR_NEED_TO_CREATE_THREADS (9)
+#define CKR_CANT_LOCK (0xa)
+#define CKR_ATTRIBUTE_READ_ONLY (0x10)
+#define CKR_ATTRIBUTE_SENSITIVE (0x11)
+#define CKR_ATTRIBUTE_TYPE_INVALID (0x12)
+#define CKR_ATTRIBUTE_VALUE_INVALID (0x13)
+#define CKR_COPY_PROHIBITED (0x1A)
+#define CKR_DATA_INVALID (0x20)
+#define CKR_DATA_LEN_RANGE (0x21)
+#define CKR_DEVICE_ERROR (0x30)
+#define CKR_DEVICE_MEMORY (0x31)
+#define CKR_DEVICE_REMOVED (0x32)
+#define CKR_ENCRYPTED_DATA_INVALID (0x40)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41)
+#define CKR_FUNCTION_CANCELED (0x50)
+#define CKR_FUNCTION_NOT_PARALLEL (0x51)
+#define CKR_FUNCTION_NOT_SUPPORTED (0x54)
+#define CKR_KEY_HANDLE_INVALID (0x60)
+#define CKR_KEY_SIZE_RANGE (0x62)
+#define CKR_KEY_TYPE_INCONSISTENT (0x63)
+#define CKR_KEY_NOT_NEEDED (0x64)
+#define CKR_KEY_CHANGED (0x65)
+#define CKR_KEY_NEEDED (0x66)
+#define CKR_KEY_INDIGESTIBLE (0x67)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68)
+#define CKR_KEY_NOT_WRAPPABLE (0x69)
+#define CKR_KEY_UNEXTRACTABLE (0x6a)
+#define CKR_MECHANISM_INVALID (0x70)
+#define CKR_MECHANISM_PARAM_INVALID (0x71)
+#define CKR_OBJECT_HANDLE_INVALID (0x82)
+#define CKR_OPERATION_ACTIVE (0x90)
+#define CKR_OPERATION_NOT_INITIALIZED (0x91)
+#define CKR_PIN_INCORRECT (0xa0)
+#define CKR_PIN_INVALID (0xa1)
+#define CKR_PIN_LEN_RANGE (0xa2)
+#define CKR_PIN_EXPIRED (0xa3)
+#define CKR_PIN_LOCKED (0xa4)
+#define CKR_SESSION_CLOSED (0xb0)
+#define CKR_SESSION_COUNT (0xb1)
+#define CKR_SESSION_HANDLE_INVALID (0xb3)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4)
+#define CKR_SESSION_READ_ONLY (0xb5)
+#define CKR_SESSION_EXISTS (0xb6)
+#define CKR_SESSION_READ_ONLY_EXISTS (0xb7)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8)
+#define CKR_SIGNATURE_INVALID (0xc0)
+#define CKR_SIGNATURE_LEN_RANGE (0xc1)
+#define CKR_TEMPLATE_INCOMPLETE (0xd0)
+#define CKR_TEMPLATE_INCONSISTENT (0xd1)
+#define CKR_TOKEN_NOT_PRESENT (0xe0)
+#define CKR_TOKEN_NOT_RECOGNIZED (0xe1)
+#define CKR_TOKEN_WRITE_PROTECTED (0xe2)
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2)
+#define CKR_USER_ALREADY_LOGGED_IN (0x100)
+#define CKR_USER_NOT_LOGGED_IN (0x101)
+#define CKR_USER_PIN_NOT_INITIALIZED (0x102)
+#define CKR_USER_TYPE_INVALID (0x103)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104)
+#define CKR_USER_TOO_MANY_TYPES (0x105)
+#define CKR_WRAPPED_KEY_INVALID (0x110)
+#define CKR_WRAPPED_KEY_LEN_RANGE (0x112)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113)
+#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120)
+#define CKR_RANDOM_NO_RNG (0x121)
+#define CKR_DOMAIN_PARAMS_INVALID (0x130)
+#define CKR_BUFFER_TOO_SMALL (0x150)
+#define CKR_SAVED_STATE_INVALID (0x160)
+#define CKR_INFORMATION_SENSITIVE (0x170)
+#define CKR_STATE_UNSAVEABLE (0x180)
+#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191)
+#define CKR_MUTEX_BAD (0x1a0)
+#define CKR_MUTEX_NOT_LOCKED (0x1a1)
+#define CKR_NEW_PIN_MODE (0x1b0)
+#define CKR_NEXT_OTP (0x1b1)
+#define CKR_FUNCTION_REJECTED (0x200)
+#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+\f
+/* Compatibility layer. */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL. */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_rsa_pkcs_oaep_params CK_RSA_PKCS_OAEP_PARAMS;
+typedef struct ck_rsa_pkcs_oaep_params *CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+#define NULL_PTR NULL
+
+/* Delete the helper macros defined at the top of the file. */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rsa_pkcs_oaep_params
+#undef hash_alg
+#undef source_data
+#undef source_data_len
+#undef slen
+
+#undef ck_ec_kdf_type_t
+#undef shared_data_len
+#undef shared_data
+#undef public_data_len
+#undef public_data
+#undef private_data_len
+#undef private_data
+#undef public_data_len2
+#undef public_data2
+#undef public_key
+
+#undef ck_x9_42_dh_kdf_type_t
+#undef other_info_len
+#undef other_info
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+\f
+/* System dependencies. */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* PKCS11_H */
diff --git a/src/lib/data_mgr/ByteString.cpp b/src/lib/data_mgr/ByteString.cpp
--- /dev/null
@@ -0,0 +1,356 @@
+/* $Id: ByteString.cpp 54 2010-04-14 12:10:06Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteString.cpp
+
+ A string class for byte strings stored in securely allocated memory
+ *****************************************************************************/
+
+#include <algorithm>
+#include <string>
+#include <stdio.h>
+#include "config.h"
+#include "log.h"
+#include "ByteString.h"
+
+// Constructors
+ByteString::ByteString()
+{
+}
+
+ByteString::ByteString(const unsigned char* bytes, const size_t bytesLen)
+{
+ byteString.resize(bytesLen);
+
+ memcpy(&byteString[0], bytes, bytesLen);
+}
+
+ByteString::ByteString(const char* hexString)
+{
+ std::string hex = std::string(hexString);
+
+ if (hex.size() % 2 != 0)
+ {
+ hex = "0" + hex;
+ }
+
+ for (size_t i = 0; i < hex.size(); i += 2)
+ {
+ std::string byteStr;
+ byteStr += hex[i];
+ byteStr += hex[i+1];
+
+ unsigned char byteVal = (unsigned char) strtoul(byteStr.c_str(), NULL, 16);
+
+ this->operator+=(byteVal);
+ }
+}
+
+ByteString::ByteString(const unsigned long longValue)
+{
+ unsigned long setValue = longValue;
+
+ // Convert the value to a big-endian byte string; N.B.: this code assumes that unsigned long
+ // values are stored as a 64-bit value, which is a safe assumption on modern systems. It will
+ // also properly handle a 32-bit value and will simply store 4 zeroes at the front of the
+ // string. If at some point in time we get 128-bit architectures, the top 8 bytes of the value
+ // will be discarded... (but hey, 640K is enough for everybody, right?)
+ //
+ // The reason for coding it this way is that implementations of SoftHSM will maintain
+ // binary compatibility between eachothers background storage (i.e. a 32-bit SoftHSM version can
+ // read the storage of a 64-bit version and vice versa under the assumption that the stored
+ // values never exceed 32-bits, which is likely since these values are only used to encode
+ // byte string lengths)
+ unsigned char byteStrIn[8];
+
+ for (size_t i = 0; i < 8; i++)
+ {
+ byteStrIn[7-i] = (unsigned char) (setValue & 0xFF);
+ setValue >>= 8;
+ }
+
+ byteString.resize(8);
+ memcpy(&byteString[0], byteStrIn, 8);
+}
+
+ByteString::ByteString(const ByteString& in)
+{
+ this->byteString = in.byteString;
+}
+
+// Append data
+ByteString& ByteString::operator+=(const ByteString& append)
+{
+ size_t curLen = byteString.size();
+ size_t toAdd = append.byteString.size();
+ size_t newLen = curLen + toAdd;
+
+ byteString.resize(newLen);
+
+ memcpy(&byteString[curLen], &append.byteString[0], toAdd);
+
+ return *this;
+}
+
+ByteString& ByteString::operator+=(const unsigned char byte)
+{
+ byteString.push_back(byte);
+
+ return *this;
+}
+
+// XORing
+ByteString& ByteString::operator^=(const ByteString& rhs)
+{
+ size_t xorLen = std::min(this->size(), rhs.size());
+
+ for (size_t i = 0; i < xorLen; i++)
+ {
+ byteString[i] ^= rhs.const_byte_str()[i];
+ }
+
+ return *this;
+}
+
+// Return a substring
+ByteString ByteString::substr(const size_t start, const size_t len /* = SIZE_T_MAX */) const
+{
+ size_t retLen = std::min(len, byteString.size() - start);
+
+ if (start >= byteString.size())
+ {
+ return ByteString();
+ }
+ else
+ {
+ return ByteString(&byteString[start], retLen);
+ }
+}
+
+// Add data
+ByteString operator+(const ByteString& lhs, const ByteString& rhs)
+{
+ ByteString rv = lhs;
+ rv += rhs;
+
+ return rv;
+}
+
+ByteString operator+(const unsigned char lhs, const ByteString& rhs)
+{
+ ByteString rv(&lhs, 1);
+ rv += rhs;
+
+ return rv;
+}
+
+ByteString operator+(const ByteString& lhs, const unsigned char rhs)
+{
+ ByteString rv = lhs;
+ rv += rhs;
+
+ return rv;
+}
+
+// Array operator
+unsigned char& ByteString::operator[](size_t pos)
+{
+ return byteString[pos];
+}
+
+// Return the byte string data
+unsigned char* ByteString::byte_str()
+{
+ return &byteString[0];
+}
+
+// Return the const byte string
+const unsigned char* ByteString::const_byte_str() const
+{
+ return (const unsigned char*) &byteString[0];
+}
+
+// Return a hexadecimal character representation of the string
+std::string ByteString::hex_str() const
+{
+ std::string rv;
+ char hex[3];
+
+ for (size_t i = 0; i < byteString.size(); i++)
+ {
+ sprintf(hex, "%02X", byteString[i]);
+
+ rv += hex;
+ }
+
+ return rv;
+}
+
+// Return the long value
+const unsigned long ByteString::long_val() const
+{
+ // Convert the first 8 bytes of the string to an unsigned long value
+ unsigned long rv = 0;
+
+ for (size_t i = 0; i < std::min(size_t(8), byteString.size()); i++)
+ {
+ rv <<= 8;
+ rv += byteString[i];
+ }
+
+ return rv;
+}
+
+// Cut of the first part of the string and convert it to a long value
+unsigned long ByteString::firstLong()
+{
+ unsigned long rv = long_val();
+
+ split(8);
+
+ return rv;
+}
+
+// Split of the specified part of the string as a separate byte string
+ByteString ByteString::split(size_t len)
+{
+ ByteString rv = substr(0, len);
+
+ size_t newSize = (byteString.size() > len) ? (byteString.size() - len) : 0;
+
+ if (newSize > 0)
+ {
+ for (size_t i = 0; i < newSize; i++)
+ {
+ byteString[i] = byteString[i + len];
+ }
+ }
+
+ byteString.resize(newSize);
+
+ return rv;
+}
+
+// The size of the byte string in bits
+size_t ByteString::bits() const
+{
+ size_t bits = byteString.size() * 8;
+
+ if (bits == 0) return 0;
+
+ for (size_t i = 0; i < byteString.size(); i++)
+ {
+ unsigned char byte = byteString[i];
+
+ for (unsigned char mask = 0x80; mask > 0; mask >>= 1)
+ {
+ if ((byte & mask) == 0)
+ {
+ bits--;
+ }
+ else
+ {
+ return bits;
+ }
+ }
+ }
+
+ return bits;
+}
+
+// The size of the byte string in bytes
+size_t ByteString::size() const
+{
+ return byteString.size();
+}
+
+void ByteString::resize(const size_t newSize)
+{
+ byteString.resize(newSize);
+}
+
+void ByteString::wipe(const size_t newSize /* = 0 */)
+{
+ this->resize(newSize);
+
+ memset(&byteString[0], 0x00, byteString.size());
+}
+
+// Comparison
+bool ByteString::operator==(const ByteString& compareTo) const
+{
+ if (compareTo.size() != this->size())
+ {
+ return false;
+ }
+
+ return (memcmp(&byteString[0], &compareTo.byteString[0], this->size()) == 0);
+}
+
+bool ByteString::operator!=(const ByteString& compareTo) const
+{
+ if (compareTo.size() != this->size())
+ {
+ return true;
+ }
+
+ return (memcmp(&byteString[0], &compareTo.byteString[0], this->size()) != 0);
+}
+
+// XOR data
+ByteString operator^(const ByteString& lhs, const ByteString& rhs)
+{
+ size_t xorLen = std::min(lhs.size(), rhs.size());
+ ByteString rv;
+
+ for (size_t i = 0; i < xorLen; i++)
+ {
+ rv += lhs.const_byte_str()[i] ^ rhs.const_byte_str()[i];
+ }
+
+ return rv;
+}
+
+// Serialisation/deserialisation
+ByteString ByteString::serialise() const
+{
+ ByteString len((unsigned long) size());
+
+ return len + *this;
+}
+
+/* static */ ByteString ByteString::chainDeserialise(ByteString& serialised)
+{
+ size_t len = (size_t) serialised.firstLong();
+
+ ByteString rv = serialised.split(len);
+
+ return rv;
+}
+
diff --git a/src/lib/data_mgr/ByteString.h b/src/lib/data_mgr/ByteString.h
--- /dev/null
@@ -0,0 +1,133 @@
+/* $Id: ByteString.h 54 2010-04-14 12:10:06Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteString.h
+
+ A string class for byte strings stored in securely allocated memory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BYTESTRING_H
+#define _SOFTHSM_V2_BYTESTRING_H
+
+#include <cstddef>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+#include <limits.h>
+#include "config.h"
+#include "SecureAllocator.h"
+#include "Serialisable.h"
+
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX ((size_t) -1)
+#endif // !SIZE_T_MAX
+
+class ByteString
+{
+public:
+ // Constructors
+ ByteString();
+
+ ByteString(const unsigned char* bytes, const size_t bytesLen);
+
+ ByteString(const char* hexString);
+
+ ByteString(const unsigned long longValue);
+
+ ByteString(const ByteString& in);
+
+ // Destructor
+ virtual ~ByteString() { }
+
+ // Append data
+ ByteString& operator+=(const ByteString& append);
+ ByteString& operator+=(const unsigned char byte);
+
+ // Return a substring
+ ByteString substr(const size_t start, const size_t len = SIZE_T_MAX) const;
+
+ // Array operator
+ unsigned char& operator[](size_t pos);
+
+ // Return the byte string
+ unsigned char* byte_str();
+
+ // Return the const byte string
+ const unsigned char* const_byte_str() const;
+
+ // Return a hexadecimal character representation of the string
+ std::string hex_str() const;
+
+ // Return the long value
+ const unsigned long long_val() const;
+
+ // Cut of the first part of the string and convert it to a long value
+ unsigned long firstLong();
+
+ // Split of the specified part of the string as a separate byte string
+ ByteString split(size_t len);
+
+ // Return the size in bits
+ size_t bits() const;
+
+ // Return the size in bytes
+ size_t size() const;
+
+ // Resize
+ void resize(const size_t newSize);
+
+ // Wipe
+ void wipe(const size_t newSize = 0);
+
+ // Comparison
+ bool operator==(const ByteString& compareTo) const;
+ bool operator!=(const ByteString& compareTo) const;
+
+ // XORing
+ ByteString& operator^=(const ByteString& rhs);
+
+ // Serialisation/deserialisation
+ virtual ByteString serialise() const;
+
+ static ByteString chainDeserialise(ByteString& serialised);
+
+private:
+ std::vector<unsigned char, SecureAllocator<unsigned char> > byteString;
+};
+
+// Add data
+ByteString operator+(const ByteString& lhs, const ByteString& rhs);
+ByteString operator+(const unsigned char lhs, const ByteString& rhs);
+ByteString operator+(const ByteString& lhs, const unsigned char rhs);
+
+// XOR data
+ByteString operator^(const ByteString& lhs, const ByteString& rhs);
+
+#endif // !_SOFTHSM_V2_BYTESTRING_H
+
diff --git a/src/lib/data_mgr/Makefile.am b/src/lib/data_mgr/Makefile.am
--- /dev/null
@@ -0,0 +1,19 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/..
+
+noinst_LTLIBRARIES = libsofthsm_datamgr.la
+libsofthsm_datamgr_la_SOURCES = ByteString.cpp \
+ RFC4880.cpp \
+ salloc.cpp \
+ SecureDataManager.cpp \
+ SecureMemoryRegistry.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/data_mgr/RFC4880.cpp b/src/lib/data_mgr/RFC4880.cpp
--- /dev/null
@@ -0,0 +1,112 @@
+/* $Id: RFC4880.cpp 4780 2010-05-13 16:18:07Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880.cpp
+
+ Implements a secure password-based key derivation scheme. It is not a generic
+ implementation of the RFC but only generates 256-bit AES keys according to
+ the "iterated and salted" scheme.
+ *****************************************************************************/
+
+#include "config.h"
+#include "RFC4880.h"
+#include "CryptoFactory.h"
+#include "HashAlgorithm.h"
+
+// This function derives a 256-bit AES key from the supplied password data
+bool RFC4880::PBEDeriveKey(const ByteString& password, ByteString& salt, AESKey** ppKey)
+{
+ // Check that a proper salt value was supplied; it should be at least 8 bytes long
+ if (salt.size() < 8)
+ {
+ ERROR_MSG("Insufficient salt data supplied for password-based encryption");
+
+ return false;
+ }
+
+ // Check other parameters
+ if ((password.size() == 0) || (ppKey == NULL))
+ {
+ return false;
+ }
+
+ // Determine the iteration count based on the last byte of the salt
+ unsigned int iter = PBE_ITERATION_BASE_COUNT + salt[salt.size() - 1];
+
+ // Get a hash instance
+ HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm("sha256");
+
+ if (hash == NULL)
+ {
+ ERROR_MSG("Could not get a SHA-256 instance");
+
+ return false;
+ }
+
+ // Perform the first iteration which takes as input the salt value and
+ // the password
+ ByteString intermediate;
+
+ if (!hash->hashInit() ||
+ !hash->hashUpdate(salt) ||
+ !hash->hashUpdate(password) ||
+ !hash->hashFinal(intermediate))
+ {
+ ERROR_MSG("Hashing failed");
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ return false;
+ }
+
+ // Perform the remaining iteration
+ while (--iter > 0)
+ {
+ if (!hash->hashInit() ||
+ !hash->hashUpdate(intermediate) ||
+ !hash->hashFinal(intermediate))
+ {
+ ERROR_MSG("Hashing failed");
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ return false;
+ }
+ }
+
+ // Create the AES key instance
+ *ppKey = new AESKey(256);
+ (*ppKey)->setKeyBits(intermediate);
+
+ // Release the hash instance
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ return true;
+}
+
diff --git a/src/lib/data_mgr/RFC4880.h b/src/lib/data_mgr/RFC4880.h
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id: RFC4880.h 4780 2010-05-13 16:18:07Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880.h
+
+ Implements a secure password-based key derivation scheme. It is not a generic
+ implementation of the RFC but only generates 256-bit AES keys according to
+ the "iterated and salted" scheme.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RFC4880_H
+#define _SOFTHSM_V2_RFC4880_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "log.h"
+#include "AESKey.h"
+
+// This define sets the base PBE iteration count; the lowest byte of the salt is added
+// to this value as a form of jitter
+#define PBE_ITERATION_BASE_COUNT 1500
+
+namespace RFC4880
+{
+ // This function derives a 256-bit AES key from the supplied password data
+ bool PBEDeriveKey(const ByteString& password, ByteString& salt, AESKey** ppKey);
+}
+
+#endif // !_SOFTHSM_V2_RFC4880_H
+
diff --git a/src/lib/data_mgr/SecureAllocator.h b/src/lib/data_mgr/SecureAllocator.h
--- /dev/null
@@ -0,0 +1,185 @@
+/* $Id: SecureAllocator.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureAllocator.h
+
+ Implements a template class for a secure C++ allocator. The allocator will
+ zero all the memory it allocates before releasing it to ensure that the
+ data stored in the memory is destroyed properly to minimise the risk of
+ obtaining sensitive data from memory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREALLOCATOR_H
+#define _SOFTHSM_V2_SECUREALLOCATOR_H
+
+#include <limits>
+#include <stdlib.h>
+#include <string.h>
+#ifdef SENSITIVE_NON_PAGED
+#include <sys/mman.h>
+#endif // SENSITIVE_NON_PAGED
+#include "config.h"
+#include "log.h"
+#include "SecureMemoryRegistry.h"
+
+template<class T> class SecureAllocator
+{
+public:
+ // Member types
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ // Rebind to another type
+ template<class U> struct rebind
+ {
+ typedef SecureAllocator<U> other;
+ };
+
+ // Constructor
+ inline SecureAllocator() { }
+
+ inline SecureAllocator(const SecureAllocator&) { }
+
+ template<class U> SecureAllocator(const SecureAllocator<U>&) { }
+
+ // Destructor
+ inline virtual ~SecureAllocator() { }
+
+ // Return the maximum allocation size
+ size_type max_size() const
+ {
+ return std::numeric_limits<std::size_t>::max() / sizeof(T);
+ }
+
+ // Return the address of values
+ inline pointer address(reference value) const
+ {
+ return &value;
+ }
+
+ inline const_pointer address(const_reference value) const
+ {
+ return &value;
+ }
+
+ // Allocate n elements of type T
+ inline pointer allocate(size_type n, const void* = NULL)
+ {
+#ifdef SENSITIVE_NON_PAGED
+ // Allocate memory on a page boundary
+ pointer r = (pointer) valloc(n * sizeof(T));
+
+ if (r == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Lock the memory so it doesn't get swapped out
+ if (mlock((const void*) r, n * sizeof(T)) != 0)
+ {
+ ERROR_MSG("Could not allocate non-paged memory for secure storage");
+
+ // Hmmm... best to not return any allocated space in this case
+ free(r);
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(r, n * sizeof(T));
+
+ return r;
+#else
+ pointer r = (pointer)(::operator new(n * sizeof(T)));
+
+ if (r == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(r, n * sizeof(T));
+
+ return r;
+#endif // SENSITIVE_NON_PAGED
+ }
+
+ // Deallocate n elements of type T
+ inline void deallocate(pointer p, size_type n)
+ {
+#ifdef PARANOID
+ // First toggle all bits on
+ memset(p, 0xFF, n * sizeof(T));
+#endif // PARANOID
+
+ // Toggle all bits off
+ memset(p, 0x00, n * sizeof(T));
+
+ // Unregister the memory from the secure memory registry
+ SecureMemoryRegistry::i()->remove(p);
+
+#ifdef SENSITIVE_NON_PAGED
+ munlock((const void*) p, n * sizeof(T));
+
+ free(p);
+#else
+ // Release the memory
+ ::operator delete((void*) p);
+#endif // SENSITIVE_NON_PAGED
+ }
+
+ // Initialise allocate storage with a value
+ void construct(pointer p, const T& value)
+ {
+ new((void*) p)T(value);
+ }
+
+ // Destroy elements of initialised storage
+ void destroy(pointer p)
+ {
+ // Call destructor
+ p->~T();
+ }
+
+ // Comparison operators
+ inline bool operator==(SecureAllocator const&) { return true; }
+ inline bool operator!=(SecureAllocator const&) { return false; }
+};
+
+#endif // !_SOFTHSM_V2_SECUREALLOCATOR_H
+
diff --git a/src/lib/data_mgr/SecureDataManager.cpp b/src/lib/data_mgr/SecureDataManager.cpp
--- /dev/null
@@ -0,0 +1,435 @@
+/* $Id: SecureDataManager.cpp 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataManager.cpp
+
+ The secure data manager main class. Every token instance has a secure data
+ manager instance member that is used to decrypt and encrypt sensitive object
+ attributes such as key material. The secure data manager maintains a key blob
+ containing a 256-bit AES key that is used in this decryption and encryption
+ process. The key blob itself is encrypted using a PBE derived key that is
+ derived from the user PIN and a PBE key that is derived from the SO PIN. It
+ is up to the token to enforce access control based on which user is logged
+ in; authentication using the SO PIN is required to be able to change the
+ user PIN. The master key that is used to decrypt/encrypt sensitive attributes
+ is stored in memory under a mask that is changed every time the key is used.
+ *****************************************************************************/
+
+#include "config.h"
+#include "SecureDataManager.h"
+#include "CryptoFactory.h"
+#include "AESKey.h"
+#include "SymmetricAlgorithm.h"
+#include "RFC4880.h"
+
+// Constructors
+
+// Initialise the object; called by all constructors
+void SecureDataManager::initObject()
+{
+ // Get an RNG instance
+ rng = CryptoFactory::i()->getRNG();
+
+ // Get an AES implementation
+ aes = CryptoFactory::i()->getSymmetricAlgorithm("aes");
+
+ // Initialise masking data
+ mask = new ByteString();
+
+ rng->generateRandom(*mask, 32);
+
+ // Set the initial login state
+ soLoggedIn = userLoggedIn = false;
+
+ // Set the magic
+ magic = ByteString("524A52"); // RJR
+
+ // Get a mutex
+ dataMgrMutex = MutexFactory::i()->getMutex();
+}
+
+// Constructs a new SecureDataManager for a blank token; actual
+// initialisation is done by setting the SO PIN
+SecureDataManager::SecureDataManager()
+{
+ initObject();
+}
+
+// Constructs a SecureDataManager using the specified key blob
+SecureDataManager::SecureDataManager(const ByteString& soPINBlob, const ByteString& userPINBlob)
+{
+ initObject();
+
+ // De-serialise the key blob
+ soEncryptedKey = soPINBlob;
+ userEncryptedKey = userPINBlob;
+}
+
+// Destructor
+SecureDataManager::~SecureDataManager()
+{
+ // Recycle the AES instance
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+
+ // Clean up the mask
+ delete mask;
+
+ MutexFactory::i()->recycleMutex(dataMgrMutex);
+}
+
+// Generic function for creating an encrypted version of the key from the specified passphrase
+bool SecureDataManager::pbeEncryptKey(const ByteString& passphrase, ByteString& encryptedKey)
+{
+ // Generate salt
+ ByteString salt;
+
+ if (!rng->generateRandom(salt, 8)) return false;
+
+ // Derive the key using RFC4880 PBE
+ AESKey* pbeKey = NULL;
+
+ if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
+ {
+ return false;
+ }
+
+ // Add the salt
+ encryptedKey.wipe();
+ encryptedKey += salt;
+
+ // Encrypt the data
+ ByteString block;
+
+ if (!aes->encryptInit(pbeKey, "cbc"))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ // First, add the magic
+ if (!aes->encryptUpdate(magic, block))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ encryptedKey += block;
+
+ // Then, add the key itself
+ ByteString key;
+
+ {
+ MutexLocker lock(dataMgrMutex);
+
+ unmask(key);
+
+ bool rv = aes->encryptUpdate(key, block);
+
+ remask(key);
+
+ if (!rv)
+ {
+ delete pbeKey;
+
+ return false;
+ }
+ }
+
+ encryptedKey += block;
+
+ // And finalise encryption
+ if (!aes->encryptFinal(block))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ encryptedKey += block;
+
+ delete pbeKey;
+
+ return true;
+}
+
+// Set the SO PIN (requires either a blank SecureDataManager or the
+// SO to have logged in previously)
+bool SecureDataManager::setSOPIN(const ByteString& soPIN)
+{
+ // Check the new PIN
+ if (soPIN.size() == 0)
+ {
+ DEBUG_MSG("Zero length PIN specified");
+
+ return false;
+ }
+
+ // Check if the SO needs to be logged in
+ if ((soEncryptedKey.size() > 0) && !soLoggedIn)
+ {
+ DEBUG_MSG("SO must be logged in to change the SO PIN");
+
+ return false;
+ }
+
+ // If no SO PIN was set, then this is a SecureDataManager for a blank token. This
+ // means a new key has to be generated
+ if (soEncryptedKey.size() == 0)
+ {
+ ByteString key;
+
+ rng->generateRandom(key, 32);
+
+ remask(key);
+ }
+
+ return pbeEncryptKey(soPIN, soEncryptedKey);
+}
+
+// Set the user PIN (requires either the SO or the user to have logged
+// in previously)
+bool SecureDataManager::setUserPIN(const ByteString& userPIN)
+{
+ // Check if the SO or the user is logged in
+ if (!soLoggedIn && !userLoggedIn)
+ {
+ DEBUG_MSG("Must be logged in to change the user PIN");
+
+ return false;
+ }
+
+ // Check the new PIN
+ if (userPIN.size() == 0)
+ {
+ DEBUG_MSG("Zero length PIN specified");
+
+ return false;
+ }
+
+ return pbeEncryptKey(userPIN, userEncryptedKey);
+}
+
+// Generic login function
+bool SecureDataManager::login(const ByteString& passphrase, const ByteString& encryptedKey)
+{
+ // Log out first
+ this->logout();
+
+ // First, take the salt from the encrypted key
+ ByteString salt = encryptedKey.substr(0,8);
+
+ // Now, take the encrypted data from the encrypted key
+ ByteString encryptedKeyData = encryptedKey.substr(8);
+
+ // Derive the PBE key
+ AESKey* pbeKey = NULL;
+
+ if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
+ {
+ return false;
+ }
+
+ // Decrypt the key data
+ ByteString decryptedKeyData;
+ ByteString finalBlock;
+
+ // NOTE: The login will fail here if incorrect passphrase is supplied
+ if (!aes->decryptInit(pbeKey, "cbc") ||
+ !aes->decryptUpdate(encryptedKeyData, decryptedKeyData) ||
+ !aes->decryptFinal(finalBlock))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ delete pbeKey;
+
+ decryptedKeyData += finalBlock;
+
+ // Check the magic
+ if (decryptedKeyData.substr(0, 3) != magic)
+ {
+ // The passphrase was incorrect
+ DEBUG_MSG("Incorrect passphrase supplied");
+
+ return false;
+ }
+
+ // Strip off the magic
+ ByteString key = decryptedKeyData.substr(3);
+
+ // And mask the key
+ decryptedKeyData.wipe();
+
+ MutexLocker lock(dataMgrMutex);
+ remask(key);
+
+ return true;
+}
+
+// Log in using the SO PIN
+bool SecureDataManager::loginSO(const ByteString& soPIN)
+{
+ return (soLoggedIn = login(soPIN, soEncryptedKey));
+}
+
+// Log in using the user PIN
+bool SecureDataManager::loginUser(const ByteString& userPIN)
+{
+ return (userLoggedIn = login(userPIN, userEncryptedKey));
+}
+
+// Log out
+void SecureDataManager::logout()
+{
+ MutexLocker lock(dataMgrMutex);
+
+ // Clear the logged in state
+ soLoggedIn = userLoggedIn = false;
+
+ // Clear the masked key
+ maskedKey.wipe();
+}
+
+// Decrypt the supplied data
+bool SecureDataManager::decrypt(const ByteString& encrypted, ByteString& plaintext)
+{
+ // Check the object logged in state
+ if ((!userLoggedIn && !soLoggedIn) || (maskedKey.size() != 32))
+ {
+ return false;
+ }
+
+ AESKey theKey(256);
+ ByteString unmaskedKey;
+
+ {
+ MutexLocker lock(dataMgrMutex);
+
+ unmask(unmaskedKey);
+
+ theKey.setKeyBits(unmaskedKey);
+
+ remask(unmaskedKey);
+ }
+
+ ByteString finalBlock;
+
+ if (!aes->decryptInit(&theKey, "cbc") ||
+ !aes->decryptUpdate(encrypted, plaintext) ||
+ !aes->decryptFinal(finalBlock))
+ {
+ return false;
+ }
+
+ plaintext += finalBlock;
+
+ return true;
+}
+
+// Encrypt the supplied data
+bool SecureDataManager::encrypt(const ByteString& plaintext, ByteString& encrypted)
+{
+ // Check the object logged in state
+ if ((!userLoggedIn && !soLoggedIn) || (maskedKey.size() != 32))
+ {
+ return false;
+ }
+
+ AESKey theKey(256);
+ ByteString unmaskedKey;
+
+ {
+ MutexLocker lock(dataMgrMutex);
+
+ unmask(unmaskedKey);
+
+ theKey.setKeyBits(unmaskedKey);
+
+ remask(unmaskedKey);
+ }
+
+ ByteString finalBlock;
+
+ if (!aes->encryptInit(&theKey, "cbc") ||
+ !aes->encryptUpdate(plaintext, encrypted) ||
+ !aes->encryptFinal(finalBlock))
+ {
+ return false;
+ }
+
+ encrypted += finalBlock;
+
+ return true;
+}
+
+// Returns the key blob for the SO PIN
+ByteString SecureDataManager::getSOPINBlob()
+{
+ return soEncryptedKey;
+}
+
+// Returns the key blob for the user PIN
+ByteString SecureDataManager::getUserPINBlob()
+{
+ return userEncryptedKey;
+}
+
+// Unmask the key
+void SecureDataManager::unmask(ByteString& key)
+{
+ key = maskedKey;
+ key ^= *mask;
+}
+
+// Remask the key
+void SecureDataManager::remask(ByteString& key)
+{
+ // Generate a new mask
+ rng->generateRandom(*mask, 32);
+
+ key ^= *mask;
+ maskedKey = key;
+}
+
+// Check if the SO is logged in
+bool SecureDataManager::isSOLoggedIn()
+{
+ return soLoggedIn;
+}
+
+// Check if the user is logged in
+bool SecureDataManager::isUserLoggedIn()
+{
+ return userLoggedIn;
+}
+
diff --git a/src/lib/data_mgr/SecureDataManager.h b/src/lib/data_mgr/SecureDataManager.h
--- /dev/null
@@ -0,0 +1,149 @@
+/* $Id: SecureDataManager.h 4902 2010-09-17 13:10:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataManager.h
+
+ The secure data manager main class. Every token instance has a secure data
+ manager instance member that is used to decrypt and encrypt sensitive object
+ attributes such as key material. The secure data manager maintains a key blob
+ containing a 256-bit AES key that is used in this decryption and encryption
+ process. The key blob itself is encrypted using a PBE derived key that is
+ derived from the user PIN and a PBE key that is derived from the SO PIN. It
+ is up to the token to enforce access control based on which user is logged
+ in; authentication using the SO PIN is required to be able to change the
+ user PIN. The master key that is used to decrypt/encrypt sensitive attributes
+ is stored in memory under a mask that is changed every time the key is used.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREDATAMANAGER_H
+#define _SOFTHSM_V2_SECUREDATAMANAGER_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "log.h"
+#include "AESKey.h"
+#include "RNG.h"
+#include "SymmetricAlgorithm.h"
+#include "MutexFactory.h"
+
+class SecureDataManager
+{
+public:
+ // Constructors
+
+ // Constructs a new SecureDataManager for a blank token; actual
+ // initialisation is done by setting the SO PIN
+ SecureDataManager();
+
+ // Constructs a SecureDataManager using the specified SO PIN and user PIN
+ SecureDataManager(const ByteString& soPINBlob, const ByteString& userPINBlob);
+
+ // Destructor
+ virtual ~SecureDataManager();
+
+ // Set the SO PIN (requires either a blank SecureDataManager or the
+ // SO to have logged in previously)
+ bool setSOPIN(const ByteString& soPIN);
+
+ // Set the user PIN (requires either the SO or the user to have logged
+ // in previously)
+ bool setUserPIN(const ByteString& userPIN);
+
+ // Log in using the SO PIN
+ bool loginSO(const ByteString& soPIN);
+ bool isSOLoggedIn();
+
+ // Log in using the user PIN
+ bool loginUser(const ByteString& userPIN);
+ bool isUserLoggedIn();
+
+ // Log out
+ void logout();
+
+ // Decrypt the supplied data
+ bool decrypt(const ByteString& encrypted, ByteString& plaintext);
+
+ // Encrypt the supplied data
+ bool encrypt(const ByteString& plaintext, ByteString& encrypted);
+
+ // Returns the key blob for the SO PIN
+ ByteString getSOPINBlob();
+
+ // Returns the key blob for the user PIN
+ ByteString getUserPINBlob();
+
+private:
+ // Initialise the object
+ void initObject();
+
+ // Generic login function
+ bool login(const ByteString& passphrase, const ByteString& encryptedKey);
+
+ // Generic function for creating an encrypted version of the key from the specified passphrase
+ bool pbeEncryptKey(const ByteString& passphrase, ByteString& encryptedKey);
+
+ // Unmask the key
+ void unmask(ByteString& key);
+
+ // Remask the key
+ void remask(ByteString& key);
+
+ // The user PIN encrypted key
+ ByteString userEncryptedKey;
+
+ // The SO PIN encrypted key
+ ByteString soEncryptedKey;
+
+ // Which users are logged in
+ bool soLoggedIn;
+ bool userLoggedIn;
+
+ // The masked version of the actual key
+ ByteString maskedKey;
+
+ // The "magic" data used to detect if a PIN was likely to be correct
+ ByteString magic;
+
+ // The mask; this is not a stack member but a heap member. This
+ // hopefully ensures that the mask ends up in a memory location
+ // that is not logically linked to the masked key
+ ByteString* mask;
+
+ // Random number generator instance
+ RNG* rng;
+
+ // AES instance
+ SymmetricAlgorithm* aes;
+
+ // Mutex
+ Mutex* dataMgrMutex;
+};
+
+#endif // !_SOFTHSM_V2_SECUREDATAMANAGER_H
+
diff --git a/src/lib/data_mgr/SecureMemoryRegistry.cpp b/src/lib/data_mgr/SecureMemoryRegistry.cpp
--- /dev/null
@@ -0,0 +1,138 @@
+/* $Id: SecureMemoryRegistry.cpp 6911 2012-12-21 10:54:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureMemoryRegistry.cpp
+
+ Implements a singleton class that keeps track of all securely allocated
+ memory. This registry can be used to wipe securely allocated memory in case
+ of a fatal exception
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "log.h"
+#include "SecureMemoryRegistry.h"
+
+// Initialise the one-and-only instance
+SecureMemoryRegistry* SecureMemoryRegistry::instance = NULL;
+
+// Constructor
+SecureMemoryRegistry::SecureMemoryRegistry()
+{
+ SecMemRegistryMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SecureMemoryRegistry::~SecureMemoryRegistry()
+{
+ MutexFactory::i()->recycleMutex(SecMemRegistryMutex);
+}
+
+// Return the one-and-only instance
+SecureMemoryRegistry* SecureMemoryRegistry::i()
+{
+ if (instance == NULL)
+ {
+ instance = new SecureMemoryRegistry();
+
+ if (instance == NULL)
+ {
+ // This is very bad!
+ ERROR_MSG("Fatal: failed to instantiate SecureMemoryRegistry");
+
+ exit(-1);
+ }
+ }
+
+ return instance;
+}
+
+// Register a block of memory
+void SecureMemoryRegistry::add(void* pointer, size_t blocksize)
+{
+ MutexLocker lock(SecMemRegistryMutex);
+
+ registry[pointer] = blocksize;
+
+ //DEBUG_MSG("Registered block of %d bytes at 0x%x", blocksize, pointer);
+}
+
+// Unregister a block of memory
+size_t SecureMemoryRegistry::remove(void* pointer)
+{
+ //DEBUG_MSG("Unregistered block of %d bytes at 0x%x", registry[pointer], pointer);
+
+ MutexLocker lock(SecMemRegistryMutex);
+
+ size_t rv = registry[pointer];
+
+ registry.erase(pointer);
+
+ return rv;
+}
+
+// Wipe all registered blocks of memory
+void SecureMemoryRegistry::wipe()
+{
+ MutexLocker lock(SecMemRegistryMutex);
+
+ // Be very careful in this method to catch any weird exceptions that
+ // may occur since if we're in this method it means something has already
+ // gone pear shaped once before and we're exiting on a fatal exception
+ try
+ {
+ for (std::map<void*, size_t>::iterator i = registry.begin(); i != registry.end(); i++)
+ {
+ try
+ {
+ DEBUG_MSG("Wiping block of %d bytes at 0x%x", i->second, i->first);
+ }
+ catch (...)
+ {
+ }
+
+ try
+ {
+ #ifdef PARANOID
+ memset(i->first, 0xFF, i->second);
+ #endif // PARANOID
+ memset(i->first, 0x00, i->second);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to wipe block of %d bytes at 0x%x", i->second, i->first);
+ }
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to enumerate the secure memory registry");
+ }
+}
+
diff --git a/src/lib/data_mgr/SecureMemoryRegistry.h b/src/lib/data_mgr/SecureMemoryRegistry.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: SecureMemoryRegistry.h 6911 2012-12-21 10:54:45Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureMemoryRegistry.h
+
+ Implements a singleton class that keeps track of all securely allocated
+ memory. This registry can be used to wipe securely allocated memory in case
+ of a fatal exception
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREMEMORYREGISTRY_H
+#define _SOFTHSM_V2_SECUREMEMORYREGISTRY_H
+
+#include <stdlib.h>
+#include <map>
+#include <memory>
+#include "MutexFactory.h"
+
+class SecureMemoryRegistry
+{
+public:
+ SecureMemoryRegistry();
+
+ virtual ~SecureMemoryRegistry();
+
+ static SecureMemoryRegistry* i();
+
+ void add(void* pointer, size_t blocksize);
+
+ size_t remove(void* pointer);
+
+ void wipe();
+
+private:
+ static SecureMemoryRegistry* instance;
+
+ std::map<void*, size_t> registry;
+
+ Mutex* SecMemRegistryMutex;
+};
+
+#endif // !_SOFTHSM_V2_SECUREMEMORYREGISTRY_H
+
diff --git a/src/lib/data_mgr/salloc.cpp b/src/lib/data_mgr/salloc.cpp
--- /dev/null
@@ -0,0 +1,111 @@
+/* $Id: salloc.cpp 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ salloc.cpp
+
+ Contains an implementation of malloc that allocates memory securely
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "salloc.h"
+#include <limits>
+#ifdef SENSITIVE_NON_PAGED
+#include <sys/mman.h>
+#endif // SENSITIVE_NON_PAGED
+#include <string.h>
+#include "SecureMemoryRegistry.h"
+
+// Allocate memory
+void* salloc(size_t len)
+{
+#ifdef SENSITIVE_NON_PAGED
+ // Allocate memory on a page boundary
+ void* ptr = (void*) valloc(len);
+
+ if (ptr == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Lock the memory so it doesn't get swapped out
+ if (mlock((const void*) ptr, len) != 0)
+ {
+ ERROR_MSG("Could not allocate non-paged memory for secure storage");
+
+ // Hmmm... best to not return any allocated space in this case
+ free(ptr);
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(ptr, len);
+
+ return ptr;
+#else
+ void* ptr = (void*) malloc(len);
+
+ if (ptr == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(ptr, len);
+
+ return ptr;
+#endif // SENSITIVE_NON_PAGED
+}
+
+// Free memory
+void sfree(void* ptr)
+{
+ // Unregister the memory from the secure memory registry
+ size_t len = SecureMemoryRegistry::i()->remove(ptr);
+
+#ifdef PARANOID
+ // First toggle all bits on
+ memset(ptr, 0xFF, len);
+#endif // PARANOID
+
+ // Toggle all bits off
+ memset(ptr, 0x00, len);
+
+#ifdef SENSITIVE_NON_PAGED
+ munlock((const void*) ptr, len);
+#endif // SENSITIVE_NON_PAGED
+
+ free(ptr);
+}
+
diff --git a/src/lib/data_mgr/salloc.h b/src/lib/data_mgr/salloc.h
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: salloc.h 4773 2010-04-18 21:56:03Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ salloc.h
+
+ Contains an implementation of malloc that allocates memory securely
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SALLOC_H
+#define _SOFTHSM_V2_SALLOC_H
+
+#include <stdlib.h>
+#include "config.h"
+#include "log.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/* Allocate memory */
+void* salloc(size_t len);
+
+/* Free memory */
+void sfree(void* ptr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_SOFTHSM_V2_SALLOC_H */
+
diff --git a/src/lib/data_mgr/test/ByteStringTests.cpp b/src/lib/data_mgr/test/ByteStringTests.cpp
--- /dev/null
@@ -0,0 +1,358 @@
+/* $Id: ByteStringTests.cpp 6749 2012-10-22 12:37:58Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteStringTests.cpp
+
+ Contains test cases to test the ByteString class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <string>
+#include "ByteStringTests.h"
+#include "ByteString.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ByteStringTests);
+
+void ByteStringTests::setUp()
+{
+}
+
+void ByteStringTests::tearDown()
+{
+ fflush(stdout);
+}
+
+void ByteStringTests::testIntegrity()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b(testData, sizeof(testData));
+
+ // Test if the right data is returned
+ CPPUNIT_ASSERT(memcmp(testData, b.byte_str(), sizeof(testData)) == 0);
+
+ // Test size
+ CPPUNIT_ASSERT(b.size() == sizeof(testData));
+
+ // Test the copy constructor
+ ByteString b2(b);
+
+ // Test using comparison operator
+ CPPUNIT_ASSERT(b == b2);
+
+ // Test using memcmp
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), b2.byte_str(), b.size()) == 0);
+
+ // Modify the copied version and test again
+ b2[1] = 0x20;
+
+ // Test using comparison operator
+ CPPUNIT_ASSERT(b != b2);
+
+ // Test using memcmp directly
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), b2.byte_str(), b.size()) != 0);
+
+ // Verify that b was not affected
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), testData, sizeof(testData)) == 0);
+
+ // Modify the source data and check if the array operator has functioned correctly
+ testData[1] = 0x20;
+
+ // Test if the right data is in b2
+ CPPUNIT_ASSERT(memcmp(b2.byte_str(), testData, sizeof(testData)) == 0);
+}
+
+void ByteStringTests::testAppend()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b;
+ ByteString b1(testData, sizeof(testData));
+
+ // Test that b is empty and b1 is not
+ CPPUNIT_ASSERT((b.size() == 0) && (b1.size() == sizeof(testData)));
+
+ // Append 1 byte to b
+ b += 0x01;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 1);
+ CPPUNIT_ASSERT(b[0] == 0x01);
+
+ // Append another byte to b
+ b += 0x02;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 2);
+ CPPUNIT_ASSERT((b[0] == 0x01) && (b[1] == 0x02));
+
+ // Append b1 to b
+ b += b1;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 2 + sizeof(testData));
+ CPPUNIT_ASSERT((b[0] == 0x01) && (b[1] == 0x02));
+ CPPUNIT_ASSERT(memcmp(&b[2], testData, sizeof(testData)) == 0);
+
+ // Append b to b
+ b += b;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 2 * (2 + sizeof(testData)));
+ CPPUNIT_ASSERT((b[0] == 0x01) && (b[1] == 0x02) &&
+ (b[(2 + sizeof(testData)) + 0] == 0x01) &&
+ (b[(2 + sizeof(testData)) + 1] == 0x02));
+ CPPUNIT_ASSERT((memcmp(&b[2], testData, sizeof(testData)) == 0) &&
+ (memcmp(&b[2 + 2 + sizeof(testData)], testData, sizeof(testData)) == 0));
+}
+
+void ByteStringTests::testSubstr()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b;
+ ByteString b1(testData, sizeof(testData));
+
+ // Take a substring
+ b = b1.substr(8, 4);
+
+ // Check b
+ CPPUNIT_ASSERT(b.size() == 4);
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), &testData[8], 4) == 0);
+
+ // Take another substring
+ b = b1.substr(8);
+
+ // Check b
+ CPPUNIT_ASSERT(b.size() == 8);
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), &testData[8], 8) == 0);
+
+ // Two substrings added should yield the original string
+ b = b1.substr(0, 8) + b1.substr(8);
+
+ // Check b
+ CPPUNIT_ASSERT(b.size() == sizeof(testData));
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), testData, sizeof(testData)) == 0);
+}
+
+void ByteStringTests::testFromHexStr()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b("0102030405060708090a0b0c0d0e0f10");
+ ByteString b1("0102030405060708090A0B0C0D0E0F10");
+
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), testData, sizeof(testData)) == 0);
+ CPPUNIT_ASSERT(memcmp(b1.byte_str(), testData, sizeof(testData)) == 0);
+}
+
+void ByteStringTests::testXOR()
+{
+ unsigned char left[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
+ unsigned char right[] = { 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10 };
+ unsigned char xorred[] = { 0x81, 0x72, 0x63, 0x54, 0x45, 0x36, 0x27, 0x18 };
+
+ ByteString l(left, 8);
+ ByteString r(right, 8);
+ ByteString x(xorred, 8);
+ ByteString xed;
+
+ xed = l ^ r;
+
+ CPPUNIT_ASSERT(xed == x);
+
+ ByteString l1(left, 8);
+ ByteString r1(right, 8);
+
+ l1 ^= r1;
+
+ CPPUNIT_ASSERT(l1 == x);
+
+ l1 ^= l;
+
+ CPPUNIT_ASSERT(l1 == r);
+
+ ByteString l_(left, 7);
+
+ xed = l_ ^ r;
+
+ CPPUNIT_ASSERT((xed.size() == 7) && (xed == x.substr(0, 7)));
+
+ ByteString r_(right, 7);
+
+ xed = l ^ r_;
+
+ CPPUNIT_ASSERT((xed.size() == 7) && (xed == x.substr(0, 7)));
+
+ ByteString l1_(left, 8);
+
+ l1_ ^= r_;
+
+ CPPUNIT_ASSERT((l1.size() == 8) && (l1_.substr(0, 7) == x.substr(0,7)) && (l1_[7] == l[7]));
+
+ ByteString l1__(left, 7);
+
+ l1__ ^= r;
+
+ CPPUNIT_ASSERT((l1__ == x.substr(0,7)) && (l1__.size() == 7));
+}
+
+void ByteStringTests::testToHexStr()
+{
+ ByteString b("0102030405060708090A0B0C0D0E0F");
+ ByteString b1("DEADBEEF");
+ ByteString b2("deadC0FFEE");
+
+ std::string s = b.hex_str();
+ std::string s1 = b1.hex_str();
+ std::string s2 = b2.hex_str();
+
+ CPPUNIT_ASSERT(s.compare("0102030405060708090A0B0C0D0E0F") == 0);
+ CPPUNIT_ASSERT(s1.compare("DEADBEEF") == 0);
+ CPPUNIT_ASSERT(s2.compare("DEADC0FFEE") == 0);
+}
+
+void ByteStringTests::testLongValues()
+{
+ unsigned long ul1 = 0x00112233;
+ unsigned long ul2 = 0x10203040;
+ unsigned long ul3 = 0xF0E0D0C0;
+
+ ByteString b1(ul1);
+ ByteString b2(ul2);
+ ByteString b3(ul3);
+
+ CPPUNIT_ASSERT(b1 == ByteString("0000000000112233"));
+ CPPUNIT_ASSERT(b2 == ByteString("0000000010203040"));
+ CPPUNIT_ASSERT(b3 == ByteString("00000000F0E0D0C0"));
+
+ CPPUNIT_ASSERT(b1.long_val() == ul1);
+ CPPUNIT_ASSERT(b2.long_val() == ul2);
+ CPPUNIT_ASSERT(b3.long_val() == ul3);
+
+ ByteString concat = b1 + b2 + b3;
+
+ CPPUNIT_ASSERT(concat == ByteString("0000000000112233000000001020304000000000F0E0D0C0"));
+
+ unsigned long ulr1 = concat.firstLong();
+
+ CPPUNIT_ASSERT(ulr1 == ul1);
+ CPPUNIT_ASSERT(concat == ByteString("000000001020304000000000F0E0D0C0"));
+
+ unsigned long ulr2 = concat.firstLong();
+
+ CPPUNIT_ASSERT(ulr2 == ul2);
+ CPPUNIT_ASSERT(concat == ByteString("00000000F0E0D0C0"));
+
+ unsigned long ulr3 = concat.firstLong();
+
+ CPPUNIT_ASSERT(ulr3 == ul3);
+ CPPUNIT_ASSERT(concat.size() == 0);
+
+ ByteString b4("ABCDEF");
+
+ CPPUNIT_ASSERT(b4.long_val() == 0xABCDEF);
+ CPPUNIT_ASSERT(b4.size() == 3);
+ CPPUNIT_ASSERT(b4.firstLong() == 0xABCDEF);
+ CPPUNIT_ASSERT(b4.size() == 0);
+}
+
+void ByteStringTests::testSplitting()
+{
+ ByteString b("AABBCCDDEEFF112233445566");
+
+ ByteString b1 = b.split(6);
+
+ CPPUNIT_ASSERT(b == ByteString("112233445566"));
+ CPPUNIT_ASSERT(b1 == ByteString("AABBCCDDEEFF"));
+
+ ByteString b2 = b1.split(8);
+
+ CPPUNIT_ASSERT(b2 == ByteString("AABBCCDDEEFF"));
+ CPPUNIT_ASSERT(b1.size() == 0);
+}
+
+void ByteStringTests::testBits()
+{
+ ByteString b1("0");
+ ByteString b2("08");
+ ByteString b3("00FFFFF");
+ ByteString b4("123456");
+
+ CPPUNIT_ASSERT(b1.bits() == 0);
+ CPPUNIT_ASSERT(b2.bits() == 4);
+ CPPUNIT_ASSERT(b3.bits() == 20);
+ CPPUNIT_ASSERT(b4.bits() == 21);
+}
+
+void ByteStringTests::testSerialising()
+{
+ ByteString b1("AA11AA11AA11AA11AA11AA11AA11");
+ ByteString b2("BB22BB22BB22BB22BB22BB22");
+ ByteString b3("CC33CC33CC33CC33CC33CC33CC33CC33");
+
+ ByteString s1 = b1.serialise();
+
+ CPPUNIT_ASSERT(s1.size() == b1.size() + 8);
+
+ ByteString d1 = ByteString::chainDeserialise(s1);
+
+ CPPUNIT_ASSERT(s1.size() == 0);
+ CPPUNIT_ASSERT(d1 == b1);
+
+ ByteString s2 = b3.serialise() + b2.serialise() + b1.serialise();
+
+ CPPUNIT_ASSERT(s2.size() == b1.size() + b2.size() + b3.size() + (3*8));
+
+ d1 = ByteString::chainDeserialise(s2);
+
+ CPPUNIT_ASSERT(d1.size() == b3.size());
+ CPPUNIT_ASSERT(s2.size() == b1.size() + b2.size() + (2*8));
+
+ ByteString d2 = ByteString::chainDeserialise(s2);
+
+ CPPUNIT_ASSERT(d2.size() == b2.size());
+ CPPUNIT_ASSERT(s2.size() == b1.size() + 8);
+
+ ByteString d3 = ByteString::chainDeserialise(s2);
+
+ CPPUNIT_ASSERT(d3.size() == b1.size());
+ CPPUNIT_ASSERT(s2.size() == 0);
+
+ CPPUNIT_ASSERT(d1 == b3);
+ CPPUNIT_ASSERT(d2 == b2);
+ CPPUNIT_ASSERT(d3 == b1);
+}
+
diff --git a/src/lib/data_mgr/test/ByteStringTests.h b/src/lib/data_mgr/test/ByteStringTests.h
--- /dev/null
@@ -0,0 +1,73 @@
+/* $Id: ByteStringTests.h 6749 2012-10-22 12:37:58Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteStringTests.h
+
+ Contains test cases to test the ByteString class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BYTESTRINGTESTS_H
+#define _SOFTHSM_V2_BYTESTRINGTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ByteStringTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ByteStringTests);
+ CPPUNIT_TEST(testIntegrity);
+ CPPUNIT_TEST(testAppend);
+ CPPUNIT_TEST(testSubstr);
+ CPPUNIT_TEST(testFromHexStr);
+ CPPUNIT_TEST(testXOR);
+ CPPUNIT_TEST(testToHexStr);
+ CPPUNIT_TEST(testLongValues);
+ CPPUNIT_TEST(testSplitting);
+ CPPUNIT_TEST(testBits);
+ CPPUNIT_TEST(testSerialising);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testIntegrity();
+ void testAppend();
+ void testSubstr();
+ void testFromHexStr();
+ void testXOR();
+ void testToHexStr();
+ void testLongValues();
+ void testSplitting();
+ void testBits();
+ void testSerialising();
+
+ void setUp();
+ void tearDown();
+
+};
+
+#endif // !_SOFTHSM_V2_BYTESTRINGTESTS_H
+
diff --git a/src/lib/data_mgr/test/Makefile.am b/src/lib/data_mgr/test/Makefile.am
--- /dev/null
@@ -0,0 +1,28 @@
+# $Id: Makefile.am 6810 2012-11-01 14:21:55Z jerry $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../cryptoki_compat \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = datamgrtest
+
+datamgrtest_SOURCES = datamgrtest.cpp \
+ ByteStringTests.cpp \
+ RFC4880Tests.cpp \
+ SecureDataMgrTests.cpp
+
+datamgrtest_LDADD = ../../libsofthsm_convarch.la
+
+datamgrtest_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs`
+
+TESTS = datamgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/data_mgr/test/RFC4880Tests.cpp b/src/lib/data_mgr/test/RFC4880Tests.cpp
--- /dev/null
@@ -0,0 +1,118 @@
+/* $Id: RFC4880Tests.cpp 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880Tests.cpp
+
+ Contains test cases to test the RFC4880 implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RFC4880Tests.h"
+#include "RFC4880.h"
+#include "ByteString.h"
+#include "CryptoFactory.h"
+#include "AESKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RFC4880Tests);
+
+void RFC4880Tests::setUp()
+{
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+}
+
+void RFC4880Tests::tearDown()
+{
+}
+
+void RFC4880Tests::testRFC4880()
+{
+ const unsigned char* pwd1String = (const unsigned char*) "monkey";
+ const unsigned char* pwd2String = (const unsigned char*) "bicycle";
+ ByteString pwd1(pwd1String, strlen("monkey"));
+ ByteString pwd2(pwd2String, strlen("bicycle"));
+
+ // Generate salt and make sure that two different salt values are generated and
+ // that the last byte is also different (resulting in a different iteration jitter
+ // when computing a PBE key using both salt values)
+ ByteString salt1, salt2;
+
+ do
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(salt1, 8) && rng->generateRandom(salt2, 8));
+ }
+ while ((salt1 == salt2) || (salt1[salt1.size() - 1] == salt2[salt2.size() - 1]));
+
+ // Create a password-based encryption key from the first and second password
+ AESKey* key1;
+ AESKey* key2;
+
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd1, salt1, &key1));
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd2, salt2, &key2));
+
+ // Check that the output keys differ and have the correct length
+ CPPUNIT_ASSERT(key1->getKeyBits().size() == 32);
+ CPPUNIT_ASSERT(key2->getKeyBits().size() == 32);
+ CPPUNIT_ASSERT(key1->getKeyBits() != key2->getKeyBits());
+
+ // Rederive the keys to check that the same output is generated every time
+ AESKey* key1_;
+ AESKey* key2_;
+
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd1, salt1, &key1_));
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd2, salt2, &key2_));
+
+ CPPUNIT_ASSERT(key1->getKeyBits() == key1_->getKeyBits());
+ CPPUNIT_ASSERT(key2->getKeyBits() == key2_->getKeyBits());
+
+ // Now reverse the salts and derive new keys
+ AESKey* key3;
+ AESKey* key4;
+
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd1, salt2, &key3));
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd2, salt1, &key4));
+
+ // Check that the keys are different and that they differ from the
+ // original keys (because different salts were used)
+ CPPUNIT_ASSERT(key3->getKeyBits() != key4->getKeyBits());
+ CPPUNIT_ASSERT(key1->getKeyBits() != key3->getKeyBits());
+ CPPUNIT_ASSERT(key1->getKeyBits() != key4->getKeyBits());
+ CPPUNIT_ASSERT(key2->getKeyBits() != key3->getKeyBits());
+ CPPUNIT_ASSERT(key2->getKeyBits() != key4->getKeyBits());
+
+ // Clean up
+ delete key1;
+ delete key2;
+ delete key1_;
+ delete key2_;
+ delete key3;
+ delete key4;
+}
+
diff --git a/src/lib/data_mgr/test/RFC4880Tests.h b/src/lib/data_mgr/test/RFC4880Tests.h
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: RFC4880Tests.h 4781 2010-05-14 11:05:13Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880Tests.h
+
+ Contains test cases to test the RFC4880 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RFC4880TESTS_H
+#define _SOFTHSM_V2_RFC4880TESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+
+class RFC4880Tests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RFC4880Tests);
+ CPPUNIT_TEST(testRFC4880);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRFC4880();
+
+ void setUp();
+ void tearDown();
+
+private:
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_RFC4880TESTS_H
+
diff --git a/src/lib/data_mgr/test/SecureDataMgrTests.cpp b/src/lib/data_mgr/test/SecureDataMgrTests.cpp
--- /dev/null
@@ -0,0 +1,190 @@
+/* $Id: SecureDataMgrTests.cpp 6771 2012-10-24 15:09:04Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataMgrTests.cpp
+
+ Contains test cases to test the secure data manager
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SecureDataMgrTests.h"
+#include "SecureDataManager.h"
+#include "CryptoFactory.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SecureDataMgrTests);
+
+void SecureDataMgrTests::setUp()
+{
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+}
+
+void SecureDataMgrTests::tearDown()
+{
+}
+
+void SecureDataMgrTests::testSecureDataManager()
+{
+ ByteString soPIN = "3132333435363738"; // "12345678"
+ ByteString userPIN = "4041424344454647"; // "ABCDEFGH"
+ ByteString newSOPIN = "3837363534333231"; // "87654321"
+ ByteString newUserPIN = "4746454443424140"; // "HGFEDCBA"
+
+ // Instantiate a blank secure data manager
+ SecureDataManager s1;
+ ByteString plaintext = "010203040506070809";
+ ByteString emptyPlaintext = "";
+ ByteString encrypted;
+
+ // Verify that no function other than setting the SO PIN works
+ CPPUNIT_ASSERT(!s1.setUserPIN(userPIN));
+ CPPUNIT_ASSERT(!s1.loginSO(soPIN));
+ CPPUNIT_ASSERT(!s1.loginUser(userPIN));
+ CPPUNIT_ASSERT(!s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s1.decrypt(encrypted, plaintext));
+ CPPUNIT_ASSERT(s1.getSOPINBlob().size() == 0);
+ CPPUNIT_ASSERT(s1.getUserPINBlob().size() == 0);
+
+ // Now set the SO PIN
+ CPPUNIT_ASSERT(s1.setSOPIN(soPIN));
+
+ // Check that it is still not possible to set the user PIN
+ CPPUNIT_ASSERT(!s1.setUserPIN(userPIN));
+
+ // Check that it is possible to log in with the SO PIN
+ CPPUNIT_ASSERT(s1.loginSO(soPIN));
+
+ // Check that it is now possible to also set the user PIN
+ CPPUNIT_ASSERT(s1.setUserPIN(userPIN));
+
+ // Check that is is now also possible to log in with the user PIN
+ CPPUNIT_ASSERT(s1.loginUser(userPIN));
+
+ // Check that it is possible to encrypt and decrypt some data
+ ByteString decrypted;
+
+ CPPUNIT_ASSERT(s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(encrypted != plaintext);
+
+ CPPUNIT_ASSERT(s1.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+
+ // Log out
+ s1.logout();
+
+ // Check that it is no longer possible to set the SO PIN
+ CPPUNIT_ASSERT(!s1.setSOPIN(soPIN));
+
+ // Check that it is no longer possible to set the user PIN
+ CPPUNIT_ASSERT(!s1.setUserPIN(userPIN));
+
+ // Check that encrypting/decrypting no longer works
+ CPPUNIT_ASSERT(!s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s1.decrypt(encrypted, plaintext));
+
+ // Export the key blobs
+ ByteString soPINBlob = s1.getSOPINBlob();
+ ByteString userPINBlob = s1.getUserPINBlob();
+
+ // Create a new instance with the exported key blobs
+ SecureDataManager s2(soPINBlob, userPINBlob);
+
+ // Check that the key blobs match
+ CPPUNIT_ASSERT(s1.getSOPINBlob() == s2.getSOPINBlob());
+ CPPUNIT_ASSERT(s1.getUserPINBlob() == s2.getUserPINBlob());
+
+ // Check that it is not possible to set the SO PIN
+ CPPUNIT_ASSERT(!s2.setSOPIN(soPIN));
+
+ // Check that it is possible to log in with the SO PIN
+ CPPUNIT_ASSERT(s2.loginSO(soPIN));
+
+ // Check that is is now also possible to log in with the user PIN
+ CPPUNIT_ASSERT(s2.loginUser(userPIN));
+
+ // Check that encrypting the data results in the same encrypted value as before
+ ByteString encrypted2;
+
+ CPPUNIT_ASSERT(s2.encrypt(plaintext, encrypted2));
+ CPPUNIT_ASSERT(encrypted == encrypted2);
+
+ // Check that decrypting earlier data can be done with the recreated key
+ CPPUNIT_ASSERT(s2.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+
+ // Log in with the SO PIN
+ CPPUNIT_ASSERT(s2.loginSO(soPIN));
+
+ // Check that the SO PIN can be changed
+ CPPUNIT_ASSERT(s2.setSOPIN(newSOPIN));
+
+ // Check that it is no longer possible to log in with the old SO PIN
+ CPPUNIT_ASSERT(!s2.loginSO(soPIN));
+
+ // Check that encrypting/decrypting no longer works
+ CPPUNIT_ASSERT(!s2.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s2.decrypt(encrypted, plaintext));
+
+ // Check that the key blobs differ
+ CPPUNIT_ASSERT(s1.getSOPINBlob() != s2.getSOPINBlob());
+
+ // Check that it is possible to log in with the new SO PIN
+ CPPUNIT_ASSERT(s2.loginSO(newSOPIN));
+
+ // Log in with the user PIN
+ CPPUNIT_ASSERT(s2.loginUser(userPIN));
+
+ // Check that it is possible to change the user PIN
+ CPPUNIT_ASSERT(s2.setUserPIN(newUserPIN));
+
+ // Check that it is no longer possible to log in with the old user PIN
+ CPPUNIT_ASSERT(!s2.loginUser(userPIN));
+
+ // Check that encrypting/decrypting no longer works
+ CPPUNIT_ASSERT(!s2.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s2.decrypt(encrypted, plaintext));
+
+ // Check that it is possible to log in with the new user PIN
+ CPPUNIT_ASSERT(s2.loginUser(newUserPIN));
+
+ // Check that encrypting the data results in the same encrypted value as before
+ CPPUNIT_ASSERT(s2.encrypt(plaintext, encrypted2));
+ CPPUNIT_ASSERT(encrypted == encrypted2);
+
+ // Check that decrypting earlier data can be done with the recreated key
+ CPPUNIT_ASSERT(s2.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+
+ // Check that empty plaintext can be handled
+ CPPUNIT_ASSERT(s2.encrypt(emptyPlaintext, encrypted));
+ CPPUNIT_ASSERT(s2.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == emptyPlaintext);
+}
+
diff --git a/src/lib/data_mgr/test/SecureDataMgrTests.h b/src/lib/data_mgr/test/SecureDataMgrTests.h
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: SecureDataMgrTests.h 4784 2010-05-15 19:07:08Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataMgrTests.h
+
+ Contains test cases to test the secure data manager
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREDATAMGRTESTS_H
+#define _SOFTHSM_V2_SECUREDATAMGRTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+
+class SecureDataMgrTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SecureDataMgrTests);
+ CPPUNIT_TEST(testSecureDataManager);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSecureDataManager();
+
+ void setUp();
+ void tearDown();
+
+private:
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_SECUREDATAMGRTESTS_H
+
diff --git a/src/lib/data_mgr/test/datamgrtest.cpp b/src/lib/data_mgr/test/datamgrtest.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: datamgrtest.cpp 6738 2012-10-15 21:28:14Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ datamgrtest.cpp
+
+ The main test executor for tests on the secure data manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/handle_mgr/Handle.cpp b/src/lib/handle_mgr/Handle.cpp
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Handle.h
+
+ This class represents a single handle
+ *****************************************************************************/
+
+#include "Handle.h"
+
+// Constructor
+Handle::Handle(CK_HANDLE_KIND _kind, CK_SLOT_ID _slotID, CK_SESSION_HANDLE _hSession)
+ : kind(_kind), slotID(_slotID), hSession(_hSession), object(NULL_PTR), isPrivate(false)
+{
+}
+
+Handle::Handle(CK_HANDLE_KIND _kind, CK_SLOT_ID _slotID)
+ : kind(_kind), slotID(_slotID), hSession(CK_INVALID_HANDLE), object(NULL_PTR), isPrivate(false)
+{
+}
+
+Handle::Handle()
+ : kind(CKH_INVALID), slotID(0), hSession(CK_INVALID_HANDLE), object(NULL_PTR), isPrivate(false)
+{
+
+}
diff --git a/src/lib/handle_mgr/Handle.h b/src/lib/handle_mgr/Handle.h
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Handle.h
+
+ This class represents a single handle
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLE_H
+#define _SOFTHSM_V2_HANDLE_H
+
+#include "cryptoki.h"
+
+enum {
+ CKH_INVALID,
+ CKH_SESSION,
+ CKH_OBJECT
+};
+
+#define CK_HANDLE_KIND CK_ULONG
+
+class Handle
+{
+public:
+ Handle(CK_HANDLE_KIND kind, CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession);
+ Handle(CK_HANDLE_KIND kind, CK_SLOT_ID slotID);
+ Handle();
+
+ CK_HANDLE_KIND kind;
+ CK_SLOT_ID slotID;
+ CK_SESSION_HANDLE hSession;
+
+ CK_VOID_PTR object;
+ bool isPrivate;
+};
+
+#endif // !_SOFTHSM_V2_HANDLE_H
+
diff --git a/src/lib/handle_mgr/HandleManager.cpp b/src/lib/handle_mgr/HandleManager.cpp
--- /dev/null
@@ -0,0 +1,241 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*****************************************************************************
+ HandleManager.cpp
+
+ One of the most difficult problems to track down is when stale cryptoki handles
+ for e.g. keys, objects and sessions get reused by a misbehaving application.
+ Especialy when handles that became invalid have since been reused.
+ A simple solution to this is to never reuse a handle once it has been issued
+ and subsequently invalidated.
+
+ The handle manager tracks issued handles along with what kind of object
+ is presented by the handle and an actual pointer to the object in question.
+
+ Issued handles are unique per application run. All session and object handles
+ use the same handle manager and therefore there will never be e.g. a session
+ with the same handle as an object.
+
+ *****************************************************************************/
+
+#include "HandleManager.h"
+#include "log.h"
+
+// Constructor
+HandleManager::HandleManager()
+{
+ handlesMutex = MutexFactory::i()->getMutex();
+ handleCounter = 0;
+}
+
+// Destructor
+HandleManager::~HandleManager()
+{
+
+ MutexFactory::i()->recycleMutex(handlesMutex);
+}
+
+CK_SESSION_HANDLE HandleManager::addSession(CK_SLOT_ID slotID, CK_VOID_PTR session)
+{
+ MutexLocker lock(handlesMutex);
+
+ Handle h( CKH_SESSION, slotID );
+ h.object = session;
+ handles[++handleCounter] = h;
+ return (CK_SESSION_HANDLE)handleCounter;
+}
+
+CK_VOID_PTR HandleManager::getSession(const CK_SESSION_HANDLE hSession)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hSession);
+ if (it == handles.end() || CKH_SESSION != it->second.kind)
+ return NULL_PTR;
+ return it->second.object;
+}
+
+CK_OBJECT_HANDLE HandleManager::addSessionObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate, CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Return existing handle when the object has already been registered.
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator oit = objects.find(object);
+ if (oit != objects.end()) {
+ std::map< CK_ULONG, Handle>::iterator hit = handles.find(oit->second);
+ if (hit == handles.end() || CKH_OBJECT != hit->second.kind || slotID != hit->second.slotID) {
+ objects.erase(oit);
+ return CK_INVALID_HANDLE;
+ } else
+ return oit->second;
+ }
+
+ Handle h( CKH_OBJECT, slotID, hSession );
+ h.isPrivate = isPrivate;
+ h.object = object;
+ handles[++handleCounter] = h;
+ objects[object] = handleCounter;
+ return (CK_OBJECT_HANDLE)handleCounter;
+}
+
+CK_OBJECT_HANDLE HandleManager::addTokenObject(CK_SLOT_ID slotID, bool isPrivate, CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Return existing handle when the object has already been registered.
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator oit = objects.find(object);
+ if (oit != objects.end()) {
+ std::map< CK_ULONG, Handle>::iterator hit = handles.find(oit->second);
+ if (hit == handles.end() || CKH_OBJECT != hit->second.kind || slotID != hit->second.slotID) {
+ objects.erase(oit);
+ return CK_INVALID_HANDLE;
+ } else
+ return oit->second;
+ }
+
+ // Token objects are not associated with a specific session.
+ Handle h( CKH_OBJECT, slotID );
+ h.isPrivate = isPrivate;
+ h.object = object;
+ handles[++handleCounter] = h;
+ objects[object] = handleCounter;
+ return (CK_OBJECT_HANDLE)handleCounter;
+}
+
+CK_VOID_PTR HandleManager::getObject(const CK_OBJECT_HANDLE hObject)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hObject);
+ if (it == handles.end() || CKH_OBJECT != it->second.kind )
+ return NULL_PTR;
+ return it->second.object;
+}
+
+CK_OBJECT_HANDLE HandleManager::getObjectHandle(CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator it = objects.find(object);
+ if (it == objects.end())
+ return CK_INVALID_HANDLE;
+ return it->second;
+}
+
+void HandleManager::destroyObject(const CK_OBJECT_HANDLE hObject)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hObject);
+ if (it != handles.end() && CKH_OBJECT == it->second.kind) {
+ objects.erase(it->second.object);
+ handles.erase(it);
+ }
+}
+
+void HandleManager::sessionClosed(const CK_SESSION_HANDLE hSession)
+{
+ CK_SLOT_ID slotID;
+ {
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hSession);
+ if (it == handles.end() || CKH_SESSION != it->second.kind)
+ return; // Unable to find the specified session.
+
+ slotID = it->second.slotID;
+
+ // session closed, so we can erase information about it.
+ handles.erase(it);
+
+ // Erase all session object handles associated with the given session handle.
+ CK_ULONG openSessionCount = 0;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (CKH_SESSION == h.kind && slotID == h.slotID) {
+ ++openSessionCount; // another session is open for this slotID.
+ } else {
+ if (CKH_OBJECT == h.kind && hSession == h.hSession) {
+ // A session object is present for the given session, so erase it.
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ }
+ ++it;
+ }
+
+ // We are done when there are still sessions open.
+ if (openSessionCount)
+ return;
+ }
+
+ // No more sessions open for this token, so remove all object handles that are still valid for the given slotID.
+ allSessionsClosed(slotID);
+}
+
+void HandleManager::allSessionsClosed(const CK_SLOT_ID slotID)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Erase all "session", "session object" and "token object" handles for a given slot id.
+ std::map< CK_ULONG, Handle>::iterator it;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (slotID == h.slotID) {
+ if (CKH_OBJECT == it->second.kind)
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+}
+
+void HandleManager::tokenLoggedOut(const CK_SLOT_ID slotID)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Erase all private "token object" or "session object" handles for a given slot id.
+ std::map< CK_ULONG, Handle>::iterator it;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (CKH_OBJECT == h.kind && slotID == h.slotID && h.isPrivate) {
+ // A private object is present for the given slotID so we need to remove it.
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+}
diff --git a/src/lib/handle_mgr/HandleManager.h b/src/lib/handle_mgr/HandleManager.h
--- /dev/null
@@ -0,0 +1,96 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManager.h
+
+ Keeps track of the issued cryptoki handles within SoftHSM
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEMANAGER_H
+#define _SOFTHSM_V2_HANDLEMANAGER_H
+
+#include "MutexFactory.h"
+#include "Handle.h"
+#include "cryptoki.h"
+
+#include <map>
+
+#define CK_INTERNAL_SESSION_HANDLE CK_SESSION_HANDLE
+
+class HandleManager
+{
+public:
+ HandleManager();
+
+ virtual ~HandleManager();
+
+ CK_SESSION_HANDLE addSession(CK_SLOT_ID slotID, CK_VOID_PTR session);
+ CK_VOID_PTR getSession(const CK_SESSION_HANDLE hSession);
+
+ // Add the session object and return a handle. For objects that have already been registered, check that the
+ // slotID matches. The hSession may be different as the object may be added as part of a find objects operation.
+ CK_OBJECT_HANDLE addSessionObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate, CK_VOID_PTR object);
+
+ // Add the token object and return a handle. For objects that have already been registered, check that the
+ // slotID mathces.
+ CK_OBJECT_HANDLE addTokenObject(CK_SLOT_ID slotID, bool isPrivate, CK_VOID_PTR object);
+
+ // Get the object pointer associated with the given object handle.
+ CK_VOID_PTR getObject(const CK_OBJECT_HANDLE hObject);
+
+ // Get the object handle for the object pointer that has been previously registered.
+ // When the object is not found CK_INVALID_HANDLE is returned.
+ CK_OBJECT_HANDLE getObjectHandle(CK_VOID_PTR object);
+
+ // Remove the given object handle.
+ void destroyObject(const CK_OBJECT_HANDLE hObject);
+
+ // Remove the given session handle and all session object handles for the session.
+ // The token object handles retrieved using the session will remain valid unless
+ // this is the last session of a token being closed. In that case remove all token
+ // object handles for the slot/token associated with the session.
+ void sessionClosed(const CK_SESSION_HANDLE hSession);
+
+ // Remove all session and object handles for the given slotID.
+ // All handles for the given slotID will become invalid.
+ void allSessionsClosed(const CK_SLOT_ID slotID);
+
+ // Remove all handles to private objects for the given slotID.
+ // All handles to public objects for the given slotID remain valid.
+ void tokenLoggedOut(const CK_SLOT_ID slotID);
+
+private:
+ Mutex* handlesMutex;
+ std::map< CK_ULONG, Handle> handles;
+ std::map< CK_VOID_PTR, CK_ULONG> objects;
+ CK_ULONG handleCounter;
+};
+
+#endif // !_SOFTHSM_V2_HANDLEMANAGER_H
+
diff --git a/src/lib/handle_mgr/Makefile.am b/src/lib/handle_mgr/Makefile.am
--- /dev/null
@@ -0,0 +1,19 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../slot_mgr \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/..
+
+noinst_LTLIBRARIES = libsofthsm_handlemgr.la
+libsofthsm_handlemgr_la_SOURCES = HandleManager.cpp \
+ Handle.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/handle_mgr/test/HandleManagerTests.cpp b/src/lib/handle_mgr/test/HandleManagerTests.cpp
--- /dev/null
@@ -0,0 +1,180 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManagerTests.cpp
+
+ Contains test cases to test the handle manager implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "HandleManagerTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HandleManagerTests);
+
+void HandleManagerTests::setUp()
+{
+ handleManager = new HandleManager();
+}
+
+void HandleManagerTests::tearDown()
+{
+ delete handleManager;
+}
+
+void HandleManagerTests::testHandleManager()
+{
+ CPPUNIT_ASSERT(handleManager != NULL);
+
+ CK_SLOT_ID slotID = 1234; // we need a unique value
+ CK_SESSION_HANDLE hSession;
+ CK_VOID_PTR session = &hSession; // we need a unique value
+ CK_SESSION_HANDLE hSession2;
+ CK_VOID_PTR session2 = &hSession2; // we need a unique value
+ CK_OBJECT_HANDLE hObject;
+ CK_VOID_PTR object = &hObject; // we need a unique value
+ CK_OBJECT_HANDLE hObject2;
+ CK_VOID_PTR object2 = &hObject2; // we need a unique value
+ CK_OBJECT_HANDLE hObject3;
+ CK_VOID_PTR object3 = &hObject3; // we need a unique value
+ CK_OBJECT_HANDLE hObject4;
+ CK_VOID_PTR object4 = &hObject4; // we need a unique value
+ CK_OBJECT_HANDLE hObject5;
+ CK_VOID_PTR object5 = &hObject5; // we need a unique value
+
+ // Check session object management.
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT_NO_THROW(handleManager->sessionClosed(123124));
+ handleManager->sessionClosed(hSession);
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+
+ // Add an object, hSession doesn't have to exists
+ hObject = handleManager->addSessionObject(slotID, 4412412, true, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ handleManager->sessionClosed(4412412);
+ // Object still exists as the hSession was invalid
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ handleManager->allSessionsClosed(slotID);
+ // Object is now gone as all sessions for the given slotID have been removed.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ // Add an object and then destroy it.
+ hObject = handleManager->addSessionObject(slotID, 4412412, true, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ handleManager->destroyObject(hObject);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ hObject = handleManager->addTokenObject(slotID, false, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ handleManager->destroyObject(hObject);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ // Create a valid session again
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+
+ // Now some magic with a couple of objects
+ // First add a public object
+ hObject = handleManager->addTokenObject(slotID, false, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+
+ // Now add a private object
+ hObject2 = handleManager->addTokenObject(slotID, true, object2);
+ CPPUNIT_ASSERT(hObject2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object2 == handleManager->getObject(hObject2));
+
+ // Now add another private object
+ hObject3 = handleManager->addTokenObject(slotID, true, object3);
+ CPPUNIT_ASSERT(hObject3 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object3 == handleManager->getObject(hObject3));
+
+ // Adding the same object will return the same handle whether the object is marked private or public.
+ CPPUNIT_ASSERT(hObject2 == handleManager->addTokenObject(slotID, true, object2));
+ // Because the private state of an object cannot be changed it won't be marked as public, it remains private
+ CPPUNIT_ASSERT(hObject2 == handleManager->addTokenObject(slotID, false, object2));
+
+ // It is not allowed to migrate an object from one slot to another, so here we return an invalid handle.
+ CPPUNIT_ASSERT(CK_INVALID_HANDLE == handleManager->addTokenObject(124121, false, object2));
+
+ // Now add another private session object
+ hObject4 = handleManager->addSessionObject(slotID, hSession, true, object4);
+ CPPUNIT_ASSERT(hObject4 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object4 == handleManager->getObject(hObject4));
+
+ // Now add another public session object
+ hObject5 = handleManager->addSessionObject(slotID, hSession, false, object5);
+ CPPUNIT_ASSERT(hObject5 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object5 == handleManager->getObject(hObject5));
+
+ // Logout, now private objects should be gone.
+ handleManager->tokenLoggedOut(slotID);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject2)); // should still be private and removed.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject3));
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject4));
+ CPPUNIT_ASSERT(object5 == handleManager->getObject(hObject5));
+
+ // Create another valid session for the slot
+ hSession2 = handleManager->addSession(slotID, session2);
+ CPPUNIT_ASSERT(hSession2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session2 == handleManager->getSession(hSession2));
+
+ handleManager->sessionClosed(hSession);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject)); // token object should still be there.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject5)); // session object should be gone.
+
+ // Removing the last remaining session should kill the remaining handle.
+ handleManager->sessionClosed(hSession2);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject)); // should be gone now.
+
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession2));
+
+
+ // Create a valid session again
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+
+ // Create another valid session for the slot
+ hSession2 = handleManager->addSession(slotID, session2);
+ CPPUNIT_ASSERT(hSession2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session2 == handleManager->getSession(hSession2));
+
+ handleManager->allSessionsClosed(slotID);
+
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession2));
+}
diff --git a/src/lib/handle_mgr/test/HandleManagerTests.h b/src/lib/handle_mgr/test/HandleManagerTests.h
--- /dev/null
@@ -0,0 +1,60 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManagerTests.h
+
+ Contains test cases to test the handle manager implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEMANAGERTESTS_H
+#define _SOFTHSM_V2_HANDLEMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+#include "HandleManager.h"
+
+class HandleManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(HandleManagerTests);
+ CPPUNIT_TEST(testHandleManager);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testHandleManager();
+
+ void setUp();
+ void tearDown();
+
+private:
+ HandleManager *handleManager;
+
+};
+
+#endif // !_SOFTHSM_V2_HANDLEMANAGERTESTS_H
+
diff --git a/src/lib/handle_mgr/test/Makefile.am b/src/lib/handle_mgr/test/Makefile.am
--- /dev/null
@@ -0,0 +1,28 @@
+# $Id: $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../cryptoki_compat \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ -I$(srcdir)/../../data_mgr \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = handlemgrtest
+
+handlemgrtest_SOURCES = handlemgrtest.cpp \
+ HandleManagerTests.cpp
+
+handlemgrtest_LDADD = ../../libsofthsm_convarch.la
+
+handlemgrtest_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs`
+
+TESTS = handlemgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
+
diff --git a/src/lib/handle_mgr/test/handlemgrtest.cpp b/src/lib/handle_mgr/test/handlemgrtest.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ handlemgrtest.cpp
+
+ The main test executor for tests on the handle manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/main.cpp b/src/lib/main.cpp
--- /dev/null
+++ b/src/lib/main.cpp
@@ -0,0 +1,1182 @@
+/* $Id: main.cpp 4898 2010-09-14 13:56:02Z rb $ */
+
+/*
+ * Copyright (c)2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ main.cpp
+
+ This file contains the main entry point to the PKCS #11 library. All it does
+ is dispatch calls to the actual implementation and check for fatal exceptions
+ on the boundary of the library.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "fatal.h"
+#include "cryptoki.h"
+#include "SoftHSM.h"
+
+// PKCS #11 function list
+//
+// TODO: contrary to the SoftHSM v2 requirements, PKCS #11 v2.20 is still
+// implemented in stead of PKCS #11 v2.30 because the header files
+// for PKCS #11 v2.30 are not yet available
+static CK_FUNCTION_LIST functionList =
+{
+ // Version information
+ { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+ // Function pointers
+ C_Initialize,
+ C_Finalize,
+ C_GetInfo,
+ C_GetFunctionList,
+ C_GetSlotList,
+ C_GetSlotInfo,
+ C_GetTokenInfo,
+ C_GetMechanismList,
+ C_GetMechanismInfo,
+ C_InitToken,
+ C_InitPIN,
+ C_SetPIN,
+ C_OpenSession,
+ C_CloseSession,
+ C_CloseAllSessions,
+ C_GetSessionInfo,
+ C_GetOperationState,
+ C_SetOperationState,
+ C_Login,
+ C_Logout,
+ C_CreateObject,
+ C_CopyObject,
+ C_DestroyObject,
+ C_GetObjectSize,
+ C_GetAttributeValue,
+ C_SetAttributeValue,
+ C_FindObjectsInit,
+ C_FindObjects,
+ C_FindObjectsFinal,
+ C_EncryptInit,
+ C_Encrypt,
+ C_EncryptUpdate,
+ C_EncryptFinal,
+ C_DecryptInit,
+ C_Decrypt,
+ C_DecryptUpdate,
+ C_DecryptFinal,
+ C_DigestInit,
+ C_Digest,
+ C_DigestUpdate,
+ C_DigestKey,
+ C_DigestFinal,
+ C_SignInit,
+ C_Sign,
+ C_SignUpdate,
+ C_SignFinal,
+ C_SignRecoverInit,
+ C_SignRecover,
+ C_VerifyInit,
+ C_Verify,
+ C_VerifyUpdate,
+ C_VerifyFinal,
+ C_VerifyRecoverInit,
+ C_VerifyRecover,
+ C_DigestEncryptUpdate,
+ C_DecryptDigestUpdate,
+ C_SignEncryptUpdate,
+ C_DecryptVerifyUpdate,
+ C_GenerateKey,
+ C_GenerateKeyPair,
+ C_WrapKey,
+ C_UnwrapKey,
+ C_DeriveKey,
+ C_SeedRandom,
+ C_GenerateRandom,
+ C_GetFunctionStatus,
+ C_CancelFunction,
+ C_WaitForSlotEvent
+};
+
+// PKCS #11 initialisation function
+CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
+{
+ try
+ {
+ return SoftHSM::i()->C_Initialize(pInitArgs);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// PKCS #11 finalisation function
+CK_RV C_Finalize(CK_VOID_PTR pReserved)
+{
+ try
+ {
+ return SoftHSM::i()->C_Finalize(pReserved);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return information about the PKCS #11 module
+CK_RV C_GetInfo(CK_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetInfo(pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return the list of PKCS #11 functions
+CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
+{
+ try
+ {
+ if (ppFunctionList == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ *ppFunctionList = &functionList;
+
+ return CKR_OK;
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return a list of available slots
+CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetSlotList(tokenPresent, pSlotList, pulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return information about a slot
+CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetSlotInfo(slotID, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return information about a token in a slot
+CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetTokenInfo(slotID, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return the list of supported mechanisms for a given slot
+CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetMechanismList(slotID, pMechanismList, pulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return more information about a mechanism for a given slot
+CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetMechanismInfo(slotID, type, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise the token in the specified slot
+CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
+{
+ try
+ {
+ return SoftHSM::i()->C_InitToken(slotID, pPin, ulPinLen, pLabel);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise the user PIN
+CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_InitPIN(hSession, pPin, ulPinLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Change the PIN
+CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SetPIN(hSession, pOldPin, ulOldLen, pNewPin, ulNewLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Open a new session to the specified slot
+CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_OpenSession(slotID, flags, pApplication, notify, phSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Close the given session
+CK_RV C_CloseSession(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_CloseSession(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Close all open sessions
+CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
+{
+ try
+ {
+ return SoftHSM::i()->C_CloseAllSessions(slotID);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Retrieve information about the specified session
+CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetSessionInfo(hSession, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Determine the state of a running operation in a session
+CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetOperationState(hSession, pOperationState, pulOperationStateLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Set the operation sate in a session
+CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_SetOperationState(hSession, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Login on the token in the specified session
+CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Login(hSession, userType, pPin, ulPinLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Log out of the token in the specified session
+CK_RV C_Logout(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_Logout(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Create a new object on the token in the specified session using the given attribute template
+CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_CreateObject(hSession, pTemplate, ulCount, phObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Create a copy of the object with the specified handle
+CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_CopyObject(hSession, hObject, pTemplate, ulCount, phNewObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Destroy the specified object
+CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_DestroyObject(hSession, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Determine the size of the specified object
+CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetObjectSize(hSession, hObject, pulSize);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Retrieve the specified attributes for the given object
+CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetAttributeValue(hSession, hObject, pTemplate, ulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Change or set the value of the specified attributes on the specified object
+CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_SetAttributeValue(hSession, hObject, pTemplate, ulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise object search in the specified session using the specified attribute template as search parameters
+CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_FindObjectsInit(hSession, pTemplate, ulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Continue the search for objects in the specified session
+CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_FindObjects(hSession, phObject, ulMaxObjectCount, pulObjectCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finish searching for objects
+CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_FindObjectsFinal(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise encryption using the specified object and mechanism
+CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_EncryptInit(hSession, pMechanism, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single operation encryption operation in the specified session
+CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Encrypt(hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Feed data to the running encryption operation in a session
+CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the encryption operation
+CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_EncryptFinal(hSession, pEncryptedData, pulEncryptedDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise decryption using the specified object
+CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptInit(hSession, pMechanism, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single operation decryption in the given session
+CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Decrypt(hSession, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Feed data to the running decryption operation in a session
+CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, pData, pDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the decryption operation
+CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptFinal(hSession, pData, pDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise digesting using the specified mechanism in the specified session
+CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestInit(hSession, pMechanism);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Digest the specified data in a one-pass operation and return the resulting digest
+CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Digest(hSession, pData, ulDataLen, pDigest, pulDigestLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running digest operation
+CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestUpdate(hSession, pPart, ulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running digest operation by digesting a secret key with the specified handle
+CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestKey(hSession, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the digest operation in the specified session and return the digest
+CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestFinal(hSession, pDigest, pulDigestLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a signing operation using the specified key and mechanism
+CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Sign the data in a single pass operation
+CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running signing operation with additional data
+CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignUpdate(hSession, pPart, ulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise a running signing operation and return the signature
+CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignFinal(hSession, pSignature, pulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a signing operation that allows recovery of the signed data
+CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignRecoverInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single part signing operation that allows recovery of the signed data
+CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignRecover(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a verification operation using the specified key and mechanism
+CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single pass verification operation
+CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Verify(hSession, pData, ulDataLen, pSignature, ulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running verification operation with additional data
+CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyUpdate(hSession, pPart, ulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the verification operation and check the signature
+CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyFinal(hSession, pSignature, ulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a verification operation the allows recovery of the signed data from the signature
+CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyRecoverInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single part verification operation and recover the signed data
+CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyRecover(hSession, pSignature, ulSignatureLen, pData, pulDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part encryption and digesting operation
+CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestEncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part decryption and digesting operation
+CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pDecryptedPart, CK_ULONG_PTR pulDecryptedPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptDigestUpdate(hSession, pPart, ulPartLen, pDecryptedPart, pulDecryptedPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part signing and encryption operation
+CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignEncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part decryption and verification operation
+CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptVerifyUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Generate a secret key using the specified mechanism
+CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_GenerateKey(hSession, pMechanism, pTemplate, ulCount, phKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Generate a key-pair using the specified mechanism
+CK_RV C_GenerateKeyPair
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Wrap the specified key using the specified wrapping key and mechanism
+CK_RV C_WrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey,
+ CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_WrapKey(hSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Unwrap the specified key using the specified unwrapping key
+CK_RV C_UnwrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_UnwrapKey(hSession, pMechanism, hUnwrappingKey, pWrappedKey, ulWrappedKeyLen, pTemplate, ulCount, phKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Derive a key from the specified base key
+CK_RV C_DeriveKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_DeriveKey(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Seed the random number generator with new data
+CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SeedRandom(hSession, pSeed, ulSeedLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Generate the specified amount of random data
+CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_GenerateRandom(hSession, pRandomData, ulRandomLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Legacy function
+CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetFunctionStatus(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Legacy function
+CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_CancelFunction(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Wait or poll for a slot even on the specified slot
+CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ try
+ {
+ return SoftHSM::i()->C_WaitForSlotEvent(flags, pSlot, pReserved);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
diff --git a/src/lib/object_store/Directory.cpp b/src/lib/object_store/Directory.cpp
--- /dev/null
@@ -0,0 +1,169 @@
+/* $Id: Directory.cpp 6786 2012-10-26 11:58:40Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Directory.cpp
+
+ Helper functions for accessing directories.
+ *****************************************************************************/
+
+#include "config.h"
+#include "Directory.h"
+#include "OSPathSep.h"
+#include "log.h"
+#include <string>
+#include <vector>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// Constructor
+Directory::Directory(std::string path)
+{
+ this->path = path;
+
+ valid = refresh();
+}
+
+// Check if the directory is valid
+bool Directory::isValid()
+{
+ return valid;
+}
+
+// Return a list of all files in a directory
+std::vector<std::string> Directory::getFiles()
+{
+ return files;
+}
+
+// Return a list of all subdirectories in a directory
+std::vector<std::string> Directory::getSubDirs()
+{
+ return subDirs;
+}
+
+// Refresh the directory listing
+bool Directory::refresh()
+{
+ // Reset the state
+ valid = false;
+
+ subDirs.clear();
+ files.clear();
+
+ // Enumerate the directory
+ DIR* dir = opendir(path.c_str());
+
+ if (dir == NULL)
+ {
+ DEBUG_MSG("Failed to open directory %s", path.c_str());
+
+ return false;
+ }
+
+ // Enumerate the directory
+ struct dirent* entry = NULL;
+
+ while ((entry = readdir(dir)) != NULL)
+ {
+ // Check if this is the . or .. entry
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
+ {
+ continue;
+ }
+
+ // Convert the name of the entry to a C++ string
+ std::string name(entry->d_name);
+
+#if defined(_DIRENT_HAVE_D_TYPE) && defined(_BSD_SOURCE)
+ // Determine the type of the entry
+ switch(entry->d_type)
+ {
+ case DT_DIR:
+ // This is a directory
+ subDirs.push_back(name);
+ break;
+ case DT_REG:
+ // This is a regular file
+ files.push_back(name);
+ break;
+ default:
+ DEBUG_MSG("File not used %s", name.c_str());
+ break;
+ }
+#else
+ // The entry type has to be determined using lstat
+ struct stat entryStatus;
+
+ std::string fullPath = path + OS_PATHSEP + name;
+
+ if (!lstat(fullPath.c_str(), &entryStatus))
+ {
+ if (S_ISDIR(entryStatus.st_mode))
+ {
+ subDirs.push_back(name);
+ }
+ else if (S_ISREG(entryStatus.st_mode))
+ {
+ files.push_back(name);
+ }
+ else
+ {
+ DEBUG_MSG("File not used %s", name.c_str());
+ }
+ }
+#endif
+ }
+
+ // Close the directory
+ closedir(dir);
+
+ valid = true;
+
+ return true;
+}
+
+// Create a new subdirectory
+bool Directory::mkdir(std::string name)
+{
+ std::string fullPath = path + OS_PATHSEP + name;
+
+ return (!::mkdir(fullPath.c_str(), S_IFDIR | S_IRWXU) && refresh());
+}
+
+// Delete a file or subdirectory in the directory
+bool Directory::remove(std::string name)
+{
+ std::string fullPath = path + OS_PATHSEP + name;
+
+ return (!::remove(fullPath.c_str()) && refresh());
+}
+
diff --git a/src/lib/object_store/Directory.h b/src/lib/object_store/Directory.h
--- /dev/null
@@ -0,0 +1,84 @@
+/* $Id: Directory.h 4814 2010-06-24 10:17:40Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Directory.h
+
+ Helper functions for accessing directories.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIRECTORY_H
+#define _SOFTHSM_V2_DIRECTORY_H
+
+#include "config.h"
+#include <string>
+#include <vector>
+
+class Directory
+{
+public:
+ // Constructor
+ Directory(std::string path);
+
+ // Destructor
+ virtual ~Directory() { }
+
+ // Check if the directory is valid
+ bool isValid();
+
+ // Return a list of all files in a directory
+ std::vector<std::string> getFiles();
+
+ // Return a list of all subdirectories in a directory
+ std::vector<std::string> getSubDirs();
+
+ // Refresh the directory listing
+ bool refresh();
+
+ // Create a new subdirectory
+ bool mkdir(std::string name);
+
+ // Delete a file or subdirectory in the directory
+ bool remove(std::string name);
+
+private:
+ // The directory path
+ std::string path;
+
+ // The status
+ bool valid;
+
+ // All files in the directory
+ std::vector<std::string> files;
+
+ // All subdirectories in the directory
+ std::vector<std::string> subDirs;
+};
+
+#endif // !_SOFTHSM_V2_DIRECTORY_H
+
diff --git a/src/lib/object_store/File.cpp b/src/lib/object_store/File.cpp
--- /dev/null
@@ -0,0 +1,337 @@
+/* $Id: File.cpp 6799 2012-10-30 12:53:19Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ File.h
+
+ This class wraps standard C file I/O in a convenient way for the object store
+ *****************************************************************************/
+
+#include "config.h"
+#include "File.h"
+#include "log.h"
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <errno.h>
+
+// Constructor
+//
+// N.B.: the create flag only has a function when a file is opened read/write
+File::File(std::string path, bool forRead /* = true */, bool forWrite /* = false */, bool create /* = false */)
+{
+ stream = NULL;
+
+ isReadable = forRead;
+ isWritable = forWrite;
+ locked = false;
+
+ this->path = path;
+
+ if (forRead || forWrite)
+ {
+ std::string fileMode = "";
+
+ if (forRead && !forWrite) fileMode = "r";
+ if (!forRead && forWrite) fileMode = "w";
+ if (forRead && forWrite && !create) fileMode = "r+";
+ if (forRead && forWrite && create) fileMode = "w+";
+
+ // Open the stream
+ valid = ((stream = fopen(path.c_str(), fileMode.c_str())) != NULL);
+ }
+}
+
+// Destructor
+File::~File()
+{
+ if (locked)
+ {
+ unlock();
+ }
+
+ if (stream != NULL)
+ {
+ fclose(stream);
+ }
+}
+
+// Check if the file is valid
+bool File::isValid()
+{
+ return valid;
+}
+
+// Check if the file is readable
+bool File::isRead()
+{
+ return isReadable;
+}
+
+// Check if the file is writable
+bool File::isWrite()
+{
+ return isWritable;
+}
+
+// Check if the end-of-file was reached
+bool File::isEOF()
+{
+ return valid && feof(stream);
+}
+
+// Read an unsigned long value; warning: not thread safe without locking!
+bool File::readULong(unsigned long& value)
+{
+ if (!valid) return false;
+
+ ByteString ulongVal;
+
+ ulongVal.resize(8);
+
+ if (fread(&ulongVal[0], 1, 8, stream) != 8)
+ {
+ return false;
+ }
+
+ value = ulongVal.long_val();
+
+ return true;
+}
+
+// Read a ByteString value; warning: not thread safe without locking!
+bool File::readByteString(ByteString& value)
+{
+ if (!valid) return false;
+
+ // Retrieve the length to read from the file
+ unsigned long len;
+
+ if (!readULong(len))
+ {
+ return false;
+ }
+
+ // Read the byte string from the file
+ value.resize(len);
+
+ if (fread(&value[0], 1, len, stream) != len)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read a boolean value; warning: not thread safe without locking!
+bool File::readBool(bool& value)
+{
+ if (!valid) return false;
+
+ // Read the boolean from the file
+ unsigned char boolValue;
+
+ if (fread(&boolValue, 1, 1, stream) != 1)
+ {
+ return false;
+ }
+
+ value = boolValue ? true : false;
+
+ return true;
+}
+
+// Read a string value; warning: not thread safe without locking!
+bool File::readString(std::string& value)
+{
+ if (!valid) return false;
+
+ // Retrieve the length to read from the file
+ unsigned long len;
+
+ if (!readULong(len))
+ {
+ return false;
+ }
+
+ // Read the string from the file
+ value.resize(len);
+
+ if (fread(&value[0], 1, len, stream) != len)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write an unsigned long value; warning: not thread safe without locking!
+bool File::writeULong(const unsigned long value)
+{
+ if (!valid) return false;
+
+ ByteString toWrite(value);
+
+ // Write the value to the file
+ if (fwrite(toWrite.const_byte_str(), 1, toWrite.size(), stream) != toWrite.size())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write a ByteString value; warning: not thread safe without locking!
+bool File::writeByteString(const ByteString& value)
+{
+ if (!valid) return false;
+
+ ByteString toWrite = value.serialise();
+
+ // Write the value to the file
+ if (fwrite(toWrite.const_byte_str(), 1, toWrite.size(), stream) != toWrite.size())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write a string value; warning: not thread safe without locking!
+bool File::writeString(const std::string& value)
+{
+ if (!valid) return false;
+
+ ByteString toWrite((const unsigned long) value.size());
+
+ // Write the value to the file
+ if ((fwrite(toWrite.const_byte_str(), 1, toWrite.size(), stream) != toWrite.size()) ||
+ (fwrite(&value[0], 1, value.size(), stream) != value.size()))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write a boolean value; warning: not thread safe without locking!
+bool File::writeBool(const bool value)
+{
+ if (!valid) return false;
+
+ unsigned char toWrite = value ? 0xFF : 0x00;
+
+ // Write the value to the file
+ if (fwrite(&toWrite, 1, 1, stream) != 1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Rewind the file
+bool File::rewind()
+{
+ if (!valid) return false;
+
+ ::rewind(stream);
+
+ return true;
+}
+
+// Seek to the specified position relative to the start of the file; if no
+// argument is specified this operation seeks to the end of the file
+bool File::seek(long offset /* = -1 */)
+{
+ if (offset == -1)
+ {
+ return valid && (valid = !fseek(stream, 0, SEEK_END));
+ }
+ else
+ {
+ return valid && (valid = !fseek(stream, offset, SEEK_SET));
+ }
+}
+
+// Lock the file
+bool File::lock(bool block /* = true */)
+{
+ struct flock fl;
+ fl.l_type = isWrite() ? F_WRLCK : F_RDLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_pid = 0;
+
+ if (locked || !valid) return false;
+
+ if (fcntl(fileno(stream), block ? F_SETLKW : F_SETLK, &fl) != 0)
+ {
+ ERROR_MSG("Could not lock the file: %s", strerror(errno));
+ return false;
+ }
+
+ locked = true;
+
+ return true;
+}
+
+// Unlock the file
+bool File::unlock()
+{
+ struct flock fl;
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_pid = 0;
+
+ if (!locked || !valid) return false;
+
+ if (fcntl(fileno(stream), F_SETLK, &fl) != 0)
+ {
+ valid = false;
+
+ ERROR_MSG("Could not unlock the file: %s", strerror(errno));
+ return false;
+ }
+
+ locked = false;
+
+ return valid;
+}
+
+// Flush the buffered stream to background storage
+bool File::flush()
+{
+ return valid && !fflush(stream);
+}
+
diff --git a/src/lib/object_store/File.h b/src/lib/object_store/File.h
--- /dev/null
@@ -0,0 +1,120 @@
+/* $Id: File.h 4818 2010-06-25 10:26:45Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ File.h
+
+ This class wraps standard C file I/O in a convenient way for the object store
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FILE_H
+#define _SOFTHSM_V2_FILE_H
+
+#include "config.h"
+#include "ByteString.h"
+#include <stdio.h>
+#include <string>
+
+class File
+{
+public:
+ // Constructor
+ File(std::string path, bool forRead = true, bool forWrite = false, bool create = false);
+
+ // Destructor
+ virtual ~File();
+
+ // Check if the file is valid
+ bool isValid();
+
+ // Check if the file is readable
+ bool isRead();
+
+ // Check if the file is writable
+ bool isWrite();
+
+ // Check if the end-of-file was reached
+ bool isEOF();
+
+ // Read an unsigned long value; warning: not thread safe without locking!
+ bool readULong(unsigned long& value);
+
+ // Read a ByteString value; warning: not thread safe without locking!
+ bool readByteString(ByteString& value);
+
+ // Read a string value; warning: not thread safe without locking!
+ bool readString(std::string& value);
+
+ // Read a boolean value; warning: not thread safe without locking!
+ bool readBool(bool& value);
+
+ // Write an unsigned long value; warning: not thread safe without locking!
+ bool writeULong(const unsigned long value);
+
+ // Write a ByteString value; warning: not thread safe without locking!
+ bool writeByteString(const ByteString& value);
+
+ // Write a string value; warning: not thread safe without locking!
+ bool writeString(const std::string& value);
+
+ // Write a boolean value; warning: not thread safe without locking!
+ bool writeBool(const bool value);
+
+ // Rewind the file
+ bool rewind();
+
+ // Seek to the specified position relative to the start of the file; if no
+ // argument is specified this operation seeks to the end of the file
+ bool seek(long offset = -1);
+
+ // Lock the file
+ bool lock(bool block = true);
+
+ // Unlock the file
+ bool unlock();
+
+ // Flush the buffered stream to background storage
+ bool flush();
+
+private:
+ // The file path
+ std::string path;
+
+ // The status
+ bool valid;
+ bool locked;
+
+ // Read, write or both?
+ bool isReadable, isWritable;
+
+ // The FILE stream
+ FILE* stream;
+};
+
+#endif // !_SOFTHSM_V2_FILE_H
+
diff --git a/src/lib/object_store/FindOperation.cpp b/src/lib/object_store/FindOperation.cpp
--- /dev/null
@@ -0,0 +1,82 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FindOperation.cpp
+
+ This class represents the find operation that can be used to collect
+ objects that match the attributes contained in a given template.
+ *****************************************************************************/
+
+#include "config.h"
+#include "FindOperation.h"
+
+FindOperation::FindOperation()
+{
+}
+
+FindOperation *FindOperation::create()
+{
+ return new FindOperation();
+}
+
+void FindOperation::recycle()
+{
+ delete this;
+}
+
+void FindOperation::setHandles(const std::set<CK_OBJECT_HANDLE> &handles)
+{
+ _handles = handles;
+}
+
+CK_ULONG FindOperation::retrieveHandles(CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulCount)
+{
+ CK_ULONG ulReturn = 0;
+ std::set<CK_OBJECT_HANDLE>::const_iterator it;
+ for (it=_handles.begin(); it != _handles.end(); ++it) {
+ if (ulReturn >= ulCount) break;
+
+ phObject[ulReturn++] = *it;
+ }
+ return ulReturn;
+}
+
+CK_ULONG FindOperation::eraseHandles(CK_ULONG ulIndex, CK_ULONG ulCount)
+{
+ std::set<CK_OBJECT_HANDLE>::const_iterator it;
+ for (it=_handles.begin(); it != _handles.end() && ulIndex != 0; --ulIndex) {
+ ++it;
+ }
+
+ CK_ULONG ulReturn = 0;
+ for ( ; it != _handles.end() && ulReturn < ulCount; ++ulReturn) {
+ _handles.erase(it++);
+ }
+ return ulReturn;
+}
diff --git a/src/lib/object_store/FindOperation.h b/src/lib/object_store/FindOperation.h
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id: $ */
+
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FindOperation.h
+
+ This class represents the find operation that can be used to collect
+ objects that match the attributes contained in a given template.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FINDOPERATION_H
+#define _SOFTHSM_V2_FINDOPERATION_H
+
+#include "config.h"
+
+#include <set>
+#include "OSObject.h"
+
+class FindOperation
+{
+public:
+ // Factory method creates a new find operation
+ static FindOperation* create();
+
+ // Hand this operation back to the factory for recycling.
+ void recycle();
+
+ // Add the objects from thet set that match the attributes in the given template to the find operation.
+ void setHandles(const std::set<CK_OBJECT_HANDLE> &handles);
+
+ // Retrieve handles
+ CK_ULONG retrieveHandles(CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulCount);
+
+ // Erase handles from the handles set.
+ CK_ULONG eraseHandles(CK_ULONG ulIndex, CK_ULONG ulCount);
+
+protected:
+ // Use a protected constructor to force creation via factory method.
+ FindOperation();
+
+ std::set<CK_OBJECT_HANDLE> _handles;
+};
+
+#endif // _SOFTHSM_V2_FINDOPERATION_H
diff --git a/src/lib/object_store/Makefile.am b/src/lib/object_store/Makefile.am
--- /dev/null
@@ -0,0 +1,25 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/..
+
+noinst_LTLIBRARIES = libsofthsm_objectstore.la
+libsofthsm_objectstore_la_SOURCES = ObjectStore.cpp \
+ UUID.cpp \
+ Directory.cpp \
+ File.cpp \
+ OSAttribute.cpp \
+ OSToken.cpp \
+ ObjectFile.cpp \
+ SessionObject.cpp \
+ SessionObjectStore.cpp \
+ FindOperation.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/object_store/OSAttribute.cpp b/src/lib/object_store/OSAttribute.cpp
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: OSAttribute.cpp 4822 2010-07-03 16:35:05Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSAttribute.cpp
+
+ This class represents the object store view on an object's attribute
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSAttribute.h"
+
+// Copy constructor
+OSAttribute::OSAttribute(const OSAttribute& in)
+{
+ this->attributeType = in.attributeType;
+ this->boolValue = in.boolValue;
+ this->ulongValue = in.ulongValue;
+ this->byteStrValue = in.byteStrValue;
+}
+
+// Constructor for a boolean type attribute
+OSAttribute::OSAttribute(const bool value)
+{
+ boolValue = value;
+ attributeType = BOOL;
+}
+
+// Constructor for an unsigned long type attribute
+OSAttribute::OSAttribute(const unsigned long value)
+{
+ ulongValue = value;
+ attributeType = ULONG;
+}
+
+// Constructor for a byte string type attribute
+OSAttribute::OSAttribute(const ByteString& value)
+{
+ byteStrValue = value;
+ attributeType = BYTESTR;
+}
+
+// Check the attribute type
+bool OSAttribute::isBooleanAttribute() const
+{
+ return (attributeType == BOOL);
+}
+
+bool OSAttribute::isUnsignedLongAttribute() const
+{
+ return (attributeType == ULONG);
+}
+
+bool OSAttribute::isByteStringAttribute() const
+{
+ return (attributeType == BYTESTR);
+}
+
+// Retrieve the attribute value
+const bool OSAttribute::getBooleanValue() const
+{
+ return boolValue;
+}
+
+const unsigned long OSAttribute::getUnsignedLongValue() const
+{
+ return ulongValue;
+}
+
+const ByteString& OSAttribute::getByteStringValue() const
+{
+ return byteStrValue;
+}
+
+// Set the attribute value
+void OSAttribute::setBooleanValue(const bool value)
+{
+ boolValue = value;
+}
+
+void OSAttribute::setUnsignedLongValue(const unsigned long value)
+{
+ ulongValue = value;
+}
+
+void OSAttribute::setByteStringValue(const ByteString& value)
+{
+ byteStrValue = value;
+}
+
diff --git a/src/lib/object_store/OSAttribute.h b/src/lib/object_store/OSAttribute.h
--- /dev/null
@@ -0,0 +1,91 @@
+/* $Id: OSAttribute.h 4822 2010-07-03 16:35:05Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSAttribute.h
+
+ This class represents the object store view on an object's attribute
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSATTRIBUTE_H
+#define _SOFTHSM_V2_OSATTRIBUTE_H
+
+#include "config.h"
+#include "ByteString.h"
+
+class OSAttribute
+{
+public:
+ // Copy constructor
+ OSAttribute(const OSAttribute& in);
+
+ // Constructor for a boolean type attribute
+ OSAttribute(const bool value);
+
+ // Constructor for an unsigned long type attribute
+ OSAttribute(const unsigned long value);
+
+ // Constructor for a byte string type attribute
+ OSAttribute(const ByteString& value);
+
+ // Destructor
+ virtual ~OSAttribute() { }
+
+ // Check the attribute type
+ bool isBooleanAttribute() const;
+ bool isUnsignedLongAttribute() const;
+ bool isByteStringAttribute() const;
+
+ // Retrieve the attribute value
+ const bool getBooleanValue() const;
+ const unsigned long getUnsignedLongValue() const;
+ const ByteString& getByteStringValue() const;
+
+ // Set the attribute value
+ void setBooleanValue(const bool value);
+ void setUnsignedLongValue(const unsigned long value);
+ void setByteStringValue(const ByteString& value);
+
+private:
+ // The attribute type
+ enum
+ {
+ BOOL,
+ ULONG,
+ BYTESTR
+ }
+ attributeType;
+
+ // The attribute value
+ bool boolValue;
+ unsigned long ulongValue;
+ ByteString byteStrValue;
+};
+
+#endif // !_SOFTHSM_V2_OSATTRIBUTE_H
+
diff --git a/src/lib/object_store/OSAttributes.h b/src/lib/object_store/OSAttributes.h
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: OSAttributes.h 4844 2010-08-11 07:04:38Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSAttributes.h
+
+ Specifies vendor defined attributes for use in internal object store files
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSATTRIBUTES_H
+#define _SOFTHSM_V2_OSATTRIBUTES_H
+
+#include "config.h"
+#include "cryptoki.h"
+
+// Define vendor tag; presumably the one below is reasonably unique
+#define CKA_VENDOR_SOFTHSM CKA_VENDOR_DEFINED + 0x5348 // 'SH'
+
+// Vendor defined attribute types for the token file
+#define CKA_OS_TOKENLABEL CKA_VENDOR_SOFTHSM + 1
+#define CKA_OS_TOKENSERIAL CKA_VENDOR_SOFTHSM + 2
+#define CKA_OS_TOKENFLAGS CKA_VENDOR_SOFTHSM + 3
+#define CKA_OS_SOPIN CKA_VENDOR_SOFTHSM + 4
+#define CKA_OS_USERPIN CKA_VENDOR_SOFTHSM + 5
+
+#endif // !_SOFTHSM_V2_OSATTRIBUTES_H
+
diff --git a/src/lib/object_store/OSObject.h b/src/lib/object_store/OSObject.h
--- /dev/null
@@ -0,0 +1,81 @@
+/* $Id: OSObject.h 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSObject.h
+
+ This file contains the abstract interface for ObjectStore objects. It is
+ implemented by persistent objects in the form of the ObjectFile class and
+ by session objects in the form of the SessionObject class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSOBJECT_H
+#define _SOFTHSM_V2_OSOBJECT_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+
+class OSObject
+{
+public:
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type) = 0;
+
+ // Retrieve the specified attribute
+ virtual OSAttribute* getAttribute(CK_ATTRIBUTE_TYPE type) = 0;
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute) = 0;
+
+ // The validity state of the object
+ virtual bool isValid() = 0;
+
+ // Start an attribute set transaction; this method is used when - for
+ // example - a key is generated and all its attributes need to be
+ // persisted in one go.
+ //
+ // N.B.: Starting a transaction locks the object!
+ //
+ // Function returns false in case a transaction is already in progress
+ virtual bool startTransaction() = 0;
+
+ // Commit an attribute transaction; returns false if no transaction is in progress
+ virtual bool commitTransaction() = 0;
+
+ // Abort an attribute transaction; loads back the previous version of the object from disk;
+ // returns false if no transaction was in progress
+ virtual bool abortTransaction() = 0;
+
+ // Destroys the object (warning, any pointers to the object are no longer
+ // valid after this call because delete is called!)
+ virtual bool destroyObject() = 0;
+};
+
+#endif // !_SOFTHSM_V2_OSOBJECT_H
+
diff --git a/src/lib/object_store/OSPathSep.h b/src/lib/object_store/OSPathSep.h
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id: OSPathSep.h 4822 2010-07-03 16:35:05Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSPathSep.h
+
+ Determine the OS specific path separator
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSPATHSEP_H
+#define _SOFTHSM_V2_OSPATHSEP_H
+
+#include "config.h"
+
+#ifdef _WIN32
+#define OS_PATHSEP "\\"
+#else
+#define OS_PATHSEP "/"
+#endif
+
+#endif // !_SOFTHSM_V2_OSPATHSEP_H
+
diff --git a/src/lib/object_store/OSToken.cpp b/src/lib/object_store/OSToken.cpp
--- /dev/null
@@ -0,0 +1,575 @@
+/* $Id: OSToken.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSToken.cpp
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSAttributes.h"
+#include "OSAttribute.h"
+#include "ObjectFile.h"
+#include "Directory.h"
+#include "UUID.h"
+#include "IPCSignal.h"
+#include "cryptoki.h"
+#include "OSToken.h"
+#include "OSPathSep.h"
+#include <vector>
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+#include <stdio.h>
+
+// Constructor
+OSToken::OSToken(const std::string tokenPath)
+{
+ tokenDir = new Directory(tokenPath);
+ tokenObject = new ObjectFile(this, tokenPath + OS_PATHSEP + "tokenObject");
+ sync = IPCSignal::create(tokenPath);
+ tokenMutex = MutexFactory::i()->getMutex();
+ this->tokenPath = tokenPath;
+ valid = (sync != NULL) && (tokenMutex != NULL) && tokenDir->isValid() && tokenObject->isValid();
+
+ DEBUG_MSG("Opened token %s", tokenPath.c_str());
+
+ index(true);
+}
+
+// Create a new token
+/*static*/ OSToken* OSToken::createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial)
+{
+ Directory baseDir(basePath);
+
+ if (!baseDir.isValid())
+ {
+ return NULL;
+ }
+
+ // Create the token directory
+ if (!baseDir.mkdir(tokenDir))
+ {
+ return NULL;
+ }
+
+ // Create the token object
+ ObjectFile tokenObject(NULL, basePath + OS_PATHSEP + tokenDir + OS_PATHSEP + "tokenObject", true);
+
+ if (!tokenObject.isValid())
+ {
+ baseDir.remove(tokenDir);
+
+ return NULL;
+ }
+
+ // Set the initial attributes
+ CK_ULONG flags =
+ CKF_RNG |
+ CKF_LOGIN_REQUIRED | // FIXME: check
+ CKF_RESTORE_KEY_NOT_NEEDED |
+ CKF_TOKEN_INITIALIZED |
+ CKF_SO_PIN_LOCKED |
+ CKF_SO_PIN_TO_BE_CHANGED;
+
+ OSAttribute tokenLabel(label);
+ OSAttribute tokenSerial(serial);
+ OSAttribute tokenFlags(flags);
+
+ if (!tokenObject.setAttribute(CKA_OS_TOKENLABEL, tokenLabel) ||
+ !tokenObject.setAttribute(CKA_OS_TOKENSERIAL, tokenSerial) ||
+ !tokenObject.setAttribute(CKA_OS_TOKENFLAGS, tokenFlags))
+ {
+ baseDir.remove(tokenDir + OS_PATHSEP + "tokenObject");
+ baseDir.remove(tokenDir);
+
+ return NULL;
+ }
+
+ DEBUG_MSG("Created new token %s", tokenDir.c_str());
+
+ return new OSToken(basePath + OS_PATHSEP + tokenDir);
+}
+
+// Destructor
+OSToken::~OSToken()
+{
+ // Clean up
+ std::set<ObjectFile*> cleanUp = allObjects;
+ allObjects.clear();
+
+ for (std::set<ObjectFile*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ delete *i;
+ }
+
+ delete tokenDir;
+ if (sync != NULL) delete sync;
+ MutexFactory::i()->recycleMutex(tokenMutex);
+ delete tokenObject;
+}
+
+// Set the SO PIN
+bool OSToken::setSOPIN(const ByteString& soPINBlob)
+{
+ if (!valid) return false;
+
+ OSAttribute soPIN(soPINBlob);
+
+ CK_ULONG flags;
+
+ if (tokenObject->setAttribute(CKA_OS_SOPIN, soPIN) &&
+ getTokenFlags(flags))
+ {
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ flags &= ~CKF_SO_PIN_FINAL_TRY;
+ flags &= ~CKF_SO_PIN_LOCKED;
+ flags &= ~CKF_SO_PIN_TO_BE_CHANGED;
+
+ return setTokenFlags(flags);
+ }
+
+ return false;
+}
+
+// Get the SO PIN
+bool OSToken::getSOPIN(ByteString& soPINBlob)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ OSAttribute* soPIN = tokenObject->getAttribute(CKA_OS_SOPIN);
+
+ if (soPIN != NULL)
+ {
+ soPINBlob = soPIN->getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Set the user PIN
+bool OSToken::setUserPIN(ByteString userPINBlob)
+{
+ if (!valid) return false;
+
+ OSAttribute userPIN(userPINBlob);
+
+ CK_ULONG flags;
+
+ if (tokenObject->setAttribute(CKA_OS_USERPIN, userPIN) &&
+ getTokenFlags(flags))
+ {
+ flags |= CKF_USER_PIN_INITIALIZED;
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ flags &= ~CKF_USER_PIN_FINAL_TRY;
+ flags &= ~CKF_USER_PIN_LOCKED;
+ flags &= ~CKF_USER_PIN_TO_BE_CHANGED;
+
+ return setTokenFlags(flags);
+ }
+
+ return false;
+}
+
+// Get the user PIN
+bool OSToken::getUserPIN(ByteString& userPINBlob)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ OSAttribute* userPIN = tokenObject->getAttribute(CKA_OS_USERPIN);
+
+ if (userPIN != NULL)
+ {
+ userPINBlob = userPIN->getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Retrieve the token label
+bool OSToken::getTokenLabel(ByteString& label)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ OSAttribute* tokenLabel = tokenObject->getAttribute(CKA_OS_TOKENLABEL);
+
+ if (tokenLabel != NULL)
+ {
+ label = tokenLabel->getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Retrieve the token serial
+bool OSToken::getTokenSerial(ByteString& serial)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ OSAttribute* tokenSerial = tokenObject->getAttribute(CKA_OS_TOKENSERIAL);
+
+ if (tokenSerial != NULL)
+ {
+ serial = tokenSerial->getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Get the token flags
+bool OSToken::getTokenFlags(CK_ULONG& flags)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ OSAttribute* tokenFlags = tokenObject->getAttribute(CKA_OS_TOKENFLAGS);
+
+ if (tokenFlags != NULL)
+ {
+ flags = tokenFlags->getUnsignedLongValue();
+
+ // Check if the user PIN is initialised
+ if (tokenObject->attributeExists(CKA_OS_USERPIN))
+ {
+ flags |= CKF_USER_PIN_INITIALIZED;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Set the token flags
+bool OSToken::setTokenFlags(const CK_ULONG flags)
+{
+ if (!valid) return false;
+
+ OSAttribute tokenFlags(flags);
+
+ return tokenObject->setAttribute(CKA_OS_TOKENFLAGS, tokenFlags);
+}
+
+// Retrieve objects
+std::set<ObjectFile*> OSToken::getObjects()
+{
+ index();
+
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(tokenMutex);
+
+ return objects;
+}
+
+void OSToken::getObjects(std::set<OSObject*> &objects)
+{
+ index();
+
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(tokenMutex);
+
+ objects.insert(this->objects.begin(),this->objects.end());
+}
+
+// Create a new object
+ObjectFile* OSToken::createObject()
+{
+ if (!valid) return NULL;
+
+ // Generate a name for the object
+ std::string objectPath = tokenPath + OS_PATHSEP + UUID::newUUID() + ".object";
+
+ // Create the new object file
+ ObjectFile* newObject = new ObjectFile(this, objectPath, true);
+
+ if (!newObject->isValid())
+ {
+ ERROR_MSG("Failed to create new object %s", objectPath.c_str());
+
+ delete newObject;
+
+ return NULL;
+ }
+
+ // Now add it to the set of objects
+ MutexLocker lock(tokenMutex);
+
+ objects.insert(newObject);
+ allObjects.insert(newObject);
+ currentFiles.insert(newObject->getFilename());
+
+ DEBUG_MSG("(0x%08X) Created new object %s (0x%08X)", this, objectPath.c_str(), newObject);
+
+ sync->trigger();
+
+ return newObject;
+}
+
+// Delete an object
+bool OSToken::deleteObject(ObjectFile* object)
+{
+ if (!valid) return false;
+
+ if (objects.find(object) == objects.end())
+ {
+ ERROR_MSG("Cannot delete non-existent object 0x%08X", object);
+
+ return false;
+ }
+
+ MutexLocker lock(tokenMutex);
+
+ // Invalidate the object instance
+ object->invalidate();
+
+ // Retrieve the filename of the object
+ std::string objectFilename = object->getFilename();
+
+ // Attempt to delete the file
+ if (!tokenDir->remove(objectFilename))
+ {
+ ERROR_MSG("Failed to delete object file %s", objectFilename.c_str());
+
+ return false;
+ }
+
+ objects.erase(object);
+
+ DEBUG_MSG("Deleted object %s", objectFilename.c_str());
+
+ sync->trigger();
+
+ return true;
+}
+
+// Checks if the token is consistent
+bool OSToken::isValid()
+{
+ return valid;
+}
+
+// Invalidate the token (for instance if it is deleted)
+void OSToken::invalidate()
+{
+ valid = false;
+}
+
+// Delete the token
+bool OSToken::clearToken()
+{
+ MutexLocker lock(tokenMutex);
+
+ // Invalidate the token
+ invalidate();
+
+ // First, clear out all objects
+ objects.clear();
+
+ // Now, delete all files in the token directory
+ if (!tokenDir->refresh())
+ {
+ return false;
+ }
+
+ std::vector<std::string> tokenFiles = tokenDir->getFiles();
+
+ for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++)
+ {
+ if (!tokenDir->remove(*i))
+ {
+ ERROR_MSG("Failed to remove %s from token directory %s", i->c_str(), tokenPath.c_str());
+
+ return false;
+ }
+ }
+
+ // Now remove the token directory
+ if (remove(tokenPath.c_str()))
+ {
+ ERROR_MSG("Failed to remove the token directory %s", tokenPath.c_str());
+
+ return false;
+ }
+
+ DEBUG_MSG("Token instance %s was succesfully cleared", tokenPath.c_str());
+
+ return true;
+}
+
+// Index the token
+bool OSToken::index(bool isFirstTime /* = false */)
+{
+ // Check if re-indexing is required
+ if (!isFirstTime && (!valid || !sync->wasTriggered()))
+ {
+ return true;
+ }
+
+ // Check the integrity
+ if (!tokenDir->refresh() || !tokenObject->isValid())
+ {
+ valid = false;
+
+ return false;
+ }
+
+ DEBUG_MSG("Token %s has changed", tokenPath.c_str());
+
+ // Retrieve the directory listing
+ std::vector<std::string> tokenFiles = tokenDir->getFiles();
+
+ // Filter out the objects
+ std::set<std::string> newSet;
+
+ for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++)
+ {
+ if ((i->size() > 7) && (!(i->substr(i->size() - 7).compare(".object"))))
+ {
+ newSet.insert(*i);
+ }
+ else
+ {
+ DEBUG_MSG("Ignored file %s", i->c_str());
+ }
+ }
+
+ // Compute the changes compared to the last list of files
+ std::set<std::string> addedFiles;
+ std::set<std::string> removedFiles;
+
+ if (!isFirstTime)
+ {
+ // First compute which files were added
+ for (std::set<std::string>::iterator i = newSet.begin(); i != newSet.end(); i++)
+ {
+ if (currentFiles.find(*i) == currentFiles.end())
+ {
+ addedFiles.insert(*i);
+ }
+ }
+
+ // Now compute which files were removed
+ for (std::set<std::string>::iterator i = currentFiles.begin(); i != currentFiles.end(); i++)
+ {
+ if (newSet.find(*i) == newSet.end())
+ {
+ removedFiles.insert(*i);
+ }
+ }
+ }
+ else
+ {
+ addedFiles = newSet;
+ }
+
+ currentFiles = newSet;
+
+ DEBUG_MSG("%d objects were added and %d objects were removed", addedFiles.size(), removedFiles.size());
+ DEBUG_MSG("Current directory set contains %d objects", currentFiles.size());
+
+ // Now update the set of objects
+ MutexLocker lock(tokenMutex);
+
+ // Add new objects
+ for (std::set<std::string>::iterator i = addedFiles.begin(); i != addedFiles.end(); i++)
+ {
+ // Create a new token object for the added file
+ ObjectFile* newObject = new ObjectFile(this, tokenPath + OS_PATHSEP + *i);
+
+ DEBUG_MSG("(0x%08X) New object %s (0x%08X) added", this, newObject->getFilename().c_str(), newObject);
+
+ objects.insert(newObject);
+ allObjects.insert(newObject);
+ }
+
+ // Remove deleted objects
+ std::set<ObjectFile*> newObjects;
+
+ for (std::set<ObjectFile*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ DEBUG_MSG("Processing %s (0x%08X)", (*i)->getFilename().c_str(), *i);
+
+ if (removedFiles.find((*i)->getFilename()) == removedFiles.end())
+ {
+ DEBUG_MSG("Adding object %s", (*i)->getFilename().c_str());
+ // This object gets to stay in the set
+ newObjects.insert(*i);
+ }
+ else
+ {
+ (*i)->invalidate();
+ }
+ }
+
+ // Set the new objects
+ objects = newObjects;
+
+ DEBUG_MSG("The token now contains %d objects", objects.size());
+
+ return true;
+}
+
diff --git a/src/lib/object_store/OSToken.h b/src/lib/object_store/OSToken.h
--- /dev/null
@@ -0,0 +1,155 @@
+/* $Id: OSToken.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSToken.h
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSTOKEN_H
+#define _SOFTHSM_V2_OSTOKEN_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include "ObjectFile.h"
+#include "Directory.h"
+#include "UUID.h"
+#include "IPCSignal.h"
+#include "MutexFactory.h"
+#include "cryptoki.h"
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+
+class OSToken
+{
+public:
+ // Constructor
+ OSToken(const std::string tokenPath);
+
+ // Create a new token
+ static OSToken* createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial);
+
+ // Constructor for new tokens
+ OSToken(const std::string tokenPath, const ByteString& label, const ByteString& serialNumber);
+
+ // Set the SO PIN
+ bool setSOPIN(const ByteString& soPINBlob);
+
+ // Get the SO PIN
+ bool getSOPIN(ByteString& soPINBlob);
+
+ // Set the user PIN
+ bool setUserPIN(ByteString userPINBlob);
+
+ // Get the user PIN
+ bool getUserPIN(ByteString& userPINBlob);
+
+ // Get the token flags
+ bool getTokenFlags(CK_ULONG& flags);
+
+ // Set the token flags
+ bool setTokenFlags(const CK_ULONG flags);
+
+ // Retrieve the token label
+ bool getTokenLabel(ByteString& label);
+
+ // Retrieve the token serial
+ bool getTokenSerial(ByteString& serial);
+
+ // Retrieve objects
+ std::set<ObjectFile*> getObjects();
+
+ // Insert objects into the given set
+ void getObjects(std::set<OSObject*> &objects);
+
+ // Create a new object
+ ObjectFile* createObject();
+
+ // Delete an object
+ bool deleteObject(ObjectFile* object);
+
+ // Destructor
+ virtual ~OSToken();
+
+ // Checks if the token is consistent
+ bool isValid();
+
+ // Invalidate the token (for instance if it is deleted)
+ void invalidate();
+
+ // Delete the token
+ bool clearToken();
+
+private:
+ // ObjectFile instances can call the index() function
+ friend class ObjectFile;
+
+ // Index the token
+ bool index(bool isFirstTime = false);
+
+ // Is the token consistent and valid?
+ bool valid;
+
+ // The token path
+ std::string tokenPath;
+
+ // The current objects of the token
+ std::set<ObjectFile*> objects;
+
+ // All the objects ever associated with this token
+ //
+ // This set is kept to be able to clean up when the token
+ // instance is discarded; in case the contents of a token
+ // change, some objects may disappear but we cannot simply
+ // delete them since they may still be referenced from an
+ // object outside of this class.
+ std::set<ObjectFile*> allObjects;
+
+ // The current list of files
+ std::set<std::string> currentFiles;
+
+ // The token object
+ ObjectFile* tokenObject;
+
+ // Inter-process synchronisation
+ IPCSignal* sync;
+
+ // The directory object for this token
+ Directory* tokenDir;
+
+ // For thread safeness
+ Mutex* tokenMutex;
+};
+
+#endif // !_SOFTHSM_V2_OSTOKEN_H
+
diff --git a/src/lib/object_store/ObjectFile.cpp b/src/lib/object_store/ObjectFile.cpp
--- /dev/null
@@ -0,0 +1,566 @@
+/* $Id: ObjectFile.cpp 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFile.h
+
+ This class represents object files
+ *****************************************************************************/
+
+#include "config.h"
+#include "ObjectFile.h"
+#include "OSToken.h"
+#include "OSPathSep.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// Attribute types
+#define BOOLEAN_ATTR 0x1
+#define ULONG_ATTR 0x2
+#define BYTESTR_ATTR 0x3
+
+// Constructor
+ObjectFile::ObjectFile(OSToken* parent, std::string path, bool isNew /* = false */)
+{
+ this->path = path;
+ ipcSignal = IPCSignal::create(path);
+ objectMutex = MutexFactory::i()->getMutex();
+ valid = (ipcSignal != NULL) && (objectMutex != NULL);
+ token = parent;
+ inTransaction = false;
+ transactionLockFile = NULL;
+
+ if (!valid) return;
+
+ if (!isNew)
+ {
+ DEBUG_MSG("Opened existing object %s", path.c_str());
+
+ refresh(true);
+ }
+ else
+ {
+ DEBUG_MSG("Created new object %s", path.c_str());
+
+ // Create an empty object file
+ store();
+ }
+
+}
+
+// Destructor
+ObjectFile::~ObjectFile()
+{
+ discardAttributes();
+
+ if (ipcSignal != NULL)
+ {
+ delete ipcSignal;
+ }
+
+ MutexFactory::i()->recycleMutex(objectMutex);
+}
+
+// Check if the specified attribute exists
+bool ObjectFile::attributeExists(CK_ATTRIBUTE_TYPE type)
+{
+ refresh();
+
+ MutexLocker lock(objectMutex);
+
+ return valid && (attributes[type] != NULL);
+}
+
+// Retrieve the specified attribute
+OSAttribute* ObjectFile::getAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ refresh();
+
+ MutexLocker lock(objectMutex);
+
+ return attributes[type];
+}
+
+// Set the specified attribute
+bool ObjectFile::setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute)
+{
+ refresh();
+
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot update invalid object %s", path.c_str());
+
+ return false;
+ }
+
+ {
+ MutexLocker lock(objectMutex);
+
+ if (attributes[type] != NULL)
+ {
+ delete attributes[type];
+
+ attributes[type] = NULL;
+ }
+
+ attributes[type] = new OSAttribute(attribute);
+ }
+
+ store();
+
+ return isValid();
+}
+
+// The validity state of the object
+bool ObjectFile::isValid()
+{
+ return valid;
+}
+
+// Invalidate the object file externally; this method is normally
+// only called by the OSToken class in case an object file has
+// been deleted.
+void ObjectFile::invalidate()
+{
+ valid = false;
+
+ discardAttributes();
+}
+
+// Refresh the object if necessary
+void ObjectFile::refresh(bool isFirstTime /* = false */)
+{
+ // Check if we're in the middle of a transaction
+ if (inTransaction)
+ {
+ return;
+ }
+
+ // Refresh the associated token if set
+ if (!isFirstTime && (token != NULL))
+ {
+ // This may cause this instance to become invalid
+ token->index();
+ }
+
+ // Check the IPC signal
+ if (!isFirstTime && (!valid || !ipcSignal->wasTriggered()))
+ {
+ return;
+ }
+
+ File objectFile(path);
+
+ if (!objectFile.isValid())
+ {
+ valid = false;
+
+ return;
+ }
+
+ DEBUG_MSG("Object %s has changed", path.c_str());
+
+ // Discard the existing set of attributes
+ discardAttributes();
+
+ objectFile.lock();
+
+ MutexLocker lock(objectMutex);
+
+ // Read back the attributes
+ do
+ {
+ unsigned long p11AttrType;
+ unsigned long osAttrType;
+
+ if (!objectFile.readULong(p11AttrType))
+ {
+ if (objectFile.isEOF())
+ {
+ break;
+ }
+
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (!objectFile.readULong(osAttrType))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ // Depending on the type, read back the actual value
+ if (osAttrType == BOOLEAN_ATTR)
+ {
+ bool value;
+
+ if (!objectFile.readBool(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else if (osAttrType == ULONG_ATTR)
+ {
+ unsigned long value;
+
+ if (!objectFile.readULong(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else if (osAttrType == BYTESTR_ATTR)
+ {
+ ByteString value;
+
+ if (!objectFile.readByteString(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else
+ {
+ DEBUG_MSG("Corrupt object file %s with unknown attribute of type %d", path.c_str(), osAttrType);
+
+ valid = false;
+
+ return;
+ }
+ }
+ while (!objectFile.isEOF());
+
+ objectFile.unlock();
+
+ valid = true;
+}
+
+// Write the object to background storage
+void ObjectFile::store()
+{
+ // Check if we're in the middle of a transaction
+ if (inTransaction)
+ {
+ return;
+ }
+
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot write back an invalid object %s", path.c_str());
+
+ return;
+ }
+
+ File objectFile(path, false, true, true);
+
+ if (!objectFile.isValid())
+ {
+ DEBUG_MSG("Cannot open object %s for writing", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ objectFile.lock();
+
+ MutexLocker lock(objectMutex);
+
+ for (std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator i = attributes.begin(); i != attributes.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ unsigned long p11AttrType = i->first;
+
+ if (!objectFile.writeULong(p11AttrType))
+ {
+ DEBUG_MSG("Failed to write PKCS #11 attribute type to object %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (i->second->isBooleanAttribute())
+ {
+ unsigned long osAttrType = BOOLEAN_ATTR;
+ bool value = i->second->getBooleanValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeBool(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+ }
+ else if (i->second->isUnsignedLongAttribute())
+ {
+ unsigned long osAttrType = ULONG_ATTR;
+ unsigned long value = i->second->getUnsignedLongValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeULong(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+ }
+ else if (i->second->isByteStringAttribute())
+ {
+ unsigned long osAttrType = BYTESTR_ATTR;
+ const ByteString& value = i->second->getByteStringValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeByteString(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+ }
+ else
+ {
+ DEBUG_MSG("Unknown attribute type for object %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+ }
+
+ objectFile.unlock();
+
+ // Trigger the IPC signal
+ ipcSignal->trigger();
+
+ valid = true;
+}
+
+// Discard the cached attributes
+void ObjectFile::discardAttributes()
+{
+ MutexLocker lock(objectMutex);
+
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> cleanUp = attributes;
+ attributes.clear();
+
+ for (std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ delete i->second;
+ i->second = NULL;
+ }
+}
+
+
+// Returns the file name of the object
+std::string ObjectFile::getFilename() const
+{
+ if ((path.find_last_of(OS_PATHSEP) != std::string::npos) &&
+ (path.find_last_of(OS_PATHSEP) < path.size()))
+ {
+ return path.substr(path.find_last_of(OS_PATHSEP) + 1);
+ }
+ else
+ {
+ return path;
+ }
+}
+
+// Start an attribute set transaction; this method is used when - for
+// example - a key is generated and all its attributes need to be
+// persisted in one go.
+//
+// N.B.: Starting a transaction locks the object!
+bool ObjectFile::startTransaction()
+{
+ MutexLocker lock(objectMutex);
+
+ if (inTransaction)
+ {
+ return false;
+ }
+
+ transactionLockFile = new File(path);
+
+ if (!transactionLockFile->isValid() || !transactionLockFile->lock())
+ {
+ delete transactionLockFile;
+ transactionLockFile = NULL;
+
+ ERROR_MSG("Failed to lock file %s for attribute transaction", path.c_str());
+
+ return false;
+ }
+
+ inTransaction = true;
+
+ return true;
+}
+
+// Commit an attribute transaction
+bool ObjectFile::commitTransaction()
+{
+ {
+ MutexLocker lock(objectMutex);
+
+ if (!inTransaction)
+ {
+ return false;
+ }
+
+ // Unlock the file; theoretically, this can mean that another instance
+ // of SoftHSM now gets the lock and writes back attributes that will be
+ // overwritten when this transaction is committed. The chances of this
+ // are deemed to be so small that we do nothing to prevent this...
+ if (transactionLockFile == NULL)
+ {
+ ERROR_MSG("Transaction lock file instance invalid!");
+
+ return false;
+ }
+
+ transactionLockFile->unlock();
+
+ delete transactionLockFile;
+ transactionLockFile = NULL;
+ inTransaction = false;
+ }
+
+ store();
+
+ return true;
+}
+
+// Abort an attribute transaction; loads back the previous version of the object from disk
+bool ObjectFile::abortTransaction()
+{
+ {
+ MutexLocker lock(objectMutex);
+
+ if (!inTransaction)
+ {
+ return false;
+ }
+
+ if (transactionLockFile == NULL)
+ {
+ ERROR_MSG("Transaction lock file instance invalid!");
+
+ return false;
+ }
+
+ transactionLockFile->unlock();
+
+ delete transactionLockFile;
+ transactionLockFile = NULL;
+ inTransaction = false;
+ }
+
+ // Force reload from disk
+ refresh(true);
+
+ return true;
+}
+
+// Destroy the object; WARNING: pointers to the object become invalid after this call
+bool ObjectFile::destroyObject()
+{
+ if (token == NULL)
+ {
+ ERROR_MSG("Cannot destroy an object that is not associated with a token");
+
+ return false;
+ }
+
+ return token->deleteObject(this);
+}
+
diff --git a/src/lib/object_store/ObjectFile.h b/src/lib/object_store/ObjectFile.h
--- /dev/null
@@ -0,0 +1,137 @@
+/* $Id: ObjectFile.h 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFile.h
+
+ This class represents object files
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTFILE_H
+#define _SOFTHSM_V2_OBJECTFILE_H
+
+#include "config.h"
+#include "File.h"
+#include "ByteString.h"
+#include "OSAttribute.h"
+#include "IPCSignal.h"
+#include "MutexFactory.h"
+#include <string>
+#include <map>
+#include <time.h>
+#include "cryptoki.h"
+#include "OSObject.h"
+
+// OSToken forward declaration
+class OSToken;
+
+class ObjectFile : public OSObject
+{
+public:
+ // Constructor
+ ObjectFile(OSToken* parent, const std::string path, bool isNew = false);
+
+ // Destructor
+ virtual ~ObjectFile();
+
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the specified attribute
+ virtual OSAttribute* getAttribute(CK_ATTRIBUTE_TYPE type);
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute);
+
+ // The validity state of the object
+ virtual bool isValid();
+
+ // Invalidate the object file externally; this method is normally
+ // only called by the OSToken class in case an object file has
+ // been deleted.
+ void invalidate();
+
+ // Returns the file name of the object
+ std::string getFilename() const;
+
+ // Start an attribute set transaction; this method is used when - for
+ // example - a key is generated and all its attributes need to be
+ // persisted in one go.
+ //
+ // N.B.: Starting a transaction locks the object!
+ //
+ // Function returns false in case a transaction is already in progress
+ virtual bool startTransaction();
+
+ // Commit an attribute transaction; returns false if no transaction is in progress
+ virtual bool commitTransaction();
+
+ // Abort an attribute transaction; loads back the previous version of the object from disk;
+ // returns false if no transaction was in progress
+ virtual bool abortTransaction();
+
+ // Destroys the object; WARNING: pointers to the object become invalid after this
+ // call!
+ virtual bool destroyObject();
+
+private:
+ // Refresh the object if necessary
+ void refresh(bool isFirstTime = false);
+
+ // Write the object to background storage
+ void store();
+
+ // Discard the cached attributes
+ void discardAttributes();
+
+ // The path to the file
+ std::string path;
+
+ // The IPC object that is used to signal changes in the object file
+ // to other SoftHSM instances
+ IPCSignal* ipcSignal;
+
+ // The object's raw attributes
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> attributes;
+
+ // The object's validity state
+ bool valid;
+
+ // The token this object is associated with
+ OSToken* token;
+
+ // Mutex object for thread-safeness
+ Mutex* objectMutex;
+
+ // Is the object undergoing an attribute transaction?
+ bool inTransaction;
+ File* transactionLockFile;
+};
+
+#endif // !_SOFTHSM_V2_OBJECTFILE_H
+
diff --git a/src/lib/object_store/ObjectStore.cpp b/src/lib/object_store/ObjectStore.cpp
--- /dev/null
@@ -0,0 +1,187 @@
+/* $Id: ObjectStore.cpp 4874 2010-08-27 10:37:29Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStore.h
+
+ The object store manages the separate tokens that the SoftHSM supports. Each
+ token is organised as a directory containing files that are contain the
+ token's objects. The object store is initialised with a root directory from
+ which it enumerates the tokens.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "ObjectStore.h"
+#include "Directory.h"
+#include "OSToken.h"
+#include "UUID.h"
+#include <stdio.h>
+
+// Constructor
+ObjectStore::ObjectStore(std::string storePath)
+{
+ this->storePath = storePath;
+ valid = false;
+ storeMutex = MutexFactory::i()->getMutex();
+
+ MutexLocker lock(storeMutex);
+
+ // Find all tokens in the specified path
+ Directory storeDir(storePath);
+
+ if (!storeDir.isValid())
+ {
+ ERROR_MSG("Failed to enumerate object store in %s", storePath.c_str());
+
+ return;
+ }
+
+ // Assume that all subdirectories are tokens
+ std::vector<std::string> dirs = storeDir.getSubDirs();
+
+ for (std::vector<std::string>::iterator i = dirs.begin(); i != dirs.end(); i++)
+ {
+ // Create a token instance
+ OSToken* token = new OSToken(storePath + "/" + *i);
+
+ if (!token->isValid())
+ {
+ ERROR_MSG("Failed to open token %s", i->c_str());
+
+ delete token;
+
+ continue;
+ }
+
+ tokens.push_back(token);
+ allTokens.push_back(token);
+ }
+
+ valid = true;
+}
+
+// Destructor
+ObjectStore::~ObjectStore()
+{
+ {
+ MutexLocker lock(storeMutex);
+
+ // Clean up
+ tokens.clear();
+
+ for (std::vector<OSToken*>::iterator i = allTokens.begin(); i != allTokens.end(); i++)
+ {
+ delete *i;
+ }
+ }
+
+ MutexFactory::i()->recycleMutex(storeMutex);
+}
+
+// Check if the object store is valid
+bool ObjectStore::isValid()
+{
+ return valid;
+}
+
+// Return the number of tokens that is present
+size_t ObjectStore::getTokenCount()
+{
+ MutexLocker lock(storeMutex);
+
+ return tokens.size();
+}
+
+// Return a pointer to the n-th token (counting starts at 0)
+OSToken* ObjectStore::getToken(size_t whichToken)
+{
+ MutexLocker lock(storeMutex);
+
+ if (whichToken >= tokens.size())
+ {
+ return NULL;
+ }
+
+ return tokens[whichToken];
+}
+
+// Create a new token
+OSToken* ObjectStore::newToken(const ByteString& label)
+{
+ MutexLocker lock(storeMutex);
+
+ // Generate a UUID for the token
+ std::string tokenUUID = UUID::newUUID();
+
+ // Convert the UUID to a serial number
+ std::string serialNumber = tokenUUID.substr(19, 4) + tokenUUID.substr(24);
+ ByteString serial((const unsigned char*) serialNumber.c_str(), serialNumber.size());
+
+ // Create the token
+ OSToken* newToken = OSToken::createToken(storePath, tokenUUID, label, serial);
+
+ if (newToken != NULL)
+ {
+ tokens.push_back(newToken);
+ allTokens.push_back(newToken);
+ }
+
+ return newToken;
+}
+
+// Destroy a token
+bool ObjectStore::destroyToken(OSToken* token)
+{
+ MutexLocker lock(storeMutex);
+
+ // Find the token
+ for (std::vector<OSToken*>::iterator i = tokens.begin(); i != tokens.end(); i++)
+ {
+ if (*i == token)
+ {
+ // Found the token, now destroy the token
+ if (!token->clearToken())
+ {
+ ERROR_MSG("Failed to clear token instance");
+
+ return false;
+ }
+
+ // And remove it from the vector
+ tokens.erase(i);
+
+ return true;
+ }
+ }
+
+ ERROR_MSG("Could not find the token instance to destroy");
+
+ return false;
+}
+
diff --git a/src/lib/object_store/ObjectStore.h b/src/lib/object_store/ObjectStore.h
--- /dev/null
@@ -0,0 +1,90 @@
+/* $Id: ObjectStore.h 4874 2010-08-27 10:37:29Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStore.h
+
+ The object store manages the separate tokens that the SoftHSM supports. Each
+ token is organised as a directory containing files that are contain the
+ token's objects. The object store is initialised with a root directory from
+ which it enumerates the tokens.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTSTORE_H
+#define _SOFTHSM_V2_OBJECTSTORE_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "OSToken.h"
+#include "MutexFactory.h"
+#include <string>
+#include <vector>
+
+class ObjectStore
+{
+public:
+ // Constructor
+ ObjectStore(std::string storePath);
+
+ // Destructor
+ virtual ~ObjectStore();
+
+ // Return the number of tokens that is present
+ size_t getTokenCount();
+
+ // Return a pointer to the n-th token (counting starts at 0)
+ OSToken* getToken(size_t whichToken);
+
+ // Create a new token
+ OSToken* newToken(const ByteString& label);
+
+ // Destroy a token
+ bool destroyToken(OSToken* token);
+
+ // Check if the object store is valid
+ bool isValid();
+
+private:
+ // The tokens
+ std::vector<OSToken*> tokens;
+
+ // All tokens
+ std::vector<OSToken*> allTokens;
+
+ // The object store root directory
+ std::string storePath;
+
+ // The status
+ bool valid;
+
+ // Object store synchronisation
+ Mutex* storeMutex;
+};
+
+#endif // !_SOFTHSM_V2_OBJECTSTORE_H
+
diff --git a/src/lib/object_store/SessionObject.cpp b/src/lib/object_store/SessionObject.cpp
--- /dev/null
@@ -0,0 +1,213 @@
+/* $Id: SessionObject.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObject.cpp
+
+ This class implements session objects (i.e. objects that are non-persistent)
+ *****************************************************************************/
+
+#include "config.h"
+#include "SessionObject.h"
+#include "SessionObjectStore.h"
+
+// Constructor
+SessionObject::SessionObject(SessionObjectStore* parent, CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate)
+{
+ this->hSession = hSession;
+ this->slotID = slotID;
+ this->isPrivate = isPrivate;
+ objectMutex = MutexFactory::i()->getMutex();
+ valid = (objectMutex != NULL);
+ this->parent = parent;
+}
+
+// Destructor
+SessionObject::~SessionObject()
+{
+ discardAttributes();
+
+ MutexFactory::i()->recycleMutex(objectMutex);
+}
+
+// Check if the specified attribute exists
+bool SessionObject::attributeExists(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ return valid && (attributes[type] != NULL);
+}
+
+// Retrieve the specified attribute
+OSAttribute* SessionObject::getAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ return attributes[type];
+}
+
+// Set the specified attribute
+bool SessionObject::setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute)
+{
+ MutexLocker lock(objectMutex);
+
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot update invalid session object 0x%08X", this);
+
+ return false;
+ }
+
+ if (attributes[type] != NULL)
+ {
+ delete attributes[type];
+
+ attributes[type] = NULL;
+ }
+
+ attributes[type] = new OSAttribute(attribute);
+
+ return true;
+}
+
+// The validity state of the object
+bool SessionObject::isValid()
+{
+ return valid;
+}
+
+bool SessionObject::hasSlotID(CK_SLOT_ID slotID)
+{
+ return this->slotID == slotID;
+}
+
+// Called by the session object store when a session is closed. If it's the
+// session this object was associated with, the function returns true and the
+// object is invalidated
+bool SessionObject::removeOnSessionClose(CK_SESSION_HANDLE hSession)
+{
+ if (this->hSession == hSession)
+ {
+ // Save space
+ discardAttributes();
+
+ valid = false;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Called by the session object store when a token is logged out.
+// Remove when this session object is a private object for this token.
+bool SessionObject::removeOnAllSessionsClose(CK_SLOT_ID slotID)
+{
+ if (this->slotID == slotID)
+ {
+ discardAttributes();
+
+ valid = false;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Called by the session object store when a token is logged out.
+// Remove when this session object is a private object for this token.
+bool SessionObject::removeOnTokenLogout(CK_SLOT_ID slotID)
+{
+ if (this->slotID == slotID && this->isPrivate)
+ {
+ discardAttributes();
+
+ valid = false;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Discard the object's attributes
+void SessionObject::discardAttributes()
+{
+ MutexLocker lock(objectMutex);
+
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> cleanUp = attributes;
+ attributes.clear();
+
+ for (std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ delete i->second;
+ i->second = NULL;
+ }
+}
+
+// These functions are just stubs for session objects
+bool SessionObject::startTransaction()
+{
+ return true;
+}
+
+bool SessionObject::commitTransaction()
+{
+ return true;
+}
+
+bool SessionObject::abortTransaction()
+{
+ return true;
+}
+
+bool SessionObject::destroyObject()
+{
+ if (parent == NULL)
+ {
+ ERROR_MSG("Cannot destroy object that is not associated with a session object store");
+
+ return false;
+ }
+
+ return parent->deleteObject(this);
+}
+
+// Invalidate the object
+void SessionObject::invalidate()
+{
+ valid = false;
+ discardAttributes();
+}
+
diff --git a/src/lib/object_store/SessionObject.h b/src/lib/object_store/SessionObject.h
--- /dev/null
@@ -0,0 +1,125 @@
+/* $Id: SessionObject.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObject.h
+
+ This class implements session objects (i.e. objects that are non-persistent)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECT_H
+#define _SOFTHSM_V2_SESSIONOBJECT_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "OSAttribute.h"
+#include "MutexFactory.h"
+#include <string>
+#include <map>
+#include "cryptoki.h"
+#include "OSObject.h"
+
+// Forward declaration of the session object store
+class SessionObjectStore;
+
+class SessionObject : public OSObject
+{
+public:
+ // Constructor
+ SessionObject(SessionObjectStore* parent, CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate = false);
+
+ // Destructor
+ virtual ~SessionObject();
+
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the specified attribute
+ virtual OSAttribute* getAttribute(CK_ATTRIBUTE_TYPE type);
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute);
+
+ // The validity state of the object
+ virtual bool isValid();
+
+ bool hasSlotID(CK_SLOT_ID slotID);
+
+ // Called by the session object store when a session is closed. If it's the
+ // session this object was associated with, the function returns true and the
+ // object is invalidated
+ bool removeOnSessionClose(CK_SESSION_HANDLE hSession);
+
+ // Called by the session object store when all the sessions for a token
+ // have been closed.
+ bool removeOnAllSessionsClose(CK_SLOT_ID slotID);
+
+ // Called by the session object store when a token is logged out.
+ // Remove when this session object is a private object for this token.
+ bool removeOnTokenLogout(CK_SLOT_ID slotID);
+
+ // These functions are just stubs for session objects
+ virtual bool startTransaction();
+ virtual bool commitTransaction();
+ virtual bool abortTransaction();
+
+ // Destroys the object; WARNING: pointers to the object become invalid after this
+ // call!
+ virtual bool destroyObject();
+
+ // Invalidate the object
+ void invalidate();
+
+private:
+ // Discard the object's attributes
+ void discardAttributes();
+
+ // The object's raw attributes
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> attributes;
+
+ // The object's validity state
+ bool valid;
+
+ // Mutex object for thread-safeness
+ Mutex* objectMutex;
+
+ // The slotID of the object is associated with.
+ CK_SLOT_ID slotID;
+
+ // The session the object is associated with.
+ CK_SESSION_HANDLE hSession;
+
+ // Indicates whether this object is private
+ bool isPrivate;
+
+ // The parent SessionObjectStore
+ SessionObjectStore* parent;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECT_H
+
diff --git a/src/lib/object_store/SessionObjectStore.cpp b/src/lib/object_store/SessionObjectStore.cpp
--- /dev/null
@@ -0,0 +1,231 @@
+/* $Id: SessionObjectStore.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStore.cpp
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSAttributes.h"
+#include "OSAttribute.h"
+#include "SessionObject.h"
+#include "cryptoki.h"
+#include "SessionObjectStore.h"
+#include <vector>
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+
+#if HAVE_SOS_SINGLETON
+// The one-and-only instance
+/*static*/ std::auto_ptr<SessionObjectStore> SessionObjectStore::_instance(NULL);
+
+// Get the one-and-only instance
+/*static*/ SessionObjectStore* SessionObjectStore::i()
+{
+ if (!_instance.get())
+ {
+ _instance = std::auto_ptr<SessionObjectStore>(new SessionObjectStore());
+ }
+
+ return _instance.get();
+}
+#endif
+
+// Constructor
+SessionObjectStore::SessionObjectStore()
+{
+ storeMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SessionObjectStore::~SessionObjectStore()
+{
+ // Clean up
+ objects.clear();
+ std::set<SessionObject*> cleanUp = allObjects;
+ allObjects.clear();
+
+ for (std::set<SessionObject*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if ((*i) == NULL) continue;
+
+ SessionObject* that = *i;
+
+ delete that;
+ }
+
+ MutexFactory::i()->recycleMutex(storeMutex);
+}
+
+// Retrieve objects
+std::set<SessionObject*> SessionObjectStore::getObjects()
+{
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(storeMutex);
+
+ return objects;
+}
+
+void SessionObjectStore::getObjects(CK_SLOT_ID slotID, std::set<OSObject*> &objects)
+{
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*>::iterator it;
+ for (it=this->objects.begin(); it!=this->objects.end(); ++it) {
+ if ((*it)->hasSlotID(slotID))
+ objects.insert(*it);
+ }
+}
+
+// Create a new object
+SessionObject* SessionObjectStore::createObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate)
+{
+ // Create the new object file
+ SessionObject* newObject = new SessionObject(this, slotID, hSession, isPrivate);
+
+ if (!newObject->isValid())
+ {
+ ERROR_MSG("Failed to create new object");
+
+ delete newObject;
+
+ return NULL;
+ }
+
+ // Now add it to the set of objects
+ MutexLocker lock(storeMutex);
+
+ objects.insert(newObject);
+ allObjects.insert(newObject);
+
+ DEBUG_MSG("(0x%08X) Created new object (0x%08X)", this, newObject);
+
+ return newObject;
+}
+
+// Delete an object
+bool SessionObjectStore::deleteObject(SessionObject* object)
+{
+ if (objects.find(object) == objects.end())
+ {
+ ERROR_MSG("Cannot delete non-existent object 0x%08X", object);
+
+ return false;
+ }
+
+ MutexLocker lock(storeMutex);
+
+ // Invalidate the object instance
+ object->invalidate();
+
+ objects.erase(object);
+
+ return true;
+}
+
+// Indicate that a session has been closed; invalidates all objects
+// associated with this session
+void SessionObjectStore::sessionClosed(CK_SESSION_HANDLE hSession)
+{
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*> checkObjects = objects;
+
+ for (std::set<SessionObject*>::iterator i = checkObjects.begin(); i != checkObjects.end(); i++)
+ {
+ if ((*i)->removeOnSessionClose(hSession))
+ {
+ // Since the object remains in the allObjects set, any pointers to it will
+ // remain valid but it will no longer be returned when the set of objects
+ // is requested
+ objects.erase(*i);
+ }
+ }
+}
+
+void SessionObjectStore::allSessionsClosed(CK_SLOT_ID slotID)
+{
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*> checkObjects = objects;
+
+ for (std::set<SessionObject*>::iterator i = checkObjects.begin(); i != checkObjects.end(); i++)
+ {
+ if ((*i)->removeOnAllSessionsClose(slotID))
+ {
+ // Since the object remains in the allObjects set, any pointers to it will
+ // remain valid but it will no longer be returned when the set of objects
+ // is requested
+ objects.erase(*i);
+ }
+ }
+}
+
+void SessionObjectStore::tokenLoggedOut(CK_SLOT_ID slotID)
+{
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*> checkObjects = objects;
+
+ for (std::set<SessionObject*>::iterator i = checkObjects.begin(); i != checkObjects.end(); i++)
+ {
+ if ((*i)->removeOnTokenLogout(slotID))
+ {
+ // Since the object remains in the allObjects set, any pointers to it will
+ // remain valid but it will no longer be returned when the set of objects
+ // is requested
+ objects.erase(*i);
+ }
+ }
+}
+
+// Clear the whole store
+void SessionObjectStore::clearStore()
+{
+ MutexLocker lock(storeMutex);
+
+ objects.clear();
+ std::set<SessionObject*> clearObjects = allObjects;
+ allObjects.clear();
+
+ for (std::set<SessionObject*>::iterator i = clearObjects.begin(); i != clearObjects.end(); i++)
+ {
+ delete *i;
+ }
+}
+
diff --git a/src/lib/object_store/SessionObjectStore.h b/src/lib/object_store/SessionObjectStore.h
--- /dev/null
@@ -0,0 +1,115 @@
+/* $Id: SessionObjectStore.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStore.h
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTSTORE_H
+#define _SOFTHSM_V2_SESSIONOBJECTSTORE_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include "SessionObject.h"
+#include "MutexFactory.h"
+#include "cryptoki.h"
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+#include <memory>
+
+class SessionObjectStore
+{
+public:
+#if HAVE_SOS_SINGLETON
+ // Get the one-and-only instance
+ static SessionObjectStore* i();
+#else
+ // Constructor
+ SessionObjectStore();
+#endif
+
+ // Retrieve objects
+ std::set<SessionObject*> getObjects();
+
+ // Insert the session objects for the given slotID into the given OSObject set
+ void getObjects(CK_SLOT_ID slotID, std::set<OSObject*> &objects);
+
+ // Create a new object
+ SessionObject* createObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate = false);
+
+ // Delete an object
+ bool deleteObject(SessionObject* object);
+
+ // Indicate that a session has been closed; invalidates all objects
+ // associated with this session.
+ void sessionClosed(CK_SESSION_HANDLE hSession);
+
+ // Indicate that for a token all sessions have been closed.
+ // Invalidates all objects associated with the token.
+ void allSessionsClosed(CK_SLOT_ID slotID);
+
+ // Indicate that a token has been logged out; invalidates all private
+ // objects associated with this token.
+ void tokenLoggedOut(CK_SLOT_ID slotID);
+
+ // Destructor
+ virtual ~SessionObjectStore();
+
+ // Clears the store; should be called when all sessions are closed
+ void clearStore();
+
+private:
+#if HAVE_SOS_SINGLETON
+ // Constructor
+ SessionObjectStore();
+
+ // The one-and-only instance
+ static std::auto_ptr<SessionObjectStore> _instance;
+#endif
+
+ // The current objects in the store
+ std::set<SessionObject*> objects;
+
+ // All the objects ever kept in the store
+ std::set<SessionObject*> allObjects;
+
+ // The current list of files
+ std::set<std::string> currentFiles;
+
+ // For thread safeness
+ Mutex* storeMutex;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTSTORE_H
+
diff --git a/src/lib/object_store/UUID.cpp b/src/lib/object_store/UUID.cpp
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: UUID.cpp 4922 2010-11-22 12:25:09Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUID.cpp
+
+ UUID generation helper functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "UUID.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+// Generate a new UUID string
+std::string UUID::newUUID()
+{
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ ByteString uuid;
+
+ if (!rng->generateRandom(uuid, 16))
+ {
+ ERROR_MSG("Fatal, could not generate random UUID");
+
+ throw -1;
+ }
+
+ // Convert it to a string
+ char uuidStr[37];
+
+ sprintf(uuidStr, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5],
+ uuid[6], uuid[7],
+ uuid[8], uuid[9],
+ uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
+
+ return std::string(uuidStr);
+}
+
diff --git a/src/lib/object_store/UUID.h b/src/lib/object_store/UUID.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: UUID.h 4814 2010-06-24 10:17:40Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUID.h
+
+ UUID generation helper functions; for now, this just wraps the OSF/DCE's
+ UUID generation implementation, but if SoftHSM gets ported to non UNIX/BSD-
+ like OSes this may incorporate other implementations
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_UUID_H
+#define _SOFTHSM_V2_UUID_H
+
+#include "config.h"
+#include <string>
+
+namespace UUID
+{
+ // Generate a new UUID string
+ std::string newUUID();
+};
+
+#endif // !_SOFTHSM_V2_UUID_H
+
diff --git a/src/lib/object_store/test/DirectoryTests.cpp b/src/lib/object_store/test/DirectoryTests.cpp
--- /dev/null
@@ -0,0 +1,214 @@
+/* $Id: DirectoryTests.cpp 4814 2010-06-24 10:17:40Z rijswijk $
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DirectoryTests.cpp
+
+ Contains test cases to test the directory implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DirectoryTests.h"
+#include "Directory.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DirectoryTests);
+
+void DirectoryTests::setUp()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir2"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir3"));
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/afile"));
+ CPPUNIT_ASSERT(!system("echo someOtherStuff > testdir/anotherFile"));
+ CPPUNIT_ASSERT(!system("echo justStuff > testdir/justaFile"));
+}
+
+void DirectoryTests::tearDown()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+}
+
+void DirectoryTests::testDirectory()
+{
+ // FIXME: Path separator is not platform independent
+ Directory testdir("./testdir");
+
+ CPPUNIT_ASSERT(testdir.isValid());
+
+ std::vector<std::string> files = testdir.getFiles();
+ std::vector<std::string> subDirs = testdir.getSubDirs();
+
+ CPPUNIT_ASSERT(files.size() == 3);
+ CPPUNIT_ASSERT(subDirs.size() == 3);
+
+ CPPUNIT_ASSERT(testdir.refresh());
+
+ CPPUNIT_ASSERT(files.size() == 3);
+ CPPUNIT_ASSERT(subDirs.size() == 3);
+
+ bool fileSeen[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare("afile"))
+ {
+ fileSeen[0] = true;
+ }
+ else if (!i->compare("anotherFile"))
+ {
+ fileSeen[1] = true;
+ }
+ else if (!i->compare("justaFile"))
+ {
+ fileSeen[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(fileSeen[0] && fileSeen[1] && fileSeen[2]);
+
+ bool dirSeen[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen[0] = true;
+ }
+ else if (!i->compare("anotherdir2"))
+ {
+ dirSeen[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen[0] && dirSeen[1] && dirSeen[2]);
+
+ // Create a directory
+ CPPUNIT_ASSERT(testdir.mkdir("newDir"));
+
+ subDirs = testdir.getSubDirs();
+
+ bool dirSeen2[4] = { false, false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen2[0] = true;
+ }
+ else if (!i->compare("anotherdir2"))
+ {
+ dirSeen2[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen2[2] = true;
+ }
+ else if (!i->compare("newDir"))
+ {
+ dirSeen2[3] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen2[0] && dirSeen2[1] && dirSeen2[2] && dirSeen2[3]);
+
+ // Remove a directory
+ CPPUNIT_ASSERT(testdir.remove("anotherdir2"));
+
+ subDirs = testdir.getSubDirs();
+
+ bool dirSeen3[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen3[0] = true;
+ }
+ else if (!i->compare("newDir"))
+ {
+ dirSeen3[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen3[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen3[0] && dirSeen3[1] && dirSeen3[2]);
+
+ // Remove a file
+ CPPUNIT_ASSERT(testdir.remove("anotherFile"));
+
+ files = testdir.getFiles();
+
+ bool fileSeen2[2] = { false, false };
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare("afile"))
+ {
+ fileSeen2[0] = true;
+ }
+ else if (!i->compare("justaFile"))
+ {
+ fileSeen2[1] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(fileSeen2[0] && fileSeen2[1]);
+}
+
diff --git a/src/lib/object_store/test/DirectoryTests.h b/src/lib/object_store/test/DirectoryTests.h
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id: DirectoryTests.h 4815 2010-06-24 14:57:12Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DirectoryTests.h
+
+ Contains test cases to test the Directory implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIRECTORYTESTS_H
+#define _SOFTHSM_V2_DIRECTORYTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class DirectoryTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DirectoryTests);
+ CPPUNIT_TEST(testDirectory);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDirectory();
+
+ void setUp();
+ void tearDown();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DIRECTORYTESTS_H
+
diff --git a/src/lib/object_store/test/FileTests.cpp b/src/lib/object_store/test/FileTests.cpp
--- /dev/null
@@ -0,0 +1,272 @@
+/* $Id: FileTests.cpp 6799 2012-10-30 12:53:19Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FileTests.cpp
+
+ Contains test cases to test the file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "FileTests.h"
+#include "File.h"
+#include "Directory.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FileTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void FileTests::setUp()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ int rv = system("rm -rf testdir");
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void FileTests::tearDown()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+}
+
+void FileTests::testExistNotExist()
+{
+ // Test pre-condition
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+
+ // Attempt to open a file known not to exist
+ File doesntExist("testdir/nonExistentFile");
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+
+ // Attempt to open a file known to exist
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/existingFile"));
+ CPPUNIT_ASSERT(exists("existingFile"));
+
+ File exists("testdir/existingFile");
+
+ CPPUNIT_ASSERT(exists.isValid());
+}
+
+void FileTests::testCreateNotCreate()
+{
+ // Test pre-condition
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+ CPPUNIT_ASSERT(!exists("nonExistentFile2"));
+
+ // Attempt to open a file known not to exist
+ File doesntExist("testdir/nonExistentFile", true, true, false);
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+
+ // Attempt to open a file known not to exist in create mode
+ File willBeCreated("testdir/nonExistentFile2", true, true, true);
+
+ CPPUNIT_ASSERT(willBeCreated.isValid());
+ CPPUNIT_ASSERT(exists("nonExistentFile2"));
+}
+
+void FileTests::testLockUnlock()
+{
+ // Create pre-condition
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/existingFile"));
+ CPPUNIT_ASSERT(exists("existingFile"));
+
+ File file1("testdir/existingFile");
+ File file2("testdir/existingFile");
+
+ CPPUNIT_ASSERT(file1.lock(false));
+ CPPUNIT_ASSERT(!file1.lock(false));
+ CPPUNIT_ASSERT(file2.lock(false));
+ CPPUNIT_ASSERT(file2.unlock());
+ CPPUNIT_ASSERT(file1.unlock());
+ CPPUNIT_ASSERT(file1.lock());
+ CPPUNIT_ASSERT(file2.lock());
+ CPPUNIT_ASSERT(file2.unlock());
+ CPPUNIT_ASSERT(file1.unlock());
+}
+
+void FileTests::testWriteRead()
+{
+ // Generate some test data
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ ByteString testData1;
+
+ CPPUNIT_ASSERT(rng->generateRandom(testData1, 187));
+
+ // More test data
+ std::string testString = "This is a test of the File class";
+
+ // Create a file for writing
+ {
+ File newFile("testdir/newFile", false, true);
+
+ CPPUNIT_ASSERT(newFile.isValid());
+
+ // Write two booleans into the file
+ CPPUNIT_ASSERT(newFile.writeBool(true));
+ CPPUNIT_ASSERT(newFile.writeBool(false));
+
+ // Write an ulong into the file
+ CPPUNIT_ASSERT(newFile.writeULong(0x12345678));
+
+ // Write a ByteString into the file
+ CPPUNIT_ASSERT(newFile.writeByteString(testData1));
+
+ // Write a string into the file
+ CPPUNIT_ASSERT(newFile.writeString(testString));
+ }
+
+ CPPUNIT_ASSERT(exists("newFile"));
+
+ // Read the created file back
+ {
+ File newFile("testdir/newFile");
+
+ CPPUNIT_ASSERT(newFile.isValid());
+
+ // Read back the two booleans
+ bool b1, b2;
+
+ CPPUNIT_ASSERT(newFile.readBool(b1) && newFile.readBool(b2));
+ CPPUNIT_ASSERT(b1 && !b2);
+
+ // Read back the ulong
+ unsigned long ulongValue;
+
+ CPPUNIT_ASSERT(newFile.readULong(ulongValue));
+ CPPUNIT_ASSERT(ulongValue == 0x12345678);
+
+ // Read back the byte string
+ ByteString bsValue;
+
+ CPPUNIT_ASSERT(newFile.readByteString(bsValue));
+ CPPUNIT_ASSERT(bsValue == testData1);
+
+ // Read back the string value
+ std::string stringVal;
+
+ CPPUNIT_ASSERT(newFile.readString(stringVal));
+ CPPUNIT_ASSERT(!testString.compare(stringVal));
+
+ // Check for EOF
+ CPPUNIT_ASSERT(!newFile.readBool(b1));
+ CPPUNIT_ASSERT(newFile.isEOF());
+ }
+}
+
+void FileTests::testSeek()
+{
+ ByteString t1 = "112233445566778899"; // 9 long
+ ByteString t2 = "AABBCCDDEEFFAABBCCDDEEFF"; // 12 long
+
+ {
+ // Create the test file
+ File testFile("testdir/testFile", false, true, true);
+
+ CPPUNIT_ASSERT(testFile.isValid());
+
+ // Write the test data to the test file
+ CPPUNIT_ASSERT(testFile.writeByteString(t1) && testFile.writeByteString(t2));
+ }
+
+ // Open the test file for reading
+ File testFile("testdir/testFile");
+
+ CPPUNIT_ASSERT(testFile.isValid());
+
+ // First, read back the test data
+ ByteString tr1, tr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(tr1) && testFile.readByteString(tr2));
+ CPPUNIT_ASSERT(tr1 == t1);
+ CPPUNIT_ASSERT(tr2 == t2);
+
+ // Seek to the length field of the second byte string
+ CPPUNIT_ASSERT(testFile.seek(8+9));
+
+ // Read back the size as an ulong value
+ unsigned long value;
+ unsigned long expectedValue = (unsigned long)0x1122334455667788ULL;
+
+ CPPUNIT_ASSERT(testFile.readULong(value));
+ CPPUNIT_ASSERT(value == 12);
+
+ // Seek to the start of the first byte string's data
+ CPPUNIT_ASSERT(testFile.seek(8));
+
+ // Read back the ulong value stored there
+ CPPUNIT_ASSERT(testFile.readULong(value));
+
+ CPPUNIT_ASSERT(value == expectedValue);
+
+ // Seek to the start of second byte string
+ CPPUNIT_ASSERT(testFile.seek(8+9));
+
+ // Read it
+ ByteString trr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(trr2));
+ CPPUNIT_ASSERT(trr2 == t2);
+
+ // Rewind the file
+ CPPUNIT_ASSERT(testFile.rewind());
+
+ // Read back both byte strings
+ ByteString trrr1, trrr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(trrr1) && testFile.readByteString(trrr2));
+ CPPUNIT_ASSERT(trrr1 == t1);
+ CPPUNIT_ASSERT(trrr2 == t2);
+}
+
+bool FileTests::exists(std::string name)
+{
+ Directory dir("./testdir");
+
+ CPPUNIT_ASSERT(dir.isValid());
+
+ std::vector<std::string> files = dir.getFiles();
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare(name))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
diff --git a/src/lib/object_store/test/FileTests.h b/src/lib/object_store/test/FileTests.h
--- /dev/null
@@ -0,0 +1,65 @@
+/* $Id: FileTests.h 4817 2010-06-25 10:26:28Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FileTests.h
+
+ Contains test cases to test the File implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FILETESTS_H
+#define _SOFTHSM_V2_FILETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FileTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(FileTests);
+ CPPUNIT_TEST(testExistNotExist);
+ CPPUNIT_TEST(testCreateNotCreate);
+ CPPUNIT_TEST(testLockUnlock);
+ CPPUNIT_TEST(testWriteRead);
+ CPPUNIT_TEST(testSeek);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testExistNotExist();
+ void testCreateNotCreate();
+ void testLockUnlock();
+ void testWriteRead();
+ void testSeek();
+
+ void setUp();
+ void tearDown();
+
+private:
+ bool exists(std::string path);
+};
+
+#endif // !_SOFTHSM_V2_FILETESTS_H
+
diff --git a/src/lib/object_store/test/Makefile.am b/src/lib/object_store/test/Makefile.am
--- /dev/null
@@ -0,0 +1,33 @@
+# $Id: Makefile.am 6810 2012-11-01 14:21:55Z jerry $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../cryptoki_compat \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = objstoretest
+
+objstoretest_SOURCES = objstoretest.cpp \
+ DirectoryTests.cpp \
+ UUIDTests.cpp \
+ FileTests.cpp \
+ ObjectFileTests.cpp \
+ OSTokenTests.cpp \
+ ObjectStoreTests.cpp \
+ SessionObjectTests.cpp \
+ SessionObjectStoreTests.cpp
+
+objstoretest_LDADD = ../../libsofthsm_convarch.la
+
+objstoretest_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs` -pthread
+
+TESTS = objstoretest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/object_store/test/OSTokenTests.cpp b/src/lib/object_store/test/OSTokenTests.cpp
--- /dev/null
@@ -0,0 +1,444 @@
+/* $Id: OSTokenTests.cpp 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSTokenTests.cpp
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "OSTokenTests.h"
+#include "OSToken.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(OSTokenTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void OSTokenTests::setUp()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void OSTokenTests::tearDown()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+}
+
+void OSTokenTests::testNewToken()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ OSToken* newToken = OSToken::createToken("./testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED);
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED);
+
+ delete newToken;
+
+ // Now reopen the newly created token
+ OSToken reopenedToken("./testdir/newToken");
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED);
+}
+
+void OSTokenTests::testExistingToken()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+ ByteString soPIN = "31323334"; // 1234
+ ByteString userPIN = "30303030"; // 0000
+ ByteString id1 = "ABCDEF";
+ ByteString id2 = "FEDCBA";
+ ByteString id3 = "AABBCC";
+
+ {
+ // Create the token dir
+ CPPUNIT_ASSERT(!system("mkdir testdir/existingToken"));
+
+ // Create the token object
+ ObjectFile tokenObject(NULL, "./testdir/existingToken/tokenObject", true);
+
+ OSAttribute labelAtt(label);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENLABEL, labelAtt));
+ OSAttribute serialAtt(serial);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENSERIAL, serialAtt));
+ OSAttribute soPINAtt(soPIN);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_SOPIN, soPINAtt));
+ OSAttribute userPINAtt(userPIN);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_USERPIN, userPINAtt));
+ CK_ULONG flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED;
+ OSAttribute flagsAtt(flags);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENFLAGS, flagsAtt));
+
+ // Create 3 objects
+ ObjectFile obj1(NULL, "./testdir/existingToken/1.object", true);
+ ObjectFile obj2(NULL, "./testdir/existingToken/2.object", true);
+ ObjectFile obj3(NULL, "./testdir/existingToken/3.object", true);
+
+ OSAttribute id1Att(id1);
+ OSAttribute id2Att(id2);
+ OSAttribute id3Att(id3);
+
+ CPPUNIT_ASSERT(obj1.setAttribute(CKA_ID, id1));
+ CPPUNIT_ASSERT(obj2.setAttribute(CKA_ID, id2));
+ CPPUNIT_ASSERT(obj3.setAttribute(CKA_ID, id3));
+ }
+
+ // Now open the token
+ OSToken existingToken("./testdir/existingToken");
+
+ CPPUNIT_ASSERT(existingToken.isValid());
+
+ // Retrieve SO PIN, user PIN, label, serial number and flags
+ ByteString retrievedSOPIN, retrievedUserPIN, retrievedLabel, retrievedSerial;
+ CK_ULONG flags;
+
+ CPPUNIT_ASSERT(existingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(existingToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(existingToken.getTokenLabel(retrievedLabel));
+ CPPUNIT_ASSERT(existingToken.getTokenSerial(retrievedSerial));
+ CPPUNIT_ASSERT(existingToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(retrievedLabel == label);
+ CPPUNIT_ASSERT(retrievedSerial == serial);
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED);
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT(existingToken.getObjects().size() == 3);
+
+ // Check that all the tokens are presented
+ bool present[3] = { false, false, false };
+ std::set<ObjectFile*> objects = existingToken.getObjects();
+
+ for (std::set<ObjectFile*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id1)
+ {
+ present[0] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id2)
+ {
+ present[1] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id3)
+ {
+ present[2] = true;
+ }
+ }
+
+ CPPUNIT_ASSERT(present[0] == true);
+ CPPUNIT_ASSERT(present[1] == true);
+ CPPUNIT_ASSERT(present[2] == true);
+}
+
+void OSTokenTests::testNonExistentToken()
+{
+ OSToken doesntExist("./testdir/doesntExist");
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+}
+
+void OSTokenTests::testCreateDeleteObjects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Instantiate a new token
+ OSToken* testToken = OSToken::createToken("./testdir", "testToken", label, serial);
+
+ CPPUNIT_ASSERT(testToken != NULL);
+ CPPUNIT_ASSERT(testToken->isValid());
+
+ // Open the same token
+ OSToken sameToken("./testdir/testToken");
+
+ CPPUNIT_ASSERT(sameToken.isValid());
+
+ // Create 3 objects on the token
+ ObjectFile* obj1 = testToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ ObjectFile* obj2 = testToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ ObjectFile* obj3 = testToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT(testToken->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<ObjectFile*> objects = testToken->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<ObjectFile*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now check that the same objects are present in the other instance of the same token
+ std::set<ObjectFile*> otherObjects = sameToken.getObjects();
+ CPPUNIT_ASSERT(otherObjects.size() == 3);
+
+ bool present2[3] = { false, false, false };
+
+ for (std::set<ObjectFile*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[j])
+ {
+ present2[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present2[j] == true);
+ }
+
+ // Now delete the second object
+ for (std::set<ObjectFile*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testToken->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(testToken->getObjects().size() == 2);
+
+ objects = testToken->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<ObjectFile*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ // Now check the other instance
+ CPPUNIT_ASSERT(sameToken.getObjects().size() == 2);
+
+ otherObjects = sameToken.getObjects();
+ bool present4[2] = { false, false };
+
+ for (std::set<ObjectFile*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[0])
+ {
+ present4[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[2])
+ {
+ present4[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present4[j] == true);
+ }
+
+
+ // Release the test token
+ delete testToken;
+}
+
+void OSTokenTests::testClearToken()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ OSToken* newToken = OSToken::createToken("./testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED);
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED);
+
+ delete newToken;
+
+ // Now reopen the newly created token
+ OSToken reopenedToken("./testdir/newToken");
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(flags == CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED);
+
+ // Now clear the token
+ CPPUNIT_ASSERT(reopenedToken.clearToken());
+ CPPUNIT_ASSERT(!reopenedToken.isValid());
+
+ // Try to open it once more
+ OSToken clearedToken("./testdir/newToken");
+
+ CPPUNIT_ASSERT(!clearedToken.isValid());
+}
+
diff --git a/src/lib/object_store/test/OSTokenTests.h b/src/lib/object_store/test/OSTokenTests.h
--- /dev/null
@@ -0,0 +1,62 @@
+/* $Id: OSTokenTests.h 4874 2010-08-27 10:37:29Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSTokenTests.h
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSTOKENTESTS_H
+#define _SOFTHSM_V2_OSTOKENTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class OSTokenTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(OSTokenTests);
+ CPPUNIT_TEST(testNewToken);
+ CPPUNIT_TEST(testExistingToken);
+ CPPUNIT_TEST(testNonExistentToken);
+ CPPUNIT_TEST(testCreateDeleteObjects);
+ CPPUNIT_TEST(testClearToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testNewToken();
+ void testExistingToken();
+ void testNonExistentToken();
+ void testCreateDeleteObjects();
+ void testClearToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OSTOKENTESTS_H
+
diff --git a/src/lib/object_store/test/ObjectFileTests.cpp b/src/lib/object_store/test/ObjectFileTests.cpp
--- /dev/null
@@ -0,0 +1,636 @@
+/* $Id: ObjectFileTests.cpp 6775 2012-10-25 06:47:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectObjectFileTests.cpp
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectFileTests.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectFileTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void ObjectFileTests::setUp()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void ObjectFileTests::tearDown()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+}
+
+void ObjectFileTests::testBoolAttr()
+{
+ // Create the test object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+ }
+
+ // Now read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID) == NULL);
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE)->getBooleanValue() == false);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN)->getBooleanValue() == false);
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY)->getBooleanValue() == value6);
+ }
+}
+
+void ObjectFileTests::testULongAttr()
+{
+ // Create the test object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUB_PRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+ }
+
+ // Now read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUB_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUB_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE)->isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS)->getUnsignedLongValue() == 0x12345678);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS)->getUnsignedLongValue() == 0x01010101);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUB_PRIME_BITS)->getUnsignedLongValue() == 0x10101010);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE)->getUnsignedLongValue() == 0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS)->getUnsignedLongValue() == value6);
+ }
+}
+
+void ObjectFileTests::testByteStrAttr()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ // Create the test object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+ }
+
+ // Now read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS)->getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT)->getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT)->getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER)->getByteStringValue() == value6);
+ }
+}
+
+void ObjectFileTests::testMixedAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ // Create the test object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ }
+
+ // Now read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+ }
+}
+
+void ObjectFileTests::testDoubleAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+
+ // Create the test object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ }
+
+ // Now read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+ }
+
+ // Now re-read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+ }
+}
+
+void ObjectFileTests::testRefresh()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+
+ // Create the test object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ }
+
+ // Now read back the object
+ {
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ // Open the object a second time
+ ObjectFile testObject2(NULL, "testdir/testobject");
+
+ // Check the attributes on the second instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ // Add an attribute on the second object
+ ByteString id = "0102010201020102010201020102010201020102";
+
+ OSAttribute attr4(id);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID)->getByteStringValue() == id);
+
+ // Now check that the first instance also knows about it
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID)->getByteStringValue() == id);
+
+ // Now change another attribute
+ unsigned long value2a = 0x89898989;
+
+ OSAttribute attr2a(value2a);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+
+ // Now check that the second instance also knows about the change
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ }
+}
+
+void ObjectFileTests::testCorruptFile()
+{
+ CPPUNIT_ASSERT(system("dd if=/dev/urandom of=testdir/testobject bs=13 count=24") != -1);
+
+ ObjectFile testObject(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(!testObject.isValid());
+}
+
+void ObjectFileTests::testTransactions()
+{
+ // Create test object instance
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ // Create secondary instance for the same object
+ ObjectFile testObject2(NULL, "testdir/testobject");
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check that it has the same attributes
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ // New values
+ bool value1a = false;
+ unsigned long value2a = 0x12345678;
+ ByteString value3a = "ABABABABABABABABABABABABABABAB";
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction());
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ // Commit the transaction
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ // Verify that they have now changed on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction());
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ // Abort the transaction
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+
+ // Verify that they are unchanged on both instances
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+}
+
+void ObjectFileTests::testDestroyObjectFails()
+{
+ // Create test object instance
+ ObjectFile testObject(NULL, "testdir/testobject", true);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSObject* testIF = (OSObject*) &testObject;
+
+ CPPUNIT_ASSERT(!testIF->destroyObject());
+}
+
diff --git a/src/lib/object_store/test/ObjectFileTests.h b/src/lib/object_store/test/ObjectFileTests.h
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: ObjectFileTests.h 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFileTests.h
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTFILETESTS_H
+#define _SOFTHSM_V2_OBJECTFILETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectFileTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectFileTests);
+ CPPUNIT_TEST(testBoolAttr);
+ CPPUNIT_TEST(testULongAttr);
+ CPPUNIT_TEST(testByteStrAttr);
+ CPPUNIT_TEST(testMixedAttr);
+ CPPUNIT_TEST(testDoubleAttr);
+ CPPUNIT_TEST(testRefresh);
+ CPPUNIT_TEST(testCorruptFile);
+ CPPUNIT_TEST(testTransactions);
+ CPPUNIT_TEST(testDestroyObjectFails);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBoolAttr();
+ void testULongAttr();
+ void testByteStrAttr();
+ void testMixedAttr();
+ void testDoubleAttr();
+ void testRefresh();
+ void testCorruptFile();
+ void testTransactions();
+ void testDestroyObjectFails();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OBJECTFILETESTS_H
+
diff --git a/src/lib/object_store/test/ObjectStoreTests.cpp b/src/lib/object_store/test/ObjectStoreTests.cpp
--- /dev/null
@@ -0,0 +1,250 @@
+/* $Id: ObjectStoreTests.cpp 4874 2010-08-27 10:37:29Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectStoreTests.h"
+#include "ObjectStore.h"
+#include "OSToken.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStoreTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void ObjectStoreTests::setUp()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void ObjectStoreTests::tearDown()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+}
+
+void ObjectStoreTests::testEmptyStore()
+{
+ // Create the store for an empty dir
+ ObjectStore store("./testdir");
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 0);
+}
+
+void ObjectStoreTests::testNewTokens()
+{
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ {
+ // Create an empty store
+ ObjectStore store("./testdir");
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 0);
+
+ // Create a new token
+ OSToken* token1 = store.newToken(label1);
+
+ CPPUNIT_ASSERT(token1 != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 1);
+
+ // Create another new token
+ OSToken* token2 = store.newToken(label2);
+
+ CPPUNIT_ASSERT(token2 != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+ }
+
+ // Now reopen that same store
+ ObjectStore store("./testdir");
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ OSToken* token1 = store.getToken(0);
+ OSToken* token2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2;
+
+ CPPUNIT_ASSERT(token1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(token2->getTokenLabel(retrieveLabel2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel2 == label1));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+
+ ByteString retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(token1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(token2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
+
+void ObjectStoreTests::testExistingTokens()
+{
+ // Create some tokens
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+ ByteString serial1 = "0011001100110011";
+ ByteString serial2 = "2233223322332233";
+
+ OSToken* token1 = OSToken::createToken("./testdir", "token1", label1, serial1);
+ OSToken* token2 = OSToken::createToken("./testdir", "token2", label2, serial2);
+
+ CPPUNIT_ASSERT((token1 != NULL) && (token2 != NULL));
+
+ delete token1;
+ delete token2;
+
+ // Now associate a store with the test directory
+ ObjectStore store("./testdir");
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ OSToken* retrieveToken1 = store.getToken(0);
+ OSToken* retrieveToken2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2, retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(retrieveToken1 != NULL);
+ CPPUNIT_ASSERT(retrieveToken2 != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel1 == label2));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+ CPPUNIT_ASSERT((retrieveSerial1 == serial1) || (retrieveSerial1 == serial2));
+ CPPUNIT_ASSERT((retrieveSerial2 == serial1) || (retrieveSerial2 == serial2));
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
+
+void ObjectStoreTests::testDeleteToken()
+{
+ // Create some tokens
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+ ByteString serial1 = "0011001100110011";
+ ByteString serial2 = "2233223322332233";
+
+ OSToken* token1 = OSToken::createToken("./testdir", "token1", label1, serial1);
+ OSToken* token2 = OSToken::createToken("./testdir", "token2", label2, serial2);
+
+ CPPUNIT_ASSERT((token1 != NULL) && (token2 != NULL));
+
+ delete token1;
+ delete token2;
+
+ // Now associate a store with the test directory
+ ObjectStore store("./testdir");
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ OSToken* retrieveToken1 = store.getToken(0);
+ OSToken* retrieveToken2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2, retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(retrieveToken1 != NULL);
+ CPPUNIT_ASSERT(retrieveToken2 != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel1 == label2));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+ CPPUNIT_ASSERT((retrieveSerial1 == serial1) || (retrieveSerial1 == serial2));
+ CPPUNIT_ASSERT((retrieveSerial2 == serial1) || (retrieveSerial2 == serial2));
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+
+ // Now, delete token #1
+ CPPUNIT_ASSERT(store.destroyToken(retrieveToken1));
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 1);
+
+ OSToken* retrieveToken_ = store.getToken(0);
+
+ ByteString retrieveLabel_,retrieveSerial_;
+
+ CPPUNIT_ASSERT(retrieveToken_->getTokenLabel(retrieveLabel_));
+ CPPUNIT_ASSERT(retrieveToken_->getTokenSerial(retrieveSerial_));
+
+ CPPUNIT_ASSERT(((retrieveLabel_ == label1) && (retrieveSerial_ == serial1)) ||
+ ((retrieveLabel_ == label2) && (retrieveSerial_ == serial2)));
+
+ // Now add a new token
+ ByteString label3 = "DEADC0FFEEBEEF";
+
+ // Create a new token
+ OSToken* tokenNew = store.newToken(label3);
+
+ CPPUNIT_ASSERT(tokenNew != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ OSToken* retrieveToken1_ = store.getToken(0);
+ OSToken* retrieveToken2_ = store.getToken(1);
+
+ CPPUNIT_ASSERT(retrieveToken1_ != NULL);
+ CPPUNIT_ASSERT(retrieveToken2_ != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1_->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2_->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1_->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2_->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label3) || (retrieveLabel2 == label3));
+ CPPUNIT_ASSERT(((retrieveLabel1 == label1) && (retrieveLabel2 != label2)) ||
+ ((retrieveLabel1 == label2) && (retrieveLabel2 != label1)));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+}
+
diff --git a/src/lib/object_store/test/ObjectStoreTests.h b/src/lib/object_store/test/ObjectStoreTests.h
--- /dev/null
@@ -0,0 +1,60 @@
+/* $Id: ObjectStoreTests.h 4874 2010-08-27 10:37:29Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreTests.h
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTSTORETESTS_H
+#define _SOFTHSM_V2_OBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectStoreTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectStoreTests);
+ CPPUNIT_TEST(testEmptyStore);
+ CPPUNIT_TEST(testNewTokens);
+ CPPUNIT_TEST(testExistingTokens);
+ CPPUNIT_TEST(testDeleteToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testEmptyStore();
+ void testNewTokens();
+ void testExistingTokens();
+ void testDeleteToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OBJECTSTORETESTS_H
+
diff --git a/src/lib/object_store/test/SessionObjectStoreTests.cpp b/src/lib/object_store/test/SessionObjectStoreTests.cpp
--- /dev/null
@@ -0,0 +1,322 @@
+/* $Id: SessionObjectStoreTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStoreTests.cpp
+
+ Contains test cases to test the session object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <memory>
+#include "SessionObjectStoreTests.h"
+#include "SessionObjectStore.h"
+#include "SessionObject.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionObjectStoreTests);
+
+void SessionObjectStoreTests::setUp()
+{
+#if HAVE_SOS_SINGLETON
+ // Clear the session object store
+ SessionObjectStore::i()->clearStore();
+#endif
+}
+
+void SessionObjectStoreTests::tearDown()
+{
+}
+
+void SessionObjectStoreTests::testCreateDeleteObjects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Get access to the session object store
+ std::auto_ptr<SessionObjectStore> testStore( new SessionObjectStore );
+
+ CPPUNIT_ASSERT(testStore.get() != NULL);
+
+ // Create 3 objects in the store
+ SessionObject* obj1 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the store contains 3 objects
+ CPPUNIT_ASSERT(testStore->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<SessionObject*> objects = testStore->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now delete the second object
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testStore->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(testStore->getObjects().size() == 2);
+
+ objects = testStore->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+}
+
+void SessionObjectStoreTests::testMultiSession()
+{
+ // Get access to the store
+ std::auto_ptr<SessionObjectStore> store( new SessionObjectStore );
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+
+ // Create 3 objects in the store for three different sessions
+ SessionObject* obj1 = store->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = store->createObject(1, 2);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = store->createObject(1, 3);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the store contains 3 objects
+ CPPUNIT_ASSERT(store->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<SessionObject*> objects = store->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now indicate that the second session has been closed
+ store->sessionClosed(2);
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(store->getObjects().size() == 2);
+
+ objects = store->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID)->isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID)->getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ // Create two more objects for session 7
+ SessionObject* obj4 = store->createObject(1, 7);
+ CPPUNIT_ASSERT(obj4 != NULL);
+ SessionObject* obj5 = store->createObject(1, 7);
+ CPPUNIT_ASSERT(obj5 != NULL);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 4);
+
+ // Close session 1
+ store->sessionClosed(1);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 3);
+
+ objects = store->getObjects();
+
+ CPPUNIT_ASSERT(objects.find(obj1) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj2) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj3) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj4) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj5) != objects.end());
+
+ CPPUNIT_ASSERT(!obj1->isValid());
+ CPPUNIT_ASSERT(!obj2->isValid());
+ CPPUNIT_ASSERT(obj3->isValid());
+ CPPUNIT_ASSERT(obj4->isValid());
+ CPPUNIT_ASSERT(obj5->isValid());
+
+ // Close session 7
+ store->sessionClosed(7);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 1);
+
+ objects = store->getObjects();
+
+ CPPUNIT_ASSERT(objects.find(obj1) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj2) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj3) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj4) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj5) == objects.end());
+
+ CPPUNIT_ASSERT(!obj1->isValid());
+ CPPUNIT_ASSERT(!obj2->isValid());
+ CPPUNIT_ASSERT(obj3->isValid());
+ CPPUNIT_ASSERT(!obj4->isValid());
+ CPPUNIT_ASSERT(!obj5->isValid());
+}
+
+void SessionObjectStoreTests::testWipeStore()
+{
+ // Get access to the store
+ std::auto_ptr<SessionObjectStore> store( new SessionObjectStore );
+
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ // Create 3 objects in the store for three different sessions
+ SessionObject* obj1 = store->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = store->createObject(1, 2);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = store->createObject(1, 3);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Wipe the store
+ store->clearStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+}
+
diff --git a/src/lib/object_store/test/SessionObjectStoreTests.h b/src/lib/object_store/test/SessionObjectStoreTests.h
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: SessionObjectStoreTests.h 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStoreTests.h
+
+ Contains test cases to test the session object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+#define _SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionObjectStoreTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionObjectStoreTests);
+ CPPUNIT_TEST(testCreateDeleteObjects);
+ CPPUNIT_TEST(testMultiSession);
+ CPPUNIT_TEST(testWipeStore);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCreateDeleteObjects();
+ void testMultiSession();
+ void testWipeStore();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+
diff --git a/src/lib/object_store/test/SessionObjectTests.cpp b/src/lib/object_store/test/SessionObjectTests.cpp
--- /dev/null
@@ -0,0 +1,365 @@
+/* $Id: SessionObjectTests.cpp 6775 2012-10-25 06:47:07Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectTests.cpp
+
+ Contains test cases to test the session object implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionObjectTests.h"
+#include "SessionObject.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionObjectTests);
+
+void SessionObjectTests::setUp()
+{
+}
+
+void SessionObjectTests::tearDown()
+{
+}
+
+void SessionObjectTests::testBoolAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID) == NULL);
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE)->getBooleanValue() == false);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN)->getBooleanValue() == false);
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY)->getBooleanValue() == value6);
+}
+
+void SessionObjectTests::testULongAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUB_PRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUB_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUB_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE)->isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS)->getUnsignedLongValue() == 0x12345678);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS)->getUnsignedLongValue() == 0x01010101);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUB_PRIME_BITS)->getUnsignedLongValue() == 0x10101010);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE)->getUnsignedLongValue() == 0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS)->getUnsignedLongValue() == value6);
+}
+
+void SessionObjectTests::testByteStrAttr()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS)->getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT)->getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT)->getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER)->isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER)->getByteStringValue() == value6);
+}
+
+void SessionObjectTests::testMixedAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+}
+
+void SessionObjectTests::testDoubleAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ bool value1a = false;
+ unsigned long value2a = 0x76767676;
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3a);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+}
+
+void SessionObjectTests::testCloseSession()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS)->getByteStringValue() == value3);
+
+ // Now close the session
+ testObject.removeOnSessionClose(1);
+
+ CPPUNIT_ASSERT(!testObject.isValid());
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_VALUE_BITS));
+}
+
+void SessionObjectTests::testDestroyObjectFails()
+{
+ // Create test object instance
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSObject* testIF = (OSObject*) &testObject;
+
+ CPPUNIT_ASSERT(!testIF->destroyObject());
+}
+
diff --git a/src/lib/object_store/test/SessionObjectTests.h b/src/lib/object_store/test/SessionObjectTests.h
--- /dev/null
@@ -0,0 +1,66 @@
+/* $Id: SessionObjectTests.h 4934 2011-01-04 16:14:33Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectTests.h
+
+ Contains test cases to test the session object implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTTESTS_H
+#define _SOFTHSM_V2_SESSIONOBJECTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionObjectTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionObjectTests);
+ CPPUNIT_TEST(testBoolAttr);
+ CPPUNIT_TEST(testULongAttr);
+ CPPUNIT_TEST(testByteStrAttr);
+ CPPUNIT_TEST(testMixedAttr);
+ CPPUNIT_TEST(testDoubleAttr);
+ CPPUNIT_TEST(testCloseSession);
+ CPPUNIT_TEST(testDestroyObjectFails);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBoolAttr();
+ void testULongAttr();
+ void testByteStrAttr();
+ void testMixedAttr();
+ void testDoubleAttr();
+ void testCloseSession();
+ void testDestroyObjectFails();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTTESTS_H
+
diff --git a/src/lib/object_store/test/UUIDTests.cpp b/src/lib/object_store/test/UUIDTests.cpp
--- /dev/null
@@ -0,0 +1,63 @@
+/* $Id: UUIDTests.cpp 4814 2010-06-24 10:17:40Z rijswijk $
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUIDTests.cpp
+
+ Contains test cases to test the UUID implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "UUIDTests.h"
+#include "UUID.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(UUIDTests);
+
+void UUIDTests::setUp()
+{
+}
+
+void UUIDTests::tearDown()
+{
+}
+
+void UUIDTests::testUUID()
+{
+ std::string uuid1 = UUID::newUUID();
+ std::string uuid2 = UUID::newUUID();
+ std::string uuid3 = UUID::newUUID();
+
+ CPPUNIT_ASSERT((uuid1.size() == 36) && (uuid2.size() == 36) && (uuid3.size() == 36));
+
+ CPPUNIT_ASSERT(uuid1.compare(uuid2));
+ CPPUNIT_ASSERT(uuid1.compare(uuid3));
+ CPPUNIT_ASSERT(uuid2.compare(uuid3));
+}
+
diff --git a/src/lib/object_store/test/UUIDTests.h b/src/lib/object_store/test/UUIDTests.h
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id: UUIDTests.h 4815 2010-06-24 14:57:12Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUIDTests.h
+
+ Contains test cases to test the UUID implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_UUIDTESTS_H
+#define _SOFTHSM_V2_UUIDTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class UUIDTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(UUIDTests);
+ CPPUNIT_TEST(testUUID);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testUUID();
+
+ void setUp();
+ void tearDown();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_UUIDTESTS_H
+
diff --git a/src/lib/object_store/test/objstoretest.cpp b/src/lib/object_store/test/objstoretest.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: objstoretest.cpp 6738 2012-10-15 21:28:14Z rb $
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ objstoretest.cpp
+
+ The main test executor for tests on the object store in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/session_mgr/Makefile.am b/src/lib/session_mgr/Makefile.am
--- /dev/null
@@ -0,0 +1,19 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../slot_mgr \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/..
+
+noinst_LTLIBRARIES = libsofthsm_sessionmgr.la
+libsofthsm_sessionmgr_la_SOURCES = SessionManager.cpp \
+ Session.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/session_mgr/Session.cpp b/src/lib/session_mgr/Session.cpp
--- /dev/null
@@ -0,0 +1,305 @@
+/* $Id: Session.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Session.h
+
+ This class represents a single session
+ *****************************************************************************/
+
+#include "CryptoFactory.h"
+#include "Session.h"
+
+// Constructor
+Session::Session(Slot* slot, bool isReadWrite, CK_VOID_PTR pApplication, CK_NOTIFY notify)
+{
+ this->slot = slot;
+ this->token = slot->getToken();
+ this->isReadWrite = isReadWrite;
+ hSession = CK_INVALID_HANDLE;
+ this->pApplication = pApplication;
+ this->notify = notify;
+ operation = SESSION_OP_NONE;
+ findOp = NULL;
+ digestOp = NULL;
+ asymmetricCryptoOp = NULL;
+ publicKey = NULL;
+ privateKey = NULL;
+}
+
+// Constructor
+Session::Session()
+{
+ slot = NULL;
+ token = NULL;
+ isReadWrite = false;
+ hSession = CK_INVALID_HANDLE;
+ pApplication = NULL;
+ notify = NULL;
+ operation = SESSION_OP_NONE;
+ findOp = NULL;
+ digestOp = NULL;
+ asymmetricCryptoOp = NULL;
+ publicKey = NULL;
+ privateKey = NULL;
+}
+
+// Destructor
+Session::~Session()
+{
+ resetOp();
+}
+
+// Get session info
+CK_RV Session::getInfo(CK_SESSION_INFO_PTR pInfo)
+{
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ pInfo->slotID = slot->getSlotID();
+
+ pInfo->state = getState();
+ pInfo->flags = CKF_SERIAL_SESSION;
+ if (isRW())
+ {
+ pInfo->flags |= CKF_RW_SESSION;
+ }
+ pInfo->ulDeviceError = 0;
+
+ return CKR_OK;
+}
+
+// Is a read and write session
+bool Session::isRW()
+{
+ return isReadWrite;
+}
+
+// Get session state
+CK_STATE Session::getState()
+{
+ if (token->isSOLoggedIn())
+ {
+ return CKS_RW_SO_FUNCTIONS;
+ }
+
+ if (token->isUserLoggedIn())
+ {
+ if (isRW())
+ {
+ return CKS_RW_USER_FUNCTIONS;
+ }
+ else
+ {
+ return CKS_RO_USER_FUNCTIONS;
+ }
+ }
+
+ if (isRW())
+ {
+ return CKS_RW_PUBLIC_SESSION;
+ }
+ else
+ {
+ return CKS_RO_PUBLIC_SESSION;
+ }
+}
+
+void Session::setHandle(CK_SESSION_HANDLE hSession)
+{
+ this->hSession = hSession;
+}
+
+CK_SESSION_HANDLE Session::getHandle()
+{
+ return hSession;
+}
+
+// Return the slot that the session is connected to
+Slot* Session::getSlot()
+{
+ return slot;
+}
+
+// Return the token that the session is connected to
+Token* Session::getToken()
+{
+ return token;
+}
+
+// Set the operation type
+void Session::setOpType(int operation)
+{
+ this->operation = operation;
+}
+
+// Get the operation type
+int Session::getOpType()
+{
+ return operation;
+}
+
+// Reset the operations
+void Session::resetOp()
+{
+ if (digestOp != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(digestOp);
+ digestOp = NULL;
+ }
+ else
+ {
+ if (findOp != NULL)
+ {
+ findOp->recycle();
+ findOp = NULL;
+ }
+ else
+ {
+ if (asymmetricCryptoOp != NULL)
+ {
+ if (publicKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePublicKey(publicKey);
+ publicKey = NULL;
+ }
+ if (privateKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePrivateKey(privateKey);
+ privateKey = NULL;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymmetricCryptoOp);
+ asymmetricCryptoOp = NULL;
+ }
+ }
+ }
+
+ operation = SESSION_OP_NONE;
+}
+
+void Session::setFindOp(FindOperation *findOp)
+{
+ if (this->findOp != NULL) {
+ delete this->findOp;
+ }
+ this->findOp = findOp;
+}
+
+FindOperation *Session::getFindOp()
+{
+ return findOp;
+}
+
+// Set the digesting operator
+void Session::setDigestOp(HashAlgorithm* digestOp)
+{
+ if (this->digestOp != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(this->digestOp);
+ }
+
+ this->digestOp = digestOp;
+}
+
+// Get the digesting operator
+HashAlgorithm* Session::getDigestOp()
+{
+ return digestOp;
+}
+
+void Session::setAsymmetricCryptoOp(AsymmetricAlgorithm *asymmetricCryptoOp)
+{
+ if (this->asymmetricCryptoOp != NULL)
+ {
+ setPublicKey(NULL);
+ setPrivateKey(NULL);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymmetricCryptoOp);
+ }
+
+ this->asymmetricCryptoOp = asymmetricCryptoOp;
+}
+
+AsymmetricAlgorithm *Session::getAsymmetricCryptoOp()
+{
+ return asymmetricCryptoOp;
+}
+
+void Session::setMechanism(const char *mechanism)
+{
+ this->mechanism = mechanism;
+}
+
+const char *Session::getMechanism()
+{
+ return mechanism;
+}
+
+void Session::setIsMultiPartOp(bool isMultiPartOp)
+{
+ this->isMultiPartOp = isMultiPartOp;
+}
+
+bool Session::getIsMultiPartOp()
+{
+ return isMultiPartOp;
+}
+
+void Session::setPublicKey(PublicKey* publicKey)
+{
+ if (asymmetricCryptoOp == NULL)
+ return;
+
+ if (this->publicKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePublicKey(publicKey);
+ }
+
+ this->publicKey = publicKey;
+}
+
+PublicKey* Session::getPublicKey()
+{
+ return publicKey;
+}
+
+void Session::setPrivateKey(PrivateKey* privateKey)
+{
+ if (asymmetricCryptoOp == NULL)
+ return;
+
+ if (this->privateKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePrivateKey(privateKey);
+ }
+
+ this->privateKey = privateKey;
+}
+
+PrivateKey* Session::getPrivateKey()
+{
+ return privateKey;
+}
diff --git a/src/lib/session_mgr/Session.h b/src/lib/session_mgr/Session.h
--- /dev/null
@@ -0,0 +1,138 @@
+/* $Id: Session.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Session.h
+
+ This class represents a single session
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSION_H
+#define _SOFTHSM_V2_SESSION_H
+
+#include "Slot.h"
+#include "FindOperation.h"
+#include "HashAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "Token.h"
+#include "cryptoki.h"
+
+#define SESSION_OP_NONE 0x0
+#define SESSION_OP_FIND 0x1
+#define SESSION_OP_ENCRYPT 0x2
+#define SESSION_OP_DECRYPT 0x3
+#define SESSION_OP_DIGEST 0x4
+#define SESSION_OP_SIGN 0x5
+#define SESSION_OP_VERIFY 0x6
+#define SESSION_OP_DIGEST_ENCRYPT 0x7
+#define SESSION_OP_DECRYPT_DIGEST 0x8
+#define SESSION_OP_SIGN_ENCRYPT 0x9
+#define SESSION_OP_DECRYPT_VERIFY 0x10
+
+class Session
+{
+public:
+ Session(Slot* slot, bool isReadWrite, CK_VOID_PTR pApplication, CK_NOTIFY notify);
+
+ // Destructor
+ virtual ~Session();
+
+ // Slot and token
+ Slot* getSlot();
+ Token* getToken();
+
+ // Session properties
+ CK_RV getInfo(CK_SESSION_INFO_PTR pInfo);
+ bool isRW();
+ CK_STATE getState();
+ void setHandle(CK_SESSION_HANDLE hSession);
+ CK_SESSION_HANDLE getHandle();
+
+ // Operations
+ int getOpType();
+ void setOpType(int operation);
+ void resetOp();
+
+ // Find
+ void setFindOp(FindOperation *findOp);
+ FindOperation *getFindOp();
+
+ // Digest
+ void setDigestOp(HashAlgorithm* digestOp);
+ HashAlgorithm* getDigestOp();
+
+ // Asymetric Crypto
+ void setAsymmetricCryptoOp(AsymmetricAlgorithm* asymmetricCryptoOp);
+ AsymmetricAlgorithm* getAsymmetricCryptoOp();
+
+ void setMechanism(const char *mechanism);
+ const char *getMechanism();
+
+ void setIsMultiPartOp(bool isMultiPartOp);
+ bool getIsMultiPartOp();
+
+ void setPublicKey(PublicKey* publicKey);
+ PublicKey* getPublicKey();
+
+ void setPrivateKey(PrivateKey* privateKey);
+ PrivateKey* getPrivateKey();
+
+private:
+ // Constructor
+ Session();
+
+ // Slot and token
+ Slot* slot;
+ Token* token;
+
+ // Application data (not in use)
+ CK_VOID_PTR pApplication;
+ CK_NOTIFY notify;
+
+ // Session properties
+ bool isReadWrite;
+ CK_SESSION_HANDLE hSession;
+
+ // Operations
+ int operation;
+
+ // Find
+ FindOperation *findOp;
+
+ // Digest
+ HashAlgorithm* digestOp;
+
+ // Asymetric Crypto
+ AsymmetricAlgorithm* asymmetricCryptoOp;
+ const char * mechanism;
+ bool isMultiPartOp;
+ PublicKey* publicKey;
+ PrivateKey* privateKey;
+};
+
+#endif // !_SOFTHSM_V2_SESSION_H
diff --git a/src/lib/session_mgr/SessionManager.cpp b/src/lib/session_mgr/SessionManager.cpp
--- /dev/null
@@ -0,0 +1,248 @@
+/* $Id: SessionManager.cpp 4950 2011-03-29 08:07:48Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManager.cpp
+
+ Keeps track of the sessions within SoftHSM. The sessions are stored in a
+ vector. When a session is closed, its spot in the vector will be replaced
+ with NULL. Because we want to keep track of the session ID which is
+ equal to its location in the vector. New sessions will first fill up the NULL
+ locations and if there is no empty spots, then they are added to the end.
+ *****************************************************************************/
+
+#include "SessionManager.h"
+#include "log.h"
+
+// Constructor
+SessionManager::SessionManager()
+{
+ sessionsMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SessionManager::~SessionManager()
+{
+ std::vector<Session*> toDelete = sessions;
+ sessions.clear();
+
+ for (std::vector<Session*>::iterator i = toDelete.begin(); i != toDelete.end(); i++)
+ {
+ if (*i != NULL) delete *i;
+ }
+
+ MutexFactory::i()->recycleMutex(sessionsMutex);
+}
+
+// Open a new session
+CK_RV SessionManager::openSession
+(
+ Slot* slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR pApplication,
+ CK_NOTIFY notify,
+ CK_SESSION_HANDLE_PTR phSession
+)
+{
+ if (phSession == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+ if ((flags & CKF_SERIAL_SESSION) == 0) return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+ if (!token->isInitialized()) return CKR_TOKEN_NOT_RECOGNIZED;
+
+ // Can not open a Read-Only session when in SO mode
+ if ((flags & CKF_RW_SESSION) == 0 && token->isSOLoggedIn()) return CKR_SESSION_READ_WRITE_SO_EXISTS;
+
+ // TODO: Do we want to check for maximum number of sessions?
+ // return CKR_SESSION_COUNT
+
+ // Create the session
+ bool rwSession = ((flags & CKF_RW_SESSION) == CKF_RW_SESSION) ? true : false;
+ Session* session = new Session(slot, rwSession, pApplication, notify);
+
+ // First fill any empty spot in the list
+ for (int i = 0; i < sessions.size(); i++)
+ {
+ if (sessions[i] != NULL)
+ {
+ continue;
+ }
+
+ sessions[i] = session;
+ session->setHandle(i + 1);
+ *phSession = session->getHandle();
+
+ return CKR_OK;
+ }
+
+ // Or add it to the end
+ sessions.push_back(session);
+ session->setHandle(sessions.size());
+ *phSession = session->getHandle();
+
+ return CKR_OK;
+}
+
+// Close a session
+CK_RV SessionManager::closeSession(CK_SESSION_HANDLE hSession)
+{
+ if (hSession == CK_INVALID_HANDLE) return CKR_SESSION_HANDLE_INVALID;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Check if we are out of range
+ if (hSession > sessions.size()) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if it is a closed session
+ unsigned long sessionID = hSession - 1;
+ if (sessions[sessionID] == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if this is the last session on the token
+ bool lastSession = true;
+ CK_ULONG slotID = sessions[sessionID]->getSlot()->getSlotID();
+ for (int i = 0; i < sessions.size(); i++)
+ {
+ if (sessions[i] == NULL) continue;
+
+ if (sessions[i]->getSlot()->getSlotID() == slotID && i != sessionID)
+ {
+ lastSession = false;
+ break;
+ }
+ }
+
+ // Logout if this is the last session on the token
+ if (lastSession)
+ {
+ sessions[sessionID]->getSlot()->getToken()->logout();
+ }
+
+ // Close the session
+ delete sessions[sessionID];
+ sessions[sessionID] = NULL;
+
+ return CKR_OK;
+}
+
+// Close all sessions
+CK_RV SessionManager::closeAllSessions(Slot* slot)
+{
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+
+ // Close all sessions on this slot
+ CK_ULONG slotID = slot->getSlotID();
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() == slotID)
+ {
+ delete *i;
+ *i = NULL;
+ }
+ }
+
+ // Logout from the token
+ token->logout();
+
+ return CKR_OK;
+}
+
+// Get session info
+CK_RV SessionManager::getSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ // Get the session
+ Session* session = getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return session->getInfo(pInfo);
+}
+
+// Get the session
+Session* SessionManager::getSession(CK_SESSION_HANDLE hSession)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // We do not want to get a negative number below
+ if (hSession == CK_INVALID_HANDLE) return NULL;
+
+ // Check if we are out of range
+ if (hSession > sessions.size()) return NULL;
+
+ return sessions[hSession - 1];
+}
+
+bool SessionManager::haveSession(size_t slotID)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() == slotID)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SessionManager::haveROSession(size_t slotID)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() != slotID) continue;
+
+ if ((*i)->isRW() == false) return true;
+ }
+
+ return false;
+}
diff --git a/src/lib/session_mgr/SessionManager.h b/src/lib/session_mgr/SessionManager.h
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id: SessionManager.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManager.h
+
+ Keeps track of the sessions within SoftHSM
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONMANAGER_H
+#define _SOFTHSM_V2_SESSIONMANAGER_H
+
+#include "Slot.h"
+#include "Session.h"
+#include "MutexFactory.h"
+#include "config.h"
+#include "cryptoki.h"
+#include <memory>
+#include <vector>
+
+class SessionManager
+{
+public:
+ SessionManager();
+
+ virtual ~SessionManager();
+
+ CK_RV openSession(Slot* slot, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession);
+ CK_RV closeSession(CK_SESSION_HANDLE hSession);
+ CK_RV closeAllSessions(Slot* slot);
+ CK_RV getSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo);
+ Session* getSession(CK_SESSION_HANDLE hSession);
+ bool haveSession(size_t slotID);
+ bool haveROSession(size_t slotID);
+
+private:
+ // The sessions
+ std::vector<Session*> sessions;
+ Mutex* sessionsMutex;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONMANAGER_H
+
diff --git a/src/lib/session_mgr/test/Makefile.am b/src/lib/session_mgr/test/Makefile.am
--- /dev/null
@@ -0,0 +1,27 @@
+# $Id: Makefile.am 6810 2012-11-01 14:21:55Z jerry $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../cryptoki_compat \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ -I$(srcdir)/../../object_store \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = sessionmgrtest
+
+sessionmgrtest_SOURCES = sessionmgrtest.cpp \
+ SessionManagerTests.cpp
+
+sessionmgrtest_LDADD = ../../libsofthsm_convarch.la
+
+sessionmgrtest_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs` -pthread
+
+TESTS = sessionmgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/session_mgr/test/SessionManagerTests.cpp b/src/lib/session_mgr/test/SessionManagerTests.cpp
--- /dev/null
@@ -0,0 +1,59 @@
+/* $Id: SessionManagerTests.cpp 4900 2010-09-17 11:17:22Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManagerTests.cpp
+
+ Contains test cases for SessionManager
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionManagerTests.h"
+#include "SessionManager.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionManagerTests);
+
+void SessionManagerTests::setUp()
+{
+}
+
+void SessionManagerTests::tearDown()
+{
+}
+
+void SessionManagerTests::testOpenClose()
+{
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv;
+
+ // rv = SessionManager::i()->openSession()
+ // CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/src/lib/session_mgr/test/SessionManagerTests.h b/src/lib/session_mgr/test/SessionManagerTests.h
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: SessionManagerTests.h 4900 2010-09-17 11:17:22Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManagerTests.h
+
+ Contains test cases for SessionManager
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONMANAGERTESTS_H
+#define _SOFTHSM_V2_SESSIONMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionManagerTests);
+ CPPUNIT_TEST(testOpenClose);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testOpenClose();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONMANAGERTESTS_H
diff --git a/src/lib/session_mgr/test/sessionmgrtest.cpp b/src/lib/session_mgr/test/sessionmgrtest.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: sessionmgrtest.cpp 6738 2012-10-15 21:28:14Z rb $
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ sessionmgrtest.cpp
+
+ The main test executor for tests on the session manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/slot_mgr/Makefile.am b/src/lib/slot_mgr/Makefile.am
--- /dev/null
@@ -0,0 +1,20 @@
+# $Id: Makefile.am 32 2010-03-05 13:10:43Z rb $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../session_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/..
+
+noinst_LTLIBRARIES = libsofthsm_slotmgr.la
+libsofthsm_slotmgr_la_SOURCES = SlotManager.cpp \
+ Slot.cpp \
+ Token.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/slot_mgr/Slot.cpp b/src/lib/slot_mgr/Slot.cpp
--- /dev/null
@@ -0,0 +1,116 @@
+/* $Id: Slot.cpp 4910 2010-09-28 17:05:35Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Slot.h
+
+ This class represents a single PKCS #11 slot
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "SessionManager.h"
+#include "SlotManager.h"
+#include "Token.h"
+#include <stdio.h>
+#include <string.h>
+
+// Constructor
+Slot::Slot(ObjectStore* objectStore, size_t slotID, OSToken* token /* = NULL */)
+{
+ this->objectStore = objectStore;
+ this->slotID = slotID;
+
+ if (token != NULL)
+ {
+ this->token = new Token(token);
+ }
+ else
+ {
+ this->token = new Token();
+ }
+}
+
+// Destructor
+Slot::~Slot()
+{
+ delete token;
+}
+
+// Retrieve the token in the slot
+Token* Slot::getToken()
+{
+ return token;
+}
+
+// Initialise the token in the slot
+CK_RV Slot::initToken(ByteString& soPIN, CK_UTF8CHAR_PTR label)
+{
+ return token->createToken(objectStore, soPIN, label);
+}
+
+// Retrieve slot information for the slot
+CK_RV Slot::getSlotInfo(CK_SLOT_INFO_PTR info)
+{
+ if (info == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ char description[65];
+ char mfgID[33];
+
+ snprintf(description, 65, "SoftHSM slot %d", (int) slotID);
+ snprintf(mfgID, 33, "SoftHSM project");
+
+ memset(info->slotDescription, ' ', 64);
+ memset(info->manufacturerID, ' ', 32);
+ strncpy((char*) info->slotDescription, description, strlen(description));
+ strncpy((char*) info->manufacturerID, mfgID, strlen(mfgID));
+
+ info->flags = CKF_TOKEN_PRESENT;
+
+ info->hardwareVersion.major = VERSION_MAJOR;
+ info->hardwareVersion.minor = VERSION_MINOR;
+ info->firmwareVersion.major = VERSION_MAJOR;
+ info->firmwareVersion.minor = VERSION_MINOR;
+
+ return CKR_OK;
+}
+
+// Get the slot ID
+size_t Slot::getSlotID()
+{
+ return slotID;
+}
+
+// Is a token present?
+bool Slot::isTokenPresent()
+{
+ return true;
+}
diff --git a/src/lib/slot_mgr/Slot.h b/src/lib/slot_mgr/Slot.h
--- /dev/null
+++ b/src/lib/slot_mgr/Slot.h
@@ -0,0 +1,83 @@
+/* $Id: Slot.h 4910 2010-09-28 17:05:35Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Slot.h
+
+ This class represents a single PKCS #11 slot
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOT_H
+#define _SOFTHSM_V2_SLOT_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "OSToken.h"
+#include "Token.h"
+#include "cryptoki.h"
+#include <string>
+#include <vector>
+
+class Slot
+{
+public:
+ // Constructor
+ Slot(ObjectStore* objectStore, size_t slotID, OSToken* token = NULL);
+
+ // Destructor
+ virtual ~Slot();
+
+ // Retrieve the token in the slot
+ Token* getToken();
+
+ // Initialise the token in the slot
+ CK_RV initToken(ByteString& pin, CK_UTF8CHAR_PTR label);
+
+ // Retrieve slot information for the slot
+ CK_RV getSlotInfo(CK_SLOT_INFO_PTR info);
+
+ // Get the slot ID
+ size_t getSlotID();
+
+ // Is a token present?
+ bool isTokenPresent();
+
+private:
+ // A reference to the object store
+ ObjectStore* objectStore;
+
+ // The token in the slot
+ Token* token;
+
+ // The slot ID
+ size_t slotID;
+};
+
+#endif // !_SOFTHSM_V2_SLOT_H
+
diff --git a/src/lib/slot_mgr/SlotManager.cpp b/src/lib/slot_mgr/SlotManager.cpp
--- /dev/null
@@ -0,0 +1,133 @@
+/* $Id: SlotManager.cpp 4877 2010-08-30 16:21:24Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManager.cpp
+
+ The slot manager is a class that forms part of the PKCS #11 core. It manages
+ all the slots that SoftHSM is aware of. To make it possible to add new
+ tokens, SoftHSM always has one slot available that contains an uninitialised
+ token. Users can choose to initialise this token to create a new token.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "SlotManager.h"
+
+// Constructor
+SlotManager::SlotManager(ObjectStore* objectStore)
+{
+ // Add a slot for each token that already exists
+ for (size_t i = 0; i < objectStore->getTokenCount(); i++)
+ {
+ Slot* newSlot = new Slot(objectStore, i, objectStore->getToken(i));
+ slots.push_back(newSlot);
+ }
+
+ // Add an empty slot
+ slots.push_back(new Slot(objectStore, objectStore->getTokenCount()));
+}
+
+// Destructor
+SlotManager::~SlotManager()
+{
+ std::vector<Slot*> toDelete = slots;
+ slots.clear();
+
+ for (std::vector<Slot*>::iterator i = toDelete.begin(); i != toDelete.end(); i++)
+ {
+ delete *i;
+ }
+}
+
+// Get the slot list
+CK_RV SlotManager::getSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ CK_ULONG size = 0;
+
+ if (pulCount == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Calculate the size of the list
+ for (std::vector<Slot*>::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((tokenPresent == CK_FALSE) || (*i)->isTokenPresent())
+ {
+ size++;
+ }
+ }
+
+ // The user wants the size of the list
+ if (pSlotList == NULL)
+ {
+ *pulCount = size;
+
+ return CKR_OK;
+ }
+
+ // Is the given buffer too small?
+ if (*pulCount < size)
+ {
+ *pulCount = size;
+
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ size = 0;
+
+ for (std::vector<Slot*>::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((tokenPresent == CK_FALSE) || (*i)->isTokenPresent())
+ {
+ pSlotList[size++] = (CK_ULONG)(*i)->getSlotID();
+ }
+ }
+
+ *pulCount = size;
+
+ return CKR_OK;
+}
+
+// Get the slots
+std::vector<Slot*> SlotManager::getSlots()
+{
+ return slots;
+}
+
+// Get one slot
+Slot* SlotManager::getSlot(CK_SLOT_ID slotID)
+{
+ for (std::vector<Slot*>::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((*i)->getSlotID() == slotID)
+ {
+ return *i;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/lib/slot_mgr/SlotManager.h b/src/lib/slot_mgr/SlotManager.h
--- /dev/null
@@ -0,0 +1,71 @@
+/* $Id: SlotManager.h 4867 2010-08-25 10:08:17Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManager.h
+
+ The slot manager is a class that forms part of the PKCS #11 core. It manages
+ all the slots that SoftHSM is aware of. To make it possible to add new
+ tokens, SoftHSM always has one slot available that contains an uninitialised
+ token. Users can choose to initialise this token to create a new token.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOTMANAGER_H
+#define _SOFTHSM_V2_SLOTMANAGER_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "Slot.h"
+#include <string>
+#include <vector>
+
+class SlotManager
+{
+public:
+ // Constructor
+ SlotManager(ObjectStore* objectStore);
+
+ // Destructor
+ virtual ~SlotManager();
+
+ // Get the slots
+ std::vector<Slot*> getSlots();
+
+ // Get the slot list
+ CK_RV getSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+
+ // Get one slot
+ Slot* getSlot(CK_SLOT_ID slotID);
+private:
+ // The slots
+ std::vector<Slot*> slots;
+};
+
+#endif // !_SOFTHSM_V2_SLOTMANAGER_H
+
diff --git a/src/lib/slot_mgr/Token.cpp b/src/lib/slot_mgr/Token.cpp
--- /dev/null
@@ -0,0 +1,512 @@
+/* $Id: Token.cpp 6727 2012-10-09 14:55:27Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "log.h"
+#include "ObjectStore.h"
+#include "Token.h"
+#include "OSAttribute.h"
+#include "ByteString.h"
+#include "SecureDataManager.h"
+
+#include <sys/time.h>
+
+// Constructor
+Token::Token()
+{
+ tokenMutex = MutexFactory::i()->getMutex();
+
+ token = NULL;
+ sdm = NULL;
+ valid = false;
+}
+
+// Constructor
+Token::Token(OSToken* token)
+{
+ tokenMutex = MutexFactory::i()->getMutex();
+
+ this->token = token;
+
+ ByteString soPINBlob, userPINBlob;
+
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ sdm = new SecureDataManager(soPINBlob, userPINBlob);
+}
+
+// Destructor
+Token::~Token()
+{
+ if (sdm != NULL) delete sdm;
+
+ MutexFactory::i()->recycleMutex(tokenMutex);
+}
+
+// Check if the token is still valid
+bool Token::isValid()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ return (valid && token->isValid());
+}
+
+// Check if the token is initialized
+bool Token::isInitialized()
+{
+ if (token == NULL) return false;
+
+ return true;
+}
+
+// Check if SO is logged in
+bool Token::isSOLoggedIn()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->isSOLoggedIn();
+}
+
+// Check if user is logged in
+bool Token::isUserLoggedIn()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->isUserLoggedIn();
+}
+
+// Login SO
+CK_RV Token::loginSO(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // User cannot be logged in
+ if (sdm->isUserLoggedIn()) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ // SO cannot be logged in
+ if (sdm->isSOLoggedIn()) return CKR_USER_ALREADY_LOGGED_IN;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Login
+ if (!sdm->loginSO(pin))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_OK;
+}
+
+// Login user
+CK_RV Token::loginUser(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // SO cannot be logged in
+ if (sdm->isSOLoggedIn()) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ // User cannot be logged in
+ if (sdm->isUserLoggedIn()) return CKR_USER_ALREADY_LOGGED_IN;
+
+ // The user PIN has to be initialized;
+ if (sdm->getUserPINBlob().size() == 0) return CKR_USER_PIN_NOT_INITIALIZED;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Login
+ if (!sdm->loginUser(pin))
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_OK;
+}
+
+// Logout any user on this token;
+void Token::logout()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return;
+
+ sdm->logout();
+}
+
+// Change SO PIN
+CK_RV Token::setSOPIN(ByteString& oldPIN, ByteString& newPIN)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify oldPIN
+ SecureDataManager* verifier = new SecureDataManager(sdm->getSOPINBlob(), sdm->getUserPINBlob());
+ bool result = verifier->loginSO(oldPIN);
+ delete verifier;
+ if (result == false)
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ if (sdm->setSOPIN(newPIN) == false) return CKR_GENERAL_ERROR;
+
+ // Save PIN to token file
+ if (token->setSOPIN(sdm->getSOPINBlob()) == false) return CKR_GENERAL_ERROR;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ return CKR_OK;
+}
+
+// Change the user PIN
+CK_RV Token::setUserPIN(ByteString& oldPIN, ByteString& newPIN)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Check if user should stay logged in
+ bool stayLoggedIn = sdm->isUserLoggedIn();
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify oldPIN
+ SecureDataManager* newSdm = new SecureDataManager(sdm->getSOPINBlob(), sdm->getUserPINBlob());
+ if (newSdm->loginUser(oldPIN) == false)
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ delete newSdm;
+ return CKR_PIN_INCORRECT;
+ }
+
+ // Set the new user PIN
+ if (newSdm->setUserPIN(newPIN) == false)
+ {
+ delete newSdm;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Save PIN to token file
+ if (token->setUserPIN(newSdm->getUserPINBlob()) == false)
+ {
+ delete newSdm;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Restore previous login state
+ if (!stayLoggedIn) newSdm->logout();
+
+ // Switch sdm
+ delete sdm;
+ sdm = newSdm;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ return CKR_OK;
+}
+
+// Init the user PIN
+CK_RV Token::initUserPIN(ByteString& pin)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ if (sdm->setUserPIN(pin) == false) return CKR_GENERAL_ERROR;
+
+ // Save PIN to token file
+ if (token->setUserPIN(sdm->getUserPINBlob()) == false) return CKR_GENERAL_ERROR;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ return CKR_OK;
+}
+
+// Create a new token
+CK_RV Token::createToken(ObjectStore* objectStore, ByteString& soPIN, CK_UTF8CHAR_PTR label)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (objectStore == NULL) return CKR_GENERAL_ERROR;
+ if (label == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ if (token != NULL)
+ {
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (sdm->getSOPINBlob().size() > 0 && !sdm->loginSO(soPIN))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ ERROR_MSG("Incorrect SO PIN");
+ return CKR_PIN_INCORRECT;
+ }
+
+ // The token is already initialised. Destroy it first.
+ if (!objectStore->destroyToken(token))
+ {
+ ERROR_MSG("Failed to destroy existing token");
+ return CKR_DEVICE_ERROR;
+ }
+
+ token = NULL;
+ }
+
+ // Generate the SO PIN blob
+ SecureDataManager soPINBlobGen;
+
+ if (!soPINBlobGen.setSOPIN(soPIN))
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Convert the label
+ ByteString labelByteStr((const unsigned char*) label, 32);
+
+ // Create the token
+ OSToken* newToken = objectStore->newToken(labelByteStr);
+
+ if (newToken == NULL)
+ {
+ return CKR_DEVICE_ERROR;
+ }
+
+ // Set the SO PIN on the token
+ if (!newToken->setSOPIN(soPINBlobGen.getSOPINBlob()))
+ {
+ ERROR_MSG("Failed to set SO PIN on new token");
+
+ if (!objectStore->destroyToken(newToken))
+ {
+ ERROR_MSG("Failed to destroy incomplete token");
+ }
+
+ return CKR_DEVICE_ERROR;
+ }
+
+ token = newToken;
+
+ ByteString soPINBlob, userPINBlob;
+
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ if (sdm != NULL) delete sdm;
+ sdm = new SecureDataManager(soPINBlob, userPINBlob);
+
+ return CKR_OK;
+}
+
+// Retrieve token information for the token
+CK_RV Token::getTokenInfo(CK_TOKEN_INFO_PTR info)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ ByteString label, serial;
+
+ if (info == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ memset(info->label, ' ', 32);
+ memset(info->serialNumber, ' ', 16);
+
+ // Token specific information
+ if (token)
+ {
+ if (!token->getTokenFlags(info->flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (token->getTokenLabel(label))
+ {
+ strncpy((char*) info->label, (char*) label.byte_str(), label.size());
+ }
+
+ if (token->getTokenSerial(serial))
+ {
+ strncpy((char*) info->serialNumber, (char*) serial.byte_str(), serial.size());
+ }
+ }
+ else
+ {
+ info->flags = CKF_RNG |
+ CKF_LOGIN_REQUIRED |
+ CKF_RESTORE_KEY_NOT_NEEDED |
+ CKF_SO_PIN_LOCKED |
+ CKF_SO_PIN_TO_BE_CHANGED;
+ }
+
+ // Information shared by all tokens
+ char mfgID[33];
+ char model[17];
+
+ snprintf(mfgID, 33, "SoftHSM project");
+ snprintf(model, 17, "SoftHSM v2");
+
+ memset(info->manufacturerID, ' ', 32);
+ memset(info->model, ' ', 16);
+ strncpy((char*) info->manufacturerID, mfgID, strlen(mfgID));
+ strncpy((char*) info->model, model, strlen(model));
+
+ // TODO: Can we set these?
+ info->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
+ info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
+
+ info->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxPinLen = MAX_PIN_LEN;
+ info->ulMinPinLen = MIN_PIN_LEN;
+ info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->hardwareVersion.major = VERSION_MAJOR;
+ info->hardwareVersion.minor = VERSION_MINOR;
+ info->firmwareVersion.major = VERSION_MAJOR;
+ info->firmwareVersion.minor = VERSION_MINOR;
+
+ // Current time
+ time_t rawtime;
+ time(&rawtime);
+ char dateTime[17];
+ strftime(dateTime, 17, "%Y%m%d%H%M%S00", gmtime(&rawtime));
+ memcpy(info->utcTime, dateTime, 16);
+
+ return CKR_OK;
+}
+
+// Create an object
+ObjectFile* Token::createObject()
+{
+ return token->createObject();
+}
+
+void Token::getObjects(std::set<OSObject *> &objects)
+{
+ token->getObjects(objects);
+}
+
+bool Token::decrypt(const ByteString &encrypted, ByteString &plaintext)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->decrypt(encrypted,plaintext);
+}
+
+bool Token::encrypt(const ByteString &plaintext, ByteString &encrypted)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->encrypt(plaintext,encrypted);
+}
diff --git a/src/lib/slot_mgr/Token.h b/src/lib/slot_mgr/Token.h
--- /dev/null
+++ b/src/lib/slot_mgr/Token.h
@@ -0,0 +1,111 @@
+/* $Id: Token.h 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Token.h
+
+ This class represents a single PKCS #11 token
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TOKEN_H
+#define _SOFTHSM_V2_TOKEN_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "OSToken.h"
+#include "SecureDataManager.h"
+#include "cryptoki.h"
+#include <string>
+#include <vector>
+
+class Token
+{
+public:
+ // Constructor
+ Token();
+ Token(OSToken* token);
+
+ // Destructor
+ virtual ~Token();
+
+ // Create a new token
+ CK_RV createToken(ObjectStore* objectStore, ByteString& soPIN, CK_UTF8CHAR_PTR label);
+
+ // Is the token valid?
+ bool isValid();
+
+ // Is the token initialized?
+ bool isInitialized();
+
+ // Is SO or user logged in?
+ bool isSOLoggedIn();
+ bool isUserLoggedIn();
+
+ // Login
+ CK_RV loginSO(ByteString& pin);
+ CK_RV loginUser(ByteString& pin);
+
+ // Logout any user on this token;
+ void logout();
+
+ // Change PIN
+ CK_RV setSOPIN(ByteString& oldPIN, ByteString& newPIN);
+ CK_RV setUserPIN(ByteString& oldPIN, ByteString& newPIN);
+ CK_RV initUserPIN(ByteString& pin);
+
+ // Retrieve token information for the token
+ CK_RV getTokenInfo(CK_TOKEN_INFO_PTR info);
+
+ // Create object
+ ObjectFile* createObject();
+
+ // Insert all token objects into the given set.
+ void getObjects(std::set<OSObject *> &objects);
+
+ // Decrypt the supplied data
+ bool decrypt(const ByteString& encrypted, ByteString& plaintext);
+
+ // Encrypt the supplied data
+ bool encrypt(const ByteString& plaintext, ByteString& encrypted);
+
+private:
+ // Token validity
+ bool valid;
+
+ // A reference to the object store token
+ OSToken* token;
+
+ // The secure data manager for this token
+ SecureDataManager* sdm;
+
+ Mutex* tokenMutex;
+};
+
+#endif // !_SOFTHSM_V2_TOKEN_H
+
diff --git a/src/lib/slot_mgr/test/Makefile.am b/src/lib/slot_mgr/test/Makefile.am
--- /dev/null
@@ -0,0 +1,26 @@
+# $Id: Makefile.am 6810 2012-11-01 14:21:55Z jerry $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../cryptoki_compat \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../data_mgr \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = slotmgrtest
+
+slotmgrtest_SOURCES = slotmgrtest.cpp \
+ SlotManagerTests.cpp
+
+slotmgrtest_LDADD = ../../libsofthsm_convarch.la
+
+slotmgrtest_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs` -pthread
+
+TESTS = slotmgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/src/lib/slot_mgr/test/SlotManagerTests.cpp b/src/lib/slot_mgr/test/SlotManagerTests.cpp
--- /dev/null
@@ -0,0 +1,378 @@
+/* $Id: SlotManagerTests.cpp 4910 2010-09-28 17:05:35Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManagerTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SlotManagerTests.h"
+#include "SlotManager.h"
+#include "Token.h"
+#include "ObjectStore.h"
+#include "OSToken.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SlotManagerTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void SlotManagerTests::setUp()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void SlotManagerTests::tearDown()
+{
+ // FIXME: this only works on *NIX/BSD, not on other platforms
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+}
+
+void SlotManagerTests::testNoExistingTokens()
+{
+ // Create an empty object store
+ ObjectStore store("./testdir");
+
+ // Create the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotID() == testList[0]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testExistingTokens()
+{
+ // Create an empty object store
+ ObjectStore store("./testdir");
+
+ // Create two tokens
+ ByteString label1 = "DEADBEEF";
+ ByteString label2 = "DEADC0FFEE";
+
+ CPPUNIT_ASSERT(store.newToken(label1) != NULL);
+ CPPUNIT_ASSERT(store.newToken(label2) != NULL);
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 3);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotID() == testList[1]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getSlotID() == testList[2]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testInitialiseTokenInLastSlot()
+{
+ {
+ // Create an empty object store
+ ObjectStore store("./testdir");
+
+ // Create the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotID() == testList[0]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Now initialise the token in the first slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->initToken(soPIN, label) == CKR_OK);
+
+ // Retrieve slot information about the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+ }
+
+ // Attach a fresh slot manager
+ ObjectStore store("./testdir");
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 2);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotID() == testList[1]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testReinitialiseExistingToken()
+{
+ // Create an empty object store
+ ObjectStore store("./testdir");
+
+ // Create two tokens
+ ByteString label1 = "DEADBEEF";
+ ByteString label2 = "DEADC0FFEE";
+
+ CPPUNIT_ASSERT(store.newToken(label1) != NULL);
+ CPPUNIT_ASSERT(store.newToken(label2) != NULL);
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 3);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotID() == testList[1]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getSlotID() == testList[2]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[0]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[2]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Now reinitialise the token in the second slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->initToken(soPIN, label) == CKR_OK);
+
+ // Retrieve slot information about the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[1]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+}
+
diff --git a/src/lib/slot_mgr/test/SlotManagerTests.h b/src/lib/slot_mgr/test/SlotManagerTests.h
--- /dev/null
@@ -0,0 +1,60 @@
+/* $Id: SlotManagerTests.h 4873 2010-08-27 07:46:21Z rijswijk $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManagerTests.h
+
+ Contains test cases to test the slot manager implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOTMANAGERTESTS_H
+#define _SOFTHSM_V2_SLOTMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SlotManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SlotManagerTests);
+ CPPUNIT_TEST(testNoExistingTokens);
+ CPPUNIT_TEST(testExistingTokens);
+ CPPUNIT_TEST(testInitialiseTokenInLastSlot);
+ CPPUNIT_TEST(testReinitialiseExistingToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testNoExistingTokens();
+ void testExistingTokens();
+ void testInitialiseTokenInLastSlot();
+ void testReinitialiseExistingToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SLOTMANAGERTESTS_H
+
diff --git a/src/lib/slot_mgr/test/slotmgrtest.cpp b/src/lib/slot_mgr/test/slotmgrtest.cpp
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: slotmgrtest.cpp 6738 2012-10-15 21:28:14Z rb $ */
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ slotmgrtest.cpp
+
+ The main test executor for tests on the slot manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/test/DigestTests.cpp b/src/lib/test/DigestTests.cpp
--- /dev/null
@@ -0,0 +1,291 @@
+/* $Id: DigestTests.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DigestTests.cpp
+
+ Contains test cases to C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DigestTests.h"
+#include "testconfig.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DigestTests);
+
+void DigestTests::setUp()
+{
+// printf("\nDigestTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ CK_RV rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+}
+
+void DigestTests::tearDown()
+{
+ C_Finalize(NULL_PTR);
+}
+
+void DigestTests::testDigestInit()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = {
+ CKM_VENDOR_DEFINED, NULL_PTR, 0
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestInit(hSession, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_DigestInit(CK_INVALID_HANDLE, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ mechanism.mechanism = CKM_SHA512;
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_ACTIVE);
+}
+
+void DigestTests::testDigest()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Digest(CK_INVALID_HANDLE, data, sizeof(data)-1, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Digest(hSession, NULL_PTR, sizeof(data)-1, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+ digestLen = 0;
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(digest);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+}
+
+void DigestTests::testDigestUpdate()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_DigestUpdate(hSession, data, sizeof(data)-1);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestUpdate(CK_INVALID_HANDLE, data, sizeof(data)-1);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_DigestUpdate(hSession, data, sizeof(data)-1);
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestUpdate(hSession, NULL_PTR, sizeof(data)-1);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_DigestUpdate(hSession, data, sizeof(data)-1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void DigestTests::testDigestFinal()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_BYTE data[] = {"Text to digest"};
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_DigestFinal(hSession, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestFinal(CK_INVALID_HANDLE, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_DigestFinal(hSession, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = C_DigestInit(hSession, &mechanism);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestUpdate(hSession, data, sizeof(data)-1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_DigestFinal(hSession, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_DigestFinal(hSession, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+ digestLen = 0;
+
+ rv = C_DigestFinal(hSession, digest, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ rv = C_DigestFinal(hSession, digest, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(digest);
+
+ rv = C_DigestFinal(hSession, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+}
+
+void DigestTests::testDigestAll()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanisms[] = {
+ { CKM_MD5, NULL_PTR, 0 },
+ { CKM_SHA_1, NULL_PTR, 0 },
+ { CKM_SHA224, NULL_PTR, 0 },
+ { CKM_SHA256, NULL_PTR, 0 },
+ { CKM_SHA384, NULL_PTR, 0 },
+ { CKM_SHA512, NULL_PTR, 0 },
+ };
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ for (int i = 0; i < 6; i++)
+ {
+ rv = C_DigestInit(hSession, &mechanisms[i]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+
+ rv = C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(digest);
+ }
+}
diff --git a/src/lib/test/DigestTests.h b/src/lib/test/DigestTests.h
--- /dev/null
@@ -0,0 +1,63 @@
+/* $Id: DigestTests.h 4919 2010-11-02 17:13:23Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DigestTests.h
+
+ Contains test cases to C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIGESTTESTS_H
+#define _SOFTHSM_V2_DIGESTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class DigestTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DigestTests);
+ CPPUNIT_TEST(testDigestInit);
+ CPPUNIT_TEST(testDigest);
+ CPPUNIT_TEST(testDigestUpdate);
+ CPPUNIT_TEST(testDigestFinal);
+ CPPUNIT_TEST(testDigestAll);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDigestInit();
+ void testDigest();
+ void testDigestUpdate();
+ void testDigestFinal();
+ void testDigestAll();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_DIGESTTESTS_H
+
diff --git a/src/lib/test/EncryptDecryptTests.cpp b/src/lib/test/EncryptDecryptTests.cpp
--- /dev/null
@@ -0,0 +1,212 @@
+/* $Id: EncryptDecryptTests.cpp 6754 2012-10-22 12:45:31Z rb $ */
+
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EncryptDecryptTests.cpp
+
+ Contains test cases for:
+ C_EncryptInit
+ C_Encrypt
+ C_DecryptInit
+ C_Decrypt
+
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "EncryptDecryptTests.h"
+#include "testconfig.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(EncryptDecryptTests);
+
+void EncryptDecryptTests::setUp()
+{
+// printf("\nObjectTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, sopin,sopinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login SO
+ rv = C_Login(hSession,CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Initialize the user pin
+ rv = C_InitPIN(hSession, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void EncryptDecryptTests::tearDown()
+{
+ C_Finalize(NULL_PTR);
+}
+
+CK_RV EncryptDecryptTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk);
+}
+
+void EncryptDecryptTests::rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, 1, NULL_PTR, 0 };
+ CK_BYTE plainText[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE cipherText[256];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE recoveredText[256];
+ CK_ULONG ulRecoveredTextLen;
+ CK_RV rv;
+
+ if (mechanismType == CKM_RSA_PKCS_OAEP)
+ {
+ mechanism.pParameter = &oaepParams;
+ mechanism.ulParameterLen = sizeof(oaepParams);
+ }
+
+ rv = C_EncryptInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulCipherTextLen = sizeof(cipherText);
+ rv =C_Encrypt(hSession,plainText,sizeof(plainText),cipherText,&ulCipherTextLen);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_DecryptInit(hSession,&mechanism,hPrivateKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulRecoveredTextLen = sizeof(recoveredText);
+ rv = C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CPPUNIT_ASSERT(memcmp(plainText, &recoveredText[ulRecoveredTextLen-sizeof(plainText)], sizeof(plainText)) == 0);
+}
+
+void EncryptDecryptTests::testRsaEncryptDecrypt()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token public/private key pairs.
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaEncryptDecrypt(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
+ rsaEncryptDecrypt(CKM_RSA_X_509,hSessionRO,hPublicKey,hPrivateKey);
+ rsaEncryptDecrypt(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
+}
diff --git a/src/lib/test/EncryptDecryptTests.h b/src/lib/test/EncryptDecryptTests.h
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id: EncryptDecryptTests.h 6754 2012-10-22 12:45:31Z rb $ */
+
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EncryptDecryptTests.h
+
+ Contains test cases to C_EncryptInit, C_Encrypt, C_DecryptInit, C_Decrypt
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ENCRYPTDECRYPTTESTS_H
+#define _SOFTHSM_V2_ENCRYPTDECRYPTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class EncryptDecryptTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(EncryptDecryptTests);
+ CPPUNIT_TEST(testRsaEncryptDecrypt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaEncryptDecrypt();
+
+ void setUp();
+ void tearDown();
+
+protected:
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+};
+
+#endif // !_SOFTHSM_V2_ENCRYPTDECRYPTTESTS_H
diff --git a/src/lib/test/InfoTests.cpp b/src/lib/test/InfoTests.cpp
--- /dev/null
@@ -0,0 +1,296 @@
+/* $Id: InfoTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InfoTests.cpp
+
+ Contains test cases to C_GetInfo, C_GetFunctionList, C_GetSlotList,
+ C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, and C_GetMechanismInfo
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "InfoTests.h"
+#include "testconfig.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InfoTests);
+
+void InfoTests::setUp()
+{
+// printf("\nInfoTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ CK_RV rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::tearDown()
+{
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::testGetInfo()
+{
+ CK_RV rv;
+ CK_INFO ckInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetInfo(&ckInfo);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetInfo(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetInfo(&ckInfo);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::testGetFunctionList()
+{
+ CK_RV rv;
+ CK_FUNCTION_LIST_PTR ckFuncList;
+
+ rv = C_GetFunctionList(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetFunctionList(&ckFuncList);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InfoTests::testGetSlotList()
+{
+ CK_RV rv;
+ CK_ULONG ulSlotCount = 0;
+ CK_SLOT_ID_PTR pSlotList;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetSlotList(CK_FALSE, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Get the size of the buffer
+ rv = C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ pSlotList = (CK_SLOT_ID_PTR)malloc(ulSlotCount * sizeof(CK_SLOT_ID));
+
+ // Check if we have a too small buffer
+ ulSlotCount = 0;
+ rv = C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the slot list
+ rv = C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pSlotList);
+
+ // Get the number of slots with tokens
+ rv = C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ pSlotList = (CK_SLOT_ID_PTR)malloc(ulSlotCount * sizeof(CK_SLOT_ID));
+
+ // Check if we have a too small buffer
+ ulSlotCount = 0;
+ rv = C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the slot list
+ rv = C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pSlotList);
+
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::testGetSlotInfo()
+{
+ CK_RV rv;
+ CK_SLOT_INFO slotInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetSlotInfo(SLOT_NO_INIT_TOKEN, &slotInfo);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetSlotInfo(SLOT_NO_INIT_TOKEN, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetSlotInfo(SLOT_INVALID, &slotInfo);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = C_GetSlotInfo(SLOT_NO_INIT_TOKEN, &slotInfo);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::testGetTokenInfo()
+{
+ CK_RV rv;
+ CK_TOKEN_INFO tokenInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetTokenInfo(SLOT_NO_INIT_TOKEN, &tokenInfo);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetTokenInfo(SLOT_NO_INIT_TOKEN, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetTokenInfo(SLOT_INVALID, &tokenInfo);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = C_GetTokenInfo(SLOT_NO_INIT_TOKEN, &tokenInfo);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0);
+
+ rv = C_GetTokenInfo(SLOT_INIT_TOKEN, &tokenInfo);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::testGetMechanismList()
+{
+ CK_RV rv;
+ CK_ULONG ulMechCount = 0;
+ CK_MECHANISM_TYPE_PTR pMechanismList;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetMechanismList(SLOT_INVALID, NULL_PTR, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ // Get the size of the buffer
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ pMechanismList = (CK_MECHANISM_TYPE_PTR)malloc(ulMechCount * sizeof(CK_MECHANISM_TYPE_PTR));
+
+ // Check if we have a too small buffer
+ ulMechCount = 0;
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, pMechanismList, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the mechanism list
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, pMechanismList, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pMechanismList);
+
+ C_Finalize(NULL_PTR);
+}
+
+void InfoTests::testGetMechanismInfo()
+{
+ CK_RV rv;
+ CK_MECHANISM_INFO info;
+ CK_ULONG ulMechCount = 0;
+ CK_MECHANISM_TYPE_PTR pMechanismList;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, CKM_RSA_PKCS, &info);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get the mechanism list
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(ulMechCount != 0);
+ pMechanismList = (CK_MECHANISM_TYPE_PTR)malloc(ulMechCount * sizeof(CK_MECHANISM_TYPE_PTR));
+ rv = C_GetMechanismList(SLOT_INIT_TOKEN, pMechanismList, &ulMechCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, pMechanismList[0], NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetMechanismInfo(SLOT_INVALID, pMechanismList[0], &info);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, CKM_VENDOR_DEFINED, &info);
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ for (int i = 0; i < ulMechCount; i++)
+ {
+ rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, pMechanismList[i], &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ }
+
+ free(pMechanismList);
+
+ C_Finalize(NULL_PTR);
+}
diff --git a/src/lib/test/InfoTests.h b/src/lib/test/InfoTests.h
--- /dev/null
+++ b/src/lib/test/InfoTests.h
@@ -0,0 +1,68 @@
+/* $Id: InfoTests.h 4896 2010-09-14 09:32:24Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InfoTests.h
+
+ Contains test cases to C_GetInfo, C_GetFunctionList, C_GetSlotList,
+ C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, and C_GetMechanismInfo
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_INFOTESTS_H
+#define _SOFTHSM_V2_INFOTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class InfoTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(InfoTests);
+ CPPUNIT_TEST(testGetInfo);
+ CPPUNIT_TEST(testGetFunctionList);
+ CPPUNIT_TEST(testGetSlotList);
+ CPPUNIT_TEST(testGetSlotInfo);
+ CPPUNIT_TEST(testGetTokenInfo);
+ CPPUNIT_TEST(testGetMechanismList);
+ CPPUNIT_TEST(testGetMechanismInfo);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testGetInfo();
+ void testGetFunctionList();
+ void testGetSlotList();
+ void testGetSlotInfo();
+ void testGetTokenInfo();
+ void testGetMechanismList();
+ void testGetMechanismInfo();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_INFOTESTS_H
+
diff --git a/src/lib/test/InitTests.cpp b/src/lib/test/InitTests.cpp
--- /dev/null
@@ -0,0 +1,241 @@
+/* $Id: InitTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InitTests.cpp
+
+ Contains test cases to C_Initialize and C_Finalize
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "InitTests.h"
+#include "cryptoki.h"
+#include "osmutex.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InitTests);
+
+void InitTests::setUp()
+{
+// printf("\nInitTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+}
+
+void InitTests::tearDown()
+{
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+}
+
+void InitTests::testInit1()
+{
+ CK_RV rv;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit2()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = (CK_VOID_PTR)1;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.pReserved = NULL_PTR;
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit3()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = (CK_UNLOCKMUTEX)1;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = NULL_PTR;
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit4()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = (CK_UNLOCKMUTEX)1;
+ InitArgs.flags = CKF_OS_LOCKING_OK;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = NULL_PTR;
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit5()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = OSCreateMutex;
+ InitArgs.DestroyMutex = OSDestroyMutex;
+ InitArgs.LockMutex = OSLockMutex;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = OSUnlockMutex;
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit6()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = OSCreateMutex;
+ InitArgs.DestroyMutex = OSDestroyMutex;
+ InitArgs.LockMutex = OSLockMutex;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = CKF_OS_LOCKING_OK;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = OSUnlockMutex;
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Initialize((CK_VOID_PTR)&InitArgs);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testFinal()
+{
+ CK_RV rv;
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // pReserved is reserved for future versions
+ rv = C_Finalize((CK_VOID_PTR)1);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_Finalize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/src/lib/test/InitTests.h b/src/lib/test/InitTests.h
--- /dev/null
+++ b/src/lib/test/InitTests.h
@@ -0,0 +1,66 @@
+/* $Id: InitTests.h 4883 2010-09-06 14:00:29Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InitTests.h
+
+ Contains test cases to C_Initialize and C_Finalize
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_INITTESTS_H
+#define _SOFTHSM_V2_INITTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class InitTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(InitTests);
+ CPPUNIT_TEST(testInit1);
+ CPPUNIT_TEST(testInit2);
+ CPPUNIT_TEST(testInit3);
+ CPPUNIT_TEST(testInit4);
+ CPPUNIT_TEST(testInit5);
+ CPPUNIT_TEST(testInit6);
+ CPPUNIT_TEST(testFinal);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInit1();
+ void testInit2();
+ void testInit3();
+ void testInit4();
+ void testInit5();
+ void testInit6();
+ void testFinal();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_INITTESTS_H
+
diff --git a/src/lib/test/Makefile.am b/src/lib/test/Makefile.am
--- /dev/null
+++ b/src/lib/test/Makefile.am
@@ -0,0 +1,32 @@
+# $Id: Makefile.am 6810 2012-11-01 14:21:55Z jerry $
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../cryptoki_compat \
+ -I$(srcdir)/../common \
+ `cppunit-config --cflags`
+
+check_PROGRAMS = p11test
+
+p11test_SOURCES = p11test.cpp \
+ DigestTests.cpp \
+ InitTests.cpp \
+ InfoTests.cpp \
+ RandomTests.cpp \
+ SessionTests.cpp \
+ TokenTests.cpp \
+ UserTests.cpp \
+ ObjectTests.cpp \
+ SignVerifyTests.cpp \
+ EncryptDecryptTests.cpp \
+ ../common/osmutex.cpp
+
+p11test_LDADD = ../libsofthsm.la
+
+p11test_LDFLAGS = @CRYPTO_LIBS@ -no-install `cppunit-config --libs` -pthread -static
+
+TESTS = p11test
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/tokens/dummy.in
diff --git a/src/lib/test/ObjectTests.cpp b/src/lib/test/ObjectTests.cpp
--- /dev/null
@@ -0,0 +1,1718 @@
+/* $Id: ObjectTests.cpp 6776 2012-10-25 11:39:46Z rb $ */
+
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectTests.cpp
+
+ Contains test cases for:
+ C_CreateObject
+ C_DestroyObject
+ C_GetAttributeValue
+ C_SetAttributeValue
+ C_FindObjectsInit
+ C_FindObjects
+ C_FindObjectsFinal
+ C_GenererateKeyPair
+
+ Below is a list of tests we need to add in order to verify that the PKCS#11 library
+ is working as expected.
+
+ We want to be sure that order of attributes does not impact the tests, therefore
+ every function involving attributes should have the order of the attributes
+ in the template randomized.
+
+ We want to be sure that only attributes that are specified as being part of an
+ object class can be used when creating an object.
+ Using other attributes should return an error on creation of the object.
+
+ We want to be sure that attributes that are required but missing will result
+ in a template incomplete return value.
+
+ We want to be sure that we get an error when trying to modify an attribute that
+ may not be modified
+
+ We want to be sure that attributes that may be changed to one value but not
+ back to the previous value are handled correctly.
+
+ We want to verify that an error is returned when we are trying to modify
+ read-only attributes.
+
+ We want to verify that sensitive attributes cannot be read.
+
+ Because the teardown also removes token objects it is not really
+ required to destroy objects created during the test in the CreateObject tests.
+
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectTests.h"
+#include "testconfig.h"
+
+// Common object attributes
+const CK_BBOOL CKA_TOKEN_DEFAULT = CK_FALSE;
+//const CK_BBOOL CKA_PRIVATE_DEFAULT = <token/object attribute dependent>
+const CK_BBOOL CKA_MODIFIABLE_DEFAULT = CK_TRUE;
+const CK_UTF8CHAR_PTR CKA_LABEL_DEFAULT = NULL;
+const CK_BBOOL CKA_COPYABLE_DEFAULT = CK_TRUE;
+
+// Data Object Attributes
+const CK_UTF8CHAR_PTR CKA_APPLICATION_DEFAULT = NULL;
+const CK_BYTE_PTR CKA_OBJECT_ID_DEFAULT = NULL;
+const CK_BYTE_PTR CKA_VALUE_DEFAULT = NULL;
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectTests);
+
+void ObjectTests::setUp()
+{
+// printf("\nObjectTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, sopin,sopinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login SO
+ rv = C_Login(hSession,CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Initialize the user pin
+ rv = C_InitPIN(hSession, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::tearDown()
+{
+ C_Finalize(NULL_PTR);
+}
+
+void ObjectTests::checkCommonObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_OBJECT_CLASS objClass)
+{
+ CK_RV rv;
+
+ CK_OBJECT_CLASS obj_class = CKO_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &obj_class, sizeof(obj_class) }
+ };
+
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(obj_class == objClass);
+}
+
+void ObjectTests::checkCommonStorageObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_BBOOL bModifiable, CK_UTF8CHAR_PTR pLabel, CK_ULONG ulLabelLen, CK_BBOOL bCopyable)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_token = CK_FALSE;
+ CK_BBOOL obj_private = CK_FALSE;
+ CK_BBOOL obj_modifiable = CK_FALSE;
+ CK_BBOOL obj_copyable = CK_FALSE;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, NULL_PTR, 0 },
+ { CKA_TOKEN, &obj_token, sizeof(obj_token) },
+ { CKA_PRIVATE, &obj_private, sizeof(obj_private) },
+ { CKA_MODIFIABLE, &obj_modifiable, sizeof(obj_modifiable) },
+ { CKA_COPYABLE, &obj_copyable, sizeof(obj_copyable) }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 5);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulLabelLen);
+ CPPUNIT_ASSERT(obj_token == bToken);
+ /* Default is token-specifict
+ CPPUNIT_ASSERT(obj_private == bPrivate); */
+ CPPUNIT_ASSERT(obj_modifiable == bModifiable);
+ CPPUNIT_ASSERT(obj_copyable == bCopyable);
+ if (ulLabelLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pLabel, ulLabelLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkDataObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_UTF8CHAR_PTR pApplication, CK_ULONG ulApplicationLen, CK_BYTE_PTR pObjectID, CK_ULONG ulObjectIdLen, CK_BYTE_PTR pValue, CK_ULONG ulValueLen)
+{
+ CK_RV rv;
+
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_APPLICATION, NULL_PTR, 0 },
+ { CKA_OBJECT_ID, NULL_PTR, 0 },
+ { CKA_VALUE, NULL_PTR, 0 }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 3);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+ attribs[2].pValue = (CK_VOID_PTR)malloc(attribs[2].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 3);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulApplicationLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulObjectIdLen);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulValueLen);
+ if (ulApplicationLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pApplication, ulApplicationLen) == 0);
+ if (ulObjectIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pObjectID, ulObjectIdLen) == 0);
+ if (ulValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, pValue, ulValueLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+ free(attribs[2].pValue);
+}
+
+void ObjectTests::checkCommonCertificateObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_CERTIFICATE_TYPE certType, CK_BBOOL bTrusted, CK_ULONG ulCertificateCategory, CK_BYTE_PTR pCheckValue, CK_ULONG ulCheckValueLen, CK_DATE startDate, CK_ULONG ulStartDateLen, CK_DATE endDate, CK_ULONG ulEndDateLen)
+{
+ CK_RV rv;
+
+ CK_CERTIFICATE_TYPE obj_type = CKC_X_509;
+ CK_BBOOL obj_trusted = CK_FALSE;
+ CK_ULONG obj_category = 0;
+ CK_DATE obj_start;
+ CK_DATE obj_end;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CHECK_VALUE, NULL_PTR, 0 },
+ { CKA_CERTIFICATE_TYPE, &obj_type, sizeof(obj_type) },
+ { CKA_TRUSTED, &obj_trusted, sizeof(obj_trusted) },
+ { CKA_CERTIFICATE_CATEGORY, &obj_category, sizeof(obj_category) },
+ { CKA_START_DATE, &obj_start, sizeof(obj_start) },
+ { CKA_END_DATE, &obj_end, sizeof(obj_end) }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 6);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulCheckValueLen);
+ CPPUNIT_ASSERT(obj_type == certType);
+ CPPUNIT_ASSERT(obj_trusted == bTrusted);
+ CPPUNIT_ASSERT(obj_category == ulCertificateCategory);
+ CPPUNIT_ASSERT(attribs[4].ulValueLen == ulStartDateLen);
+ CPPUNIT_ASSERT(attribs[5].ulValueLen == ulEndDateLen);
+ if (ulCheckValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pCheckValue, ulCheckValueLen) == 0);
+ if (ulStartDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, &startDate, ulStartDateLen) == 0);
+ if (ulEndDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[5].pValue, &endDate, ulEndDateLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkX509CertificateObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BYTE_PTR pId, CK_ULONG ulIdLen, CK_BYTE_PTR pIssuer, CK_ULONG ulIssuerLen, CK_BYTE_PTR pSerialNumber, CK_ULONG ulSerialNumberLen, CK_BYTE_PTR pValue, CK_ULONG ulValueLen, CK_BYTE_PTR pUrl, CK_ULONG ulUrlLen, CK_BYTE_PTR pHashOfSubjectPublicKey, CK_ULONG ulHashOfSubjectPublicKeyLen, CK_BYTE_PTR pHashOfIssuerPublicKey, CK_ULONG ulHashOfIssuerPublicKeyLen, CK_ULONG ulJavaMidpSecurityDomain, CK_MECHANISM_TYPE nameHashAlgorithm)
+{
+ CK_RV rv;
+
+ CK_ULONG obj_java = 0;
+ CK_MECHANISM_TYPE obj_mech = CKM_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_ID, NULL_PTR, 0 },
+ { CKA_ISSUER, NULL_PTR, 0 },
+ { CKA_SERIAL_NUMBER, NULL_PTR, 0 },
+ { CKA_VALUE, NULL_PTR, 0 },
+ { CKA_URL, NULL_PTR, 0 },
+ { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, NULL_PTR, 0 },
+ { CKA_HASH_OF_ISSUER_PUBLIC_KEY, NULL_PTR, 0 },
+ { CKA_JAVA_MIDP_SECURITY_DOMAIN, &obj_java, sizeof(obj_java) },
+ { CKA_NAME_HASH_ALGORITHM, &obj_mech, sizeof(obj_mech) }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 8);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+ attribs[2].pValue = (CK_VOID_PTR)malloc(attribs[2].ulValueLen);
+ attribs[3].pValue = (CK_VOID_PTR)malloc(attribs[3].ulValueLen);
+ attribs[4].pValue = (CK_VOID_PTR)malloc(attribs[4].ulValueLen);
+ attribs[5].pValue = (CK_VOID_PTR)malloc(attribs[5].ulValueLen);
+ attribs[6].pValue = (CK_VOID_PTR)malloc(attribs[6].ulValueLen);
+ attribs[7].pValue = (CK_VOID_PTR)malloc(attribs[7].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 10);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulIdLen);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulIssuerLen);
+ CPPUNIT_ASSERT(attribs[3].ulValueLen == ulSerialNumberLen);
+ CPPUNIT_ASSERT(attribs[4].ulValueLen == ulValueLen);
+ CPPUNIT_ASSERT(attribs[5].ulValueLen == ulUrlLen);
+ CPPUNIT_ASSERT(attribs[6].ulValueLen == ulHashOfSubjectPublicKeyLen);
+ CPPUNIT_ASSERT(attribs[7].ulValueLen == ulHashOfIssuerPublicKeyLen);
+ CPPUNIT_ASSERT(obj_java == ulJavaMidpSecurityDomain);
+ CPPUNIT_ASSERT(obj_mech == nameHashAlgorithm);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+ if (ulIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pId, ulIdLen) == 0);
+ if (ulIssuerLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, pIssuer, ulIssuerLen) == 0);
+ if (ulSerialNumberLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[3].pValue, pSerialNumber, ulSerialNumberLen) == 0);
+ if (ulValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, pValue, ulValueLen) == 0);
+ if (ulUrlLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[5].pValue, pUrl, ulUrlLen) == 0);
+ if (ulHashOfSubjectPublicKeyLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[6].pValue, pHashOfSubjectPublicKey, ulHashOfSubjectPublicKeyLen) == 0);
+ if (ulHashOfIssuerPublicKeyLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[7].pValue, pHashOfIssuerPublicKey, ulHashOfIssuerPublicKeyLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+ free(attribs[2].pValue);
+ free(attribs[3].pValue);
+ free(attribs[4].pValue);
+ free(attribs[5].pValue);
+ free(attribs[6].pValue);
+ free(attribs[7].pValue);
+}
+
+void ObjectTests::checkCommonKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_KEY_TYPE keyType, CK_BYTE_PTR pId, CK_ULONG ulIdLen, CK_DATE startDate, CK_ULONG ulStartDateLen, CK_DATE endDate, CK_ULONG ulEndDateLen, CK_BBOOL bDerive, CK_BBOOL bLocal, CK_MECHANISM_TYPE keyMechanismType, CK_MECHANISM_TYPE_PTR pAllowedMechanisms, CK_ULONG ulAllowedMechanismsLen)
+{
+ CK_RV rv;
+
+ CK_KEY_TYPE obj_type = CKK_VENDOR_DEFINED;
+ CK_DATE obj_start;
+ CK_DATE obj_end;
+ CK_BBOOL obj_derive = CK_FALSE;
+ CK_BBOOL obj_local = CK_FALSE;
+ CK_MECHANISM_TYPE obj_mech = CKM_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_ID, NULL_PTR, 0 },
+ /* Not supported
+ { CKA_ALLOWED_MECHANISMS, NULL_PTR, 0 }, */
+ { CKA_KEY_TYPE, &obj_type, sizeof(obj_type) },
+ { CKA_START_DATE, &obj_start, sizeof(obj_start) },
+ { CKA_END_DATE, &obj_end, sizeof(obj_end) },
+ { CKA_DERIVE, &obj_derive, sizeof(obj_derive) },
+ { CKA_LOCAL, &obj_local, sizeof(obj_local) },
+ { CKA_KEY_GEN_MECHANISM, &obj_mech, sizeof(obj_mech) }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 7);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulIdLen);
+ CPPUNIT_ASSERT(obj_type == keyType);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulStartDateLen);
+ CPPUNIT_ASSERT(attribs[3].ulValueLen == ulEndDateLen);
+ CPPUNIT_ASSERT(obj_derive == bDerive);
+ CPPUNIT_ASSERT(obj_local == bLocal);
+ CPPUNIT_ASSERT(obj_mech == keyMechanismType);
+ if (ulIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pId, ulIdLen) == 0);
+ if (ulStartDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[3].pValue, &startDate, ulStartDateLen) == 0);
+ if (ulEndDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, &endDate, ulEndDateLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonPublicKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BBOOL bEncrypt, CK_BBOOL bVerify, CK_BBOOL bVerifyRecover, CK_BBOOL bWrap, CK_BBOOL bTrusted, CK_ATTRIBUTE_PTR pWrapTemplate, CK_ULONG ulWrapTemplateLen)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_encrypt = CK_FALSE;
+ CK_BBOOL obj_verify = CK_FALSE;
+ CK_BBOOL obj_verify_recover = CK_FALSE;
+ CK_BBOOL obj_wrap = CK_FALSE;
+ CK_BBOOL obj_trusted = CK_FALSE;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_ENCRYPT, &obj_encrypt, sizeof(obj_encrypt) },
+ { CKA_VERIFY, &obj_verify, sizeof(obj_verify) },
+ { CKA_VERIFY_RECOVER, &obj_verify_recover, sizeof(obj_verify_recover) },
+ { CKA_WRAP, &obj_wrap, sizeof(obj_wrap) },
+ { CKA_TRUSTED, &obj_trusted, sizeof(obj_trusted) }
+ /* Not supported
+ { CKA_WRAP_TEMPLATE, NULL_PTR, 0 } */
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 6);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ /* Default is token-specifict
+ CPPUNIT_ASSERT(obj_encrypt == bEncrypt);
+ CPPUNIT_ASSERT(obj_verify == bVerify);
+ CPPUNIT_ASSERT(obj_verify_recover == bVerifyRecover);
+ CPPUNIT_ASSERT(obj_wrap == bWrap); */
+ CPPUNIT_ASSERT(obj_trusted == bTrusted);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonPrivateKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BBOOL bSensitive, CK_BBOOL bDecrypt, CK_BBOOL bSign, CK_BBOOL bSignRecover, CK_BBOOL bUnwrap, CK_BBOOL bExtractable, CK_BBOOL bAlwaysSensitive, CK_BBOOL bNeverExtractable, CK_BBOOL bWrapWithTrusted, CK_ATTRIBUTE_PTR pUnwrapTemplate, CK_ULONG ulUnwrapTemplateLen, CK_BBOOL bAlwaysAuthenticate)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_sensitive = CK_FALSE;
+ CK_BBOOL obj_decrypt = CK_FALSE;
+ CK_BBOOL obj_sign = CK_FALSE;
+ CK_BBOOL obj_sign_recover = CK_FALSE;
+ CK_BBOOL obj_unwrap = CK_FALSE;
+ CK_BBOOL obj_extractable = CK_FALSE;
+ CK_BBOOL obj_always_sensitive = CK_FALSE;
+ CK_BBOOL obj_never_extractable = CK_FALSE;
+ CK_BBOOL obj_wrap_with_trusted = CK_FALSE;
+ CK_BBOOL obj_always_authenticate = CK_FALSE;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_SENSITIVE, &obj_sensitive, sizeof(obj_sensitive) },
+ { CKA_DECRYPT, &obj_decrypt, sizeof(obj_decrypt) },
+ { CKA_SIGN, &obj_sign, sizeof(obj_sign) },
+ { CKA_SIGN_RECOVER, &obj_sign_recover, sizeof(obj_sign_recover) },
+ { CKA_UNWRAP, &obj_unwrap, sizeof(obj_unwrap) },
+ { CKA_EXTRACTABLE, &obj_extractable, sizeof(obj_extractable) },
+ { CKA_ALWAYS_SENSITIVE, &obj_always_sensitive, sizeof(obj_always_sensitive) },
+ { CKA_NEVER_EXTRACTABLE, &obj_never_extractable, sizeof(obj_never_extractable) },
+ { CKA_WRAP_WITH_TRUSTED, &obj_wrap_with_trusted, sizeof(obj_wrap_with_trusted) },
+ /* Not supported
+ { CKA_UNWRAP_TEMPLATE, NULL_PTR, 0 }, */
+ { CKA_ALWAYS_AUTHENTICATE, &obj_always_authenticate, sizeof(obj_always_authenticate) }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 11);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ CPPUNIT_ASSERT(obj_sensitive == bSensitive);
+ CPPUNIT_ASSERT(obj_decrypt == bDecrypt);
+ CPPUNIT_ASSERT(obj_sign == bSign);
+ CPPUNIT_ASSERT(obj_sign_recover == bSignRecover);
+ CPPUNIT_ASSERT(obj_unwrap == bUnwrap);
+ CPPUNIT_ASSERT(obj_extractable == bExtractable);
+ CPPUNIT_ASSERT(obj_always_sensitive == bAlwaysSensitive);
+ CPPUNIT_ASSERT(obj_never_extractable == bNeverExtractable);
+ CPPUNIT_ASSERT(obj_wrap_with_trusted == bWrapWithTrusted);
+ CPPUNIT_ASSERT(obj_always_authenticate == bAlwaysAuthenticate);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonRSAPublicKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen, CK_ULONG ulModulusBits, CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen)
+{
+ CK_RV rv;
+
+ CK_ULONG obj_bits = 0;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_MODULUS, NULL_PTR, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 },
+ { CKA_MODULUS_BITS, &obj_bits, sizeof(obj_bits) }
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 3);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulModulusLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulPublicExponentLen);
+ CPPUNIT_ASSERT(obj_bits == ulModulusBits);
+ if (ulModulusLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pModulus, ulModulusLen) == 0);
+ if (ulPublicExponentLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pPublicExponent, ulPublicExponentLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+}
+
+void ObjectTests::checkCommonRSAPrivateKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen, CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen, CK_BYTE_PTR pPrivateExponent, CK_ULONG ulPrivateExponentLen, CK_BYTE_PTR pPrime1, CK_ULONG ulPrime1Len, CK_BYTE_PTR pPrime2, CK_ULONG ulPrime2Len, CK_BYTE_PTR pExponent1, CK_ULONG ulExponent1Len, CK_BYTE_PTR pExponent2, CK_ULONG ulExponent2Len, CK_BYTE_PTR pCoefficient, CK_ULONG ulCoefficientLen)
+{
+ CK_RV rv;
+
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_MODULUS, NULL_PTR, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL_PTR, 0 }
+ /* Some tokens may only store modulus and private exponent
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 },
+ { CKA_PRIME_1, NULL_PTR, 0 },
+ { CKA_PRIME_2, NULL_PTR, 0 },
+ { CKA_EXPONENT_1, NULL_PTR, 0 },
+ { CKA_EXPONENT_2, NULL_PTR, 0 },
+ { CKA_COEFFICIENT, NULL_PTR, 0 }, */
+ };
+
+ // Get length
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+
+ // Check values
+ rv = C_GetAttributeValue(hSession, hObject, &attribs[0], 2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulModulusLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulPrivateExponentLen);
+ if (ulModulusLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pModulus, ulModulusLen) == 0);
+ if (ulPrivateExponentLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pPrivateExponent, ulPrivateExponentLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+}
+
+CK_RV ObjectTests::createDataObjectMinimal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_RV rv;
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ //CKA_MODIFIABLE
+ { CKA_LABEL, label, sizeof(label)-1 },
+ //CKA_COPYABLE
+
+ // Data
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject);
+}
+
+CK_RV ObjectTests::createDataObjectNormal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+
+ CK_UTF8CHAR application[] = "An application";
+ CK_BYTE objectID[] = "invalid object id";
+ CK_BYTE data[] = "Sample data";
+
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ //CKA_MODIFIABLE
+ { CKA_LABEL, label, sizeof(label)-1 },
+ //CKA_COPYABLE
+
+ // Data
+ { CKA_APPLICATION, application, sizeof(application)-1 },
+ { CKA_OBJECT_ID, objectID, sizeof(objectID) },
+ { CKA_VALUE, data, sizeof(data) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject);
+}
+
+CK_RV ObjectTests::createCertificateObjectIncomplete(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_CERTIFICATE;
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject);
+}
+
+CK_RV ObjectTests::createCertificateObjectValue(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE cType = CKC_X_509;
+ const char *pSubject = "invalid subject der";
+ const char *pValue = "invalid certificate der";
+
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+ // Common Certificate Object Attributes
+ { CKA_CERTIFICATE_TYPE, &cType, sizeof(cType) },
+ // X.509 Certificate Object Attributes
+ { CKA_SUBJECT, (CK_VOID_PTR)pSubject, strlen(pSubject) },
+ { CKA_VALUE, (CK_VOID_PTR)pValue, strlen(pValue) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject);
+}
+
+CK_RV ObjectTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk);
+}
+
+void ObjectTests::testCreateObject()
+{
+// printf("\ntestCreateObject\n");
+
+ // [PKCS#11 v2.3 p126]
+ // a. Only session objects can be created during read-only session.
+ // b. Only public objects can be created unless the normal user is logged in.
+ // c. TODO: Key object will have CKA_LOCAL == CK_FALSE.
+ // d. TODO: If key object is secret or a private key then both CKA_ALWAYS_SENSITIVE == CK_FALSE and CKA_NEVER_EXTRACTABLE == CKA_FALSE.
+
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-ONLY & PUBLIC
+ /////////////////////////////////
+
+ // Open read-only session and don't login
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ // [PKCS#11 v2.3 p97] seems to indicate CKR_OK while [PKCS#11 v2.3 p126] clearly indicates CKR_USER_NOT_LOGGED_IN
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should not be allowed to create token objects because the session is read-only
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ /////////////////////////////////
+ // READ-ONLY & USER
+ /////////////////////////////////
+
+ // Login USER into the read-only session
+ rv = C_Login(hSession,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create private session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be allowed to create token objects.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Close session
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & PUBLIC
+ /////////////////////////////////
+
+ // Open as read-write session but don't login.
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // [PKCS#11 v2.3 p97] seems to indicate CKR_OK while [PKCS#11 v2.3 p126] clearly indicates CKR_USER_NOT_LOGGED_IN
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be able to create private token objects because we are not logged in now
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & USER
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = C_Login(hSession,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should always be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be able allowed to create private session objects because we are logged in.
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be able to create private token objects because we are logged in now
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & SO
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = C_Login(hSession,CKU_SO,sopin,sopinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should always be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in.
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_DestroyObject(hSession,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testDestroyObject()
+{
+// printf("\ntestDestroyObject\n");
+
+ // [PKCS#11 v2.3 p124] When logout is successful...
+ // a. Any of the application's handles to private objects become invalid.
+ // b. Even if a user is later logged back into the token those handles remain invalid.
+ // c. All private session objects from sessions belonging to the application area destroyed.
+
+ // [PKCS#11 v2.3 p126]
+ // Only session objects can be created during read-only session.
+ // Only public objects can be created unless the normal user is logged in.
+
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Try to destroy an invalid object using an invalid session
+ rv = C_DestroyObject(hSessionRO,CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ // Create a read-only session.
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Trying to destroy an invalid object in a read-only session
+ rv = C_DestroyObject(hSessionRO,CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Create a read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Trying to destroy an invalid object in a read-write session
+ rv = C_DestroyObject(hSessionRO,CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // On a read-only session we should not be able to destroy the public token object
+ rv = C_DestroyObject(hSessionRO,hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // On a read-only session we should not be able to destroy the private token object
+ rv = C_DestroyObject(hSessionRO,hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Logout with a different session than the one used for login should be fine.
+ rv = C_Logout(hSessionRW);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Login USER into the sessions so we can destroy private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should be able to destroy the public session object from a read-only session.
+ rv = C_DestroyObject(hSessionRO,hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // All private session objects should have been destroyed when logging out.
+ rv = C_DestroyObject(hSessionRW,hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // We should be able to destroy the public token object now.
+ rv = C_DestroyObject(hSessionRW,hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // All handles to private token objects should have been invalidated when logging out.
+ rv = C_DestroyObject(hSessionRW,hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Close session
+ rv = C_CloseSession(hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = C_CloseSession(hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testGetAttributeValue()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Try to destroy an invalid object using an invalid session
+ rv = C_GetAttributeValue(hSessionRO,CK_INVALID_HANDLE,NULL,1);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_OBJECT_CLASS cClass = CKO_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &cClass, sizeof(cClass) }
+ };
+
+ rv = C_GetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1);//sizeof(attribs)/sizeof(CK_ATTRIBUTE));
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = C_CloseSession(hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = C_CloseSession(hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testSetAttributeValue()
+{
+ // [PKCS#11 v2.3 pg. 61]
+
+ // 1. If the supplied template specifies a value for an invalid attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_TYPE_INVALID. An attribute
+ // is valid if it is either one of the attributes described in the Cryptoki specification or an
+ // additional vendor-specific attribute supported by the library and token.
+ //
+ // 2. If the supplied template specifies an invalid value for a valid attribute, then the
+ // attempt should fail with the error code CKR_ATTRIBUTE_VALUE_INVALID.
+ // The valid values for Cryptoki attributes are described in the Cryptoki specification.
+ //
+ // 3. If the supplied template specifies a value for a read-only attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_READ_ONLY. Whether or not a
+ // given Cryptoki attribute is read-only is explicitly stated in the Cryptoki specification;
+ // however, a particular library and token may be even more restrictive than Cryptoki
+ // specifies. In other words, an attribute which Cryptoki says is not read-only may
+ // nonetheless be read-only under certain circumstances (i.e., in conjunction with some
+ // combinations of other attributes) for a particular library and token. Whether or not a
+ // given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki.
+ //
+ // 4. N/A (Does not apply to C_SetAttributeValue)
+ //
+ // 5. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are inconsistent, then the attempt should fail with the error code
+ // CKR_TEMPLATE_INCONSISTENT. A set of attribute values is inconsistent if not
+ // all of its members can be satisfied simultaneously by the token, although each value
+ // individually is valid in Cryptoki. One example of an inconsistent template would be
+ // using a template which specifies two different values for the same attribute. Another
+ // example would be trying to create a secret key object with an attribute which is
+ // appropriate for various types of public keys or private keys, but not for secret keys.
+ // A final example would be a template with an attribute that violates some token
+ // specific requirement. Note that this final example of an inconsistent template is
+ // token-dependent—on a different token, such a template might not be inconsistent.
+ //
+ // 6. If the supplied template specifies the same value for a particular attribute more than
+ // once (or the template specifies the same value for a particular attribute that the object-
+ // creation function itself contributes to the object), then the behavior of Cryptoki is not
+ // completely specified. The attempt to create an object can either succeed—thereby
+ // creating the same object that would have been created if the multiply-specified
+ // attribute had only appeared once—or it can fail with error code
+ // CKR_TEMPLATE_INCONSISTENT. Library developers are encouraged to make
+ // their libraries behave as though the attribute had only appeared once in the template;
+ // application developers are strongly encouraged never to put a particular attribute into
+ // a particular template more than once.
+
+
+
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check that label can be modified on all combintations of session/token and public/private objects
+ const char *pLabel = "Label modified via C_SetAttributeValue";
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) }
+ };
+
+ rv = C_SetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_SetAttributeValue (hSessionRO,hObjectSessionPrivate,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_SetAttributeValue (hSessionRO,hObjectTokenPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = C_SetAttributeValue (hSessionRW,hObjectTokenPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_SetAttributeValue (hSessionRO,hObjectTokenPrivate,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = C_SetAttributeValue (hSessionRW,hObjectTokenPrivate,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ attribs[0].pValue = NULL_PTR;
+ rv = C_GetAttributeValue(hSessionRO,hObjectSessionPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == strlen(pLabel));
+
+ char pStoredLabel[64];
+ attribs[0].pValue = &pStoredLabel[0];
+ attribs[0].ulValueLen = 64;
+ rv = C_GetAttributeValue(hSessionRO,hObjectSessionPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == strlen(pLabel));
+ CPPUNIT_ASSERT(memcmp(pLabel,pStoredLabel,strlen(pLabel)) == 0);
+
+
+ // Close session
+ rv = C_CloseSession(hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = C_CloseSession(hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testFindObjects()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Set labels for the objects
+ const char *pLabel = "Label modified via C_SetAttributeValue";
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) }
+ };
+ rv = C_SetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_SetAttributeValue (hSessionRO,hObjectSessionPrivate,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_SetAttributeValue (hSessionRW,hObjectTokenPublic,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_SetAttributeValue (hSessionRW,hObjectTokenPrivate,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find the objects while logged in should find them all.
+ rv = C_FindObjectsInit(hSessionRO,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hObjects[16];
+ CK_ULONG ulObjectCount = 0;
+ rv = C_FindObjects(hSessionRO,&hObjects[0],16,&ulObjectCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(4 == ulObjectCount);
+ rv = C_FindObjectsFinal(hSessionRO);
+
+
+ rv = C_Logout(hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find the objects while no longer logged in should find only 2
+ rv = C_FindObjectsInit(hSessionRO,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_FindObjects(hSessionRO,&hObjects[0],16,&ulObjectCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(2 == ulObjectCount);
+ rv = C_FindObjectsFinal(hSessionRO);
+
+ // Close the session used to create the session objects, should also destroy the session objects.
+ rv = C_CloseSession(hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find just the public token object as public session object should be gone now.
+ rv = C_FindObjectsInit(hSessionRW,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_FindObjects(hSessionRW,&hObjects[0],16,&ulObjectCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(1 == ulObjectCount);
+ rv = C_FindObjectsFinal(hSessionRW);
+
+ // Login USER into the sessions so we can gain access to private objects
+ rv = C_Login(hSessionRW,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Now find just the public token object as public session object should be gone now.
+ rv = C_FindObjectsInit(hSessionRW,&attribs[0],1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_FindObjects(hSessionRW,&hObjects[0],16,&ulObjectCount);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(2 == ulObjectCount);
+ rv = C_FindObjectsFinal(hSessionRW);
+}
+
+
+void ObjectTests::testGenerateKeys()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token public/private key pairs.
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testDefaultDataAttributes()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal data object
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal data object
+ rv = C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in data object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE);
+ checkDataObjectAttributes(hSession, hObject, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0);
+}
+
+void ObjectTests::testDefaultX509CertAttributes()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal X509 certificate object
+ CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE certificateType = CKC_X_509;
+ CK_BYTE pSubject[] = "Test1";
+ CK_BYTE pValue[] = "Test2";
+ CK_DATE emptyDate;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_CERTIFICATE_TYPE, &certificateType, sizeof(certificateType) },
+ { CKA_SUBJECT, pSubject, sizeof(pSubject)-1 },
+ { CKA_VALUE, pValue, sizeof(pValue)-1 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal X509 certificate
+ rv = C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in X509 certificate object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE);
+ checkCommonCertificateObjectAttributes(hSession, hObject, CKC_X_509, CK_FALSE, 0, NULL_PTR, 0, emptyDate, 0, emptyDate, 0);
+ checkX509CertificateObjectAttributes(hSession, hObject, pSubject, sizeof(pSubject)-1, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, pValue, sizeof(pValue)-1, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, 0, CKM_SHA_1);
+}
+
+void ObjectTests::testDefaultRSAPubAttributes()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal RSA public key object
+ CK_OBJECT_CLASS objClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_BYTE pE[] = { 0x01, 0x00, 0x01 };
+ CK_DATE emptyDate;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in RSA public key object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE);
+ checkCommonKeyAttributes(hSession, hObject, objType, NULL_PTR, 0, emptyDate, 0, emptyDate, 0, CK_FALSE, CK_FALSE, CK_UNAVAILABLE_INFORMATION, NULL_PTR, 0);
+ checkCommonPublicKeyAttributes(hSession, hObject, NULL_PTR, 0, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_FALSE, NULL_PTR, 0);
+ checkCommonRSAPublicKeyAttributes(hSession, hObject, pN, sizeof(pN), 512, pE, sizeof(pE));
+}
+
+void ObjectTests::testDefaultRSAPrivAttributes()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal RSA private key object
+ CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_BYTE pD[] = { 0x6D, 0x94, 0x6B, 0xEB, 0xFF, 0xDC, 0x03, 0x80, 0x7B, 0x0A,
+ 0x4F, 0x0A, 0x98, 0x6C, 0xA3, 0x2A, 0x8A, 0xE4, 0xAA, 0x18,
+ 0x44, 0xA4, 0xA5, 0x39, 0x37, 0x0A, 0x2C, 0xFC, 0x5F, 0xD1,
+ 0x44, 0x6E, 0xCE, 0x25, 0x9B, 0xE5, 0xD1, 0x51, 0xAF, 0xA8,
+ 0x30, 0xD1, 0x4D, 0x3C, 0x60, 0x33, 0xB5, 0xED, 0x4C, 0x39,
+ 0xDA, 0x68, 0x78, 0xF9, 0x6B, 0x4F, 0x47, 0x55, 0xB2, 0x02,
+ 0x00, 0x7E, 0x9C, 0x05 };
+ CK_DATE emptyDate;
+ // Make the key non-sensitive and extractable so that we can test it.
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PRIVATE_EXPONENT, pD, sizeof(pD) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in RSA public key object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE);
+ checkCommonKeyAttributes(hSession, hObject, objType, NULL_PTR, 0, emptyDate, 0, emptyDate, 0, CK_FALSE, CK_FALSE, CK_UNAVAILABLE_INFORMATION, NULL_PTR, 0);
+ checkCommonPrivateKeyAttributes(hSession, hObject, NULL_PTR, 0, CK_FALSE, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_FALSE, CK_FALSE, CK_FALSE, NULL_PTR, 0, CK_FALSE);
+ checkCommonRSAPrivateKeyAttributes(hSession, hObject, pN, sizeof(pN), NULL_PTR, 0, pD, sizeof(pD), NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0);
+}
+
+void ObjectTests::testAlwaysNeverAttribute()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL always;
+ CK_BBOOL never;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_ALWAYS_SENSITIVE, &always, sizeof(always) },
+ { CKA_NEVER_EXTRACTABLE, &never, sizeof(never) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = C_GetAttributeValue(hSession, hPrk, getTemplate, 2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(always == CK_TRUE);
+ CPPUNIT_ASSERT(never == CK_TRUE);
+
+ // Set value
+ rv = C_SetAttributeValue(hSession, hPrk, prkAttribs, 2);
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Create object
+ prkAttribs[0].pValue = &bFalse;
+ prkAttribs[1].pValue = &bTrue;
+ rv = C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = C_GetAttributeValue(hSession, hPrk, getTemplate, 2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(always == CK_FALSE);
+ CPPUNIT_ASSERT(never == CK_FALSE);
+}
+
+void ObjectTests::testSensitiveAttributes()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_PRIVATE_EXPONENT, NULL_PTR, 0 },
+ { CKA_PRIME_1, NULL_PTR, 0 },
+ { CKA_PRIME_2, NULL_PTR, 0 },
+ { CKA_EXPONENT_1, NULL_PTR, 0 },
+ { CKA_EXPONENT_2, NULL_PTR, 0 },
+ { CKA_COEFFICIENT, NULL_PTR, 0 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ for (int i = 0; i < 6; i++)
+ {
+ rv = C_GetAttributeValue(hSession, hPrk, &getTemplate[i], 1);
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_SENSITIVE);
+ }
+}
+
+void ObjectTests::testGetInvalidAttribute()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal data object
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_BBOOL bSign;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_SIGN, &bSign, sizeof(bSign) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSession, CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal data object
+ rv = C_CreateObject(hSession, objTemplate, 1, &hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = C_GetAttributeValue(hSession, hObject, getTemplate, 1);
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_TYPE_INVALID);
+}
diff --git a/src/lib/test/ObjectTests.h b/src/lib/test/ObjectTests.h
--- /dev/null
@@ -0,0 +1,183 @@
+/* $Id: ObjectTests.h 6776 2012-10-25 11:39:46Z rb $ */
+
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectTests.h
+
+ Contains test cases to C_CreateObject, C_DestroyObject, C_GetAttributeValue,
+ C_SetAttributeValue, C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal,
+ C_GenerateKeyPair
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTTESTS_H
+#define _SOFTHSM_V2_OBJECTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class ObjectTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectTests);
+ CPPUNIT_TEST(testCreateObject);
+ CPPUNIT_TEST(testDestroyObject);
+ CPPUNIT_TEST(testGetAttributeValue);
+ CPPUNIT_TEST(testSetAttributeValue);
+ CPPUNIT_TEST(testFindObjects);
+ CPPUNIT_TEST(testGenerateKeys);
+ CPPUNIT_TEST(testDefaultDataAttributes);
+ CPPUNIT_TEST(testDefaultX509CertAttributes);
+ CPPUNIT_TEST(testDefaultRSAPubAttributes);
+ CPPUNIT_TEST(testDefaultRSAPrivAttributes);
+ CPPUNIT_TEST(testAlwaysNeverAttribute);
+ CPPUNIT_TEST(testSensitiveAttributes);
+ CPPUNIT_TEST(testGetInvalidAttribute);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCreateObject();
+ void testDestroyObject();
+ void testGetAttributeValue();
+ void testSetAttributeValue();
+ void testFindObjects();
+ void testGenerateKeys();
+ void testDefaultDataAttributes();
+ void testDefaultX509CertAttributes();
+ void testDefaultRSAPubAttributes();
+ void testDefaultRSAPrivAttributes();
+ void testAlwaysNeverAttribute();
+ void testSensitiveAttributes();
+ void testGetInvalidAttribute();
+
+ void setUp();
+ void tearDown();
+
+protected:
+ void checkCommonObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_OBJECT_CLASS objectClass
+ );
+ void checkCommonStorageObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BBOOL bToken,
+ CK_BBOOL bPrivate,
+ CK_BBOOL bModifiable,
+ CK_UTF8CHAR_PTR pLabel, CK_ULONG ulLabelLen,
+ CK_BBOOL bCopyable
+ );
+ void checkDataObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_UTF8CHAR_PTR pApplication, CK_ULONG ulApplicationLen,
+ CK_BYTE_PTR pObjectID, CK_ULONG ulObjectIdLen,
+ CK_BYTE_PTR pValue, CK_ULONG ulValueLen
+ );
+ void checkCommonCertificateObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_CERTIFICATE_TYPE certType,
+ CK_BBOOL bTrusted,
+ CK_ULONG ulCertificateCategory,
+ CK_BYTE_PTR pCheckValue, CK_ULONG ulCheckValueLen,
+ CK_DATE startDate, CK_ULONG ulStartDateLen,
+ CK_DATE endDate, CK_ULONG ulEndDateLen
+ );
+ void checkX509CertificateObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BYTE_PTR pId, CK_ULONG ulIdLen,
+ CK_BYTE_PTR pIssuer, CK_ULONG ulIssuerLen,
+ CK_BYTE_PTR pSerialNumber, CK_ULONG ulSerialNumberLen,
+ CK_BYTE_PTR pValue, CK_ULONG ulValueLen,
+ CK_BYTE_PTR pUrl, CK_ULONG ulUrlLen,
+ CK_BYTE_PTR pHashOfSubjectPublicKey, CK_ULONG ulHashOfSubjectPublicKeyLen,
+ CK_BYTE_PTR pHashOfIssuerPublicKey, CK_ULONG ulHashOfIssuerPublicKeyLen,
+ CK_ULONG ulJavaMidpSecurityDomain,
+ CK_MECHANISM_TYPE nameHashAlgorithm
+ );
+ void checkCommonKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_KEY_TYPE keyType,
+ CK_BYTE_PTR pId, CK_ULONG ulIdLen,
+ CK_DATE startDate, CK_ULONG ulStartDateLen,
+ CK_DATE endDate, CK_ULONG ulEndDateLen,
+ CK_BBOOL bDerive,
+ CK_BBOOL bLocal,
+ CK_MECHANISM_TYPE keyMechanismType,
+ CK_MECHANISM_TYPE_PTR pAllowedMechanisms, CK_ULONG ulAllowedMechanismsLen /* len = count * sizeof(CK_MECHANISM_TYPE) */
+ );
+ void checkCommonPublicKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BBOOL bEncrypt,
+ CK_BBOOL bVerify,
+ CK_BBOOL bVerifyRecover,
+ CK_BBOOL bWrap,
+ CK_BBOOL bTrusted,
+ CK_ATTRIBUTE_PTR pWrapTemplate, CK_ULONG ulWrapTemplateLen /* len = count * sizeof(CK_ATTRIBUTE) */
+ );
+ void checkCommonPrivateKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BBOOL bSensitive,
+ CK_BBOOL bDecrypt,
+ CK_BBOOL bSign,
+ CK_BBOOL bSignRecover,
+ CK_BBOOL bUnwrap,
+ CK_BBOOL bExtractable,
+ CK_BBOOL bAlwaysSensitive,
+ CK_BBOOL bNeverExtractable,
+ CK_BBOOL bWrapWithTrusted,
+ CK_ATTRIBUTE_PTR pUnwrapTemplate, CK_ULONG ulUnwrapTemplateLen, /* len = count * sizeof(CK_ATTRIBUTE) */
+ CK_BBOOL bAlwaysAuthenticate
+ );
+ void checkCommonRSAPublicKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen,
+ CK_ULONG ulModulusBits,
+ CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen
+ );
+ void checkCommonRSAPrivateKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen,
+ CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen,
+ CK_BYTE_PTR pPrivateExponent, CK_ULONG ulPrivateExponentLen,
+ CK_BYTE_PTR pPrime1, CK_ULONG ulPrime1Len,
+ CK_BYTE_PTR pPrime2, CK_ULONG ulPrime2Len,
+ CK_BYTE_PTR pExponent1, CK_ULONG ulExponent1Len,
+ CK_BYTE_PTR pExponent2, CK_ULONG ulExponent2Len,
+ CK_BYTE_PTR pCoefficient, CK_ULONG ulCoefficientLen
+ );
+
+ CK_RV createDataObjectMinimal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+ CK_RV createDataObjectNormal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+
+ CK_RV createCertificateObjectIncomplete(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+ CK_RV createCertificateObjectValue(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+};
+
+#endif // !_SOFTHSM_V2_OBJECTTESTS_H
diff --git a/src/lib/test/RandomTests.cpp b/src/lib/test/RandomTests.cpp
--- /dev/null
@@ -0,0 +1,122 @@
+/* $Id: RandomTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RandomTests.cpp
+
+ Contains test cases to C_SeedRandom and C_GenerateRandom
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RandomTests.h"
+#include "testconfig.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RandomTests);
+
+void RandomTests::setUp()
+{
+// printf("\nRandomTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ CK_RV rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+}
+
+void RandomTests::tearDown()
+{
+ C_Finalize(NULL_PTR);
+}
+
+void RandomTests::testSeedRandom()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE seed[] = {"Some random data"};
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_SeedRandom(CK_INVALID_HANDLE, seed, sizeof(seed));
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SeedRandom(hSession, NULL_PTR, sizeof(seed));
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_SeedRandom(hSession, seed, sizeof(seed));
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SeedRandom(hSession, seed, sizeof(seed));
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void RandomTests::testGenerateRandom()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE randomData[40];
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GenerateRandom(CK_INVALID_HANDLE, randomData, 40);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GenerateRandom(hSession, NULL_PTR, 40);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GenerateRandom(hSession, randomData, 40);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GenerateRandom(hSession, randomData, 40);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/src/lib/test/RandomTests.h b/src/lib/test/RandomTests.h
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id: RandomTests.h 4923 2010-11-22 13:22:32Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RandomTests.h
+
+ Contains test cases to C_SeedRandom and C_GenerateRandom
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RANDOMTESTS_H
+#define _SOFTHSM_V2_RANDOMTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class RandomTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RandomTests);
+ CPPUNIT_TEST(testSeedRandom);
+ CPPUNIT_TEST(testGenerateRandom);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSeedRandom();
+ void testGenerateRandom();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_RANDOMTESTS_H
diff --git a/src/lib/test/SessionTests.cpp b/src/lib/test/SessionTests.cpp
--- /dev/null
@@ -0,0 +1,204 @@
+/* $Id: SessionTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionTests.cpp
+
+ Contains test cases to C_OpenSession, C_CloseSession, C_CloseAllSessions, and
+ C_GetSessionInfo
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionTests.h"
+#include "testconfig.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionTests);
+
+void SessionTests::setUp()
+{
+// printf("\nSessionTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ CK_RV rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+}
+
+void SessionTests::tearDown()
+{
+ C_Finalize(NULL_PTR);
+}
+
+void SessionTests::testOpenSession()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_OpenSession(SLOT_INVALID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = C_OpenSession(SLOT_NO_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_TOKEN_NOT_RECOGNIZED);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, 0, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_PARALLEL_NOT_SUPPORTED);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SessionTests::testCloseSession()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_CloseSession(CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_CloseSession(hSession + 1);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
+
+void SessionTests::testCloseAllSessions()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_SESSION_INFO info;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_CloseAllSessions(SLOT_INIT_TOKEN);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_CloseAllSessions(SLOT_INVALID);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = C_CloseAllSessions(SLOT_NO_INIT_TOKEN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_CloseAllSessions(SLOT_INIT_TOKEN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
+
+void SessionTests::testGetSessionInfo()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_SESSION_INFO info;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_GetSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetSessionInfo(CK_INVALID_HANDLE, &info);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_GetSessionInfo(hSession + 1, &info);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_GetSessionInfo(hSession, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_GetSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(info.state == CKS_RO_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_GetSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
diff --git a/src/lib/test/SessionTests.h b/src/lib/test/SessionTests.h
--- /dev/null
@@ -0,0 +1,62 @@
+/* $Id: SessionTests.h 4909 2010-09-28 09:13:44Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionTests.h
+
+ Contains test cases to C_OpenSession, C_CloseSession, C_CloseAllSessions, and
+ C_GetSessionInfo
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONTESTS_H
+#define _SOFTHSM_V2_SESSIONTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class SessionTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionTests);
+ CPPUNIT_TEST(testOpenSession);
+ CPPUNIT_TEST(testCloseSession);
+ CPPUNIT_TEST(testCloseAllSessions);
+ CPPUNIT_TEST(testGetSessionInfo);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testOpenSession();
+ void testCloseSession();
+ void testCloseAllSessions();
+ void testGetSessionInfo();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONTESTS_H
+
diff --git a/src/lib/test/SignVerifyTests.cpp b/src/lib/test/SignVerifyTests.cpp
--- /dev/null
@@ -0,0 +1,284 @@
+/* $Id: SignVerifyTests.cpp 6909 2012-12-21 09:58:49Z rb $ */
+
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SignVerifyTests.cpp
+
+ Contains test cases for:
+ C_SignInit
+ C_Sign
+ C_SignUpdate
+ C_SignFinal
+ C_VerifyInit
+ C_Verify
+ C_VerifyUpdate
+ C_VerifyFinal
+
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SignVerifyTests.h"
+#include "testconfig.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SignVerifyTests);
+
+void SignVerifyTests::setUp()
+{
+// printf("\nSignVerifyTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, sopin,sopinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login SO
+ rv = C_Login(hSession,CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Initialize the user pin
+ rv = C_InitPIN(hSession, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SignVerifyTests::tearDown()
+{
+ C_Finalize(NULL_PTR);
+}
+
+CK_RV SignVerifyTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk);
+}
+
+void SignVerifyTests::rsaPkcsSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = C_SignInit(hSession,&mechanism,hPrivateKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv = C_Sign(hSession,data,sizeof(data),signature,&ulSignatureLen);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_VerifyInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_Verify(hSession,data,sizeof(data),signature,ulSignatureLen);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+}
+
+void SignVerifyTests::digestRsaPkcsSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = C_SignInit(hSession,&mechanism,hPrivateKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv =C_SignUpdate(hSession,data,sizeof(data));
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv =C_SignFinal(hSession,signature,&ulSignatureLen);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_VerifyInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_VerifyUpdate(hSession,data,sizeof(data));
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_VerifyFinal(hSession,signature,ulSignatureLen);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = C_VerifyInit(hSession,&mechanism,hPublicKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = C_VerifyUpdate(hSession,data,sizeof(data));
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = C_VerifyFinal(hSession,signature,ulSignatureLen);
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+
+void SignVerifyTests::testRsaSignVerify()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Public Session keys
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaPkcsSignVerify(CKM_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ rsaPkcsSignVerify(CKM_RSA_X_509, hSessionRO, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_MD5_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA1_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA256_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA512_RSA_PKCS, hSessionRO, hPuk,hPrk);
+
+ // Private Session Keys
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaPkcsSignVerify(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ rsaPkcsSignVerify(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+
+ // Public Token Keys
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaPkcsSignVerify(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ rsaPkcsSignVerify(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+
+ // Private Token Keys
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaPkcsSignVerify(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ rsaPkcsSignVerify(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ digestRsaPkcsSignVerify(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+}
+
diff --git a/src/lib/test/SignVerifyTests.h b/src/lib/test/SignVerifyTests.h
--- /dev/null
@@ -0,0 +1,60 @@
+/* $Id: SignVerifyTests.h 6754 2012-10-22 12:45:31Z rb $ */
+
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SignVerifyTests.h
+
+ Contains test cases to C_SignInit,C_Sign,C_SignUpdate,C_SignFinal,
+ C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SIGNVERIFYTESTS_H
+#define _SOFTHSM_V2_SIGNVERIFYTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class SignVerifyTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SignVerifyTests);
+ CPPUNIT_TEST(testRsaSignVerify);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaSignVerify();
+
+ void setUp();
+ void tearDown();
+
+protected:
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void rsaPkcsSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+ void digestRsaPkcsSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+};
+
+#endif // !_SOFTHSM_V2_SIGNVERIFYTESTS_H
diff --git a/src/lib/test/TokenTests.cpp b/src/lib/test/TokenTests.cpp
--- /dev/null
@@ -0,0 +1,104 @@
+/* $Id: TokenTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TokenTests.cpp
+
+ Contains test cases to C_InitToken
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "TokenTests.h"
+#include "testconfig.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TokenTests);
+
+void TokenTests::setUp()
+{
+// printf("\nTokenTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+}
+
+void TokenTests::tearDown()
+{
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+}
+
+void TokenTests::testInitToken()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR label[32];
+ CK_SESSION_HANDLE hSession;
+
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // Just make sure that we finalize any previous failed tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_InitToken(SLOT_INIT_TOKEN, NULL_PTR, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_InitToken(SLOT_INVALID, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ // Initialize
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Initialize with wrong password
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength - 1, label);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_EXISTS);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Re-initialize
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ C_Finalize(NULL_PTR);
+}
diff --git a/src/lib/test/TokenTests.h b/src/lib/test/TokenTests.h
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id: TokenTests.h 4905 2010-09-17 16:02:27Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TokenTests.h
+
+ Contains test cases to C_InitToken
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TOKENTESTS_H
+#define _SOFTHSM_V2_TOKENTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class TokenTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(TokenTests);
+ CPPUNIT_TEST(testInitToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInitToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_TOKENTESTS_H
+
diff --git a/src/lib/test/UserTests.cpp b/src/lib/test/UserTests.cpp
--- /dev/null
@@ -0,0 +1,313 @@
+/* $Id: UserTests.cpp 6717 2012-10-02 00:04:31Z rene $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UserTests.cpp
+
+ Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "UserTests.h"
+#include "testconfig.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(UserTests);
+
+void UserTests::setUp()
+{
+// printf("\nUserTests\n");
+
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ CK_RV rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+}
+
+void UserTests::tearDown()
+{
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+}
+
+void UserTests::testInitPIN()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_InitPIN(hSession, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_InitPIN(hSession, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ rv = C_Login(hSession, CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_InitPIN(CK_INVALID_HANDLE, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_InitPIN(hSession, pin, 0);
+ CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);
+
+ rv = C_InitPIN(hSession, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void UserTests::testLogin()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession[2];
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Set up user PIN
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_PIN_NOT_INITIALIZED);
+ rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitPIN(hSession[0], pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+
+ rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(CK_INVALID_HANDLE, CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_Login(hSession[0], CKU_SO, NULL_PTR, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_Login(hSession[0], CKU_SO, sopin, 0);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession[1]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY_EXISTS);
+
+ rv = C_CloseSession(hSession[1]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = C_Logout(hSession[0]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_SO, sopin, sopinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
+
+ rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = C_Logout(hSession[0]);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_USER, pin, pinLength - 1);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession[0], CKU_USER, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
+}
+
+void UserTests::testLogout()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG pinLength = sizeof(pin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ rv = C_Logout(hSession);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession, CKU_SO, pin, pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Logout(CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_Logout(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Logout(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void UserTests::testSetPIN()
+{
+ CK_RV rv;
+ CK_UTF8CHAR pin1[] = SLOT_0_USER1_PIN;
+ CK_ULONG pin1Length = sizeof(pin1) - 1;
+ CK_UTF8CHAR pin2[] = SLOT_0_USER2_PIN;
+ CK_ULONG pin2Length = sizeof(pin2) - 1;
+ CK_UTF8CHAR so1pin[] = SLOT_0_SO1_PIN;
+ CK_ULONG so1pinLength = sizeof(so1pin) - 1;
+ CK_UTF8CHAR so2pin[] = SLOT_0_SO2_PIN;
+ CK_ULONG so2pinLength = sizeof(so2pin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ C_Finalize(NULL_PTR);
+
+ // Set up user PIN
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = C_InitPIN(hSession, pin1, pin1Length);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ C_Finalize(NULL_PTR);
+
+ rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = C_Initialize(NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SetPIN(CK_INVALID_HANDLE, pin1, pin1Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ rv = C_CloseSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SetPIN(hSession, NULL_PTR, pin1Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_SetPIN(hSession, pin1, pin1Length, NULL_PTR, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = C_SetPIN(hSession, pin1, pin1Length, pin2, 0);
+ CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);
+
+ rv = C_SetPIN(hSession, pin2, pin2Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession, CKU_USER, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SetPIN(hSession, pin1, pin1Length, pin2, pin2Length);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_SetPIN(hSession, pin2, pin2Length, pin1, pin1Length);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = C_Logout(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_Login(hSession, CKU_SO, so1pin, so1pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SetPIN(hSession, so2pin, so2pinLength, so2pin, so2pinLength);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_SetPIN(hSession, so1pin, so1pinLength, so2pin, so2pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = C_SetPIN(hSession, so1pin, so1pinLength, so1pin, so1pinLength);
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = C_SetPIN(hSession, so2pin, so2pinLength, so1pin, so1pinLength);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/src/lib/test/UserTests.h b/src/lib/test/UserTests.h
--- /dev/null
+++ b/src/lib/test/UserTests.h
@@ -0,0 +1,61 @@
+/* $Id: UserTests.h 4913 2010-09-29 09:16:31Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UserTests.h
+
+ Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_USERTESTS_H
+#define _SOFTHSM_V2_USERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "cryptoki.h"
+
+class UserTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(UserTests);
+ CPPUNIT_TEST(testInitPIN);
+ CPPUNIT_TEST(testLogin);
+ CPPUNIT_TEST(testLogout);
+ CPPUNIT_TEST(testSetPIN);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInitPIN();
+ void testLogin();
+ void testLogout();
+ void testSetPIN();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_USERTESTS_H
+
diff --git a/src/lib/test/p11test.cpp b/src/lib/test/p11test.cpp
--- /dev/null
+++ b/src/lib/test/p11test.cpp
@@ -0,0 +1,48 @@
+/* $Id: p11test.cpp 6738 2012-10-15 21:28:14Z rb $
+
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ p11test.cpp
+
+ The main test executor for tests on the PKCS#11 interface in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+int main(int argc, char* argv[])
+{
+ CppUnit::TextUi::TestRunner runner;
+ CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ bool wasSucessful = runner.run();
+
+ return wasSucessful ? 0 : 1;
+}
+
diff --git a/src/lib/test/softhsm2.conf.in b/src/lib/test/softhsm2.conf.in
--- /dev/null
@@ -0,0 +1,3 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @builddir@/tokens
diff --git a/src/lib/test/testconfig.h b/src/lib/test/testconfig.h
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id: testconfig.h 4913 2010-09-29 09:16:31Z rb $ */
+
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ testconfig.h
+
+ Contains parameters for the test cases
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TESTCONFIG_H
+#define _SOFTHSM_V2_TESTCONFIG_H
+
+// Slots
+#define SLOT_INVALID 9999
+#define SLOT_INIT_TOKEN 0
+#define SLOT_NO_INIT_TOKEN 1
+
+// PIN
+#define SLOT_0_SO1_PIN "12345678"
+#define SLOT_0_SO2_PIN "123456789"
+#define SLOT_0_USER1_PIN "1234"
+#define SLOT_0_USER2_PIN "12345"
+
+#endif // !_SOFTHSM_V2_TESTCONFIG_H
+
diff --git a/src/lib/test/tokens/dummy.in b/src/lib/test/tokens/dummy.in
diff --git a/testing/build-botan.sh b/testing/build-botan.sh
--- /dev/null
+++ b/testing/build-botan.sh
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+source `dirname "$0"`/lib.sh && init || exit 1
+
+BOTAN="Botan-1.10.3"
+BOTAN_URL="http://botan.randombit.net/files/$BOTAN.tgz"
+BOTAN_FILENAME="$BOTAN.tgz"
+BOTAN_HASH_TYPE="sha1"
+BOTAN_HASH="0c0b2f6337d94245a32e215047311526652a114d"
+
+check_if_built botan && exit 0
+start_build botan
+
+BOTAN_SRC=`fetch_src "$BOTAN_URL" "$BOTAN_FILENAME" "$BOTAN_HASH_TYPE" "$BOTAN_HASH"`
+
+build_ok=0
+case "$DISTRIBUTION" in
+ centos | \
+ redhat | \
+ fedora | \
+ sl | \
+ ubuntu | \
+ debian | \
+ opensuse | \
+ suse | \
+ freebsd )
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ ./configure.py --prefix="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+ netbsd )
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ python2.7 ./configure.py --prefix="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+ sunos )
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ ./configure.py --prefix="$INSTALL_ROOT" \
+ --disable-asm \
+ --cpu=i686 &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+ openbsd )
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ python2.7 ./configure.py --prefix="$INSTALL_ROOT" \
+ --disable-asm &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+esac
+
+finish
+
+if [ "$build_ok" -eq 1 ]; then
+ set_build_ok botan || exit 1
+ exit 0
+fi
+
+exit 1
diff --git a/testing/build-softhsm2-botan.sh b/testing/build-softhsm2-botan.sh
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/env bash
+source `dirname "$0"`/lib.sh && init || exit 1
+
+require botan
+
+check_if_built softhsm2 && exit 0
+start_build softhsm2
+
+build_ok=0
+case "$DISTRIBUTION" in
+ openbsd )
+ export AUTOCONF_VERSION="2.68"
+ export AUTOMAKE_VERSION="1.11"
+ append_ldflags "-L/usr/local/lib"
+ ;;
+esac
+case "$DISTRIBUTION" in
+ centos | \
+ redhat | \
+ fedora | \
+ sl | \
+ debian | \
+ ubuntu | \
+ opensuse )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+ netbsd )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" \
+ --with-sqlite3=/usr/pkg &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+ freebsd | \
+ openbsd )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" \
+ --with-sqlite3=/usr/local &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+ sunos | \
+ suse )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+esac
+
+finish
+
+if [ "$build_ok" -eq 1 ]; then
+ set_build_ok softhsm2 || exit 1
+ exit 0
+fi
+
+exit 1
diff --git a/testing/lib.sh b/testing/lib.sh
--- /dev/null
+++ b/testing/lib.sh
@@ -0,0 +1,2119 @@
+exit ()
+{
+ if [ -n "$_CLEANUP_TEST" ]; then
+ rm -f "$WORKSPACE_ROOT/.testing" 2>/dev/null
+ rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+ fi
+
+ if [ -n "$_SYSLOG_TRACE_PID" ]; then
+ case "$DISTRIBUTION" in
+ debian | \
+ ubuntu | \
+ redhat | \
+ centos | \
+ sl | \
+ opensuse | \
+ suse | \
+ freebsd | \
+ netbsd | \
+ openbsd | \
+ sunos )
+ kill -TERM "$_SYSLOG_TRACE_PID" 2>/dev/null &&
+ {
+ wait "$_SYSLOG_TRACE_PID"
+ unset _SYSLOG_TRACE_PID
+ }
+ ;;
+ esac
+ fi
+
+ builtin exit $*
+}
+
+append_path ()
+{
+ if [ -d "$1" ]; then
+ if [ -n "$PATH" ]; then
+ echo "$PATH" | $GREP -q -- "$1:" 2>/dev/null && return;
+ echo "$PATH" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ PATH="$PATH:$1"
+ else
+ PATH="$1"
+ fi
+ export PATH
+ fi
+}
+
+prepend_path ()
+{
+ if [ -d "$1" ]; then
+ if [ -n "$PATH" ]; then
+ echo "$PATH" | $GREP -q -- "$1:" 2>/dev/null && return;
+ echo "$PATH" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ PATH="$1:$PATH"
+ else
+ PATH="$1"
+ fi
+ export PATH
+ fi
+}
+
+append_cflags ()
+{
+ if [ -n "$1" ]; then
+ if [ -n "$CFLAGS" ]; then
+ echo "$CFLAGS" | $GREP -q -- "$1 " 2>/dev/null && return;
+ echo "$CFLAGS" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ CFLAGS="$CFLAGS $1"
+ else
+ CFLAGS="$1"
+ fi
+ export CFLAGS
+ fi
+}
+
+append_cppflags ()
+{
+ if [ -n "$1" ]; then
+ if [ -n "$CPPFLAGS" ]; then
+ echo "$CPPFLAGS" | $GREP -q -- "$1 " 2>/dev/null && return;
+ echo "$CPPFLAGS" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ CPPFLAGS="$CPPFLAGS $1"
+ else
+ CPPFLAGS="$1"
+ fi
+ export CPPFLAGS
+ fi
+}
+
+append_ldflags ()
+{
+ if [ -n "$1" ]; then
+ if [ -n "$LDFLAGS" ]; then
+ echo "$LDFLAGS" | $GREP -q -- "$1 " 2>/dev/null && return;
+ echo "$LDFLAGS" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ LDFLAGS="$LDFLAGS $1"
+ else
+ LDFLAGS="$1"
+ fi
+ export LDFLAGS
+ fi
+}
+
+append_ld_library_path ()
+{
+ if [ -d "$1" ]; then
+ if [ -n "$LD_LIBRARY_PATH" ]; then
+ echo "$LD_LIBRARY_PATH" | $GREP -q -- "$1:" 2>/dev/null && return;
+ echo "$LD_LIBRARY_PATH" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$1"
+ else
+ LD_LIBRARY_PATH="$1"
+ fi
+ export LD_LIBRARY_PATH
+ fi
+}
+
+find_jenkins_workspace_root ()
+{
+ if [ -z "$WORKSPACE" -o ! -d "$WORKSPACE" ]; then
+ echo "find_jenkins_workspace_root: Unable to find workspace root since no WORKSPACE has been defined" >&2
+ return 1
+ fi
+
+ local workspace="$WORKSPACE"
+ local max_iter=20
+ local currdir
+
+ while [ "$max_iter" -gt 0 ] 2>/dev/null; do
+ # check if the last dir on the path is workspace
+ currdir=`echo "$workspace" | sed 's%.*/%%' 2>/dev/null`
+ if [ "$currdir" = "workspace" ]; then
+ break
+ fi
+
+ # remove the last dir on the path
+ workspace=`echo "$workspace" | sed 's%/[^/]*$%%' 2>/dev/null`
+
+ max_iter=$(( max_iter - 1))
+ done
+
+ if [ -n "$workspace" -a "$max_iter" -gt 0 ] 2>/dev/null; then
+ WORKSPACE_ROOT="$workspace"
+ return 0
+ fi
+
+ echo "find_jenkins_workspace_root: Failed to find workspace root in WORKSPACE=$WORKSPACE" >&2
+ return 1
+}
+
+find_program ()
+{
+ if [ -n "$1" ]; then
+ local path=`which "$1" 2>/dev/null`
+ if [ -n "$path" -a -x "$path" ]; then
+ echo "$path"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+find_make ()
+{
+ local make
+ local program
+ local programs="gmake make"
+
+ case "$DISTRIBUTION" in
+ freebsd )
+ programs="gmake"
+ ;;
+ esac
+
+ for program in $programs; do
+ make=`find_program "$program"`
+ if [ -n "$make" ]; then
+ export MAKE="$make"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_m4 ()
+{
+ local m4
+ local program
+
+ for program in gm4 m4; do
+ m4=`find_program "$program"`
+ if [ -n "$m4" ]; then
+ export M4="$m4"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_md5sum ()
+{
+ local md5sum
+ local program
+
+ for program in md5sum gmd5sum md5; do
+ md5sum=`find_program "$program"`
+ if [ -n "$md5sum" ]; then
+ MD5SUM="$md5sum"
+ case "$program" in
+ md5)
+ MD5SUM="$MD5SUM -q"
+ ;;
+ esac
+ export MD5SUM
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_sha1sum ()
+{
+ local shasum
+ local program
+
+ for program in sha1sum gsha1sum shasum sha1; do
+ shasum=`find_program "$program"`
+ if [ -n "$shasum" ]; then
+ SHA1SUM="$shasum"
+ case "$program" in
+ shasum)
+ SHA1SUM="$SHA1SUM -a 1"
+ ;;
+ sha1)
+ SHA1SUM="$SHA1SUM -q"
+ ;;
+ esac
+ export SHA1SUM
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_sha256sum ()
+{
+ local sha256sum
+ local program
+
+ for program in sha256sum gsha256sum shasum sha256; do
+ sha256sum=`find_program "$program"`
+ if [ -n "$sha256sum" ]; then
+ SHA256SUM="$shasum"
+ case "$program" in
+ shasum)
+ SHA256SUM="$SHA256SUM -a 256"
+ ;;
+ sha256)
+ SHA256SUM="$SHA256SUM -q"
+ ;;
+ esac
+ export SHA256SUM
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_wget ()
+{
+ local wget
+ local program
+
+ for program in wget; do
+ wget=`find_program "$program"`
+ if [ -n "$wget" ]; then
+ export WGET="$wget"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_ccache ()
+{
+ local ccache
+ local program
+ local path
+
+ for program in ccache; do
+ ccache=`find_program "$program"`
+ if [ -n "$ccache" ]; then
+ export CCACHE="$ccache"
+ for path in /usr/lib64/ccache /usr/lib/ccache /usr/local/lib64/ccache /usr/local/lib/ccache; do
+ if [ -d "$path" ]; then
+ prepend_path "$path"
+ break
+ fi
+ done
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_cc ()
+{
+ local cc
+ local program
+
+ for program in cc gcc; do
+ cc=`find_program "$program"`
+ if [ -n "$cc" ]; then
+ export CC="$cc"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_cxx ()
+{
+ local cxx
+ local program
+
+ for program in c++ g++; do
+ cxx=`find_program "$program"`
+ if [ -n "$cxx" ]; then
+ export CXX="$cxx"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_tee ()
+{
+ local tee
+ local program
+
+ for program in tee; do
+ tee=`find_program "$program"`
+ if [ -n "$tee" ]; then
+ export TEE="$tee"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_date ()
+{
+ local date
+ local program
+ local time_now
+
+ for program in date; do
+ date=`find_program "$program"`
+ if [ -n "$date" ]; then
+ time_now=`$date '+%s' 2>/dev/null`
+ if [ -n "$time_now" -a "$time_now" -gt 0 ] 2>/dev/null; then
+ export DATE="$date"
+ return 0
+ fi
+ fi
+ done
+
+ return 1
+}
+
+find_tail ()
+{
+ local tail
+ local tail_follow
+ local program
+ local programs="tail"
+
+ case "$DISTRIBUTION" in
+ sunos )
+ programs="gtail"
+ ;;
+ esac
+
+ for program in $programs; do
+ tail=`find_program "$program"`
+ if [ -n "$tail" ]; then
+ break
+ fi
+ done
+
+ if [ -z "$tail" ]; then
+ return 1
+ fi
+
+ case "$DISTRIBUTION" in
+ debian | \
+ ubuntu | \
+ redhat | \
+ centos | \
+ sl | \
+ opensuse | \
+ suse | \
+ sunos )
+ tail_follow="$tail --follow=name -n 0"
+ ;;
+ freebsd | \
+ netbsd )
+ tail_follow="$tail -f -F -n 0"
+ ;;
+ openbsd )
+ tail_follow="$tail -f -n 0"
+ ;;
+ esac
+
+ if [ -z "$tail_follow" ]; then
+ return 1
+ fi
+
+ export TAIL="$tail"
+ export TAIL_FOLLOW="$tail_follow"
+
+ return 0
+}
+
+find_grep ()
+{
+ local grep
+ local program
+
+ for program in ggrep grep; do
+ grep=`find_program "$program"`
+ if [ -n "$grep" ]; then
+ export GREP="$grep"
+ return
+ fi
+ done
+
+ return 1
+}
+
+setup_install_root ()
+{
+ if [ -n "$INSTALL_ROOT" ]; then
+ if [ -d "$INSTALL_ROOT" ]; then
+ return 0
+ else
+ return 1
+ fi
+ fi
+
+ if [ ! -d "$WORKSPACE_ROOT/root" ]; then
+ if ! mkdir -p "$WORKSPACE_ROOT/root" 2>/dev/null; then
+ echo "setup_install_root: Unable to create INSTALL_ROOT at $WORKSPACE_ROOT/root" >&2
+ return 1
+ fi
+ fi
+
+ if [ -n "$INSTALL_TAG" ]; then
+ if [ ! -d "$WORKSPACE_ROOT/root/$INSTALL_TAG" ]; then
+ if ! mkdir -p "$WORKSPACE_ROOT/root/$INSTALL_TAG" 2>/dev/null; then
+ echo "setup_install_root: Unable to create INSTALL_ROOT at $WORKSPACE_ROOT/root/$INSTALL_TAG" >&2
+ return 1
+ fi
+ fi
+
+ INSTALL_ROOT="$WORKSPACE_ROOT/root/$INSTALL_TAG"
+
+ if [ -d "$INSTALL_ROOT/bin" ]; then
+ prepend_path "$INSTALL_ROOT/bin"
+ fi
+ if [ -d "$INSTALL_ROOT/sbin" ]; then
+ prepend_path "$INSTALL_ROOT/sbin"
+ fi
+ if [ -d "$INSTALL_ROOT/lib64" ]; then
+ append_ldflags "-L$INSTALL_ROOT/lib64"
+ append_ld_library_path "$INSTALL_ROOT/lib64"
+ fi
+ if [ -d "$INSTALL_ROOT/lib" ]; then
+ append_ldflags "-L$INSTALL_ROOT/lib"
+ append_ld_library_path "$INSTALL_ROOT/lib"
+ fi
+ if [ -d "$INSTALL_ROOT/include" ]; then
+ append_cflags "-I$INSTALL_ROOT/include"
+ append_cppflags "-I$INSTALL_ROOT/include"
+ fi
+
+ return 0
+ fi
+
+ echo "setup_install_root: INSTALL_TAG or INSTALL_ROOT is not set, need to know in where to build/test" >&2
+ return 1
+}
+
+detect_distribution ()
+{
+ DISTRIBUTION="UNKNOWN"
+
+ if [ -f "/etc/debian_version" ]; then
+ if uname -a 2>/dev/null | $GREP -q -i ubuntu 2>/dev/null; then
+ DISTRIBUTION="ubuntu"
+ else
+ DISTRIBUTION="debian"
+ fi
+ elif [ -f "/etc/redhat-release" ]; then
+ if $GREP -q -i centos /etc/redhat-release 2>/dev/null; then
+ DISTRIBUTION="centos"
+ elif $GREP -q -i fedora /etc/redhat-release 2>/dev/null; then
+ DISTRIBUTION="fedora"
+ elif $GREP -q -i "scientific linux" /etc/redhat-release 2>/dev/null; then
+ DISTRIBUTION="sl"
+ else
+ DISTRIBUTION="redhat"
+ fi
+ elif [ -f "/etc/os-release" ]; then
+ if $GREP -q -i opensuse /etc/os-release 2>/dev/null; then
+ DISTRIBUTION="opensuse"
+ fi
+ elif [ -f "/etc/SuSE-release" ]; then
+ if $GREP -q -i "suse linux enterprise" /etc/SuSE-release 2>/dev/null; then
+ DISTRIBUTION="suse"
+ fi
+ elif uname -a 2>/dev/null | $GREP -q -i freebsd 2>/dev/null; then
+ DISTRIBUTION="freebsd"
+ elif uname -a 2>/dev/null | $GREP -q -i sunos 2>/dev/null; then
+ DISTRIBUTION="sunos"
+ elif uname -a 2>/dev/null | $GREP -q -i openbsd 2>/dev/null; then
+ DISTRIBUTION="openbsd"
+ elif uname -a 2>/dev/null | $GREP -q -i netbsd 2>/dev/null; then
+ DISTRIBUTION="netbsd"
+ fi
+
+ export DISTRIBUTION
+}
+
+init ()
+{
+ unset _CLEANUP_TEST
+ unset _SYSLOG_TRACE_PID
+ unset PRE_TEST
+ unset POST_TEST
+
+ find_grep || exit 1
+ detect_distribution
+ find_jenkins_workspace_root || exit 1
+ setup_install_root || exit 1
+ find_make || exit 1
+ find_m4 || exit 1
+ find_wget || exit 1
+ find_md5sum || exit 1
+ find_sha1sum || exit 1
+ find_sha256sum || exit 1
+ find_ccache # ccache needs to be found before cc/cxx
+ find_cc || exit 1
+ find_cxx || exit 1
+ find_tee || exit 1
+ find_date || exit 1
+ find_tail || exit 1
+
+ return 0
+}
+
+finish ()
+{
+ local core
+
+ find "$WORKSPACE" "$INSTALL_ROOT" -name '*core' -type f 2>/dev/null | while read core; do
+ chmod a+r "$core" 2>/dev/null
+ done
+}
+
+check_if_built ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: check_if_built <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$SVN_REVISION" ]; then
+ echo "check_if_built: No SVN_REVISION is set, can't check if build is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$WORKSPACE/.$name_tag.build" ]; then
+ local build_svn_rev=`cat "$WORKSPACE/.$name_tag.build" 2>/dev/null`
+
+ if [ "$SVN_REVISION" = "$build_svn_rev" ]; then
+ if [ -f "$INSTALL_ROOT/.$name_tag.build" ]; then
+ local build_svn_rev=`cat "$INSTALL_ROOT/.$name_tag.build" 2>/dev/null`
+
+ if [ "$SVN_REVISION" = "$build_svn_rev" ]; then
+ return 0
+ fi
+ fi
+ fi
+ fi
+
+ return 1
+}
+
+start_build ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: start_build <name tag>" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok" ]; then
+ if ! rm "$INSTALL_ROOT/.$name_tag.ok" 2>/dev/null; then
+ echo "start_build: can't remove old ok file $INSTALL_ROOT/.$name_tag.ok !" >&2
+ exit 1
+ fi
+ fi
+
+ echo "start_build: Starting build for $name_tag on $DISTRIBUTION"
+ return 0
+}
+
+set_build_ok ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: set_build_ok <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$SVN_REVISION" ]; then
+ echo "set_build_ok: No SVN_REVISION is set, can't check if build is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok" ]; then
+ echo "set_build_ok: Build already mark ok, this should not happend. Did you forget to start_build?" >&2
+ exit 1
+ fi
+
+ echo "$SVN_REVISION" > "$WORKSPACE/.$name_tag.build"
+
+ if [ -f "$WORKSPACE/.$name_tag.build" ]; then
+ local build_svn_rev=`cat "$WORKSPACE/.$name_tag.build" 2>/dev/null`
+
+ if [ "$SVN_REVISION" != "$build_svn_rev" ]; then
+ echo "set_build_ok: Can't tag build file $WORKSPACE/.$name_tag.build !" >&2
+ return 1
+ fi
+ else
+ echo "set_build_ok: Can't tag build file $WORKSPACE/.$name_tag.build !" >&2
+ return 1
+ fi
+
+ echo "$SVN_REVISION" > "$INSTALL_ROOT/.$name_tag.build"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.build" ]; then
+ local build_svn_rev=`cat "$INSTALL_ROOT/.$name_tag.build" 2>/dev/null`
+
+ if [ "$SVN_REVISION" = "$build_svn_rev" ]; then
+ if ! touch "$INSTALL_ROOT/.$name_tag.ok" 2>/dev/null; then
+ echo "set_build_ok: Can't tag build ok $INSTALL_ROOT/.$name_tag.ok !" >&2
+ return 1
+ fi
+ return 0
+ fi
+ fi
+
+ echo "set_build_ok: Was not able to tag build ok!" >&2
+ return 1
+}
+
+check_if_tested ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: check_if_tested <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$SVN_REVISION" ]; then
+ echo "check_if_tested: No SVN_REVISION is set, can't check if test is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$WORKSPACE/.$name_tag.test" ]; then
+ local build_svn_rev=`cat "$WORKSPACE/.$name_tag.test" 2>/dev/null`
+
+ if [ "$SVN_REVISION" = "$build_svn_rev" ]; then
+ if [ -f "$INSTALL_ROOT/.$name_tag.test" ]; then
+ local build_svn_rev=`cat "$INSTALL_ROOT/.$name_tag.test" 2>/dev/null`
+
+ if [ "$SVN_REVISION" = "$build_svn_rev" ]; then
+ return 0
+ fi
+ fi
+ fi
+ fi
+
+ return 1
+}
+
+start_test ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: start_test <name tag>" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+# local time_start=`$DATE '+%s' 2>/dev/null`
+# local timeout=3600
+# local time_stop=$(( time_start + timeout ))
+# local time_now
+# local build_tag
+#
+# echo "$BUILD_TAG $$" > "$WORKSPACE_ROOT/.testing.$$"
+# build_tag=`cat "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null`
+# if [ "$build_tag" != "$BUILD_TAG $$" ]; then
+# echo "start_test: Unable to add test lock!" >&2
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# return 1
+# fi
+#
+# while true; do
+# if [ ! -f "$WORKSPACE_ROOT/.testing" ]; then
+# if ln -s "$WORKSPACE_ROOT/.testing.$$" "$WORKSPACE_ROOT/.testing" 2>/dev/null; then
+# build_tag=`cat "$WORKSPACE_ROOT/.testing" 2>/dev/null`
+# if [ "$build_tag" = "$BUILD_TAG $$" ]; then
+# if [ -f "$INSTALL_ROOT/.$name_tag.ok.test" ]; then
+# if ! rm "$INSTALL_ROOT/.$name_tag.ok.test" 2>/dev/null; then
+# echo "start_test: can't remove old ok file $INSTALL_ROOT/.$name_tag.ok.test !" >&2
+# exit 1
+# fi
+# fi
+# export _CLEANUP_TEST=1
+# return 0
+# fi
+# fi
+# fi
+#
+# if [ -z "$time_now" ]; then
+# echo "start_test: waiting for other tests to finish (timeout $timeout)"
+# fi
+#
+# time_now=`$DATE '+%s' 2>/dev/null`
+# if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+# break
+# fi
+# if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+# echo "start_test: Invalid timestamp from date!" >&2
+# exit 1
+# fi
+# sleep 2
+# done
+#
+# echo "start_test: Unable to get test lock, timeout" >&2
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# exit 1
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok.test" ]; then
+ if ! rm "$INSTALL_ROOT/.$name_tag.ok.test" 2>/dev/null; then
+ echo "start_test: can't remove old ok file $INSTALL_ROOT/.$name_tag.ok.test !" >&2
+ exit 1
+ fi
+ fi
+
+ echo "start_test: Starting test for $name_tag on $DISTRIBUTION"
+ return 0
+}
+
+stop_test ()
+{
+# local build_tag
+#
+# if [ ! -f "$WORKSPACE_ROOT/.testing" ]; then
+# echo "stop_test: Called without a test lock file, this should not happen!" >&2
+# return 1
+# fi
+#
+# build_tag=`cat "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null`
+# if [ "$build_tag" != "$BUILD_TAG $$" ]; then
+# echo "stop_test: Our test lock does not exist or is not our own!" >&2
+# return 1
+# fi
+#
+# build_tag=`cat "$WORKSPACE_ROOT/.testing" 2>/dev/null`
+# if [ "$build_tag" != "$BUILD_TAG $$" ]; then
+# echo "stop_test: Content of test lock changed during test!" >&2
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# return 1
+# fi
+#
+# rm -f "$WORKSPACE_ROOT/.testing" 2>/dev/null
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# export _CLEANUP_TEST=""
+ return 0
+}
+
+set_test_ok ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: set_test_ok <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$SVN_REVISION" ]; then
+ echo "set_test_ok: No SVN_REVISION is set, can't check if test is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok.test" ]; then
+ echo "set_test_ok: Test already mark ok, this should not happend. Did you forget to start_test?" >&2
+ exit 1
+ fi
+
+ echo "$SVN_REVISION" > "$WORKSPACE/.$name_tag.test"
+
+ if [ -f "$WORKSPACE/.$name_tag.test" ]; then
+ local test_svn_rev=`cat "$WORKSPACE/.$name_tag.test" 2>/dev/null`
+
+ if [ "$SVN_REVISION" != "$test_svn_rev" ]; then
+ echo "set_test_ok: Can't tag test file $WORKSPACE/.$name_tag.test !" >&2
+ return 1
+ fi
+ else
+ echo "set_test_ok: Can't tag test file $WORKSPACE/.$name_tag.test !" >&2
+ return 1
+ fi
+
+ echo "$SVN_REVISION" > "$INSTALL_ROOT/.$name_tag.test"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.test" ]; then
+ local test_svn_rev=`cat "$INSTALL_ROOT/.$name_tag.test" 2>/dev/null`
+
+ if [ "$SVN_REVISION" = "$test_svn_rev" ]; then
+ if ! touch "$INSTALL_ROOT/.$name_tag.ok.test" 2>/dev/null; then
+ echo "set_test_ok: Can't tag test ok $INSTALL_ROOT/.$name_tag.ok.test !" >&2
+ return 1
+ fi
+ return 0
+ fi
+ fi
+
+ echo "set_test_ok: Was not able to tag test ok!" >&2
+ return 1
+}
+
+
+require ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: require <name tag>" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ ! -f "$INSTALL_ROOT/.$name_tag.ok" ]; then
+ echo "require: Required program $name_tag not found or not built!" >&2
+ exit 1
+ fi
+
+ if [ ! -f "$INSTALL_ROOT/.$name_tag.build" ]; then
+ echo "require: Required program $name_tag corrupt, can't find build version!" >&2
+ exit 1
+ fi
+
+ local require_svn_rev=`cat "$INSTALL_ROOT/.$name_tag.build" 2>/dev/null`
+
+ if [ -z "$require_svn_rev" ]; then
+ echo "require: There is no build version for $name_tag!" >&2
+ exit 1
+ fi
+
+ export SVN_REVISION="$SVN_REVISION-$name_tag:$require_svn_rev"
+}
+
+check_hash ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: check_hash <filename> <type> <hash>" >&2
+ exit 1
+ fi
+
+ local filename="$1"
+ local type="$2"
+ local hash="$3"
+ local file_hash
+
+ if [ -f "$filename" ]; then
+ case "$type" in
+ md5)
+ file_hash=`$MD5SUM "$filename" 2>/dev/null | awk '{print $1}'`
+ ;;
+ sha1)
+ file_hash=`$SHA1SUM "$filename" 2>/dev/null | awk '{print $1}'`
+ ;;
+ sha256)
+ file_hash=`$SHA256SUM "$filename" 2>/dev/null | awk '{print $1}'`
+ ;;
+ esac
+ if [ -n "$file_hash" -a "$hash" = "$file_hash" ]; then
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+fetch_src ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ]; then
+ echo "usage: fetch_src <url> <filename> <type> <hash>" >&2
+ exit 1
+ fi
+
+ local url="$1"
+ local filename="$2"
+ local type="$3"
+ local hash="$4"
+ local path_filename
+
+ if [ ! -d "$WORKSPACE_ROOT/cache" ]; then
+ if ! mkdir -p "$WORKSPACE_ROOT/cache" 2>/dev/null; then
+ echo "fetch_src: Unable to create cache directory $WORKSPACE_ROOT/cache!" >&2
+ exit 1
+ fi
+ fi
+
+ path_filename="$WORKSPACE_ROOT/cache/$filename"
+
+ if [ -f "$path_filename" ]; then
+ if check_hash "$path_filename" "$type" "$hash"; then
+ echo "$path_filename"
+ return 0
+ fi
+ if ! rm "$path_filename" 2>/dev/null; then
+ echo "fetch_src: Unable to remove old invalid file $path_filename!" >&2
+ exit 1
+ fi
+ fi
+
+ if ! $WGET -O "$path_filename" "$url" 2>/dev/null; then
+ echo "fetch_src: wget failed!" >&2
+ rm -f "$path_filename" 2>/dev/null
+ exit 1
+ fi
+
+ if [ ! -f "$path_filename" ]; then
+ echo "fetch_src: File at $url not found at $path_filename!" >&2
+ exit 1
+ fi
+
+ if ! check_hash "$path_filename" "$type" "$hash"; then
+ echo "fetch_src: Checksum does not match for $path_filename!" >&2
+ exit 1
+ fi
+
+ echo "$path_filename"
+}
+
+log_init ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_this <log name>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+
+ touch "$log_stderr" "$log_stdout"
+}
+
+log_this ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: log_this <log name> <command> [options ...]" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ shift
+
+ touch "$log_stderr" "$log_stdout"
+
+ echo "log_this: logging $name for command: $*"
+ $* 2>>"$log_stderr" >>"$log_stdout"
+}
+
+log_this_timeout ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: log_this_timeout <log name> <timeout in seconds> <command ... >" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$2"
+ local pid
+ shift 2
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "log_this_timeout: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "log_this_timeout: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "log_this_timeout: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ touch "$log_stderr" "$log_stdout"
+
+ echo "log_this_timeout: logging $name with timeout $timeout for command: $*"
+ ( $* 2>>"$log_stderr" >>"$log_stdout" ) &
+ pid="$!"
+
+ if [ -z "$pid" -o "$pid" -le 0 ] 2>/dev/null; then
+ echo "log_this_timeout: No pid from backgrounded program?" >&2
+ return 1
+ fi
+
+ while true; do
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "log_this_timeout: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ if ! kill -0 "$pid" 2>/dev/null; then
+ wait "$pid"
+ return "$?"
+ fi
+ sleep 1
+ done
+
+ kill -TERM "$pid"
+ sleep 1
+ if kill -0 "$pid" 2>/dev/null; then
+ kill -KILL "$pid"
+ fi
+ return 1
+}
+
+log_force_stop ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_force_stop <log name> [grace period in seconds]" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local grace="$2"
+ local log_stderr_pid="_log_pid.$BUILD_TAG.$name.stderr"
+ local log_stdout_pid="_log_pid.$BUILD_TAG.$name.stdout"
+ local stderr_pid
+ local stdout_pid
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop=$(( time_start + 5 ))
+ local time_now
+
+ if [ -n "$grace" -a "$grace" -gt 0 ] 2>/dev/null; then
+ time_stop=$(( time_start + grace ))
+ fi
+
+ while true; do
+ if [ ! -f "$log_stderr_pid" -a ! -f "$log_stdout_pid" ]; then
+ break
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break;
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "log_force_stop: Invalid timestamp from date!" >&2
+ return 1
+ fi
+ sleep 1
+ done
+
+ if [ -f "$log_stderr_pid" ]; then
+ stderr_pid=`cat "$log_stderr_pid"`
+ if [ "$stderr_pid" -gt 0 ] 2>/dev/null; then
+ kill -TERM "$stderr_pid" 2>/dev/null
+ fi
+ rm -f "$log_stderr_pid"
+ fi
+
+ if [ -f "$log_stdout_pid" ]; then
+ stdout_pid=`cat "$log_stdout_pid"`
+ if [ "$stdout_pid" -gt 0 ] 2>/dev/null; then
+ kill -TERM "$stdout_pid" 2>/dev/null
+ fi
+ rm -f "$log_stdout_pid"
+ fi
+
+ return 0
+}
+
+log_grep ()
+{
+ local output=""
+ OPTIND=1
+ while getopts ":o" opt; do
+ case "$opt" in
+ o)
+ output=1
+ ;;
+ \?)
+ echo "log_grep: Invalid option: -$OPTARG" >&2
+ exit 1
+ ;;
+ esac
+ done
+ shift $((OPTIND-1))
+
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: log_grep [-o] <log name> <stdout|stderr|both> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local type="$2"
+ local grep_string="$3"
+ local log_files
+
+ case "$type" in
+ stdout)
+ if [ ! -f "$log_stdout" ]; then
+ return 1
+ fi
+ log_files="$log_stdout"
+ ;;
+ stderr)
+ if [ ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stderr"
+ ;;
+ both)
+ if [ ! -f "$log_stdout" -a ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stdout $log_stderr"
+ ;;
+ esac
+
+ if [ -z "$log_files" ]; then
+ echo "log_grep: Wrong type of log file specified, should be stdout, stderr or both!" >&2
+ exit 1
+ fi
+
+ if [ -n "$output" ]; then
+ $GREP -- "$grep_string" $log_files 2>/dev/null
+ else
+ echo "log_grep: greping in $name for: $grep_string"
+ $GREP -q -- "$grep_string" $log_files 2>/dev/null
+ fi
+}
+
+log_grep_count ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$3" ]; then
+ echo "usage: log_grep_count <log name> <stdout|stderr|both> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local type="$2"
+ local grep_string="$3"
+ local count="$4"
+ local log_files
+ local count_found
+
+ case "$type" in
+ stdout)
+ if [ ! -f "$log_stdout" ]; then
+ return 1
+ fi
+ log_files="$log_stdout"
+ ;;
+ stderr)
+ if [ ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stderr"
+ ;;
+ both)
+ if [ ! -f "$log_stdout" -a ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stdout $log_stderr"
+ ;;
+ esac
+
+ if [ -z "$log_files" ]; then
+ echo "log_grep_count: Wrong type of log file specified, should be stdout, stderr or both!" >&2
+ exit 1
+ fi
+
+ echo "log_grep_count: greping in $name, should find $count of: $grep_string"
+ count_found=`$GREP -- "$grep_string" $log_files 2>/dev/null | wc -l 2>/dev/null`
+
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ return 1
+}
+
+log_waitfor ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$3" ]; then
+ echo "usage: log_waitfor <log name> <stdout|stderr|both> <timeout in seconds> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local type="$2"
+ local timeout="$3"
+ local grep_string="$4"
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local log_files
+
+ case "$type" in
+ stdout)
+ if [ ! -f "$log_stdout" ]; then
+ return 1
+ fi
+ log_files="$log_stdout"
+ ;;
+ stderr)
+ if [ ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stderr"
+ ;;
+ both)
+ if [ ! -f "$log_stdout" -a ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stdout $log_stderr"
+ ;;
+ esac
+
+ if [ -z "$log_files" ]; then
+ echo "log_waitfor: Wrong type of log file specified, should be stdout, stderr or both!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "log_waitfor: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "log_waitfor: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "log_waitfor: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "log_waitfor: waiting for log $name to contain (timeout $timeout): $grep_string"
+ while true; do
+ if $GREP -q -- "$grep_string" $log_files 2>/dev/null; then
+ return 0
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "log_waitfor: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+ return 1
+}
+
+log_cleanup ()
+{
+ local pid_file
+ local pid
+
+ ls _log_pid* 2>/dev/null | while read pid_file; do
+ pid=`cat $pid_file 2>/dev/null`
+
+ if [ -n "$pid" -a "$pid" -gt 0 ] 2>/dev/null; then
+ kill -TERM "$pid" 2>/dev/null
+ rm -f "$pid_file" 2>/dev/null
+ fi
+ done
+
+ rm -f "_log.$BUILD_TAG"* 2>/dev/null
+}
+
+log_remove ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_remove <log name>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+
+ rm -f "$log_stderr" "$log_stdout" 2>/dev/null
+}
+
+log_save_try ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_save_try <try>" >&2
+ exit 1
+ fi
+
+ local try="$1"
+ local log_file
+
+ ls "_log.$BUILD_TAG"* 2>/dev/null | while read log_file; do
+ if ! mv "$log_file" "$log_file-try-$try" 2>/dev/null; then
+ echo "log_save_try: Unable to save log file $log_file to $log_file-try-$try"
+ return 1
+ fi
+ done
+ return 0
+}
+
+run_tests ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: run_tests <tests directory>" >&2
+ exit 1
+ fi
+
+ local test_dir="$1"
+ local entry
+ local test=()
+ local test_num=0
+ local test_iter=0
+ local test_path
+ local test_status
+ local test_failed=0
+ local pwd=`pwd`
+ local pwd2
+ local retry
+
+ if [ -n "$PRE_TEST" ]; then
+ if ! declare -F "$PRE_TEST" >/dev/null 2>/dev/null; then
+ unset PRE_TEST
+ fi
+ fi
+
+ if [ -n "$POST_TEST" ]; then
+ if ! declare -F "$POST_TEST" >/dev/null 2>/dev/null; then
+ unset POST_TEST
+ fi
+ fi
+
+ if [ -n "$RETRY_TEST" ]; then
+ if [ ! "$RETRY_TEST" -gt 0 ] 2>/dev/null; then
+ RETRY_TEST=0
+ fi
+ else
+ RETRY_TEST=0
+ fi
+
+ if [ -n "$RETRY_SLEEP" ]; then
+ if [ ! "$RETRY_SLEEP" -ge 0 ] 2>/dev/null; then
+ RETRY_SLEEP=10
+ fi
+ else
+ RETRY_SLEEP=10
+ fi
+
+ if ! cd "$test_dir" 2>/dev/null; then
+ echo "run_tests: unable to change to test directory $test_dir!" >&2
+ return 1
+ fi
+
+ ls -1 2>/dev/null | $GREP '^[0-9]*' | $GREP -v '\.off$' 2>/dev/null >"_tests.$BUILD_TAG"
+ while read entry; do
+ if [ -d "$entry" -a -f "$entry/test.sh" -a ! -f "$entry/off" ]; then
+ test[test_num]="$entry"
+ test_num=$(( test_num + 1 ))
+ fi
+ done <"_tests.$BUILD_TAG"
+ rm -f "_tests.$BUILD_TAG" 2>/dev/null
+
+ if [ "$test_num" -le 0 ] 2>/dev/null; then
+ echo "run_tests: no tests found!" >&2
+ cd "$pwd"
+ return 1
+ fi
+
+ echo "Running tests ..."
+ while [ "$test_iter" -lt "$test_num" ] 2>/dev/null; do
+ retry=0
+ test_path="${test[test_iter]}"
+ test_iter=$(( test_iter + 1 ))
+ echo "##### `date` $test_iter/$test_num $test_path ... "
+ pwd2=`pwd`
+ cd "$test_path" 2>/dev/null &&
+ while [ "$retry" -le "$RETRY_TEST" ] 2>/dev/null; do
+ if [ "$retry" -gt 0 ] 2>/dev/null; then
+ syslog_stop &&
+ log_save_try "$retry" &&
+ syslog_save_try "$retry" ||
+ {
+ echo "##### `date` $test_iter/$test_num $test_path ... Unable to retry"
+ test_status=1
+ break
+ }
+ echo "##### `date` $test_iter/$test_num $test_path ... RETRY $retry in $RETRY_SLEEP seconds"
+ sleep "$RETRY_SLEEP"
+ fi
+ syslog_trace &&
+ if [ -n "$PRE_TEST" ]; then
+ $PRE_TEST "$test_path"
+ fi &&
+ ( source ./test.sh )
+ test_status="$?"
+ if [ "$test_status" -eq 0 ] 2>/dev/null; then
+ break
+ fi
+ retry=$(( retry + 1 ))
+ done
+ syslog_stop
+ if [ -n "$POST_TEST" ]; then
+ $POST_TEST "$test_path" "$test_status"
+ fi
+ if [ "$test_status" -eq 0 ] 2>/dev/null; then
+ echo "##### `date` $test_iter/$test_num $test_path ... OK"
+ log_cleanup
+ syslog_cleanup
+ else
+ test_failed=$(( test_failed + 1 ))
+ echo "##### `date` $test_iter/$test_num $test_path ... FAILED!"
+ fi
+
+ if ! cd "$pwd2" 2>/dev/null; then
+ echo "run_tests: unable to change back to test directory $pwd2 after running a test!" >&2
+ test_failed=1
+ break
+ fi
+ done
+
+ if ! cd "$pwd" 2>/dev/null; then
+ echo "run_tests: unable to change back to directory $pwd after running tests!" >&2
+ return 1
+ fi
+
+ if [ "$test_failed" -gt 0 ] 2>/dev/null; then
+ return 1
+ fi
+}
+
+run_test ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: run_test <test name> <test directory>" >&2
+ exit 1
+ fi
+
+ local test_name="$1"
+ local test_dir="$2"
+ local test_status
+ local pwd=`pwd`
+
+ if [ -n "$PRE_TEST" ]; then
+ if ! declare -F "$PRE_TEST" >/dev/null 2>/dev/null; then
+ unset PRE_TEST
+ fi
+ fi
+
+ if [ -n "$POST_TEST" ]; then
+ if ! declare -F "$POST_TEST" >/dev/null 2>/dev/null; then
+ unset POST_TEST
+ fi
+ fi
+
+ if [ ! -f "$test_dir/test.sh" ]; then
+ echo "run_test: no test.sh in test $test_name ($test_dir)!" >&2
+ return 1
+ fi
+
+ if ! cd "$test_dir" 2>/dev/null; then
+ echo "run_test: unable to change to test $test_name directory $test_dir!" >&2
+ return 1
+ fi
+
+ echo "##### Running test $test_name ..."
+ if [ -n "$PRE_TEST" ]; then
+ $PRE_TEST "$test_name"
+ fi &&
+ syslog_trace &&
+ ( source ./test.sh )
+ test_status="$?"
+ syslog_stop
+ if [ -n "$POST_TEST" ]; then
+ $POST_TEST "$test_name" "$test_status"
+ fi
+ if [ "$test_status" -eq 0 ] 2>/dev/null; then
+ echo "##### Test $test_name ... OK"
+ log_cleanup
+ syslog_cleanup
+ else
+ echo "##### Test $test_name ... FAILED!"
+ fi
+
+ if ! cd "$pwd" 2>/dev/null; then
+ echo "run_test: unable to change back to directory $pwd after running test $test_name!" >&2
+ return 1
+ fi
+
+ if [ "$test_status" -ne 0 ] 2>/dev/null; then
+ return 1
+ fi
+}
+
+syslog_trace ()
+{
+ if [ -n "$_SYSLOG_TRACE_PID" ]; then
+ echo "syslog_trace: Syslog trace already running (pid $_SYSLOG_TRACE_PID)!" >&2
+ exit 1
+ fi
+
+ local syslog_file
+
+ case "$DISTRIBUTION" in
+ debian | \
+ ubuntu )
+ syslog_file="/var/log/syslog"
+ ;;
+ redhat | \
+ centos | \
+ sl | \
+ opensuse | \
+ suse | \
+ freebsd | \
+ netbsd | \
+ openbsd )
+ syslog_file="/var/log/messages"
+ ;;
+ sunos )
+ syslog_file="/var/adm/messages"
+ ;;
+ esac
+
+ if [ -z "$syslog_file" ]; then
+ echo "syslog_trace: Unable to start trace of syslog: no syslog file set" >&2
+ exit 1
+ fi
+
+ if [ ! -r "$syslog_file" ]; then
+ echo "syslog_trace: Unable to start trace of syslog: no access to $syslog_file" >&2
+ exit 1
+ fi
+
+ $TAIL_FOLLOW "$syslog_file" >"_syslog.$BUILD_TAG" 2>/dev/null &
+ _SYSLOG_TRACE_PID="$!"
+
+ if [ -z "$_SYSLOG_TRACE_PID" -o ! "$_SYSLOG_TRACE_PID" -gt 0 ] 2>/dev/null; then
+ echo "syslog_trace: Unable to start trace of syslog!" >&2
+ exit 1
+ fi
+
+ if ! kill -0 "$_SYSLOG_TRACE_PID" 2>/dev/null >/dev/null; then
+ wait "$_SYSLOG_TRACE_PID"
+ echo "syslog_trace: Unable to start trace of syslog: exited with status $?"
+ exit 1
+ fi
+
+ echo "syslog_trace: trace started (pid $_SYSLOG_TRACE_PID)"
+}
+
+syslog_stop ()
+{
+ if [ -z "$_SYSLOG_TRACE_PID" ]; then
+ echo "syslog_stop: Syslog trace not started!" >&2
+ exit 1
+ fi
+
+ if kill -TERM "$_SYSLOG_TRACE_PID" 2>/dev/null; then
+ wait "$_SYSLOG_TRACE_PID"
+ unset _SYSLOG_TRACE_PID
+ fi
+
+ if [ -n "$_SYSLOG_TRACE_PID" ]; then
+ echo "syslog_stop: Unable to stop trace of syslog!" >&2
+ exit 1
+ fi
+
+ echo "syslog_stop: trace stopped"
+}
+
+syslog_waitfor ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: syslog_waitfor <timeout in seconds> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$1"
+ local grep_string="$2"
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_waitfor: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "syslog_waitfor: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "syslog_waitfor: waiting for syslog to contain (timeout $timeout): $grep_string"
+ while true; do
+ if $GREP -q -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null; then
+ return 0
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ -z "$_SYSLOG_TRACE_PID" -o "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "syslog_waitfor: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+syslog_waitfor_count ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: syslog_waitfor_count <timeout in seconds> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$1"
+ local count="$2"
+ local grep_string="$3"
+ local count_found
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_waitfor_count: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "syslog_waitfor_count: waiting for syslog to contain $count counts of (timeout $timeout): $grep_string"
+ while true; do
+ count_found=`$GREP -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null | wc -l 2>/dev/null`
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ -z "$_SYSLOG_TRACE_PID" -o "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+syslog_grep ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: syslog_grep <grep string ...>" >&2
+ exit 1
+ fi
+
+ local grep_string="$1"
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_grep: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "syslog_grep: greping syslog for: $grep_string"
+ $GREP -q -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null
+}
+
+syslog_grep_count ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: syslog_grep_count <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local count="$1"
+ local grep_string="$2"
+ local count_found
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_grep_count: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "syslog_grep_count: greping syslog, should find $count of: $grep_string"
+ count_found=`$GREP -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null | wc -l 2>/dev/null`
+
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ return 1
+}
+
+syslog_cleanup ()
+{
+ rm -f "_syslog.$BUILD_TAG"* 2>/dev/null
+}
+
+syslog_save_try ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: syslog_save_try <try>" >&2
+ exit 1
+ fi
+
+ local try="$1"
+
+ if ! mv "_syslog.$BUILD_TAG" "_syslog.$BUILD_TAG-try-$try" 2>/dev/null; then
+ echo "syslog_save_try: Unable to save syslog file _syslog.$BUILD_TAG to _syslog.$BUILD_TAG-try-$try"
+ return 1
+ fi
+ return 0
+}
+
+apply_parameter ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: apply_parameter <parameter tag> <parameter value> <files ... >" >&2
+ echo " ex: apply_parameter \"INSTALL_ROOT\" \"\$INSTALL_ROOT\" conf.xml" >&2
+ exit 1
+ fi
+
+ local parameter_tag="$1"
+ local parameter_value="$2"
+ shift 2
+ local files="$*"
+ local file
+
+ if echo "$parameter_tag" | grep -q "@" 2>/dev/null; then
+ echo "apply_parameter: parameter tag contains '@', it must not" >&2
+ return 1
+ fi
+
+ for file in $files; do
+ if [ ! -f "$file" ]; then
+ echo "apply_parameter: File $file not found" >&2
+ return 1
+ fi
+ if [ -f "$file.$$" ]; then
+ echo "apply_parameter: Temporary file $file.$$ exists but it should not" >&2
+ return 1
+ fi
+ done
+
+ for file in $files; do
+ sed 's%@'"$parameter_tag"'@%'"$parameter_value"'%g' "$file" > "$file.$$" 2>/dev/null &&
+ mv "$file.$$" "$file" 2>/dev/null ||
+ {
+ echo "apply_parameter: Unable to apply parameter $parameter_tag value $parameter_value to file $file" >&2
+ return 1
+ }
+ done
+
+ return 0
+}
+
+sed_inplace ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: sed_inplace <expression> <files ... >" >&2
+ exit 1
+ fi
+
+ local expression="$1"
+ shift 1
+ local files="$*"
+ local file
+
+ for file in $files; do
+ if [ ! -f "$file" ]; then
+ echo "sed_inplace: File $file not found" >&2
+ return 1
+ fi
+ if [ -f "$file.$$" ]; then
+ echo "sed_inplace: Temporary file $file.$$ exists but it should not" >&2
+ return 1
+ fi
+ done
+
+ for file in $files; do
+ sed "$expression" "$file" > "$file.$$" 2>/dev/null &&
+ mv "$file.$$" "$file" 2>/dev/null ||
+ {
+ echo "sed_inplace: Unable to sed inplace file $file" >&2
+ return 1
+ }
+ done
+
+ return 0
+}
+
+try_run ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: try_run <timeout in seconds> <command ... >" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$1"
+ local pid
+ shift
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "try_run: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "try_run: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "try_run: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ ( $* ) &
+ pid="$!"
+
+ if [ -z "$pid" -o "$pid" -le 0 ] 2>/dev/null; then
+ echo "try_run: No pid from backgrounded program?" >&2
+ return 1
+ fi
+
+ while true; do
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "try_run: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ if ! kill -0 "$pid" 2>/dev/null; then
+ wait "$pid"
+ return "$?"
+ fi
+ sleep 1
+ done
+
+ kill -TERM "$pid"
+ sleep 1
+ if kill -0 "$pid" 2>/dev/null; then
+ kill -KILL "$pid"
+ fi
+ return 1
+}
+
+waitfor_this ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: waitfor_this <file to grep> <timeout in seconds> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local file="$1"
+ local timeout="$2"
+ local grep_string="$3"
+
+ if [ ! -f "$file" ]; then
+ echo "waitfor_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_this: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_this: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "waitfor_this: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "waitfor_this: waiting for $file to contain (timeout $timeout): $grep_string"
+ while true; do
+ if $GREP -q -- "$grep_string" "$file" 2>/dev/null; then
+ return 0
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "waitfor_this: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+waitfor_count_this ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ]; then
+ echo "usage: waitfor_count_this <file to grep> <timeout in seconds> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local file="$1"
+ local timeout="$2"
+ local count="$3"
+ local grep_string="$4"
+ local count_found
+
+ if [ ! -f "$file" ]; then
+ echo "waitfor_count_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_count_this: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_count_this: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "waitfor_count_this: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "waitfor_count_this: waiting for $file to contain $count counts of (timeout $timeout): $grep_string"
+ while true; do
+ count_found=`$GREP -- "$grep_string" "$file" 2>/dev/null | wc -l 2>/dev/null`
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "waitfor_count_this: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+grep_this ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: grep_this <file to grep> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local file="$1"
+ local grep_string="$2"
+
+ if [ ! -f "$file" ]; then
+ echo "grep_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "grep_this: greping in $file for: $grep_string"
+ $GREP -q -- "$grep_string" "$file" 2>/dev/null
+}
+
+grep_count_this ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: grep_count_this <file to grep> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local file="$1"
+ local count="$2"
+ local grep_string="$3"
+ local count_found
+
+ if [ ! -f "$file" ]; then
+ echo "grep_count_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "grep_count_this: greping in $file, should find $count of: $grep_string"
+ count_found=`$GREP -- "$grep_string" "$file" 2>/dev/null | wc -l 2>/dev/null`
+
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ return 1
+}